1

I am working with Spring Framework 4.3.3

I have the following situation for a @Controller either for POST or PUT

For example for POST I have the following:

@PostMapping(value="/save",
             consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE,
             produces=MediaType.TEXT_HTML_VALUE)
public String saveOne(@Validated @ModelAttribute Persona persona,
        BindingResult result,
        RedirectAttributes redirectAttributes){

    logger.info("saveOne: {}", persona.toString());

    if(result.hasErrors()){
        logger.error("# Errors: {}", result.getErrorCount());
        logger.error("result: {}", result.toString());
        return "persona/saveOne";
    }

    personaRestController.saveOne(persona);

    redirectAttributes.addFlashAttribute("message", "process.successful");
    return "redirect:/message";
}

The app works how is expected, through a Web Form this @PostMapping either saves/persists the data or validates the data and if it is invalid the same web form is shown with the error messages for each field and based about i18n such as English, Spanish and Portuguese. It related with JSR-439

About Java config infrastructure configuration I have the following:

@Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
        LocaleChangeInterceptor localeChangeInterceptor=new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("language");
        //localeChangeInterceptor.setHttpMethods("post", "put");
        return localeChangeInterceptor;
}

@Bean(name="localeResolver")
public LocaleResolver cookieLocaleResolver(){
        CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
        cookieLocaleResolver.setCookieName("language");
        cookieLocaleResolver.setDefaultLocale(new Locale("en","US"));
        return cookieLocaleResolver;
}

And

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

...

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptorConfig.localeChangeInterceptor());
    }

The problem is about Spring MVC Test. I have the following:

@Before
public void setUp(){
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

...

@Test
public void saveOneHtmlPostInvalidMaxTest() throws Exception {

    logger.info("saveOneHtmlPostInvalidMaxTest");

    resultActions = mockMvc.perform(post(url)
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .locale(locale)
                .header("accept-language", locale.toString())
                .header("language", locale.toString())
                .param("id", personaInvalidMax.getId())
                .param("nombre", personaInvalidMax.getNombre())
                .param("apellido", personaInvalidMax.getApellido())
                ....
                .andDo(print());

Note observe:

                .locale(locale)
                .header("accept-language", locale.toString())
                .header("language", locale.toString())

Even when some of them have no sense, they are there because I am trying to resolve the following situation:

The validation control from the server side works how is expected until some point.

First

I can confirm through .andDo(print()) method that MockHttpServletRequest prints

Headers = {Content-Type=[application/x-www-form-urlencoded], accept-language=[pt_BR], language=[pt_BR]}

Observe pt_BR

Second

The @PostMapping that contains:

if(result.hasErrors()){
    logger.error("# Errors: {}", result.getErrorCount());
    logger.error("result: {}", result.toString());
    return "persona/saveOne";
}

Prints...

7370 [Test worker] ERROR PersonaSaveOneController - result: org.springframework.validation.BeanPropertyBindingResult: 4 errors Field error in object 'persona' on field 'id': rejected value [0]; codes [Size.persona.id,Size.id,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [persona.id,id]; arguments []; default message [id],3,3]; default message [The size for the field must be between 3 and 3]

Observe the default message [id],3,3]; default message [The size for the field must be between 3 and 3]

Here two problems:

  • The locale or accept-language are ignored
  • The error messages prints always in English

What I need is that the error data prints for example in Portuguese and Spanish according the Locale sent. It should returns the error messages for each field in an expected language, in this case Portuguese

Again, it works when I use directly the Web Form, but not through the Test. I am assuming that exists an internal Spring component that works through production and has not been defined for Testing

Therefore, what is need it to accomplish this approach?

BTW: With the following (see I use classpath:), furthermore my .properties file are located in src/main/resources

@Bean(name="messageSource")
public ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource() {
        ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
        resource.setBasenames(...
"classpath:/com/manuel/jordan/validation/validation");
        resource.setDefaultEncoding("UTF-8");
        return resource;
}

My @Test methods working around with Rest works fine about show and returning the error message according the Locale or accept-language defined (Access to MessageSource happens in the server side and works fine with the previous configuration). It just fails for non-Rest controllers

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
  • Possible duplicate of [Spring messageSource works in JSP and not works in jUnit test](http://stackoverflow.com/questions/15308773/spring-messagesource-works-in-jsp-and-not-works-in-junit-test) – rorschach Sep 24 '16 at 20:57
  • I will say is not duplicate, the code works in production, but does not work how is expected in testing. – Manuel Jordan Sep 25 '16 at 14:23
  • Just like the code in the other thread. – rorschach Sep 25 '16 at 14:24
  • You are assuming is about `ReloadableResourceBundleMessageSource`?, right? I have other test about `Rest` and works fine. The problem is the App server does not recognize the `Locale` or `accept-language` sent from the Test. All my `.properties` files are referenced through `classpath:` – Manuel Jordan Sep 25 '16 at 14:28
  • Do you use Spring Boot? If so, does `spring.messages.fallback-to-system-locale=false` fix it? If your default language is `en` but there's no `messages_en.properties`, only a `messages.properties`, Spring will use `messages_xx.properties` if the language of your default locale is `xx`. – aha Sep 28 '21 at 13:16

0 Answers0