MessageSource support for Spring MVC and WebFlux exceptions

See gh-28814
This commit is contained in:
rstoyanchev
2022-10-04 20:34:08 +01:00
parent ff81d64fb5
commit a4210854fb
31 changed files with 676 additions and 129 deletions

View File

@@ -16,12 +16,17 @@
package org.springframework.web.servlet.mvc.method.annotation;
import java.util.Locale;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
@@ -64,7 +69,7 @@ import org.springframework.web.util.WebUtils;
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class ResponseEntityExceptionHandler {
public abstract class ResponseEntityExceptionHandler implements MessageSourceAware {
/**
* Log category to use when no mapped handler is found for a request.
@@ -84,6 +89,16 @@ public abstract class ResponseEntityExceptionHandler {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private MessageSource messageSource;
@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
/**
* Handle all exceptions raised within Spring MVC handling of the request .
* @param ex the exception to handle
@@ -504,12 +519,25 @@ public abstract class ResponseEntityExceptionHandler {
}
if (body == null && ex instanceof ErrorResponse errorResponse) {
body = errorResponse.getBody();
body = resolveDetailViaMessageSource(errorResponse);
}
return createResponseEntity(body, headers, statusCode, request);
}
private ProblemDetail resolveDetailViaMessageSource(ErrorResponse response) {
ProblemDetail body = response.getBody();
if (this.messageSource != null) {
Locale locale = LocaleContextHolder.getLocale();
Object[] arguments = response.getDetailMessageArguments(this.messageSource, locale);
String detail = this.messageSource.getMessage(response.getDetailMessageCode(), arguments, null, locale);
if (detail != null) {
body.setDetail(detail);
}
}
return body;
}
/**
* Create the {@link ResponseEntity} to use from the given body, headers,
* and statusCode. Subclasses can override this method to inspect and possibly