diff --git a/spring-web/src/main/java/org/springframework/web/ErrorResponse.java b/spring-web/src/main/java/org/springframework/web/ErrorResponse.java index 7ea1f06e45..27123f1bb1 100644 --- a/spring-web/src/main/java/org/springframework/web/ErrorResponse.java +++ b/spring-web/src/main/java/org/springframework/web/ErrorResponse.java @@ -64,6 +64,9 @@ public interface ErrorResponse { */ ProblemDetail getBody(); + + // MessageSource codes and arguments + /** * Return a code to use to resolve the problem "type" for this exception * through a {@link MessageSource}. The type resolved through the @@ -76,6 +79,15 @@ public interface ErrorResponse { return getDefaultTypeMessageCode(getClass()); } + /** + * Return a code to use to resolve the problem "title" for this exception + * through a {@link MessageSource}. + *
By default this is initialized via {@link #getDefaultTitleMessageCode(Class)}. + */ + default String getTitleMessageCode() { + return getDefaultTitleMessageCode(getClass()); + } + /** * Return a code to use to resolve the problem "detail" for this exception * through a {@link MessageSource}. @@ -111,15 +123,6 @@ public interface ErrorResponse { return getDetailMessageArguments(); } - /** - * Return a code to use to resolve the problem "title" for this exception - * through a {@link MessageSource}. - *
By default this is initialized via {@link #getDefaultTitleMessageCode(Class)}.
- */
- default String getTitleMessageCode() {
- return getDefaultTitleMessageCode(getClass());
- }
-
/**
* Use the given {@link MessageSource} to resolve the
* {@link #getTypeMessageCode() type}, {@link #getTitleMessageCode() title},
@@ -159,6 +162,16 @@ public interface ErrorResponse {
return "problemDetail.type." + exceptionType.getName();
}
+ /**
+ * Build a message code for the "title" field, for the given exception type.
+ * @param exceptionType the exception type associated with the problem
+ * @return {@code "problemDetail.title."} followed by the fully qualified
+ * {@link Class#getName() class name}
+ */
+ static String getDefaultTitleMessageCode(Class> exceptionType) {
+ return "problemDetail.title." + exceptionType.getName();
+ }
+
/**
* Build a message code for the "detail" field, for the given exception type.
* @param exceptionType the exception type associated with the problem
@@ -171,15 +184,6 @@ public interface ErrorResponse {
return "problemDetail." + exceptionType.getName() + (suffix != null ? "." + suffix : "");
}
- /**
- * Build a message code for the "title" field, for the given exception type.
- * @param exceptionType the exception type associated with the problem
- * @return {@code "problemDetail.title."} followed by the fully qualified
- * {@link Class#getName() class name}
- */
- static String getDefaultTitleMessageCode(Class> exceptionType) {
- return "problemDetail.title." + exceptionType.getName();
- }
/**
* Static factory method to build an instance via
@@ -229,33 +233,6 @@ public interface ErrorResponse {
*/
Builder headers(Consumer By default, this is set to
- * {@link ErrorResponse#getDefaultDetailMessageCode(Class, String)} with the
- * associated Exception type.
- * @param messageCode the message code to use
- * @return the same builder instance
- * @see ErrorResponse#getDetailMessageCode()
- */
- Builder detailMessageCode(String messageCode);
-
- /**
- * Set the arguments to provide to the {@link MessageSource} lookup for
- * {@link #detailMessageCode(String)}.
- * @param messageArguments the arguments to provide
- * @return the same builder instance
- * @see ErrorResponse#getDetailMessageArguments()
- */
- Builder detailMessageArguments(Object... messageArguments);
-
/**
* Set the underlying {@link ProblemDetail#setType(URI) type} field.
* @return the same builder instance
@@ -286,6 +263,33 @@ public interface ErrorResponse {
*/
Builder instance(@Nullable URI instance);
+ /**
+ * Set the underlying {@link ProblemDetail#setDetail(String) detail}.
+ * @return the same builder instance
+ */
+ Builder detail(String detail);
+
+ /**
+ * Customize the {@link MessageSource} code for looking up the value for
+ * the underlying {@link #detail(String) detail}.
+ * By default, this is set to
+ * {@link ErrorResponse#getDefaultDetailMessageCode(Class, String)} with the
+ * associated Exception type.
+ * @param messageCode the message code to use
+ * @return the same builder instance
+ * @see ErrorResponse#getDetailMessageCode()
+ */
+ Builder detailMessageCode(String messageCode);
+
+ /**
+ * Set the arguments to provide to the {@link MessageSource} lookup for
+ * {@link #detailMessageCode(String)}.
+ * @param messageArguments the arguments to provide
+ * @return the same builder instance
+ * @see ErrorResponse#getDetailMessageArguments()
+ */
+ Builder detailMessageArguments(Object... messageArguments);
+
/**
* Set a "dynamic" {@link ProblemDetail#setProperty(String, Object)
* property} on the underlying {@code ProblemDetail}.
diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandlerTests.java
index bb5ef4fb96..c098c2f088 100644
--- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandlerTests.java
+++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandlerTests.java
@@ -127,37 +127,35 @@ public class ResponseEntityExceptionHandlerTests {
@Test
void errorResponseProblemDetailViaMessageSource() {
-
Locale locale = Locale.UK;
- LocaleContextHolder.setLocale(locale);
String type = "https://example.com/probs/unsupported-content";
String title = "Media type is not valid or not supported";
+ Class