How do I retrieve default validation messages from Hibernate Validator?
I'm trying to retrieve a default validation error-message using MessageSource
. The code I'm working with uses reflection to retrieve the value of the message
parameter. On a constraint that does not override the message
parameter, I would like to retrieve the def开发者_开发问答ault error message. When I invoke the message
method on the validation annotation, I get {org.hibernate.validator.constraints.NotBlank.message}
(for example, for the @NotBlank
annotation). I then tried to use MessageSource
to get the error message like so:
String message = messageSource.getMessage(key, null, Locale.US);
I tried setting key
to {org.hibernate.validator.constraints.NotBlank.message}
, org.hibernate.validator.constraints.NotBlank.message
(removed braces) and even org.hibernate.validator.constraints.NotBlank
but I keep getting null
. What am I doing wrong here?
UPDATE
A clarification. I am under the impression that Spring comes with a default message.properties
file for its constraints. Am I correct in this assumption?
UPDATE
Changing the name of the question to better reflect what I was trying to do.
After running into a blog post from one of the Hibernate guys, and after digging around in the Hibernate Validator source, I think I've figured it out:
public String getMessage(final Locale locale, final String key) {
PlatformResourceBundleLocator bundleLocator = new PlatformResourceBundleLocator("org.hibernate.validator.ValidationMessages");
ResourceBundle resourceBundle = bundleLocator.getResourceBundle(locale);
try {
final String k = key.replace("{", "").replace("}", "");
return resourceBundle.getString(k);
}
catch (MissingResourceException e) {
return key;
}
}
So first, you have to instantiate a PlatformResourceBundleLocator
with the default validation messages. Then you retrieve a ResourceBundle
from the locator and use that to get your message. I don't believe this performs any interpolation though. For that you have to use an interpolator; the blog post I linked to above goes into more detail about that.
UPDATE
Another (easier) way is to update your applicationContext.xml
and do this:
<bean id="resourceBundleSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>org.hibernate.validator.ValidationMessages</value>
</list>
</property>
</bean>
Now your MessageSource
is populated with the default messages and you can do messageSource.getMessage()
. In fact, this is probably the best way.
Spring Boot 2.4.5
In case someone needs this for testing:
package some.package;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Locale;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
public class NotNullTest {
private static MessageSource ms;
private static String VAL_MSG_NOT_NULL;
@BeforeAll
static void setUpClass() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("org/hibernate/validator/ValidationMessages");
messageSource.setDefaultEncoding("UTF-8");
ms = messageSource;
}
@BeforeEach
void setUp() {
VAL_MSG_NOT_NULL = ms.getMessage("javax.validation.constraints.NotNull.message", null, Locale.ROOT);
assertThat(VAL_MSG_NOT_NULL).isNotNull();
assertThat(VAL_MSG_NOT_NULL).isNotBlank();
}
@Test
void test() {
assertThat(VAL_MSG_NOT_NULL).isEqualTo("must not be null");
}
}
精彩评论