Affects: Spring 5.3.5
I'm using Spring MVC framework with functional controller (HandlerFunction, HandlerFunctionFilter, are landed on Spring 5.2). While using it, I encountered problem with global exception capture.
If I use onError for handling exception, I still need to use @ControllerAdvice
and @ErrorException
for non-path exceptions (AccessDeniedException
,NotFoundHandlerException
, ...). This is inconsistency. After some research, I decide to use mappedHandlerClasses
of ExceptionHandlerExceptionResolver
to handle exception in functional controller. However, when enable setting mappedHandlerClasses, ExceptionHandlerExceptionResolver
cannot handle non-path exceptions (AccessDeniedException
,NotFoundHandlerException
, ...).
In my opinion, ExceptionHandlerExceptionResolver
should capture both HandlerMethod
(annotation controller) and HandlerFunction
(functional controller) in Spring MVC. Or another suggestion, it's mappedHandlerClasses
should not effect to capability of handling HandlerMethod
of ExceptionHandlerExceptionResolver
.
Or is there any clever way to resolve this issue? Currently, I work around by creating another ExceptionHandlerExceptionResolver
with mappedHandlerClasses
for function controller exception handler, beside original ExceptionHandlerExceptionResolver
.
Comment From: poutsma
If you create your own implementation of HandlerExceptionResolver
, and make sure it acts before the default ones, you can handle exceptions from both functional endpoints as well as annotated handler methods. There is an article that describes custom HandlerExceptionResolver
here: https://www.baeldung.com/exception-handling-for-rest-with-spring
In my opinion, ExceptionHandlerExceptionResolver should capture both HandlerMethod (annotation controller) and HandlerFunction (functional controller) in Spring MVC
One of the underlying principles of the functional endpoints is that they do not require reflection to operate. Supporting @ExceptionHandler
would violate that principle.
Comment From: haupv1m
@poutsma There are some points I have to be cleared:
- Firstly, as I mentioned, I already workaround for handling exception in function controller by implementing a custom HandlerExceptionResolver
and it works well for capture functional handler exception, beside ExceptionHandlerExceptionResolver
. My problem is NOT how to implement a custom HandlerExceptionResolver
.
- Because I need handle exception when using functional handler, I have 2 approaches:
+ using onError
for route exception, combine with @ControllerAdvice
and @ErrorException
for non-path exceptions (AccessDeniedException,NotFoundHandlerException, ...). This way is inconsistency (request exceptions are handling in 2 ways).
+ or adding a custom HandlerExceptionResolver
to capture exception from functional handler (this resolver have same logic as ExceptionHandlerExceptionResolver
) and all exception will be handled in @ExceptionHandler
. And I choose this way.
One of the underlying principles of the functional endpoints is that they do not require reflection to operate
I agree with this. However, my situation is because of lacking of supporting in uniform handling global exception mechanism of functional controller usage in Spring MVC (as mention in option 1). Moreover, I do NOT suggest functional handler require reflection to operate. I suggest the old exception handler approach (HandlerExecptionResolver
) should support both annotation and functional controller until we have a handling global exception mechanism of functional controller to match with new execption handler approach (onError
).
I think, because default ExceptionHandlerExceptionResolver
's purpose is mapping caputured exception with @ExceptionHandler methods for resolving, not about exception source, and because functional handler and annotated handler are both principle components of Spring MVC, ExceptionHandlerExceptionResolver
should be capability of capturing both exceptions from annotated handler methods and functional handlers (currently, ExceptionHandlerExceptionResolver
only work with either HandlerMethod or mappedHandlerClasses).
Note, I'm using function controller in Spring MVC (functional approach similar as functional endpoints in Spring WebFlux), but not functional endpoints in Spring WebFlux.