Giving this controller
@GetMapping("/test")
@ResponseBody
public String test() {
if (!false) {
throw new IllegalArgumentException();
}
return "blank";
}
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleException(Exception e) {
return "Exception handler";
}
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public String handleIllegalException(IllegalArgumentException e) {
return "IllegalArgumentException handler";
}
Both ExceptionHandler match the IllegalArgumentException
because it's a child of Exception
class.
When I reach /test
endpoint, the method handleIllegalException
is called. If I throw a NullPointerException
, the method handleException
is called.
How does spring knows that it should execute the handleIllegalException
method and not the handleException
method ? How does it manage the priority when multiple ExceptionHandler match an Exception ?
(I thought the order or the ExceptionHandler declarations was important, but even if I declare handleIllegalException
before handleException
, the result is the same)
Global Exception Handler - Exception Handling is a cross-cutting concern, it should be done for all the pointcuts in our application. We have already looked into Spring AOP and that's why Spring provides @ControllerAdvice annotation that we can use with any class to define our global exception handler.
Spring MVC provides exception handling for your web application to make sure you are sending your own exception page instead of the server-generated exception to the user. The @ExceptionHandler annotation is used to detect certain runtime exceptions and send responses according to the exception.
As mentioned earlier, above exception handler will handle all exceptions which are either instance of given class or sub-classes of argument exception. But, if we want to configure @ExceptionHandler for multiple exceptions of different types, then we can specify all such exceptions in form of array.
In Java, exception handling is done by try, catch blocks but spring boot also allows us to provide customized global exception handling where we need not to add try catch block everwhere, we can create a separate class for handling exceptions and it also separates the exception handling code from businesss logic code.
Spring MVC provides many different methods for Exception handling definitions.
In general, it will try to find the most "specific" exception handler registered to handle the exception. If there is no such a handler, it will try to check for the superclass of exception, maybe there is a handler for it, if it's not found as well, it will go one more level up and so on and so forth, from the most specific to the most general.
If you want to see it in the code of Spring, an entry point to learn this topic would be:
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
This class resolves the exceptions registered through @ExceptionHandler
methods out of the beans registered in the application context. This class, in turn, uses the another class org.springframework.web.method.annotation.ExceptionHandlerMethodResolver
which is responsible for mapping all the methods marked with @ExceptionHandler
annotation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With