Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom @ControllerAdvice in Spring for exception handling

I am trying to map exceptions from my rest controllers to responses which have a body, and to do it in a central place.

I have tried this:

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestErrorResponseExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(
        Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        super.handleExceptionInternal(ex, body, headers, status, request);

        return ResponseEntity.status(status).body(Error.from(status));
    }
} 

The problem is that the handler is never triggered.

If I define a custom method with @ExceptionHandler in my rest controllers, or extend something that has @ExceptionHandler, then all works well, but that introduces some bad design.

It is my understanding that Spring will first try to look in controller for exception handling methods, then it will check for registered handlers.

I am trying to verify the behaviour via WebMvcTest, and responses I'm getting are not the Error objects that I'm expecting.

Is there something I'm missing?

like image 705
ioreskovic Avatar asked Jan 28 '23 01:01

ioreskovic


2 Answers

The ControllerAdvice is a configuration that have to be registered by Spring. You have to move your class in the config package or you can register it by annotation.

In my case, I work with a controllerAdvice like this one :

@ControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(MyException.class) 
    public ResponseEntity<String> reponseMyException(Exception e) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body("my message");
    }
}
like image 86
yohann henry Yohann Avatar answered Jan 30 '23 14:01

yohann henry Yohann


Spring Framework provides following ways to help us achieving robust exception handling.

  1. Controller Based – We can define exception handler methods in our controller classes. All we need is to annotate these methods with @ExceptionHandler annotation. This annotation takes Exception class as argument. So if we have defined one of these for Exception class, then all the exceptions thrown by our request handler method will have handled. These exception handler methods are just like other request handler methods and we can build error response and respond with different error page. We can also send JSON error response, that we will look later on in our example. If there are multiple exception handler methods defined, then handler method that is closest to the Exception class is used. For example, if we have two handler methods defined for IOException and Exception and our request handler method throws IOException, then handler method for IOException will get executed.

  2. 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. The handler methods in Global Controller Advice is same as Controller based exception handler methods and used when controller class is not able to handle the exception.

  3. HandlerExceptionResolver – For generic exceptions, most of the times we serve static pages. Spring Framework provides HandlerExceptionResolver interface that we can implement to create global exception handler. The reason behind this additional way to define global exception handler is that Spring framework also provides default implementation classes that we can define in our spring bean configuration file to get spring framework exception handling benefits. SimpleMappingExceptionResolver is the default implementation class, it allows us to configure exceptionMappings where we can specify which resource to use for a particular exception. We can also override it to create our own global handler with our application specific changes, such as logging of exception messages.

like image 45
0gam Avatar answered Jan 30 '23 14:01

0gam