Improve mapping any Exception to ErrorResponse

Add protected, convenience method in ResponseEntityExceptionHandler
to create a ProblemDetail for any exception, along with a
MessageSource lookup for the "detail" field.

Closes gh-29384
This commit is contained in:
rstoyanchev
2022-11-01 11:40:23 +00:00
parent 210019cad1
commit 506fbe5243
5 changed files with 171 additions and 52 deletions

View File

@@ -94,6 +94,24 @@ public interface ErrorResponse {
return getDetailMessageArguments();
}
/**
* Resolve the {@link #getDetailMessageCode() detailMessageCode} through the
* given {@link MessageSource}, and if found, update the "detail" field.
* @param messageSource the {@code MessageSource} to use for the lookup
* @param locale the {@code Locale} to use for the lookup
*/
default ProblemDetail updateAndGetBody(@Nullable MessageSource messageSource, Locale locale) {
if (messageSource != null) {
Object[] arguments = getDetailMessageArguments(messageSource, locale);
String detail = messageSource.getMessage(getDetailMessageCode(), arguments, null, locale);
if (detail != null) {
getBody().setDetail(detail);
}
}
return getBody();
}
/**
* Build a message code for the given exception type, which consists of
* {@code "problemDetail."} followed by the full {@link Class#getName() class name}.
@@ -105,4 +123,35 @@ public interface ErrorResponse {
return "problemDetail." + exceptionType.getName() + (suffix != null ? "." + suffix : "");
}
/**
* Map the given Exception to an {@link ErrorResponse}.
* @param ex the Exception, mostly to derive message codes, if not provided
* @param status the response status to use
* @param headers optional headers to add to the response
* @param defaultDetail default value for the "detail" field
* @param detailMessageCode the code to use to look up the "detail" field
* through a {@code MessageSource}, falling back on
* {@link #getDefaultDetailMessageCode(Class, String)}
* @param detailMessageArguments the arguments to go with the detailMessageCode
* @return the created {@code ErrorResponse} instance
*/
static ErrorResponse createFor(
Exception ex, HttpStatusCode status, @Nullable HttpHeaders headers,
String defaultDetail, @Nullable String detailMessageCode, @Nullable Object[] detailMessageArguments) {
if (detailMessageCode == null) {
detailMessageCode = ErrorResponse.getDefaultDetailMessageCode(ex.getClass(), null);
}
ErrorResponseException errorResponse = new ErrorResponseException(
status, ProblemDetail.forStatusAndDetail(status, defaultDetail), null,
detailMessageCode, detailMessageArguments);
if (headers != null) {
errorResponse.getHeaders().putAll(headers);
}
return errorResponse;
}
}