Note that there are some explanatory texts on larger screens.

plurals
  1. POError Handling on Java SDK for REST API service
    primarykey
    data
    text
    <p>We are building a Java SDK to simplify the access to one of our services that provide a REST API. This SDK is to be used by 3rd-party developers. I am struggling to find the best pattern to implement the error handling in the SDK that better fits the Java language.</p> <p>Let's say we have the rest endpoint: <code>GET /photos/{photoId}</code>. This may return the following HTTP status codes:</p> <ul> <li>401 : The user is not authenticated</li> <li>403 : The user does not have permission to access this photo</li> <li>404 : There's no photo with that id</li> </ul> <p>The service looks something like this:</p> <pre><code>interface RestService { public Photo getPhoto(String photoID); } </code></pre> <p>In the code above I am not addressing the error handling yet. I obviously want to provide a way for the client of the sdk to know which error happened, to potentially recover from it. Error handling in Java is done using Exceptions, so let's go with that. However, what is the best way to do this using exceptions? </p> <p><strong>1. Have a single exception with information about the error.</strong></p> <pre><code>public Photo getPhoto(String photoID) throws RestServiceException; public class RestServiceException extends Exception { int statusCode; ... } </code></pre> <p>The client of the sdk could then do something like this:</p> <pre><code>try { Photo photo = getPhoto("photo1"); } catch(RestServiceException e) { swtich(e.getStatusCode()) { case 401 : handleUnauthenticated(); break; case 403 : handleUnauthorized(); break; case 404 : handleNotFound(); break; } } </code></pre> <p>However I don't really like this solution mainly for 2 reasons:</p> <ul> <li>By looking at the method's signature the developer has no idea what kind of error situations he may need to handle.</li> <li>The developer needs to deal directly with the HTTP status codes and know what they mean in the context of this method (obviously if they are correctly used, a lot of the times the meaning is known, however that may not always be the case).</li> </ul> <p><strong>2. Have a class hierarchy of errors</strong> </p> <p>The method signature remains:</p> <pre><code>public Photo getPhoto(String photoID) throws RestServiceException; </code></pre> <p>But now we create exceptions for each error type:</p> <pre><code>public class UnauthenticatedException extends RestServiceException; public class UnauthorizedException extends RestServiceException; public class NotFoundException extends RestServiceException; </code></pre> <p>Now the client of the SDK could then do something like this:</p> <pre><code>try { Photo photo = getPhoto("photo1"); } catch(UnauthenticatedException e) { handleUnauthorized(); } catch(UnauthorizedException e) { handleUnauthenticated(); } catch(NotFoundException e) { handleNotFound(); } </code></pre> <p>With this approach the developer does not need to know about the HTTP status codes that generated the errors, he only has to handle Java Exceptions. Another advantage is that the developer may only catch the exceptions he wants to handle (unlike the previous situation where it would have to catch the single Exception (<code>RestServiceException</code>) and only then decide if he wants to deal with it or not).</p> <p>However, there's still one problem. By looking at the method's signature the developer still has no idea about the kind of errors he may need to handle because we only have the super class in the method's signature.</p> <p><strong>3. Have a class hierarchy of errors + list them in the method's signature</strong> </p> <p>Ok, so what comes to mind now is to change the method's signature to:</p> <pre><code>public Photo getPhoto(String photoID) throws UnauthenticatedException, UnauthorizedException, NotFoundException; </code></pre> <p>However, it is possible that in the future new error situations could be added to this rest endpoint. That would mean adding a new Exception to the method's signature and that would be a breaking change to the java api. We would like to have a more robust solution that would not result in breaking changes to the api in the situation described.</p> <p><strong>4. Have a class hierarchy of errors (using Unchecked exceptions) + list them in the method's signature</strong> </p> <p>So, what about Unchecked exceptions? If we change the RestServiceException to extend the RuntimeException:</p> <pre><code>public class RestServiceException extends RuntimeException </code></pre> <p>And we keep the method's signature:</p> <pre><code>public Photo getPhoto(String photoID) throws UnauthenticatedException, UnauthorizedException, NotFoundException; </code></pre> <p>This way I can add new exceptions to the method's signature without breaking existing code. However, with this solution the developer is not forced to catch any exception and won't notice that there are error situations he needs to handle until he carefully reads the documentation (yeah, right!) or noticed the Exceptions that are in the method's signature.</p> <p><strong>What's the best practice for error handling in these kind of situations?</strong></p> <p><strong>Are there other (better) alternatives to the ones I mentioned?</strong></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload