dikkini dikkini - 12 days ago 8
Java Question

Spring 4 MVC Locale changed but JSP does not respond for this

This is my configuration files:

Initializer:

public class Initializer implements WebApplicationInitializer {

private static final String DISPATCHER_SERVLET_NAME = "dispatcher";

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();

ctx.register(ApplicationConfig.class);

servletContext.addListener(new ContextLoaderListener(ctx));
servletContext.setInitParameter("defaultHtmlEscape", "true");
servletContext.addListener(new HttpSessionEventPublisher());
servletContext.addListener(new RequestContextListener());

FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter",
new CharacterEncodingFilter());
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/*");

servletContext.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");

ServletRegistration.Dynamic servlet = servletContext.addServlet(DISPATCHER_SERVLET_NAME,
new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
servlet.setAsyncSupported(true);

ctx.setServletContext(servletContext);
}

public Filter[] getServletFilters() {

CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);

return new Filter[]{characterEncodingFilter, new DelegatingFilterProxy()};
}

}


ApplicationConfig:

@Configuration
@EnableWebMvc
@ComponentScan("com.example.*")
@PropertySource("classpath:app.properties")
public class ApplicationConfig extends WebMvcConfigurerAdapter {

private static final Charset UTF8 = Charset.forName("UTF-8");

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
OpenSessionInViewInterceptor sessionInViewInterceptor = new OpenSessionInViewInterceptor();
sessionInViewInterceptor.setSessionFactory(sessionFactory);

registry.addWebRequestInterceptor(sessionInViewInterceptor);
registry.addInterceptor(localeChangeInterceptor());
}

@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}

@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource ret = new ReloadableResourceBundleMessageSource();
ret.setBasenames("classpath:messages", "classpath:labels", "classpath:exceptions");
ret.setDefaultEncoding(UTF8.name());
return ret;
}

// @Bean
// public SessionLocaleResolver localeResolver() {
// // TODO locale
// Locale ruLocale = new Locale.Builder().setLanguage("ru").build();
// SessionLocaleResolver localeResolver = new SessionLocaleResolver();
// localeResolver.setDefaultLocale(ruLocale);
// return localeResolver;
// }

@Bean
public CookieLocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setCookieName("localceCookie");
cookieLocaleResolver.setCookieMaxAge(3600);

return cookieLocaleResolver;
}

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("locale");
return localeChangeInterceptor;
}

}


So i have LocaleChangeInterceptor, CookieLocaleResolver, MessageSource. I have
labels.properties
and
labels_en.properties
.

JSP:

Language : <a href="?locale=en">English</a>|<a href="?locale=ru">Russian</a>

<h2>
lable.testLocale : <spring:message code="lable.testLocale" text="default text" />
</h2>

Current Locale : ${pageContext.response.locale}


When i click on link English, Russian, JSP reloading and Current Locale value on JSP shows Russian and English (depends on link). So locale changing successfully. Cookie with name
localceCookie
appears and it is contain ru or en value depends on chosen locale, but JSP value
label.testLocale
shows ONLY value for
en
locale and it does not changed. I looked up a lot of questions and most them were about localeInterceptor.

I tried Tomcat, Jetty, JBoss (now it is wildfly) applications servers. I tried different browsers. Also, i found this tutorial, project does not work, i made some changes like
@RequestMapping
for controller, but locale does not work in this example.

UPDATE #1

Accordingly to answer of @TechBreak i do the following:
1. Changed basenames of bundles and set default locale in CookieLocaleResolver

@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource ret = new ReloadableResourceBundleMessageSource();
ret.setBasenames("/WEB-INF/messages", "/WEB-INF/labels", "/WEB-INF/exceptions");
ret.setDefaultEncoding(UTF8.name());
return ret;
}
@Bean
public CookieLocaleResolver localeResolver() {
Locale ruLocale = new Locale.Builder().setLanguage("ru").build();
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(ruLocale);
cookieLocaleResolver.setCookieName("localceCookie");
cookieLocaleResolver.setCookieMaxAge(3600);
return cookieLocaleResolver;
}



  1. Move bundles to /WEB-INF/



Problem still exists.

UPDATE #2

Now my configuration looks like this:

@Configuration
@EnableWebMvc
@ComponentScan("com.example.*")
@PropertySource("classpath:app.properties")
public class ApplicationConfig extends WebMvcConfigurerAdapter {

@Autowired
private SessionFactory sessionFactory;

private static final Charset UTF8 = Charset.forName("UTF-8");

@Bean
public static PropertySourcesPlaceholderConfigurer propertiesBean() {
return new PropertySourcesPlaceholderConfigurer();
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("/assets/").setCachePeriod(31556926);
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}

@Bean
public RequestMappingHandlerMapping handlerMapping() {
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
handlerMapping.setInterceptors(localeChangeInterceptor());
return handlerMapping;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
OpenSessionInViewInterceptor sessionInViewInterceptor = new OpenSessionInViewInterceptor();
sessionInViewInterceptor.setSessionFactory(sessionFactory);

// registry.addWebRequestInterceptor(sessionInViewInterceptor);
registry.addInterceptor(localeChangeInterceptor());
}


// @Bean
// public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
// return new SimpleControllerHandlerAdapter();
// }

@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}

@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource ret = new ReloadableResourceBundleMessageSource();
ret.setBasenames("/WEB-INF/labels");
ret.setDefaultEncoding(UTF8.name());
return ret;
}

// @Bean
// public SessionLocaleResolver localeResolver() {
// // TODO locale
// Locale ruLocale = new Locale.Builder().setLanguage("ru").build();
// SessionLocaleResolver localeResolver = new SessionLocaleResolver();
// localeResolver.setDefaultLocale(ruLocale);
// return localeResolver;
// }

@Bean
public CookieLocaleResolver localeResolver() {
Locale ruLocale = new Locale.Builder().setLanguage("ru").build();
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(ruLocale);
cookieLocaleResolver.setCookieName("localceCookie");
cookieLocaleResolver.setCookieMaxAge(3600);

return cookieLocaleResolver;
}

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
// TODO locale
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("locale");
localeChangeInterceptor.setHttpMethods(HttpMethod.GET.name(), HttpMethod.POST.name());
return localeChangeInterceptor;
}
}


I try
DefaultAnnotationHandlerMapping
but it is deprecated and Spring says to use
RequestMappingHandlerMapping
, in both cases problem still exists. In label.properties i have Russian language and it is default locale, in label_en.properites English language. And Russian locale as default locale.

FINAL CONFIGURATION

This is important part of configuration

@Bean
public RequestMappingHandlerMapping handlerMapping() {
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
handlerMapping.setInterceptors(localeChangeInterceptor());
return handlerMapping;
}


And for default locale i made labels_ru.properties and for English locale i made labels.properties.

Answer

As you are you using

ReloadableResourceBundleMessageSource

then you have to move your resource bundle files from current src/main/resources to resource directory of your WEB-INF.

Please read the documentation for : http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/ReloadableResourceBundleMessageSource.html

It says to be able to reload they should be put into WEB-INF directories.

Also I see that you need to do configuration equivalent of following,

<bean id="handlerMapping"
        class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <ref bean="localeChangeInterceptor" />
        </property>
    </bean>

EDIT : Also make sure you have label_ru.properties file defined.

Comments