Friday, October 29, 2010

i18n Locale configuration with Spring

i18n with Spring is fairly easy.

First of all, you'll need to declare a bean named localeResolver.  DispatcherServlet will automatically looking for this bean when a request comes in.  Spring has AcceptHeaderLocaleResolver, CookieLocaleResolver, and SessionLocaleResolver.  In my case, I'll use SessionLocaleResolver to go with user sessions.

Then you'll need to define a LocaleChangeInterceptor bean and list it in your url handler mapping's interceptors list.

Here is my spring bean declaration:
<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.SessionLocaleResolver" />

<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
    <property name="interceptors">
        <list>
            <ref bean="localeChangeInterceptor" />
        </list>
    </property>
</bean>

With above configuration, I can change the locale to it_IT with a link like http://localhost:8080/myApp/home.do?lang=it_IT

In Java, there are serveral ways to get the locale:
1. If you know which locale resolver, in my case SessionLocaleResolver, I use
Locale locale = (Locale) request.getSession().getAttribute(
    SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME);
2. A universal way to get the locale
Locale locale = RequestContextUtils.getLocale(request);
3. Spring documentation says using RequestContext.getLocale() to get the locale.  However, getLocale is not a static method in RequestContext.

To get the locale in JSP page:
${sessionScope['org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE']}

If you are using displaytag, you'll need to add following configuration to displaytag.properties
locale.resolver=org.displaytag.localization.I18nSpringAdapter

After all this, there is still one more problem -- no default Locale before user pick any.
There are couple ways to solve this:
1. If you want to force use a certain Locale, LocaleResolver has a setDefaultLocale method, so specify default Locale in localeResolver bean and we now have:

<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
    <property name="defaultLocale">
        <bean class="java.util.Locale">
            <constructor-arg index="0" value="it"/>
            <constructor-arg index="1" value="IT"/>
        </bean>
    </property>
</bean>
One downside with this approach.  In JSP page though, the default Locale value can not be picked up using Expression Language above.

2. If you want to use the user's browser's language preference, then you need to manually set the locale:
In Java:
request.getSession().setAttribute(
    SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME,
    request.getLocale());
In JSP (not actually setting the default locale in session, but use the browser default when there is no locale in session):
<c:set var="language">${sessionScope['org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE']}</c:set>
<c:if test="${empty language}">
    <c:set var="language">${pageContext.request.locale}</c:set>
</c:if>

Saturday, October 16, 2010

Remote Debug Web Start, Tomcat and Standalone Application

Remote debug web start is not as easy as applet.  Same setting for applet doesn't work at all.  Finally, I managed to make it work with an alternative solution.  Instead of launching the web start from a web site, I downloaded the JNLP file and launched it from command line.

My environment: Windows 7 64-bit, JDK 6 Update 14, MyEclipse for Spring.
Here is what I did:
  1. No need to setup Runtime Parameters in Java Control Panel this time.
  2. I used port 8200 for remote debug.
  3. server=y must be used
  4. suspend can be y or n.  If suspend=n, then Web Start will launch right away.  But if suspend=y, Web Start will not launch until a debugger is attached to port 8200.
  5. In Eclipse/MyEclipse, Debug Configuration must use Socket Attach as Connection Type and use port 8200.

Remote debug Tomcat or other standalone application is very similar to Web Start. However, the runtime parameters have to be added to the application's start script. And in this case, suspend is better to set to n so that the application will not wait for a debugger to attach. Since this type of application is most likely deployed to a remote server, Host in Debug Configuration also needs to match the corresponding domain.

Thursday, October 14, 2010

Remote Debug an Applet

Remote debug is relatively new to me.  But after a few days of trying, I finally got a hand of it.  Remote debug applet is the easiest and first in success during my experiment.

My environment: Windows 7 64-bit, IE8, JRE 6 Update 21, MyEclipse for Spring.
  1. Go to Start --> Control Panel --> Java (32 bit), this will open the Java Control Panel.
  2. Go to Java Tab and click on View...
  3. Add "-Xdebug -Xrunjdwp:transport=dt_socket,address=9000,suspend=y" to the Runtime Parameters
  4. In Eclipse/MyEclipse, click Debug --> Debug Configurations ... from toolbar.
  5. Add a new configuration under Remote Java Application.  Make sure you use Socket Listen as Connection Type.  Also match the port, which is 9000 in my case.
  6. Now start the Debug Configuration just added, Applet in my case. You'll see in Progress panel that port 9000 is being listened.
  7. Add break point in code and launch the applet.