Getting the Most Out of the Struts Tag Libraries

The popularity of JSP Custom Tags has been rapidly growing
since they were first introduced in the JSP 1.1
specification. The Struts framework, which was introduced in
2000, includes a set of Tag libraries that are instrumental
in harvesting the fruits of the Struts framework. This
article looks at some of the ways to get more out of those
tags and helps make sense out of a few of the more
complicated tasks.

Reaping the Benefits of JSP Custom Tags

The problems with straight JSP have been well documented.
With JSP for instance, it's very tempting to insert Java
code into the JSP. This makes maintenance of the page
somewhat more challenging, even if they do have a cool
sounding name like "scriptlets." And reuse for JSPs is
usually nothing more than copy and paste.

We all should know by now that JSP Custom Tags were created
to solve these problems and a few others. They are easier to
maintain because the logic is programmed in once place and
the construction of web applications is made simpler because
a non-Java designer can drop them into a JSP and instantly
see the results. Most popular JSP editors such as
DreamWeaver and WSAD support Custom Tag syntax and the
ability to step through them in a debugger.

The Tags themselves are built using Java, of course.
Inserting a Tag only requires embedding an XML-like fragment
into a JSP. When a JSP that contains one or more tags is
invoked, the servlet produced from JSP compilation
calls out to the appropriate Tag handler instance to perform
its logic. All invocations of the same Tag invoke the same
code. The better application's containers will create a pool
of tag instances and not create a new instance of the Java
class for every request. This helps to improve performance
in a manner similar to how an EJB container can reuse
Stateless Session bean instances.

Overview of the Struts Tag Libraries

The Struts framework provides a set of six built-in Tag
libraries that allow you to build the view part of the MVC
without embedding Java code directly within your application
JSPs.

The six Struts libraries are:

Bean Tags

HTML Tags

Logic Tags

Nested Tags

Template Tags

Tiles Tags

The Bean Tags

The Tags within the Bean Library are used for creating and
accessing JavaBeans and a few other general purpose uses.
Although these tags work with any standard JavaBean, they
are often used with Objects that extend the Struts
ActionForm class. Table 1 lists the tags within the Bean Library.

Table 1. Tags within the Struts Bean Tag Library

Tag Name

Description

cookie

Define a scripting variable based on the
value(s) of the specified request cookie.

define

Define a scripting variable based on the
value(s) of the specified bean property.

header

Define a scripting variable based on the
value(s) of the specified request header.

include

Load the response from a dynamic application
request and make it available as a bean.

message

Render an internationalized message string to
the response.

page

Expose a specified item from the page context
as a bean.

parameter

Define a scripting variable based on the
value(s) of the specified request parameter.

resource

Load a web application resource and make it
available as a bean.

size

Define a bean containing the number of
elements in a Collection or Map.

struts

Expose a named Struts internal configuration
object as a bean.

write

Render the value of the specified bean
property to the current JspWriter.

Two of the most often used Tags from Table 1 are the message
and write Tags.

The HTML Tags

The Tags within the Struts HTML Tag Library are used to
create input forms for your application. There are also a
few other useful Tags used in the creation and
rendering of HTML-based user interfaces. The Tags included
within the HTML Library are shown in Table 2.

Table 2. Tags within the Struts HTML Tag Library

Tag Name

Description

base

Render an HTML <base> Element

button

Render a Button Input Field

cancel

Render a Cancel Button

checkbox

Render a Checkbox Input Field

errors

Conditionally display a set of accumulated error messages

file

Render a File Select Input Field

form

Define an Input Form

frame

Render an HTML frame element

hidden

Render a Hidden Field

html

Render an HTML <html> Element

image

Render an input tag of type "image"

img

Render an HTML img tag

javascript

Render JavaScript validation based on the validation rules loaded by the
ValidatorPlugIn

link

Render an HTML anchor or hyperlink

messages

Conditionally display a set of accumulated messages

