Spring MVC web app i18n - java

In a web application written using spring-MVC, I want to allow users to change the current language by clicking on a link which text is the name of the language.
I have already set up a messageSource and made all my jsp pages find the messages using this messageSource. Currently, the language is changing depending on the locale of the user browser.
So, what I want to do now is to allow to change the locale manually.
I have found that the class SessionLocaleResolver could help, but I do not know how to set it up in my application context file (which name is myAppName-servlet.xml) .
I have defined the bean :
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
</bean>
But in which bean should I plug this ? Furthermore, how do I set a cookie related to locale into an user session ?

All informations I needed were in the documentation, in front of me, at :
http://static.springframework.org/spring/docs/2.5.x/reference/mvc.html#mvc-localeresolver
In brief, I adapted the following xml to myAppName-servlet.xml
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="siteLanguage"/>
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor"/>
</list>
</property>
<property name="mappings">
<value>/**/*.view=someController</value>
</property>
</bean>
And now, it suffices to access any page with the parameter :
siteLanguage=locale
to change the locale for the whole site.
For example : http://localhost:8080/SBrowser/deliveries.html?siteLanguage=frenter code here

Related

Spring: Loading PropertyPlaceholderConfigurer

Here is the situation:
The xml configuration looks as follows:
<bean id="ppConfig1"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:c:\test\env.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
<bean id="string" class="java.lang.String" depends-on="ppConfig1">
<constructor-arg value="${env.app.type}"/>
</bean>
<bean id="ppConfig2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
<property name="locations">
<list>
<value>file:c:\test\#{string}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
</bean>
As is evident, I want load a specific property file (e.g. app1.properties) based on the value of key env.app.type in C:\test\env.properties.
The code to load/test the above config looks as follows:
ApplicationContext context = new ClassPathXmlApplicationContext(
"SpringBeans.xml");
String ss = (String)context.getBean("string");
System.out.println(ss);
This seems not working. It failing with following error:
Exception in thread "main"
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: C:\test\${env.app.type}.properties (The
system cannot find the file specified) at
org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)
The file c:\test\env.properties looks as follows
env.app.type=app1
One interesting observation is that when I comment out the ppConfig2, everything works fine and correct value of env.app.type is printed. I am open to any other suggestion to get around this. My basic requirement is to select the property file at run time based on the property specified in env.properties. (I am using spring 3.1.0)
You need something like this:
<context:component-scan base-package="com.foo.bar" />
<context:property-placeholder location="file:c:/test/${env.app.type}.properties" />
<bean id="service" class="com.foo.bar.ExampleService">
<property name="foo" value="${foo}" />
</bean>
package com.foo.bar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("file:c:/test/env.properties")
public class SpringConfig{
}
And "foo" value comes from app1.properties file. Basically, one file is being loaded with #PropertySource, the other with the regular property placeholder.
I think you are trying to do things that Spring does not like. The normal order for bean initialization is :
fully construct bean post processors
construct other beans
init other beans
As long as those 3 passes are cleanly separated, all will be ok, but you have a post processor bean (ppConfig2) depending on a simple bean (string).
IMHO, you should avoid such construct if possible. Even if it works now, you are under the risk of problem arising at any modification of you application context because you are allready on the edge.
Could it be acceptable to use environment variables or system properties to avoid that a bean post-processor depends on another bean post-processor ? If yes, you would'nt be bothered by ppConfig1 and simply have :
<bean id="ppConfig2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
<property name="locations">
<list>
<value>file:c:\test\${configured_env}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
</bean>
If environment variables or system properties are not an option, you could use programmatic configuration as suggested by Andrei Stefan.
You can do this with util:properties:
<util:properties id="envProperties" location="env.properties"/>
<util:properties id="properties" location="#{envProperties.getProperty('env.app.type')}.properties"/>
<context:property-placeholder properties-ref="envProperties" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder properties-ref="properties" ignore-unresolvable="true"/>
BTW there's a bug in Spring that prevents Spring EL from being evaluated inside location attribute in context:property-placeholder.

How to hide request parameter value in url using Spring MVC

I'm working on language changes for my page.when the client clicks on any language, page should load in that particular language. For that I configured springs.xml like this
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
The page was loading fine, when I'm give the url like this, site/companykey?lang=french,
Now my problem is , I want to hide the param value which I have given ?lang=french.
Is there any way to hide that value from the url ??
locate the form in jsp/html page in which you have included these tags used for changing locale. change the attribute method="POST". it will make sure that the parameter will pass to the mapped action class without appearing in the url.

spring -- are beans in application context binded to PropertyPlaceholderConfigurer dynamically?

I want to know if beans in my application context are binded dynamically. Specifically, if I have
<bean id="mySpringRemoteService"
class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceInterface"
value="foo.bar.services.mySpringRemoteService" />
<property name="serviceUrl" value="${spring.remote.service.url}"/>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:some.properties"/>
</bean>
if i change the property for the service url in my properties file, will retrieving the bean later reflect this change?
Well, I think it is easy for you to have a try yourself.
The answer is No (Unless behavior of Spring changed in 3.x )
I believe you have to implement runtime update behavior for config files. Take a look in Apache Commons Configurations.

