Exception handler methods may receive original as well as cause

Issue: SPR-15701
This commit is contained in:
Juergen Hoeller 2017-07-05 13:39:30 +02:00
parent 45d376b6af
commit a6d616d844
2 changed files with 40 additions and 5 deletions

View File

@ -198,20 +198,25 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
.onErrorResume(exceptionHandler)));
}
private Mono<HandlerResult> handleException(Throwable ex, HandlerMethod handlerMethod,
private Mono<HandlerResult> handleException(Throwable exception, HandlerMethod handlerMethod,
BindingContext bindingContext, ServerWebExchange exchange) {
Assert.state(this.methodResolver != null, "Not initialized");
InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod(ex, handlerMethod);
InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod(exception, handlerMethod);
if (invocable != null) {
try {
if (logger.isDebugEnabled()) {
logger.debug("Invoking @ExceptionHandler method: " + invocable.getMethod());
}
bindingContext.getModel().asMap().clear();
Throwable cause = ex.getCause() != null ? ex.getCause() : ex;
return invocable.invoke(exchange, bindingContext, cause, handlerMethod);
Throwable cause = exception.getCause();
if (cause != null) {
return invocable.invoke(exchange, bindingContext, exception, cause, handlerMethod);
}
else {
return invocable.invoke(exchange, bindingContext, exception, handlerMethod);
}
}
catch (Throwable invocationEx) {
if (logger.isWarnEnabled()) {
@ -219,7 +224,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
}
}
}
return Mono.error(ex);
return Mono.error(exception);
}
}

View File

@ -16,6 +16,8 @@
package org.springframework.web.reactive.result.method.annotation;
import java.io.IOException;
import org.junit.Test;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@ -37,6 +39,7 @@ import static org.junit.Assert.*;
* {@code @RequestMapping} integration tests with exception handling scenarios.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
*/
public class RequestMappingExceptionHandlingIntegrationTests extends AbstractRequestMappingIntegrationTests {
@ -55,6 +58,18 @@ public class RequestMappingExceptionHandlingIntegrationTests extends AbstractReq
assertEquals(expected, performGet("/thrown-exception", new HttpHeaders(), String.class).getBody());
}
@Test
public void controllerThrowingExceptionWithCause() throws Exception {
String expected = "Recovered from error: State";
assertEquals(expected, performGet("/thrown-exception-with-cause", new HttpHeaders(), String.class).getBody());
}
@Test
public void controllerThrowingExceptionWithCauseToHandle() throws Exception {
String expected = "Recovered from error: IO";
assertEquals(expected, performGet("/thrown-exception-with-cause-to-handle", new HttpHeaders(), String.class).getBody());
}
@Test
public void controllerReturnsMonoError() throws Exception {
String expected = "Recovered from error: Argument";
@ -79,11 +94,26 @@ public class RequestMappingExceptionHandlingIntegrationTests extends AbstractReq
throw new IllegalStateException("State");
}
@GetMapping("/thrown-exception-with-cause")
public Publisher<String> handleAndThrowExceptionWithCause() {
throw new IllegalStateException("State", new IOException("IO"));
}
@GetMapping("/thrown-exception-with-cause-to-handle")
public Publisher<String> handleAndThrowExceptionWithCauseToHandle() {
throw new RuntimeException("State", new IOException("IO"));
}
@GetMapping("/mono-error")
public Publisher<String> handleWithError() {
return Mono.error(new IllegalArgumentException("Argument"));
}
@ExceptionHandler
public Publisher<String> handleArgumentException(IOException ex) {
return Mono.just("Recovered from error: " + ex.getMessage());
}
@ExceptionHandler
public Publisher<String> handleArgumentException(IllegalArgumentException ex) {
return Mono.just("Recovered from error: " + ex.getMessage());