multibox

Render a Checkbox Input Field

option

Render a Select Option

options

Render a Collection of Select Options

optionsCollection

Render a Collection of Select Options

password

Render a Password Input Field

radio

Render a Radio Button Input Field

reset

Render a Reset Button Input Field

rewrite

Render an URI

select

Render a Select Element

submit

Render a Submit Button

text

Render an Input Field of Type text

textarea

Render a Textarea Field

xhtml

Render HTML tags as XHTML

Most all of the Tags within the HTML Tag library must be
nested within the Struts Form Tag.

The Logic Tags

The Logic Tag Library contains tags that are helpful with
iterating through collections, conditional generation of
output, and application flow. Table 3 lists the Tags within
the Logic Library.

Table 3. Tags within the Struts Logic Tag Library

Tag Name

Description

empty

Evaluate the nested body content of this tag if the requested variable is either null or an empty string.

equal

Evaluate the nested body content of this tag if the requested variable is equal to the specified value.

forward

Forward control to the page specified by the specified ActionForward entry.

greaterEqual

Evaluate the nested body content of this tag if the requested variable is greater than or equal to the specified value.

greaterThan

Evaluate the nested body content of this tag if the requested variable is greater than the specified value.

iterate

Repeat the nested body content of this tag over a specified collection.

lessEqual

Evaluate the nested body content of this tag if the requested variable is greater than or equal to the specified value.

lessThan

Evaluate the nested body content of this tag if the requested variable is less than the specified value.

match

Evaluate the nested body content of this tag if the specified value is an appropriate substring of the requested variable.

messagesNotPresent

Generate the nested body content of this tag if the specified message is not present in this request.

messagesPresent

Generate the nested body content of
this tag if the specified message is
present in this request.

notEmpty

Evaluate the nested body content of this tag if the requested variable is neither null, nor an empty string, nor an empty java.util.Collection (tested by the .isEmpty() method on the java.util.Collection interface).

notEqual

Evaluate the nested body content of this tag if the requested variable is not equal to the specified value.

notMatch

Evaluate the nested body content of this tag if the specified value is not an appropriate substring of the requested variable.

notPresent

Generate the nested body content of this tag if the specified value is not present in this request.

present

Generate the nested body content of this tag if the specified value is present in this request.

redirect

Render an HTTP Redirect.

The Nested Tags

The Nested Tags were added to Struts during development of
the 1.1 release. They extend the existing Tags functionality
by allowing the Tags to relate to each other is a nested
fashion. This is most useful when dealing with Object
graphs.

The Nested Tags don't add any additional functionality over
the Struts standard Tags other than to support the nested
approach. For each Tag in the Bean, HTML, and Logic
libraries, there is an equivalent nested Tag.

The Template Tags

The Template Tag Library was created to reduce the
redundancy found in most web applications. In most web
sites, there are sections within multiple pages that are
exactly the same. The header, menus, or footers are three
obvious examples. Instead of duplicating the content in each
page and having to modify all pages when something like the
look and feel changes, Templates allow you to have the
common content in one place and insert it where necessary.

However, since the Tiles framework was introduced, the
Template Tags have been deprecated and developers are
encouraged to use Tiles.

Tiles Library Tags

As mentioned earlier, the Tiles framework is now integrated
into the core Struts framework. Tiles is similar to the
Template Tags except that it adds much more functionality
and flexibility. For instance, Tiles supports inheritance
between Tiles and allows you to define layouts and reuse
those layouts within your site. They also support different
Tiles and layouts based on I18N and channel. The Tags with
the Tiles Library are shown in Table 4.

Table 4. Tags within the Struts Tiles Tag Library

Tag Name

Description

add

Add an element to the surrounding list. Equivalent to 'put', but for list element.

definition

Create a tile/component/template definition bean.

get

Gets the content from request scope that was put there by a put tag.

getAsString

Render the value of the specified tile/component/template attribute to the current JspWriter.

