Wednesday, October 28, 2009

Recipe 12.3. Using an Application-Wide Locale










Recipe 12.3. Using an Application-Wide Locale




Problem



You want your web application to use the same locale settings for all
users, regardless of their browser's language
setting. You also want the JSTL tags to honor this application-wide
locale.





Solution



Use a servlet Filter to set the
Locale to the desired value (see Example 12-3). The Filter ensures that
the Locale is set for all web requests, and not
just those handled by Struts.




Example 12-3. Using a servlet filter to set the locale

package com.oreilly.strutsckbk.ch12;

import java.io.IOException;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.jstl.core.Config;

import org.apache.struts.Globals;

public class LocaleFilter implements Filter {

// the locale code used to create the locale (e.g. en_US)
private String localeCode;

// indicates if the locale should always be set;
// even if there is currently one in the session
private boolean ignore = false;

public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
localeCode = filterConfig.getInitParameter("locale");
override = Boolean.valueOf(filterConfig.getInitParameter("ignore")).
booleanValue( );
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;

// create the session if needed
HttpSession session = req.getSession( );

Locale currentLocale = (Locale) session.getAttribute(Globals.
LOCALE_KEY);
if (currentLocale == null || ignore) {
// create the new locale
Locale locale = new Locale(localeCode);

// reset the Struts locale
session.setAttribute(Globals.LOCALE_KEY, locale);

// reset the JSTL locale
Config.set(session, Config.FMT_LOCALE, locale);
}
chain.doFilter(request, response);
}

public void destroy( ) {
// Nothing necessary
}

private FilterConfig filterConfig;
}





Declare the filter in your web.xml, as shown in
Example 12-4.




Example 12-4. Locale filter configuration (partial)

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<display-name>Struts Cookbook - Chapter 12 Examples</display-name>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>ApplicationResources</param-value>
</context-param>

<filter>
<filter-name>LocaleFilter</filter-name>
<filter-class>
com.oreilly.strutsckbk.ch12.LocaleFilter
</filter-class>
<!-- Language and country -->
<init-param>
<param-name>locale</param-name>
<param-value>en_US</param-value>
</init-param>
<!-- True to set locale even if already set in session -->
<init-param>
<param-name>ignore</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>LocaleFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...







Discussion



Usually, you want the user's
Locale to reflect the browser's
settings, as shown in Recipe 12.1. Some
applications, however, need the opposite behavior. You want the
application to reflect the same language and country regardless of
how the client's browser, or the
server's operating system, is configured. The
servlet filter shown in the Solution provides this ability. The
filter accepts two initialization parameters. The
locale parameter defines the
Locale to use by specifying a locale code (e.g.,
en_US) as its value. To use this filter, you must
turn off locale processing in the Struts
RequestProcessor using the
controller element in the
struts-config.xml file:



<controller locale="false"/>




The second parameter, the ignore parameter,
indicates if the filter should ignore any Locale
in session, always setting the locale even if one is present. You can
set this value to false if you want to define a default locale but
still allow a user to select and use a new locale (see Recipe 12.4).



Filters provide an excellent way to apply across-the-board behavior.
Though you could override the processLocale method
in a custom RequestProcessor, it would only affect
requests to Struts actions. The Solution shown here will set the
default locale for web requests to Struts actions, JSPs, and static
HTML pages.





See Also



Servlet filters are a new addition to the Servlet API, being added in
Version 2.3. Java Servlet Programming by Jason
Hunter (O'Reilly) covers servlet filters in-depth.



Sun's Java
site has a good article on the
essentials of servlet filters found at http://java.sun.com/products/servlet/Filters.html.












    No comments: