I have Java microservice that exposes multiple APIs. Under each API there are many exceptions could be thrown. The last method that catches them all has big catch block ...

catch(exc1 e1 | exc2 e2 | exc3 e3 ..... | exc10 e10){ ...}

They are all of the same level. Now I thought of combining them all under one exception. So, exc1 to exc10 extend Api1Exception. So I could jus catch it like this:

catch(Api1Exceptione){ ... }

Cleaner, and easier to control. However. I realized other APIs share some of Api1Exception exceptions. Let's say API2, is throwing something like:

catch(exc13 e13 | exc2 e2 | exc16 e16 ..... | exc19 e19){ ...}

I do not want to catch the entire Api1Exception, because some of them are not thrown in that API2 logic. So, I had to create another exception Api2Exception and I had create another copy of say exc2 to be a child of Api2Exception. This to me looks like redundant code, and I thought there should be better way to handle this. Any idea?


Following the answer, this is what I did:

  • created CustomException that extends Exception, with field errorCode
  • Every custom exception I create, extends CustomException and pass the errorCode along with the message
  • I catch it like this:

    catch(CustomException ce){    
  • handling method:

            //do something    
    else if (ce.getErrorCode().eqauls(SOME_ERROR_CODE){    
            //do something else    
         throw new Exception ....    

P.S.: Not sure why my question got downvoted. Whoever did it, it would be great if you provide some feedback.

  • 3
    Are you the designer/publisher of this API? Typically, there is one base class for the entire library (entire API, i.e. across all methods), and the next inheritance level is based on problem type (e.g. bad argument, invalid operation, network error, key not found, etc). There is a diminishing return on adding more exceptions. It would be unusual to create a base exception class just for a single API method. To decide whether it is worth to create an exception class, think about (1) how often does caller need to catch this one exactly (2) does this enable precise corrective action? – rwong May 30 '18 at 0:20
  • What do you lose by also using Api1Exception? are you handling differently the other types of exceptions ? – user7294900 May 30 '18 at 6:56
  • @user7294900 Api2Exception would share some of Api1Exception. Hence, I have to create duplicate exception classes and assign to each – Hawk May 30 '18 at 9:08

The standard approach is to create one class ApiException that is thrown by all public APIs of the library, and wrap the underlying exception into it:

try {
catch (Exception e) {
    throw new ApiException(e);

If a user's catch block needs special handling for some of the underlying exceptions, it can unwrap it (with .getCause()) and if it's not what's needed, rethrow the original exception.

The idea is that if there are all sorts of possible underlying causes unrelated to code's logic, the code can't do anything intelligent about it, and this rather requires the intervention of the app's admin. So it just passes it upstream, possibly wrapping with its own type, with the idea that it will eventually be logged.

If the code is supposed to actually be able to resolve the problem, the function should return concrete exceptions that are in line with the nature of its work, and no more than a few of them. Failing to keep the number small in this case means you probably need to split the function into a few more specialized ones which the user will call in sequence.

  • In my case, I will end with long if else statement inside catch block. Was hoping it would be better approach – Hawk May 30 '18 at 11:05
  • @Hawk got more insight into this, updated – ivan_pozdeev May 30 '18 at 11:44

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.