Browse Source

Exception handler methods may receive original as well as cause

Issue: SPR-15701
pull/1468/merge
Juergen Hoeller 7 years ago
parent
commit
a6d616d844
  1. 15
      spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java
  2. 30
      spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java

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

@ -198,20 +198,25 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application @@ -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 @@ -219,7 +224,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
}
}
}
return Mono.error(ex);
return Mono.error(exception);
}
}

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

@ -16,6 +16,8 @@ @@ -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.*; @@ -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 @@ -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 @@ -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());

Loading…
Cancel
Save