importAttribute

Import Tile's attribute in specified context.

initComponentDefinitions

Initialize Tile/Component definitions factory.

insert

Insert a tiles/component/template.

put

Put an attribute into tile/component/template context.

putList

Declare a list that will be pass as attribute to tile.

useAttribute

Use attribute value inside page.

Collections, Maps, and the Iterate Tag

There are often times within a Struts application that you
must display a collection of objects to the user. The
scenario usually goes something like this: for each item in
the collection, display one or more attributes from the
object. For example, in a page that renders a classic
shopping cart, each Object represents one item that has been
added to the cart. Figure 1 shows an example of a shopping cart
page.

Figure 1. A Shopping Cart page showing multiple items

Using JSP without Struts, this functionality would most
likely be accomplished with some rather unattractive looking
Java Scriptlets using loops. With the Struts Iterate Tag, it
becomes somewhat innocuous and much easier to manage over
the lifetime of the application.

The following example code snippet shows what this might
look like using the Iterate Tag from the Logic library.

Looking at this snippet from a JSP, you might be inclined to
comment on how formidable it appears. You should however
quickly recognize that with the exception of a few Struts
tags, most of the text is HTML; which is how it should be.

Using collections is rather straightforward. However, if
your data is for some reason stored within an instance of a
java.util.Map, getting at the properties in the map is a
little trickier, but nonetheless solvable with the Iterate
Tag. Using the Iterate Tag, we can iterate through the Map
and access each element. Normally each Object that you
iterate over is an element of the underlying collection, a
ShoppingCartBean, for example. However, when iterating over a
Map instance, the Object is of type java.util.Map.Entry.

As the Struts documentation describes, Map.Entry has two
properties:

Key: The key under which the item is stored in the Map.

Value: The value associated with the key.

Let's say you are using a Struts ActionForm (standard
or a dynamic) and it contains a property named "usermap"
that is declared as a Map and instantiated as a
java.util.HashMap. In this Map, the key is a unique user ID
and the value is a String representing the users encrypted
password. Figure 2 illustrates what this would look like.

Figure 2. Data Structure for Example 2

The following code fragment shows an example of iterating
through this Map and writing out the two values.

As you can see from this JSP fragment, using the Iterate Tag
with Maps is not much different than with Collections. The
primary distinction is that of using the key and value
attributes to access the data stored within the Map. Once
you have references to this data, you can use it within the
Iterate block just as you would with anything else.

Formatting Errors with the Errors Tag

Let's face it, as hard as you try to make GUIs user-friendly
and bulletproof, end users make mistakes. One of the most
common mistakes is incorrect data entry. Your applications
need to be very careful when accepting input from users in
order to ensure the integrity of the datastore is
maintained; Struts applications are no exception. Data
entered from the browser must be validated and if errors are
found, information needs to be displayed to the user
describing what the problems are and what steps to take
next.

The Struts framework includes the ability to catch errors
and populate an Errors collection that can be accessed from
within the JSPs. This is made even easier when using the
Validator framework. Whether you're doing programmatic or
declarative validation, the Errors collection is inserted
into the request and available to a JSP. You can use either
the Messages or the Errors Tag
(depending on which type of
validation problems occurred) to access the messages to
display to the users.

Both of the Messages and Errors Tags
support an "id"
attribute that is used to store the current error while
looping through the collection of problems. In a very simple
approach you can use the following within your JSP:

This fragment would print out each message from the problem
collection inside an HTML list.

There's a header and footer entry that you can pull from the
resource bundle, which allows you to provide some text to
the beginning and end of the errors respectively. The
following fragment shows the usage of the errors.header
element.

Dealing with Dates and Currencies

The Java language provides within its core libraries, the
ability to deal with Dates and Currencies. One of the most
sought after requirements is to format a Date or a Currency
value based on a Country or Language. Java provides the
java.util.Locale class, which encapsulates the country and
language and makes it easier for applications to understand
and deal with geographical differences.

