How to centralize exception handling in multiple methods of an API

Related searches

This is a plain Java 8+ question, no frameworks used.

We are producing an API for a higher layer which deals with the presentation layer among other activities. We have and interface agreed with the invoker, so they are happy to receive some particular exceptions we throw.

At the same time, we are also using other APIs under the same agreement, so we can do stuff by ourselves and throw exceptions or we can invoke other APIs which throw the agreed exceptions. Currently, we do nothing with the exceptions thrown by the APIs we are invoking.

Thing is, we are the best positioned in this infrastructure to deal with intermediate activities while exceptions are thrown, so we need to capture both, our exceptions and the exceptions provided by those we are invoking; basically reporting the issue, raising system controls, etc, and then re-throw the original exception so the top layer keeps as it is now.

We have around 300 methods in the entry point class of our API:

public void method1 (arguments for method 1) {
...
}

...

public void method300 (arguments for method 300) {
...
}

I clearly understand that I can create a method to centralise the actions to be taken in the exception management, something like:

public void myExceptionHandler (Exception e) {
    if (e instanceOf X) {
    } else if ...
    ...
    throw particularExceptionAccordingTheCase 
}

But I'd also avoid modifying those 300 methods.

Any idea how to inject a try-catch in those 300 methods to send the Exception to myExceptionHandler without really adding a try-catch in each of them?

Any comments and ideas are much appreciated!

----------- After mprev0 suggestion -------------------------------

I tried this approach. It really catches the exception and so on, but I can't re-trow an Exception: I'm forced to catch it, but this goes against the requirement of re-sending the exception back to the top layer. While I can throw an Error, I got a compiler error at line throw new FileNotFoundException();

public class myExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("gotcha!");
        if (e instanceof java.lang.Error) {
            System.out.println("AAT-CORE: Fatal Error");
            throw new java.lang.Error(e.getCause());

        } else if (e instanceof java.lang.Exception) {
            System.out.println("AAT-CORE: Exception Error");
            throw new FileNotFoundException();
        }
    }

}

Any ideas?

------------ After some more digging, fixed with a decorator pattern -------

Previous class implementation does not work, as I can't change the signature of the method and I need to re-throw the java.lang.Exception.

Using a decorator and handling the interface there makes the trick. As a summary:

Top layer class:

public class TopLayer {
    public static void main (String[] args) {
        MiddleLayer m = new MiddleLayer();
        m.method1();
    }
}

Bottom layer class contains specific APIs and some implementation, the only interesting thing is that it contains java.lang.Exceptions uncontrolled, expecting the top layer to do this job. But, we are working in the middle and we will do this job:

public class MiddleLayer extends BottomLayer {

    public MiddleLayer () {
        final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
        Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {

                System.out.println("gotcha2!");
                // carry on with prior flow
                subclass.uncaughtException(thread, ex);
            }
        });

    }

}

In this way, I can get the system.out and the java.lang.Exception is propagated to the Top Layer.

Decorator inspiration came from here: Rethrow UncaughtExceptionHandler Exception after Logging It

Additional comments are welcome!

You can solve this by implementing the java.lang.Thread.UncaughtExceptionHandler interface:

public class MyExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Overrides
    public void uncaughtException(Thread t, Throwable e) {
            if (e instanceOf X) {
            } else if ...
            ...
            throw particularExceptionAccordingTheCase 
    }
}

Then you associate it to all threads as follows:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler())

This will configure the exception handler to handle all uncaught exceptions in all threads of your application.

Note that this will only work for exceptions that aren't yet explicitly handled somewhere in your code and if there is no other handler configured for some particular thread (the uncaught exception handler can also be set for some specific thread).

EDIT: As discovered by @JBC, the above approach will not work for checked exceptions since we are forced to catch them explicitly in our uncaughtException method (note that we cannot add a throws clause to an overridden method). While it will work without problems if we only want to re-throw subtypes of RuntimeException and Error, there is a little adaptation needed if we want to make it work - you can find it explained in @JBC's question.

Java Exception Handling: How to Specify and Handle Exceptions, Java provides a powerful exception handling mechanism that allows you to handle When a method throws an exception object, the runtime searches the call the improper use of an API that causes an IllegalArgumentException one try block for multiple statements that might throw multiple exceptions. We can make centralize Exception handling mechanism by overriding onException() function of “ExceptionFilterAttribute” class. In this example we have override onException exception and populating object of “HttpRescponseException” object by setting exception message and HttpStatuscode property.

