Avoid MessageFormat processing for default Bean Validation messages

Closes gh-22761
This commit is contained in:
Juergen Hoeller
2019-04-08 15:33:04 +02:00
parent fc9ce7cd99
commit a1efe3cfe5
7 changed files with 123 additions and 26 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -287,6 +287,12 @@ public abstract class AbstractMessageSource extends MessageSourceSupport impleme
String defaultMessage = resolvable.getDefaultMessage();
String[] codes = resolvable.getCodes();
if (defaultMessage != null) {
if (resolvable instanceof DefaultMessageSourceResolvable &&
!((DefaultMessageSourceResolvable) resolvable).shouldRenderDefaultMessage()) {
// Given default message does not contain any argument placeholders
// (and isn't escaped for alwaysUseMessageFormat either) -> return as-is.
return defaultMessage;
}
if (!ObjectUtils.isEmpty(codes) && defaultMessage.equals(codes[0])) {
// Never format a code-as-default-message, even with alwaysUseMessageFormat=true
return defaultMessage;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -129,13 +129,28 @@ public class DefaultMessageSourceResolvable implements MessageSourceResolvable,
return this.defaultMessage;
}
/**
* Indicate whether the specified default message needs to be rendered for
* substituting placeholders and/or {@link java.text.MessageFormat} escaping.
* @return {@code true} if the default message may contain argument placeholders;
* {@code false} if it definitely does not contain placeholders or custom escaping
* and can therefore be simply exposed as-is
* @since 5.1.7
* @see #getDefaultMessage()
* @see #getArguments()
* @see AbstractMessageSource#renderDefaultMessage
*/
public boolean shouldRenderDefaultMessage() {
return true;
}
/**
* Build a default String representation for this MessageSourceResolvable:
* including codes, arguments, and default message.
*/
protected final String resolvableToString() {
StringBuilder result = new StringBuilder();
StringBuilder result = new StringBuilder(64);
result.append("codes [").append(StringUtils.arrayToDelimitedString(this.codes, ","));
result.append("]; arguments [").append(StringUtils.arrayToDelimitedString(this.arguments, ","));
result.append("]; default message [").append(this.defaultMessage).append(']');

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -148,6 +148,7 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
* @param violations the JSR-303 ConstraintViolation results
* @param errors the Spring errors object to register to
*/
@SuppressWarnings("serial")
protected void processConstraintViolations(Set<ConstraintViolation<Object>> violations, Errors errors) {
for (ConstraintViolation<Object> violation : violations) {
String field = determineField(violation);
@@ -165,7 +166,12 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
if (nestedField.isEmpty()) {
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode);
ObjectError error = new ObjectError(
errors.getObjectName(), errorCodes, errorArgs, violation.getMessage());
errors.getObjectName(), errorCodes, errorArgs, violation.getMessage()) {
@Override
public boolean shouldRenderDefaultMessage() {
return false;
}
};
error.wrap(violation);
bindingResult.addError(error);
}
@@ -173,7 +179,12 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
Object rejectedValue = getRejectedValue(field, violation, bindingResult);
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
FieldError error = new FieldError(errors.getObjectName(), nestedField,
rejectedValue, false, errorCodes, errorArgs, violation.getMessage());
rejectedValue, false, errorCodes, errorArgs, violation.getMessage()) {
@Override
public boolean shouldRenderDefaultMessage() {
return false;
}
};
error.wrap(violation);
bindingResult.addError(error);
}