Skip to content

Commit a6d616d

Browse files
committed
Exception handler methods may receive original as well as cause
Issue: SPR-15701
1 parent 45d376b commit a6d616d

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,28 +198,33 @@ public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
198198
.onErrorResume(exceptionHandler)));
199199
}
200200

201-
private Mono<HandlerResult> handleException(Throwable ex, HandlerMethod handlerMethod,
201+
private Mono<HandlerResult> handleException(Throwable exception, HandlerMethod handlerMethod,
202202
BindingContext bindingContext, ServerWebExchange exchange) {
203203

204204
Assert.state(this.methodResolver != null, "Not initialized");
205205

206-
InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod(ex, handlerMethod);
206+
InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod(exception, handlerMethod);
207207
if (invocable != null) {
208208
try {
209209
if (logger.isDebugEnabled()) {
210210
logger.debug("Invoking @ExceptionHandler method: " + invocable.getMethod());
211211
}
212212
bindingContext.getModel().asMap().clear();
213-
Throwable cause = ex.getCause() != null ? ex.getCause() : ex;
214-
return invocable.invoke(exchange, bindingContext, cause, handlerMethod);
213+
Throwable cause = exception.getCause();
214+
if (cause != null) {
215+
return invocable.invoke(exchange, bindingContext, exception, cause, handlerMethod);
216+
}
217+
else {
218+
return invocable.invoke(exchange, bindingContext, exception, handlerMethod);
219+
}
215220
}
216221
catch (Throwable invocationEx) {
217222
if (logger.isWarnEnabled()) {
218223
logger.warn("Failed to invoke: " + invocable.getMethod(), invocationEx);
219224
}
220225
}
221226
}
222-
return Mono.error(ex);
227+
return Mono.error(exception);
223228
}
224229

225230
}

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.web.reactive.result.method.annotation;
1818

19+
import java.io.IOException;
20+
1921
import org.junit.Test;
2022
import org.reactivestreams.Publisher;
2123
import reactor.core.publisher.Mono;
@@ -37,6 +39,7 @@
3739
* {@code @RequestMapping} integration tests with exception handling scenarios.
3840
*
3941
* @author Rossen Stoyanchev
42+
* @author Juergen Hoeller
4043
*/
4144
public class RequestMappingExceptionHandlingIntegrationTests extends AbstractRequestMappingIntegrationTests {
4245

@@ -55,6 +58,18 @@ public void controllerThrowingException() throws Exception {
5558
assertEquals(expected, performGet("/thrown-exception", new HttpHeaders(), String.class).getBody());
5659
}
5760

61+
@Test
62+
public void controllerThrowingExceptionWithCause() throws Exception {
63+
String expected = "Recovered from error: State";
64+
assertEquals(expected, performGet("/thrown-exception-with-cause", new HttpHeaders(), String.class).getBody());
65+
}
66+
67+
@Test
68+
public void controllerThrowingExceptionWithCauseToHandle() throws Exception {
69+
String expected = "Recovered from error: IO";
70+
assertEquals(expected, performGet("/thrown-exception-with-cause-to-handle", new HttpHeaders(), String.class).getBody());
71+
}
72+
5873
@Test
5974
public void controllerReturnsMonoError() throws Exception {
6075
String expected = "Recovered from error: Argument";
@@ -79,11 +94,26 @@ public Publisher<String> handleAndThrowException() {
7994
throw new IllegalStateException("State");
8095
}
8196

97+
@GetMapping("/thrown-exception-with-cause")
98+
public Publisher<String> handleAndThrowExceptionWithCause() {
99+
throw new IllegalStateException("State", new IOException("IO"));
100+
}
101+
102+
@GetMapping("/thrown-exception-with-cause-to-handle")
103+
public Publisher<String> handleAndThrowExceptionWithCauseToHandle() {
104+
throw new RuntimeException("State", new IOException("IO"));
105+
}
106+
82107
@GetMapping("/mono-error")
83108
public Publisher<String> handleWithError() {
84109
return Mono.error(new IllegalArgumentException("Argument"));
85110
}
86111

112+
@ExceptionHandler
113+
public Publisher<String> handleArgumentException(IOException ex) {
114+
return Mono.just("Recovered from error: " + ex.getMessage());
115+
}
116+
87117
@ExceptionHandler
88118
public Publisher<String> handleArgumentException(IllegalArgumentException ex) {
89119
return Mono.just("Recovered from error: " + ex.getMessage());

0 commit comments

Comments
 (0)