diff --git a/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java b/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java
index b4ec54e24b..febea11a70 100644
--- a/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java
+++ b/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java
@@ -80,7 +80,7 @@ public class ErrorResponseException extends NestedRuntimeException implements Er
* resolve the detail message with.
* @since 6.0
*/
- protected ErrorResponseException(
+ public ErrorResponseException(
HttpStatusCode status, ProblemDetail body, @Nullable Throwable cause,
@Nullable String messageDetailCode, @Nullable Object[] messageDetailArguments) {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java
index 1da0808ee4..a81798b464 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java
@@ -380,7 +380,8 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
/**
* Customize the handling of {@link ConversionNotSupportedException}.
*
By default this method creates a {@link ProblemDetail} with the status
- * and a short detail message, and then delegates to
+ * and a short detail message, and also looks up an override for the detail
+ * via {@link MessageSource}, before delegating to
* {@link #handleExceptionInternal}.
* @param ex the exception to handle
* @param headers the headers to use for the response
@@ -393,8 +394,10 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
protected ResponseEntity handleConversionNotSupported(
ConversionNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
- ProblemDetail body = ProblemDetail.forStatusAndDetail(status,
- "Failed to convert '" + ex.getPropertyName() + "' with value: '" + ex.getValue() + "'");
+ Object[] args = {ex.getPropertyName(), ex.getValue()};
+
+ ProblemDetail body = resolveDetailViaMessageSource(
+ status, args, "Failed to convert '" + args[0] + "' with value: '" + args[1] + "'");
return handleExceptionInternal(ex, body, headers, status, request);
}
@@ -402,7 +405,8 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
/**
* Customize the handling of {@link TypeMismatchException}.
* By default this method creates a {@link ProblemDetail} with the status
- * and a short detail message, and then delegates to
+ * and a short detail message, and also looks up an override for the detail
+ * via {@link MessageSource}, before delegating to
* {@link #handleExceptionInternal}.
* @param ex the exception to handle
* @param headers the headers to use for the response
@@ -415,8 +419,10 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
protected ResponseEntity handleTypeMismatch(
TypeMismatchException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
- ProblemDetail body = ProblemDetail.forStatusAndDetail(status,
- "Unexpected type for '" + ex.getPropertyName() + "' with value: '" + ex.getValue() + "'");
+ Object[] args = {ex.getPropertyName(), ex.getValue()};
+
+ ProblemDetail body = resolveDetailViaMessageSource(
+ status, args, "Failed to convert '" + args[0] + "' with value: '" + args[1] + "'");
return handleExceptionInternal(ex, body, headers, status, request);
}
@@ -424,7 +430,8 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
/**
* Customize the handling of {@link HttpMessageNotReadableException}.
* By default this method creates a {@link ProblemDetail} with the status
- * and a short detail message, and then delegates to
+ * and a short detail message, and also looks up an override for the detail
+ * via {@link MessageSource}, before delegating to
* {@link #handleExceptionInternal}.
* @param ex the exception to handle
* @param headers the headers to use for the response
@@ -437,14 +444,15 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
protected ResponseEntity handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
- ProblemDetail body = ProblemDetail.forStatusAndDetail(status, "Failed to read request body");
+ ProblemDetail body = resolveDetailViaMessageSource(status, null, "Failed to read request");
return handleExceptionInternal(ex, body, headers, status, request);
}
/**
* Customize the handling of {@link HttpMessageNotWritableException}.
* By default this method creates a {@link ProblemDetail} with the status
- * and a short detail message, and then delegates to
+ * and a short detail message, and also looks up an override for the detail
+ * via {@link MessageSource}, before delegating to
* {@link #handleExceptionInternal}.
* @param ex the exception to handle
* @param headers the headers to use for the response
@@ -457,7 +465,7 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
protected ResponseEntity handleHttpMessageNotWritable(
HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
- ProblemDetail body = ProblemDetail.forStatusAndDetail(status, "Failed to write response body");
+ ProblemDetail body = resolveDetailViaMessageSource(status, null, "Failed to write request");
return handleExceptionInternal(ex, body, headers, status, request);
}
@@ -528,6 +536,17 @@ public abstract class ResponseEntityExceptionHandler implements MessageSourceAwa
return createResponseEntity(body, headers, statusCode, request);
}
+ // For non-Web exceptions
+ private ProblemDetail resolveDetailViaMessageSource(
+ HttpStatusCode status, @Nullable Object[] arguments, String defaultDetail) {
+
+ ProblemDetail body = ProblemDetail.forStatusAndDetail(status, defaultDetail);
+ ErrorResponseException errorResponseEx = new ErrorResponseException(status, body, null, null, arguments);
+ body = resolveDetailViaMessageSource(errorResponseEx);
+ return body;
+ }
+
+ // For ErrorResponse exceptions
private ProblemDetail resolveDetailViaMessageSource(ErrorResponse response) {
ProblemDetail body = response.getBody();
if (this.messageSource != null) {
diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc
index db505328b2..9d3c211214 100644
--- a/src/docs/asciidoc/web/webmvc.adoc
+++ b/src/docs/asciidoc/web/webmvc.adoc
@@ -4960,6 +4960,9 @@ The actual message code value is parameterized with placeholders, e.g.
`"HTTP method {0} not supported"` to be expanded from the arguments.
- `ResponseEntityExceptionHandler` uses the message code and the message arguments
to resolve the problem "detail" field.
+- Lower level exceptions that cannot implement `ErrorResponse`, e.g. `TypeMismatchException`,
+have their problem detail, including message code and arguments set in
+`ResponseEntityExceptionHandler`.
Message codes default to "problemDetail." + the fully qualified exception class name. Some
exceptions may expose additional message codes in which case a suffix is added to
@@ -4975,6 +4978,10 @@ MVC exceptions:
| (default)
|
+| `ConversionNotSupportedException`
+| (default)
+| `{0}` property name, `{1}` property value
+
| `HttpMediaTypeNotAcceptableException`
| (default)
| `{0}` list of supported media types
@@ -4991,6 +4998,14 @@ MVC exceptions:
| (default) + ".parseError"
|
+| `HttpMessageNotReadableException`
+| (default)
+|
+
+| `HttpMessageNotWritableException`
+| (default)
+|
+
| `HttpRequestMethodNotSupportedException`
| (default)
| `{0}` the current HTTP method, `{1}` the list of supported HTTP methods
@@ -5029,6 +5044,10 @@ MVC exceptions:
| (default)
|
+| `TypeMismatchException`
+| (default)
+| `{0}` property name, `{1}` property value
+
| `UnsatisfiedServletRequestParameterException`
| (default)
| `{0}` the list of parameter conditions