Foundations of JSP design patterns: The View Helper pattern

Learn how the View Helper pattern helps you adapt model data to an application's presentation layer

The View Helper pattern specifies that you use helpers to adapt model data to the presentation layer of an application. Typically, the presentation layer contains several JSP (JavaServer Pages) pages. These pages consist of HTML and images used to present content to the user. A problem arises, however, when these pages need to display dynamic content stored in the model. You'd probably like to avoid embedding Java code within these pages to display model data, so you need to employ some helpers to do the work for you.

Recall from the previous chapter that the controller servlet attaches the model to the request as an attribute. To get at this model from within the JSP page, you have three choices. You could embed Java code as JSP scriptlets, you could use the EL, or you could use a helper to extract the data for you. In keeping with the idea of separating presentation from business logic, it makes sense to employ several helpers to adapt the model to the presentation rather than clutter the presentation code with Java code (see Figure 1).

Figure 1. View Helper pattern

As you can imagine, helpers make it a lot easier for page designers to develop the presentation layer by replacing Java code with simple-to-use helpers. Of course, developers can accomplish this only if they publish a catalog of the helpers and describe how to use them. However, if the page designers develop their pages before the application designer is ready to give them a model for the helpers with which to work, then there's a problem. A useful technique to address this problem is to code into the helper a set of dummy data to display when no model is present. An alternate approach would be to provide a dummy model with which to work. Either way, the page designer shouldn't be held up while waiting for the developers.

Using helpers has the following advantages:

  • Presentation components are standardized, creating a consistent look and feel for the application
  • Java code is abstracted away from page designers, giving them an easy-to-use set of helpers to access the model
  • You can create helpers to display dummy data if no model exists, thus letting page designers continue development regardless of the readiness of the application
  • Helpers provide a clean separation between presentation and business data by acting as intermediaries between the two

Implementing View Helper pattern strategies

When developing helpers for JSP pages, you have two choices. You could use either JavaBeans or custom tags. Which you choose really depends on the type of data you're trying to adapt. Typically, you use JavaBeans to extract individual pieces of data, and custom tags are better suited for working with sets of data. However, it's important to point out that you can use either for both types of data.

Implementing the JavaBean helper strategy

You can implement helpers as JavaBeans within a JSP page. These helpers are typically easy to use when extracting and formatting single text items. The built-in JSP tags that enable you to work with JavaBeans are simple and intuitive to use. Using JavaBeans involves simply declaring the bean and referencing it later using the special tags as follows:

 <%-- Declare bean --%>
<jsp:useBean id="myBean" class="jspBook.util.myBean"/>
<%-- Get first name from bean --%>
Hello <jsp:getProperty name="myBean" property="firstName"/>,
welcome to Acme Products' online store!

JavaBeans can do more than simply retrieve data items from the model. They can also format specific data items, perform calculations, or generate large blocks of content. Ideally, they're suited to retrieving data items using the built-in JSP tags. If you do much more with them, then your JSP pages may begin to get cluttered with too much Java code, no matter how much you try to use the EL. In that case, you may consider encapsulating any additional behavior inside a custom tag.

Implementing the custom tag helper strategy

For more complex model adaptations, custom tags have the ability to embed Java code and perform several iterations over the data while providing the page designer with a simple tag with which to work. To use custom tags, you write a class that extends either TagSupport or BodyTagSupport. You declare this class in a tag library descriptor as shown in Listing 1.

Listing 1. An Example TLD

 <?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
web-jsptaglibrary_2_0.xsd"
   version="2.0" >
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>myTags</short-name>
<description>
   Tag library to support the examples in Chapter 8
</description>
<tag>
   <name>myTag</name>
   <tag-class>jspbook.ch08.myTag</tag-class>
   <body-content>JSP</body-content>
   <attribute>
      <name>myAttribute</name>
      <required>yes</required>
      </attribute>
</tag>
</taglib>

This tag is then referenced inside the JSP page by first declaring it with the taglib directive and then by referencing the tag as follows:

 <%@ taglib uri="/helpers" prefix="helpers" %>
<helpers:myTag myAttribute="some value">
   Body text...
</helpers:myTag>

