Spring @ControllerAdvice order and precedence
Rédigé par gorki Aucun commentaireProblem :
I added a second @ControllerAdvice
to handle my 404 pages in addition to an existing @ControllerAdvice
that was handling a REST Api for the backend part.
My newer controller advice has :
@ExceptionHandler(NoHandlerFoundException.class)
public ModelAndView handleError404(HttpServletRequest request, Exception e) {
if (request.getRequestURI().startsWith("/api")) {
throw new ResourceNotFoundException();
} else {
ModelAndView mv = new ModelAndView();
mv.setViewName("forward:/index.html");
return mv;
}
}
The existing one has :
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorDTO handleException(Exception e) {
log.error(e.getMessage(), e);
return new ErrorDTO(e.getMessage(), "E01");
}
On dev environment, it works.
On production environment, it fails : only the REST API exception handler was used.
A remote debug show me that I was in : @ExceptionHandler(Exception.class)
the general exception handler, and the exception thrown is NoHandlerFoundException
Solution :
I tried this solution :
- Use @Order on each class
- as seen here
But it also fails and as noted in the answers :
I also found in the documentation that :
ExceptionHandlerMethod
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception)
Find an @ExceptionHandler method for the given exception. The default implementation searches methods in the class hierarchy of the controller first and if not found, it continues searching for additional @ExceptionHandler methods assuming some @ControllerAdvice Spring-managed beans were detected. Parameters: handlerMethod - the method where the exception was raised (may be null) exception - the raised exception Returns: a method to handle the exception, or null
So I merged the both classes and it works.
But it's not really clear :
- Older exception handler is not in the class hierarchy
- I did not check if my latest exception handler was well detected on production (code is the same and it works in dev)
So not yet the final word, but too late for today :)