I\'m trying to get Hibernate Validator setup to use messages from a Spring MessageSource. I have the following setup in my messages-context.xml
:
<
Hibernate Validation is not aware of Spring's MessageSource. You will need to implement a MessageInterpolator. It may look something like below:
public class SpringMessageInterpolator implements MessageInterpolator {
private final MessageResource messageResource;
private final MessageInterpolator delegate;
public SpringMessageInterpolator(MessageResource messageResource, MessageInterpolator delegate) {
this.messageResource = messageResource;
this.delegate = delegate;
}
@Override
public String interpolate(String messageTemplate, Context context) {
Locale locale = Locale.getDefault();
return interpolate(messageTemplate, context, locale);
}
@Override
public String interpolate(String messageTemplate, Context context, Locale locale) {
try {
Object[] args = {};
return databaseMessageResource.getMessage(messageTemplate, args, locale);
} catch (NoSuchMessageException ex) {
return delegate.interpolate(messageTemplate, context, locale);
}
}
}
Hibernate Validator is looking in a different place for the locale. Try this:
LocaleContextHolder.setLocale(locale);
This had me stumped for a while, but the problem is that you need to register with Spring the Validator used to validate @Controller methods (thanks to this answer for that insight!)
So if you are using XML config do something along these lines:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="messageInterpolator" ref="messageSource"/>
</bean>
<mvc:annotation-driven validator="validator"/>
And if you are using javaconfig, do something like this:
@EnableWebMVC
@Configuration
public MyWebAppContext extends WebMvcConfigurerAdapter {
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean();
validatorFactoryBean.setValidationMessageSource(messageSource);
return validatorFactoryBean;
}
@Override
public Validator getValidator() {
return validator();
}
(see Spring Web MVC framework documentation)
It's because Hibernate validator is looking at another place for the error message resolver.
For the easiest thing to make it works, I think you can create a file name "ValidationMessages.properties
" and put it in your classpath folder. Then put the error messages into that file (got from validation_errors_en_GB.properties
)
By the way, the brackets are required when specifying error messages in model classes (message="{validation.too.long}"
)
This has worked for me.
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>i18n/messages</value>
</property>
</bean>
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="messageInterpolator">
<bean
class="org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator">
<constructor-arg index="0">
<bean
class="org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator">
<constructor-arg index="0" ref="messageSource" />
</bean>
</constructor-arg>
</bean>
</property>
</bean>
<bean
class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator" />
</bean>
<mvc:annotation-driven validator="validator" />