I prefer to use custom tags for most view helpers. They give the developer more access to the servlet context and offer some performance benefits when they're pooled within the application server. Another reason I like to use custom tags is that they're intuitive for a non-Java page designer. Their format is much like standard HTML tags, which by now have become second nature to most of us. Finally, you can use custom tags—once they're developed and debugged— across JSP pages in your application. If the tags are designed to be generic enough, you can package them as a tag library, which can be reused across applications.

Implementing the model separation strategy

Whether using custom tags or JavaBeans, it's sometimes useful to provide standalone helpers that can present a set of dummy data in place of the model when no model exists. This would enable page designers to complete their work independent of the development team. To implement this strategy, the helper needs to check for the existence of a model and then uses either the real model or a static copy of the model to operate on (see Figure 2).

Figure 2. Model separation strategy

To make this work, the static model needs to be an exact replica of the real model. It's not always easy to keep these two in sync with each other. An alternate, and sometimes preferable, strategy is to have the development team build dummy data into its models so that designers can do their work as if the real model exists, also ensuring that the model they're working with is always the correct one (see Figure 3).

Figure 3. Alternate model separation strategy

Applying the View Helper pattern

The following helpers you'll build may be useful to you at some point, but at the very least they should give you some ideas of how you can apply the View Helper pattern to your own applications. The following items are implemented as custom tags and are declared in the helpers.tld file. This file is associated with the /helpers taglib URI inside the web.xml file with an entry like this:

 <taglib>
   <taglib-uri>/helpers</taglib-uri>
   <taglib-location>/WEB-INF/tlds/helpers.tld</taglib-location>
</taglib>

Formatting text

I'll begin this section with a view helper for adapting numeric values to various date and currency formats. Although it may be simple to do this directly in the model, you may have several reasons to format these values in the view instead. For instance, you may need to display the same value in various localized formats, or maybe the content will be accessed via multiple devices that require a different way to present the data.

You could encapsulate various formatting functions within a custom tag that reads the value to be formatted from its body and then formats it based on an attribute you set in the tag. Listing 2 shows how you would describe this tag in your tag library descriptor file.

Listing 2. helpers.tld

 <?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
web-jsptaglibrary_2_0.xsd"
   version="2.0" >
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>helperTags</short-name>
   <description>
      Tag library to support the examples in Chapter 8
   </description>
   <tag>
      <name>FormatTag</name>
      <tag-class>jspbook.ch08.FormatTag</tag-class> 
      <body-content>JSP</body-content>
      <attribute>
         <name>format</name>
         <required>yes</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
   </tag>
</taglib>

The model for this tag could be just about anything, but, for this example, you'll create a static JavaBean containing two string objects to hold a date value and a currency value. You'll set these from your JSP page using the standard JSP setProperty tag. To accomplish this, of course, your JavaBean needs to define accessor methods for both string values. Listing 3 shows the code used to create this JavaBean.

Listing 3. FormattingModel.java

 package jspbook.ch08.beans;
import java.io.Serializable;
public class FormattingModel implements Serializable {
   private String dateValue;
   private String currencyValue;
   public FormattingModel () {}
   /* Accessor Methods */
   public void setDateValue (String _date)
   {
      this.dateValue = _date;
   }
   public String getDateValue ()
   {
      return this.dateValue;
   }
   public void setCurrencyValue (String _currency)
   {
   this.currencyValue = _currency;
   }
   
   public String getCurrencyValue ()
   {
      return this.currencyValue;
   }
}

The tag itself is a simple body tag extending the BodyTagSupport class. All the actual formatting code is inside the formatValue() method. This method is called from within the doAfterBody() method once the value has been retrieved. The result of the formatValue() method is written back to the page in place of the tag. You can format dates and currencies using classes found in the java.text package. Specifically, you can use the SimpleDateFormat and DecimalFormat classes.

The tag handler also provides a Locale object, along with an appropriate set method, to accommodate specific localization of the content. Because this tag is responsible for formatting date and currency values, it may be necessary to pass different locales to the formatting operations. Take a look at the code in Listing 4, paying special attention to the formatValue() method.

Listing 4. FormatTag.java

1 2 3 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more