diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/DispatchExceptionHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/DispatchExceptionHandler.java
index 4486a38bfd3..06a2ec8a12a 100644
--- a/spring-webflux/src/main/java/org/springframework/web/reactive/DispatchExceptionHandler.java
+++ b/spring-webflux/src/main/java/org/springframework/web/reactive/DispatchExceptionHandler.java
@@ -29,7 +29,8 @@ import org.springframework.web.server.ServerWebExchange;
* a {@link HandlerAdapter} to apply its exception handling to deferred exceptions
* from asynchronous return values, and to response rendering.
*
Implemented by a {@link HandlerAdapter} in order to handle exceptions that
- * occur before a request is mapped to a handler.
+ * occur before a request is mapped to a handler, or for unhandled errors from a
+ * handler..
*
*
* @author Rossen Stoyanchev
diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java
index 766a1843544..c51a5f5026e 100644
--- a/spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java
+++ b/spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -150,7 +150,7 @@ public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, A
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
- .onErrorResume(ex -> handleDispatchError(exchange, ex))
+ .onErrorResume(ex -> handleResultMono(exchange, Mono.error(ex)))
.flatMap(handler -> handleRequestWith(exchange, handler));
}
@@ -161,8 +161,7 @@ public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, A
});
}
- private Mono handleDispatchError(ServerWebExchange exchange, Throwable ex) {
- Mono resultMono = Mono.error(ex);
+ private Mono handleResultMono(ServerWebExchange exchange, Mono resultMono) {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter instanceof DispatchExceptionHandler exceptionHandler) {
@@ -170,36 +169,19 @@ public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, A
}
}
}
- return resultMono.flatMap(result -> handleResult(exchange, result));
- }
-
- private Mono handleRequestWith(ServerWebExchange exchange, Object handler) {
- if (ObjectUtils.nullSafeEquals(exchange.getResponse().getStatusCode(), HttpStatus.FORBIDDEN)) {
- return Mono.empty(); // CORS rejection
- }
- if (this.handlerAdapters != null) {
- for (HandlerAdapter adapter : this.handlerAdapters) {
- if (adapter.supports(handler)) {
- return adapter.handle(exchange, handler)
- .flatMap(result -> handleResult(exchange, result));
- }
+ return resultMono.flatMap(result -> {
+ Mono voidMono = handleResult(exchange, result, "Handler " + result.getHandler());
+ if (result.getExceptionHandler() != null) {
+ voidMono = voidMono.onErrorResume(ex ->
+ result.getExceptionHandler().handleError(exchange, ex).flatMap(result2 ->
+ handleResult(exchange, result2, "Exception handler " +
+ result2.getHandler() + ", error=\"" + ex.getMessage() + "\"")));
}
- }
- return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
- }
-
- private Mono handleResult(ServerWebExchange exchange, HandlerResult result) {
- Mono resultMono = doHandleResult(exchange, result, "Handler " + result.getHandler());
- if (result.getExceptionHandler() != null) {
- resultMono = resultMono.onErrorResume(ex ->
- result.getExceptionHandler().handleError(exchange, ex).flatMap(result2 ->
- doHandleResult(exchange, result2, "Exception handler " +
- result2.getHandler() + ", error=\"" + ex.getMessage() + "\"")));
- }
- return resultMono;
+ return voidMono;
+ });
}
- private Mono doHandleResult(
+ private Mono handleResult(
ServerWebExchange exchange, HandlerResult handlerResult, String description) {
if (this.resultHandlers != null) {
@@ -214,6 +196,21 @@ public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, A
"No HandlerResultHandler for " + handlerResult.getReturnValue()));
}
+ private Mono handleRequestWith(ServerWebExchange exchange, Object handler) {
+ if (ObjectUtils.nullSafeEquals(exchange.getResponse().getStatusCode(), HttpStatus.FORBIDDEN)) {
+ return Mono.empty(); // CORS rejection
+ }
+ if (this.handlerAdapters != null) {
+ for (HandlerAdapter adapter : this.handlerAdapters) {
+ if (adapter.supports(handler)) {
+ Mono resultMono = adapter.handle(exchange, handler);
+ return handleResultMono(exchange, resultMono);
+ }
+ }
+ }
+ return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
+ }
+
@Override
public Mono handlePreFlight(ServerWebExchange exchange) {
return Flux.fromIterable(this.handlerMappings != null ? this.handlerMappings : Collections.emptyList())