As you can see in the question updates, the final solution is a combination of two different approaches, in one side, having the mprev0 approach of implementing the java.lang.Thread.UncaughtExceptionHandler and, on top of this, adding a Decoration pattern to be able to re-throw a run-time exception.

There were no additional approaches so far, so I'm closing the question and bring this as the most complete response.

More information about UncaughtExceptionHandler can be found in the Java documentation, but as always, is short on examples, and here: Advanced exception handling Thread.UncaughtExceptionHandler Example

More information on Decorator pattern usage, can be found here: Decorator Design Pattern in Java Design Patterns - Decorator Pattern

And how to use to manipulate exceptions here: Rethrow UncaughtExceptionHandler Exception after Logging It

9 Best Practices to Handle Java Exceptions, Nevertheless, there are several best practices that are used by most teams. Today's post is going to show you nine of the most important ones you� You can customize how Web API handles exceptions by writing an exception filter. An exception filter is executed when a controller method throws any unhandled exception that is not an HttpResponseException exception.

You could also create a proxy API on top of your current API, have an invocation handler method in the proxy and put this method in a try catch block.

https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

Spring @ExceptionHandler, If we want to centralize the exception handling logic to one class which is capable to handle exceptions thrown from any handler class/ controller class – then we can use @ControllerAdvice annotation. By default the methods in an @ControllerAdvice apply globally to all Controllers. Following is a summary of exception handling in Web API described in this article: We can use HttpResponseException when the possibility of exception is known by us. In the above example, we have thrown exception using HttpResponseException class as we know there is a chance to employee not found in the database.

Spring REST Service Exception Handling, Let's take a closer look at Spring REST service exception handling, where we This is a centralized place to handle all the application level exceptions. handleRunTimeException: This method handles all the We can group multiple similar exceptions and map a common Response Code for them. A method that throws a checked exception or that calls a method that specifies a checked exception needs to either specify or handle it. Unchecked exceptions extend the RuntimeException . You should use them for internal errors that you can’t anticipate and that, most often, the application can’t recover from.

Exception Handling in Spring, In this article, we will look into few approaches of exception handling in This will also centralize our validation/error handling logic. In this tutorial, we discussed several ways to implement an exception handling mechanism for a REST API� If we want to centralize the exception handling logic to one class which is capable to handle exceptions thrown from any handler class/ controller class – then we can use @ControllerAdvice annotation. By default the methods in an @ControllerAdvice apply globally to all Controllers.

We can apply OR operator in selector i.e. a given method would be executed if any one of given exception is encountered. Please note that ResponseEntityExceptionHandler is a convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods.

Comments
  • We have around 300 methods in the entry point class of our API, twitches. Please have a look at Separation of concerns
  • @JBC Good job finding out how to adapt it to work also for checked exceptions, thanks for sharing it! I updated my answer to include also your findings. Btw. if my or any other answer has solved your question please consider accepting it by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. Of course, there is no obligation to do this, but it would be nice :-)
  • Thanks mprev0, that sounds like a good approach. Let me spend some hours with this and revert back shortly.
  • That needs a decorator pattern!
  • Hi JBC, thanks for your feedback! Sorry, I somehow missed the detail that catched exceptions will also be re-thrown by your global exception handler, I thought that probably you will throw only runtime exceptions since checked exceptions are forcing us to catch them. Luckily you found a solution to this problem, thanks for sharing it, looks nice!
  • Hi Sameer, thanks for your answer. I'm not familiar with proxy APIs. I'll need to spend some time with the documentation and make some testings, as this looks like an alternative not only for capturing exceptions but also for adding additional functionality. Any examples will be appreciated, but not required, as I'm sure will find some around. Thanks!
  • Hi Sameer, I've been making some tests, and sorry but I can't find a proper model. I've been checking basically the links you provided plus dzone.com/articles/java-dynamic-proxy and baeldung.com/java-dynamic-proxies. The only way of implementation I see is to create a mimic class A(method1, ..., method300) which invokes the proxy and this proxy to the real class, so in the proxy I can implement the special behavior... but is there a way to avoid the mimic class with the 300 methods? Thanks again.