In Spring you can set up “global” exception handler via @ControllerAdvice and @ExceptionHandler annotation. I’m trying to utilize this mechanism to have two global exception handlers:
RestControllerExceptionHandler
– which should return error responses as json for any controller annotated with@RestController
ControllerExceptionHandler
– which should print error message to the screen for any other controller (annottated with@Controller
)The problem is that when I declare these two exception handlers spring always uses the
ControllerExceptionHandler
and neverRestControllerExceptionHandler
to handle the exception.How to make this work ?
BTW: I tried to use @Order annotation but this does not seem to work.Here are my exception handlers:
// should handle all exception for classes annotated with @ControllerAdvice(annotations = RestController.class) public class RestControllerExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) { // below object should be serialized to json ErrorResponse errorResponse = new ErrorResponse("asdasd"); return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } // should handle exceptions for all the other controllers @ControllerAdvice(annotations = Controller.class) public class ControllerExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleUnexpectedException(Exception e) { return new ResponseEntity<String>("Unexpected exception, HttpStatus.INTERNAL_SERVER_ERROR); } } }
When I remove
ControllerExceptionHandler
thanRestControllerExceptionHandler
is correctly called by spring (only for classes annotated with@RestController
)…. but when I addControllerExceptionHandler
than all goes viaControllerExceptionHandler
. Why?
Answer
After some deeper investigation it seems that the alphabetical order matters :/.
When I renamed my RestControllerExceptionHandler
to ARestControllerExceptionHandler
(which alphabetically precedes ControllerExceptionHandler
) all works as expected! ARestControllerExceptionHandler
correctly handles exceptions from RestControllers
and ControllerExceptionHandler
handles exception from other controllers.
I created a bug in spring for this: https://jira.spring.io/browse/SPR-15432
— EDIT:
I received the answer for SPR-15432 where it is suggested that this case can be solved with @Order
(org.springframework.core.annotation.Order
) annotation or by implementing Ordered interface.
This did not work for me before, but it seems that I have imported wrong @Order
annotation. (from log4j2 instead of spring). After fixing this it works. Fixed version is following:
// should handle all exception for classes annotated with
@ControllerAdvice(annotations = RestController.class)
@Order(1) // NOTE: order 1 here
public class RestControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) {
// below object should be serialized to json
ErrorResponse errorResponse = new ErrorResponse("asdasd");
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// should handle exceptions for all the other controllers
@ControllerAdvice(annotations = Controller.class)
@Order(2) // NOTE: order 2 here
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleUnexpectedException(Exception e) {
return new ResponseEntity<String>("Unexpected exception, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Attribution
Source : Link , Question Author : walkeros , Answer Author : walkeros