0

I want to interpolate validation messages based on JSR 303 specification into single file instead of ValidationMessages.properties. Just for simplicity. I have read that it is possible with setting of config class which extends from WebMvcConfigurerAdapter:

@Bean(name = "messageSource")
public MessageSource messageSource()
{
    ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
    bean.setBasename("classpath:messages");
    bean.setDefaultEncoding("UTF-8");
    return bean;
}

@Bean(name = "validator")
public LocalValidatorFactoryBean validator()
{
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    bean.setValidationMessageSource(messageSource());
    return bean;
}

@Override
public Validator getValidator()
{
    return validator();
}

where the file text.properties should be used for validation messages.

MAX_SIZE_MESSAGE = You must enter max 20 characters

Then I have entity where is used validation message e.g.

@Size(max = 20, message = "{MAX_SIZE_MESSAGE}")

However the message is not visible by spring boot after running of tests.

What is wrong? Must be the config file available only in one place or it must be a part of test package?

Update 30.1 It seems that the message bundle is not recognized after debugging. I have test profile where is located messages.properties file but not used.

Luke
  • 1,163
  • 2
  • 11
  • 19

1 Answers1

0

Spring also configures a Validator bean. To use your implementation instead mark your bean with @Primary.

@Configuration
public class MyConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Bean
    @Primary
    public LocalValidatorFactoryBean validator() {

        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename("classpath:text");

        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);
        return validator; 
    }

    @Override
    public Validator getValidator() {
        return validator();
    }
}

Then you can inject the validator you created like this,

@Component
public class TestRunner implements CommandLineRunner {

    @Autowired
    private Validator val;

    ....
}
matthias
  • 711
  • 4
  • 15
  • Thanks. I tried it with primary annotation but it did not worked. In addition, I assume that the validation message should be populated automatically when user pass bad message length instead of direct using autowired validator. Any other idea? – Luke Jan 30 '18 at 09:52
  • Can you update your question on how you use the validator? where do you call the validator. I tested the primary approach with a CommandLineRunner and I get the correct validator injected – matthias Jan 30 '18 at 10:00
  • Actually I don't call the validator at all. As I assumed the JSR-303 validation should take care about that. So for example if the size is crossed over max value then the linked error message should be populated automatically based on ValidationMessages.properties or messages.properties in my case. But it works just in first case not with messages.properties. – Luke Feb 01 '18 at 07:21
  • You don't call the validator by yourself, but how is he called? How many validator beans exists in your context? Without further information it's not possible to detect the problem. – matthias Feb 01 '18 at 09:23