How to set dynamically a bean reference in Spring?

<bean id="Mybean" class="Bean">
<property name="config" ref="dev"/>
</bean>
<bean id="dev" class="Dev">
<property name="x" ref="Dev1">
<property name="y" ref="Dev2">
<property name="z" ref="Dev3">
</bean>
<bean id="stag" class="Dev">
<property name="x" ref="Stag1">
<property name="y" ref="Stag2">
<property name="z" ref="Stag3">
</bean>
In the above scenario, the config property in the bean MyBean change from environment to environment. At the time of dev, reference of config change to dev. And in staging, the reference change to stag. The problem comes at the time of checked in the spring file. We have to analyze everytime the reference of config before checked in. If the reference of config with the value of dev checked in, we might have to explain a lot of questions.
Is there any solution to solve to make it automate?
Note: Spring version is 2.0.1
Use the PropertyPlaceholderConfigurer from Spring, and remove an unused bean :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>env.properties</value>
</property>
</bean>
<bean id="Mybean" class="Bean">
<property name="config" ref="config"/>
</bean>
<bean id="config" class="Config">
<property name="x" ref="${x}">
<property name="y" ref="${y}">
<property name="z" ref="${z}">
</bean>
and the env.properties file contains the following properties :
x=Dev1
y=Dev2
z=Dev3
or
x=Stag1
y=Stag2
z=Stag3
setup up the placeholder bean by specfiy, let spring know you want the placeholder
set up the config for the "my bean" by using the "${env}"
for example:
<beans>
<bean id="configBean" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"><value>env.properties</value></property>
</bean>
<bean id="Mybean" class="Bean">
<property name="config" ref="${env}"/>
</bean>
</beans>
and you need the add the env = dev key-value to the env.properties file
Assuming you meant Spring 3.1, rather than Spring 2.1 (which doesn't exist), then you can use the new "Environment Profiles" feature that was introduced in 3.1. This allows you to define a set of beans for each of your environments, and then select the "active" one at runtime.
See this SpringSource Blog Entry for examples.
You can do it using PropertyPlaceholderConfigurer or using #Profile
Also See
is-there-any-way-to-enable-or-disable-the-spring-bean-definition-in-applicationc
PropertyPlaceholderConfigurer example
PropertyPlaceholderConfigurer is the answer, yet I would imagine that you would like this to happen without the need to stay updating your properties file for each environment.
My suggestion would therefore be as follows
Use PropertyPlaceholderConfigurer, but do not create a properties file
By default, PropertyPlaceholderConfigurer first tries to find a value in a properties file, but if that fails, it will look for one in system properties
So all you need to do is to define both beans the same way that you are doing it, i.e. dev and stag.. which is a fine approach since you're clearly showing the different configurations... it would help if you also added some alias to show clearly the setting you want to use.
Next, pass in a system property defining what mode you are in... and ideally explicitly set PropertyPlaceholderConfigurer to use System properties.
So.. your config would look something like this
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
systemPropertiesMode="2"/>
<bean id="Mybean" class="Bean">
<property name="config" ref="${launch.mode}"/>
</bean>
<bean id="dev" name="dev_mode" class="Dev">
<property name="x" ref="Dev1">
<property name="y" ref="Dev2">
<property name="z" ref="Dev3">
</bean>
<bean id="stag" name="staging_mode" class="Dev">
<property name="x" ref="Stag1">
<property name="y" ref="Stag2">
<property name="z" ref="Stag3">
</bean>
You can then pass in the property upon startup in the following fashion
-D<property-name>=<value>
So in this case you'd use
-Dlaunch.mode=dev_mode
Or
-Dlaunch.mode=staging_mode
And you won't need to touch any of the configuration files.
Just a further note on systemPropertiesMode, accepted values are the following:
0 - never look in system properties
1 - use system properties as a fallback (i.e. if not found in properties files)
2 - system properties always override (the mode i'm suggesting)
Hope it helps :)
Note: This recommendation is only applicable to Spring < 3.1, since from 3.1 onward, the recommended approach is to use #Profile
Spring provides a mechanism called property placeholders. This way you can set certain properties in a database/properties file and spring will fill them in on startup.
The class to use for this is located here.

LocaleResolver in Spring

I am using session locale resolver for my application. I am showing the languages in dropdown. if the user selects on any of the language then repopulates all values from that language.
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="languageCode" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
But its is not reading it from the session. Always it considers the defaultlanguage from browser setting.
Please help on this.
You need to obtain the locale in this way:
Locale loc=RequestContextUtils.getLocale(request);
In Spring 4.0 we can Also use LocaleContextResolver.getLocale() method as well.

Categories

Resources