ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

JSTL 1.0: What JSP Applications Need, Part 2
Pages: 1, 2, 3, 4

Using a Controller to Select the Locale

If you've developed Web applications using Java technology for some time, you have no doubt heard about the MVC pattern and, most likely, about the Apache Struts MVC framework. The basic idea behind the MVC pattern is that an application is easier to maintain and evolve if the different parts of the application (Model, View, and Controller) are implemented as separate components. For Java, this typically means using beans as the Model (business logic), JSP pages as the View (the user interface), and a servlet as the Controller (the piece that controls the communication between the View and the Model). The Struts framework provides a generic Controller servlet that delegates the processing of specific types of requests to classes called Action classes, and then uses a JSP page specified by the Action to generate the response.



JSTL is designed to play well in an MVC-based application by exposing a class that can be used by any Java component, such as a Struts Action class, to access the configuration variables used by the JSTL actions in the JSP pages representing the View. The class is called javax.servlet.jsp.jstl.core.Config and contains constants (static final String variables) for all configuration variables, and methods for setting, getting, and removing the variables in different JSP scopes. You can use code like this in a Struts Action class to set the default locale for the session, based on profile data, when a user logs in to the application:

import javax.servlet.jsp.jstl.core.Config;
...
public class LoginAction extends Action {
public ActionForward perform(ActionMapping mapping, 
  ActionForm form, HttpServletRequest request, 
  HttpServletResponse response) 
  throws IOException, ServletException {

  String userName = request.getParameter("userName");
  String password = request.getParameter("password");
  ...
  User user = authenticate(userName, password);
  if (user != null) {
	/*
	 * Valid user. Set the default locale in the session
	 * to the user's preferred locale
	 */
	HttpSession session = request.getSession();
	Config.set(session, Config.FMT_LOCALE, user.getLocale());
	...
}    
}

Related Reading

Programming Jakarta Struts
By Chuck Cavaness

The Config class provides four versions of the set() method, one for each JSP scope (specified by the first method parameter). Here I use the one that sets the variable in the session scope. The second parameter is the name of the configuration, typically set by the corresponding constant. The third parameter is the variable value. For reading and removing variables, the class provides similar get() and remove() methods, plus a find() method for locating a variable in any scope. In addition to using these methods in a Controller, you may want to use them in your own custom tag handlers to take advantage of the JSTL configuration setting mechanism.

Generating Localized Text

While date and number formatting is important when localizing an application, the text content is, of course, even more so. JSTL is based on Java, so it leverages the generic i18n support in the Java platform. When it comes to text, this support is based on what's called a resource bundle. In its simplest form, a resource bundle is represented by a text file containing keys and a text value for each key. This example shows a file with two keys (hello and goodbye) and their values:

hello=Hello
goodbye=Goodbye

Multiple locales are supported by creating separate files for each locale, with a filename that includes the locale name. For instance, if the resource bundle file above represents the English locale, it may be stored in a file named labels_en.properties. The resource bundle for the Swedish locale would then be stored in a file named labels_sv.properties, where sv is the language code for Swedish. The fixed part of the file name, labels in this example, is called the resource bundle base name, and it's combined with a locale specification (such as a language code) to find the resource bundle for a specific locale. All resource bundle files include the same keys; only the text differs depending on the locale. The files must be located in a directory that's part of the Web container's classpath, typically the application's WEB-INF/classes directory.

The JSTL action that adds text from a resource bundle to a page is the <fmt:message> action. The bundle to use can be specified in a number of ways. One way is to nest the <fmt:message> actions within the body of a <fmt:bundle> action:

<fmt:bundle basename="labels">
Hello: <fmt:message key="hello" />
Goodbye: <fmt:message key="goodbye" />
</fmt:bundle>

In this case, the <fmt:bundle> action locates the bundle for the locale that is the closest match between the locale configuration setting (or the locales in the Accept-Language header, if no default locale is set) and the available resource bundles for the specified base name. The nested actions then get the text from this bundle for the specified key.

As with the formatting actions, you can also establish a default bundle, either for the whole application with a context parameter or with the <fmt:setBundle> action or the Config class for a specific JSP scope:

<fmt:setBundle basename="labels"/>
...
Hello: <fmt:message key="hello" />
Goodbye: <fmt:message key="goodbye" />

After a default bundle has been defined, you can use the <fmt:message> actions standalone within the scope where the default is established.

There are more options for the i18n and formatting actions than I can fit into this article. For instance, you can use messages that contain dynamic values assigned using nested <fmt:param> actions, and override which bundle to use within a certain context. Another important area when it comes to i18n is how to handle languages with non-Western characters. I describe all of this and more in JavaServer Pages, 2nd Edition.

Accessing a Database

A somewhat controversial subject is JSTL's inclusion of actions for accessing a database. Some people see this as encouraging bad practices, and argue that all database access should be performed by pure Java components in an MVC-based application instead of by JSP pages. I agree with this point of view for anything but the simplest applications, but there are a lot of applications that qualify as very simple, and where lack of programming skills or time makes a full-blown MVC architecture impractical. Without JSTL support, these applications often end up with Java database access code in scriptlets instead, and that is far worse from both a development and maintenance standpoint. I'll therefore show you how to use JSTL to access a database in JSP pages, but ask you to keep in mind that this approach is not suitable for all types of applications. If your development team includes Java programmers, you should carefully consider encapsulating the database access code in Java classes instead, and use JSP only to display the result.

The JSTL database actions are based on the general Java database API (JDBC) and use the javax.sql.DataSource abstraction introduced in JDBC 2.0 to represent the database. A DataSource provides connections to the database and can implement a feature called connection pooling. Opening a physical connection to a database is a very time-consuming operation. With connection pooling, it only needs to be done once, and the same connection can then be reused over and over, without risking problems associated with other connection-sharing approaches.

Pages: 1, 2, 3, 4

Next Pagearrow