Handle ResponseStatusException thrown by MVC functional endpoints

Prior to this commit, exceptions thrown by MVC functional handlers would
not be considered by `ExceptionHandlerExceptionResolver`. This means
that common exceptions would not be handled consistently between
annotated and functional handlers. This is true, for example, for all
`ProblemDetails`-related exception handling.

While MVC functional and annotation models are separate concepts,
WebFlux has a different error handling model that processes all
exceptions in a central place.

This commit ensures that `ExceptionHandlerExceptionResolver` considers
exceptions thrown by handlers of type `HandlerFunction<?>` and processes
them accordingly.

Closes gh-32689
This commit is contained in:
Brian Clozel
2024-06-06 14:21:17 +02:00
parent 859b97ce05
commit 52af43d6d2
2 changed files with 25 additions and 4 deletions

View File

@@ -60,6 +60,8 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.function.HandlerFunction;
import org.springframework.web.servlet.function.ServerResponse;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
@@ -82,6 +84,8 @@ import static org.mockito.Mockito.mock;
@SuppressWarnings("unused")
class ExceptionHandlerExceptionResolverTests {
//TODO
private static int DEFAULT_RESOLVER_COUNT;
private static int DEFAULT_HANDLER_COUNT;
@@ -255,6 +259,19 @@ class ExceptionHandlerExceptionResolverTests {
assertExceptionHandledAsBody(mav, "AnotherTestExceptionResolver: IllegalAccessException");
}
@Test
void resolveExceptionGlobalHandlerForHandlerFunction() throws Exception {
loadConfiguration(MyConfig.class);
IllegalAccessException ex = new IllegalAccessException();
HandlerFunction<ServerResponse> handlerFunction = req -> {
throw new IllegalAccessException();
};
ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerFunction, ex);
assertExceptionHandledAsBody(mav, "AnotherTestExceptionResolver: IllegalAccessException");
}
@Test
void resolveExceptionGlobalHandlerOrdered() throws Exception {
loadConfiguration(MyConfig.class);