diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java index 160e241bd6..505c127472 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java @@ -39,6 +39,7 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.ResponseStatusException; /** * Basic global {@link org.springframework.web.server.WebExceptionHandler}, rendering @@ -188,16 +189,43 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa } /** - * Log the original exception if handling it results in a Server Error. + * Log the original exception if handling it results in a Server Error or a Bad Request + * (Client Error with 400 status code) one. * @param request the source request * @param errorStatus the HTTP error status */ protected void logError(ServerRequest request, HttpStatus errorStatus) { if (errorStatus.is5xxServerError()) { Throwable ex = getError(request); - logger.error("Failed to handle request [" + request.methodName() + " " - + request.uri() + "]", ex); + if (ex instanceof ResponseStatusException) { + logger.error(buildMessage(request, ex)); + } + else { + logger.error(buildMessage(request, null), ex); + } + } + else if (errorStatus == HttpStatus.BAD_REQUEST) { + Throwable ex = getError(request); + if (ex instanceof ResponseStatusException) { + logger.warn(buildMessage(request, ex)); + } + else { + logger.warn(buildMessage(request, null), ex); + } } } + private String buildMessage(ServerRequest request, Throwable ex) { + StringBuilder message = new StringBuilder("Failed to handle request ["); + message.append(request.methodName()); + message.append(" "); + message.append(request.uri()); + message.append("]"); + if (ex != null) { + message.append(": "); + message.append(ex.getMessage()); + } + return message.toString(); + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java index b24c4fe17f..b79228aee4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java @@ -131,6 +131,9 @@ public class DefaultErrorWebExceptionHandlerIntegrationTests { .isEqualTo(("/bind")).jsonPath("exception").doesNotExist() .jsonPath("errors").isArray().jsonPath("message").isNotEmpty(); }); + this.output.expect(allOf(containsString("Failed to handle request [POST /bind]"), + containsString("Validation failed for argument"), + containsString("Field error in object 'dummyBody' on field 'content'"))); } @Test