-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Description
Andrzej Martynowicz opened SPR-15432 and commented
When there are multiple @ControllerAdvice
annotated classes it seems that they are selected basing on alphabetical order rather than trying to do "best match".
Consider following two controllers. First is ordinary spring webmvc controller (annotated with @Controller
) , the other is rest controlller (annotated with @RestController
):
// this one is annotated with @Controller
@Controller
public class TestController {
@ResponseBody
@RequestMapping(method = GET, value = "/test")
public String testMethod() {
if (true) {
throw new RuntimeException("asdasdsadsad");
}
return "asdsadsad";
}
}
@RestController
@RequestMapping(value = "/soume-url", produces = APPLICATION_JSON_UTF8_VALUE, consumes = APPLICATION_JSON_UTF8_VALUE)
public class SomeController {
@RequestMapping(method = GET)
public ResponseEntity<? extends Something> someMethod() {
if (true) {
throw new RuntimeException("ewewe");
}
return new Something();
}
}
}
Now let's create two exception handler classes annotated with @ControllerAdvice
. The second one is annotated with @ControllerAdvice
(annotations = RestController.class) with the intention to be executed only for @RestController
annotated classes.
@ControllerAdvice
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleUnexpectedException(Exception e) {
return new ResponseEntity<String>("some message", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@ControllerAdvice(annotations = RestController.class)
public class RestControllerExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody // not needed(?), but addded just in cases
public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) {
ErrorResponse errorResponse = new ErrorResponse("my error response");
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
My expectation would be that exceptions thrown by @RestController
classes are handled by RestControllerExceptionHandler because this one is more specialized (annotated with @ControllerAdvice
(annotations = RestController.class)). However this does not work like this - the request is handled always by ControllerExceptionHandler.
Now the interesting thing is when you rename the RestControllerExceptionHandler to ARestControllerExceptionHandler (so that it alphabetically precedes ControllerExceptionHandler) all works as exepected - ARestControllerExceptionHandler handles exceptions from classes annotated with @RestController
and @ControllerExceptionHandler
handles all the other.
See also: http://stackoverflow.com/questions/43325685/spring-different-exception-handler-for-restcontroller-and-controller where I tried to ask for assistance and finally ended up with this bug,
Affects: 4.3.7