The Struts framework makes use of this by storing the Locale
for a user in the HttpSession, which is created the first
time a request is received from a user. This functionality
can be turned off in Struts, but it's on by default.

Once the Locale is stored in the user's session, the
framework can make decisions about which localization is
performed. For example, the Struts framework will chose a
resource bundle that best matches the user's Locale. This
makes it somewhat easier to brand a site because localized
text can be rendered automatically be the framework.

Many of the Tags also support this I18N functionality. For
example, the Message Tag within the Bean Library uses the
Locale to automatically pull text from the proper bundle.
However, there are some additional ways you can format
text output. The Write Tag has a format attribute that you
can use to format currency in a particular format. Suppose
that I wanted to display currency in the following manner:

X,XXX.XX

Which is specific to mostly U.S. markets, then I could use the
Write Tag this way:

<bean:write
name="cartItem"
format="#,##0.00"
property="unitPrice"/>

Although this works, there's actually a more portable way of
doing this to support multiple formats. There's an attribute
called formatKey on the Write Tag that will pull the format
from the resource bundle. The Tag entry would look like the
following:

Doing it this way allows each resource bundle to specify a
currency format specific to its Locale.

Displaying Checkboxes with the Options Tag

One of the seemingly easiest things to do with HTML may be
one of the hardest to do when building dynamic pages. That
is rendering of checkboxes for an application; there are a
few reasons why this is true.

First, checkboxes indicate checked/unchecked on/off, or true/false, depending on how you look at it; it's a binary
condition. In the Java world, you would think this needs to
be represented as a primitive boolean or a class
java.lang.Boolean. However, since all values are sent from
the browser to the server as Strings, this complicates
things a bit. That means that something needs to convert the
String "on" or "true" to its Boolean equivalent.

The second non-obvious thing is how browsers treat
checkboxes when updating the server. If a checkbox is
checked, then a value is sent to the server like name="on",
where "name" is the name given to the checkbox in the HTML
form. Well, guess what is sent to the server when the
checkbox isn't checked? You would think name="off" or
name="false", right? Actually nothing is sent. Therefore the
application can have a tough time understanding what's going
on with the checkboxes on the pages.

The Struts Checkbox Tag renders an HTML checkbox and will
automatically check or uncheck it depending on the state of
the Boolean value of the ActionForm associated with the
page. You have to remember that if the checkbox is unchecked
by the user, no notification will be sent and you must take
this into account. (Hint: One of the easiest ways to think
about this is if you don't receive a value, then it must be
unchecked!)

When you have a large number of related checkboxes, you
should consider storing the values within an array and use
the Multibox Tag.

Switching to the Java Standard Tag Library (JSTL)

The use of the Struts Tag libraries is a great movement
forward toward smarter and faster development of web
applications. However, Struts isn't cornering the market on
the use of JSP Tags. Other frameworks use Tags and you don't
have to use Struts to get the benefits of JSP Custom Tags.

In order to standardize some of the more useful Tags, Sun
and other participants created an initiative and formalized
the most commonly used Tags. This initiative was turned into
JSR-52, which has now released 1.0. Java Standard Tag
Library (or JSTL as it's known), provides a specification for
four separate areas of concern:

Core

XML Processing

Internationalization

Database

The specification also describes an expression language (EL)
that is designed to simplify page development. As you might
imagine, there is some overlap with some of the Tags
provided by the Struts library. For example, looping, error
handling, and conditional logic is provided by JSTL as well
as Struts. The question is "which set of tags should I use?"
The answer is to use the JSTL Tags where possible. For
existing code, it's probably not worth the risk to change.
However, for new JSPs you should be looking at the JSTL for
Tag functionality. Struts 1.1 even includes a version of the
JSTL Tags based on the new Expression Language. Something
definitely to keep you eye on in future versions of Struts.