Merge branch '6.1.x'

This commit is contained in:
rstoyanchev
2024-03-06 18:17:40 +00:00
5 changed files with 69 additions and 16 deletions

View File

@@ -307,21 +307,34 @@ public class RequestMappingHandlerAdapter
exceptions.toArray(arguments); // efficient arraycopy call in ArrayList
arguments[arguments.length - 1] = handlerMethod;
return invocable.invoke(exchange, bindingContext, arguments);
return invocable.invoke(exchange, bindingContext, arguments)
.onErrorResume(invocationEx ->
handleExceptionHandlerFailure(exchange, exception, invocationEx, exceptions, invocable));
}
catch (Throwable invocationEx) {
if (!disconnectedClientHelper.checkAndLogClientDisconnectedException(invocationEx)) {
// Any other than the original exception (or a cause) is unintended here,
// probably an accident (e.g. failed assertion or the like).
if (!exceptions.contains(invocationEx) && logger.isWarnEnabled()) {
logger.warn(exchange.getLogPrefix() + "Failure in @ExceptionHandler " + invocable, invocationEx);
}
}
return handleExceptionHandlerFailure(exchange, exception, invocationEx, exceptions, invocable);
}
}
return Mono.error(exception);
}
private static Mono<HandlerResult> handleExceptionHandlerFailure(
ServerWebExchange exchange, Throwable exception, Throwable invocationEx,
ArrayList<Throwable> exceptions, InvocableHandlerMethod invocable) {
if (disconnectedClientHelper.checkAndLogClientDisconnectedException(invocationEx)) {
return Mono.empty();
}
// Any other than the original exception (or a cause) is unintended here,
// probably an accident (e.g. failed assertion or the like).
if (!exceptions.contains(invocationEx) && logger.isWarnEnabled()) {
logger.warn(exchange.getLogPrefix() + "Failure in @ExceptionHandler " + invocable, invocationEx);
}
return Mono.error(exception);
}
@Override
public Mono<HandlerResult> handleError(ServerWebExchange exchange, Throwable ex) {
return handleException(exchange, ex, null, null);

View File

@@ -38,9 +38,11 @@ import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.AsyncRequestNotUsableException;
import org.springframework.web.reactive.accept.HeaderContentTypeResolver;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.resource.ResourceWebHandler;
@@ -195,6 +197,14 @@ public class DispatcherHandlerErrorTests {
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
}
@Test
void asyncRequestNotUsableFromExceptionHandler() {
ServerWebExchange exchange = MockServerWebExchange.from(
MockServerHttpRequest.post("/request-not-usable-on-exception-handling"));
StepVerifier.create(this.dispatcherHandler.handle(exchange)).verifyComplete();
}
@Configuration
@SuppressWarnings({"unused", "WeakerAccess"})
@@ -249,6 +259,16 @@ public class DispatcherHandlerErrorTests {
public Publisher<String> requestBody(@RequestBody Publisher<String> body) {
return Mono.from(body).map(s -> "hello " + s);
}
@RequestMapping("/request-not-usable-on-exception-handling")
public void handle() throws Exception {
throw new IllegalAccessException();
}
@ExceptionHandler
public void handleException(IllegalAccessException ex) throws AsyncRequestNotUsableException {
throw new AsyncRequestNotUsableException("Simulated response failure");
}
}