1

I am developing a Micro Service which is going to be called/used internally. I'm trying to improve error handling, but got confused with two below approaches.

  1. Having multiple exception classes for every layer (Business, Rest Client, Mapper etc)
  2. Creating one general exception class with specific error codes (Business, Rest, Mapper etc).

We tried first approach now, but it seems not that good. I see redundancy and violating DRY principle. Everything is similar except Status Code.

Besides, I think for every case if we want to create a separate exception class (Of course extending parent), it will lead to class explosion.

Some people says: first approach helps with better support and maintenance, but I think with specific error codes and adding more context to the exception and response, it will be easily supportable.

Below is what I think of the second approach:

Error Code Model

public class ErrorCode {
    private int statusCode;
    private String errorCode;
    private String message;

}

Error Codes

    public abstract class ErrorCodes {

    public static ErroCode BAD_REQUEST = new ErrorCode (400, 10101, "Bad Request");
   //Adding other error codes as well

    }

Please Note that we can use enum for error codes.

Exception Class

public class CustomException extends Exception{

    private ErrorCode errorCode;
    private String description;

    public CustomException (ErrorCode errorCode, Throwable throwable, String description){
        //Constructor
    }



    public JsonObject asJson() {
        return Json.createObjectBuilder()
                .add("StatusCode", errorCode.getStatusCode())
                .add("Message", errorCode.getMessage())
                .add("Description", getDescription())
                .build();
    }
}

I thought we can handle every kind of exception, and throw a CustomException with specific error code and add more context to it.

Also it is much cleaner in Controller/Resource class to create the error response.

Please help me figure it out.

Thanks

3

In general, I prefer the first approach. It makes the code easier to read and conveys the author's intent and reason/cause for the exception much better. Let's say you want to handle 404 errors different from 401 errors.

In the first approach, you might have

class UnauthorizedException extends Exception {
   // ...
}

class NotFoundException extends Exception {
   // ...
}

Your calling code would look like

try {
   doSomething();
} catch(UnauthorizedException exc) {
   // something relevant
} catch (NotFoundException exc) {
   // something different
}

If, on the other hand, you followed the second approach, you'd have something like

try {
   doSomething();
} catch(CustomException exc) {
   switch(exc.getErrorCode()) {
       case ERROR_401:
            break;
       case ERROR_404:
            break;
   }
}

Personally, I would find that very difficult to work with.

This simple example demonstrates the kinds of maintainability issues you will have. If every method throws the same exception, every catch block has to check the error code to determine if it's something they want to handle or not. You also have to be very disciplined to document what error codes might come out of a method so that the caller can handle it correctly. And even if you do, you will get no help from the compiler if you miss handling an exception at the right place.

If you find yourself creating too many exception classes, take a step back and determine if you could generalize some of them, thus reducing the total number. You could have a general exception for most cases, then define specific exceptions as the need arises.

  • Thanks for answering. But here is a point. For example, in case of 401 or 404, it is a third party exception thrown when calling other services or auth server. You catch it and wrap with Custom exception with specific error code and more info. You don't catch your custom UnauthorizedException, do you? Also, if you have separate exception classes, won't you have more maintanance overhead and redundency? What would be different in Unauthorized and NotFoundException except ErrorCode? – Mustafa Mohammadi Oct 23 '19 at 12:50
  • Besides, if you have multiple exception class, some of method signature will have multiple throws which is not recommended (as I read in an article) – Mustafa Mohammadi Oct 23 '19 at 12:54
  • @MustafaMohammadi What would be different in Unauthorized and NotFoundException except ErrorCode? How you handle it. That was my point, you are going to do something different if the request is unauthorized than when the endpoint didn't exist. At least you might, anyway. As a matter of fact, we do a similar thing, where we wrap some HTTP errors in one exception, maybe catch and handle other HTTP errors right there, and throw others. – Matthew Oct 23 '19 at 13:10
  • I also don't like methods with long lists of exceptions getting thrown. It's up to you and your design to determine when to wrap exceptions in a more common one, throw the original, or handle it there. If I have a doFoo operation and in it, I do things that might throw an IOException and a ParserException, I will likely create a FooException. At the same time, if i have a doBar operation and it does some things locally, and then goes out to a server for something else, I may have my BarException for the local errors and then let the IOException go. It's case-dependent. – Matthew Oct 23 '19 at 13:14
  • Interesting. In fact, you move the if, else statement (to check if it is IOException or ParserException)to BarException. Same complexity as my second approach, just hiding it in BarException class, right? – Mustafa Mohammadi Oct 23 '19 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.