if I define the following validation messages,
@Size(min = 3, message = "{validation.account.name}")
private String name;
I expect spring boot would read from messages*.properties from classpath and find the validation.account.name key to interpolate the message, but it just shows {validation.account.name} on the page.
This https://github.com/Zane-XY/springboot-i18n-problem demos the problems.
We don't support that. Spring Framework does support it but only with the Hibernate validator implementation. That's interesting.
IMHO it should be easy to implement, like this:
public class MvcConfig extends WebMvcConfigurerAdapter {
@Inject
private MessageSource messageSource;
@Override
public Validator getValidator() {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
}
Why this isn't part of https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/MessageSourceAutoConfiguration.java? at least Springboot documentation/references should mention what MessageSourceAutoConfiguration has done, and how to enable reading from message sources.
Good question. Is there an answer? And how do you make use of the MessageSourceAutoConfiguration?
I believe it's still an open issue https://jira.spring.io/browse/SPR-6380
Possibly relates to #7598
It works.
To get it worked I have to move validation keys into the file ValidationMessages.properties while all oder messages reside in messages.properties.
FYI.
@selimok thanks for the feedback! FYI, you can remove all that code in 1.5 as we do that automatically.
@snicoll removed :)
@snicoll I have upgraded my app to Spring Boot 1.5.1.RELEASE, but my validator messages are still only interpolated if I follow @selimok's solution. Have I missed something?
@ben3000 that the issue is still open?
OK, I thought as much. What does "FYI, you can remove all that code in 1.5 as we do that automatically." refer to?
A comment that, unfortunately, @selimok has removed (the creation of the validator if I remember) after I told him it was no longer necessary.
I use Spring Boot 1.5.1.RELEASE and have the same problem. Tell me please, where I can look at a working solution? Thanks.
Overriding the auto-configured Validator and setting the MessageSource works for me.
ValidationConfig.java
@Configuration
public class ValidationConfig {
@Bean
public Validator validator(MessageSource messageSource) {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
}
Person.java
public class Person {
@NotNull
private String name;
}
messages.properties
NotNull.person.name=Name must not be null
I have a feeling #8223 may have improved the MVC support but we probably still don't pick up messages.properties. The docs for LocalValidatorFactoryBean state that you can't specify both a validationMessageSource and a messageInterpolator. With #7598 we added a custom MessageInterpolator so we can't just set the messageSource directly.
Argh, that's quite bad news isn't it?
it work! in messages.properties
NotNull.person.name=Name must not be null
the class name (ex. person) must start with lowercase
Solved by add ValidationMessages.properties in classpath. this file is used by JSR303 implementation.
@gemunet or @jackstevenson can you provide a full example of showing that this actually works? LocalValidatorFactoryBean does not help map the Spring Valdaiton codes (i.e., NotNull.*), it will only allow mapping to full javax.validation constraints default message (i.e., javax.validation.constraints.NotNull.message)
If you are using the WebMvcConfigurerAdapter see this post: https://stackoverflow.com/questions/45692179/spring-boot-validation-message-is-not-being-resolved
It says:
In case of extending WebMvcConfigurerAdapter you will have to provide validator by overriding getValidator() method from parent class:
@Configuration
@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Bean(name = "validationMessageResource")
public MessageSource getReloadableResourceBundleValidationMessageSource() {
ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
reloadableResourceBundleMessageSource.setBasename("classpath:exceptionmessages");
reloadableResourceBundleMessageSource.setDefaultEncoding("UTF-8");
return reloadableResourceBundleMessageSource;
}
@Bean(name = "validator")
@Override
public LocalValidatorFactoryBean getValidator() {
final LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(getReloadableResourceBundleValidationMessageSource());
return localValidatorFactoryBean;
}
}
This is super important. Previously I was defining the validator in a different bean. That was causing that the validator that I wanted to use never was setting as default. Then, I moved the validator bean where the WebMvcConfigurerAdapter was extending, overridden the getValidator() method, and it worked.
@juanalvarez123 Thanks for trying to help people out. One word of caution, though. It's unusual to have @EnableWebMvc in a Spring Boot application as it will switch off all of Boot's auto-configuration of Spring MVC. A WebMvcConfigurer without @EnableWebMvc is much more common.
Hi, I'm trying to figure out what is the current situation about this issue. I'm using Spring Boot 2.1.4 and I'm struggling on this topic.
I'm using this config right now:
@Configuration
@EnableRetry
@EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class CustomConfiguration {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/i18n/messages");
messageSource.setUseCodeAsDefaultMessage(false);
messageSource.setCacheSeconds((int) TimeUnit.HOURS.toSeconds(1));
messageSource.setFallbackToSystemLocale(false);
return messageSource;
}
@Bean
public MessageSourceAccessor messageSourceAccessor() {
return new MessageSourceAccessor(messageSource());
}
@Bean
public Validator validator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
factoryBean.setValidationMessageSource(messageSource());
return factoryBean;
}
and
@Configuration
@EnableHypermediaSupport(type = {HypermediaType.HAL})
public class WebMvcConfiguration implements WebMvcConfigurer {
private Validator validator;
@Autowired
public WebMvcConfiguration(Validator validator) {
this.validator = validator;
}
@Override
public Validator getValidator() {
return validator;
}
but still I've to follow @selimok hint: I have to move all validation keys in ValidationMessages.properties and all other keys in messages.properties.
Is this the indented behaviour? Can someone point out what is the "right" way to do this right now, until this issues is not resolved?
Thanks
I'm using SpringBoot 2.1.6.RELEASE and met this problem too. It only works with @selimok 's solution(use hardcoded ValidationMessages.properties file).
What I'm very confused is that: why messageSource.getMessage("{prop}") is OK but @Min(message="{prop}") not ?
Thanks for any advise or explaination.
My problem was with parameter interpolation:
Is lack of parameter interpolation in BindingResult's default message the expected behaviour?
Most helpful comment
It works.
To get it worked I have to move validation keys into the file ValidationMessages.properties while all oder messages reside in messages.properties.
FYI.