10.5 Making it easier on the JSP author
As convenient as the JSP might be in listing 10. 14, there is still something that bothers
us from a usability standpoint; namely, the printing of the value of a bean property
to the user is too cumbersome. To illustrate, look at the following JSP fragment:
<iter:iterate name=" cart" property=" products" id=" product">
<tr>
<td>< bean:show name="product" property="name"/> </td>
<td>< bean: show name="product" property="quantity"/></td>
<td>< bean: show name="product" property="dollars"/>.
<bean: show name="product" property=" cents"/>$</td>
</tr>
</ iter:iterate>
Seeing all those <bean:show> tags begs the question: why do we need so much
overhead associated with using the bean tag and pointing to the property in the
product? We know that we are interested in the product object (since we're iterating
on it) yet our <bean:show> tag forces us to pass it as a name attribute for every
property we print to the user. Can't we make access to bean-based, nonindexed
properties in an iterator less complicated (or friendlier)? We can, but how?
Improving access to nonindexed JavaBean properties
The first thought that comes to mind is to create a tag with a single attribute that
points to the property name. When running, this tag will fetch the iterator object
from the iteration tag and query its property value. The following JSP fragment
shows a revised version of the previous JSP fragment that uses this simplified tag.
<iter:iterate name="cart" property="products" id="product">
<tr>
<td>< bean:showp property=" name"/> </td>
<td>< bean:showp property="quantity"/></td>
<td>< bean:showp property=" dollars"/>.
<bean:showp property=" cents"/>$</td>
</tr>
</ iter:iterate>
This is an improvement; however, we still are not entirely satisfied with the new JSP
fragment, largely because the number of keystrokes we've saved is not especially significant.
To make the syntax for retrieving a property extremely terse, we don't
want to use a tag at all; we want something that is even more minimal. Syntax such
as the following is clearly an improvement for the JSP author, especially if they're
building a number of JSPs with property access in iterators.
<iter:iterate name="cart" property="products" id="product">
<tr>
<td> <$ name $> </td>
<td> <$ quantity $> </td>
<td> <$ dollars $>.<$cents$>$ </td>
</tr>
</ iter:iterate>
In this JSP fragment we no longer use tags to present the property values of the iterator.
Instead, a property value in the current iterator is referenced by using a special
directive with field placement syntax <$ property-name$>. Using this field
placement could be a time-saver, but how would we implement it? Up to this point,
everything we created was a tag; this new proprietary directive is not. The way to
implement this functionality is to modify our iteration tags to perform a pass on
their body content and translate these field placement directives into values that
should replace them. By processing the body in this way, we can easily swap any special
directive we want with some other value; in this case, the value of a JavaBean's
nonindexed property.
10.5.1 Building a better tag
Remember that the iterator tags implement the BodyTag interface; hence, the iteration
tags can have direct access to their body before they write it to the response
stream. All the tag has to do is implement some body parsing in doAfterBody(), in
which the tag will replace our field placement directives with the actual field values.
Implementing the substitution of field placement directives with their actual values
should be done in a generic manner, for several reasons:
- It is not safe to assume that we will always want to use the field placement
directives. For example, certain users may not want to use proprietary syntax. In such cases we do not want to take the performance penalty associated with
parsing the body. Thus we require the ability to disable/ enable substitutions on the fly.
- We can imagine many different objects on which we may iterate, as well as
many field types that we may want to show, from JavaBean properties to data-base
columns. We want to build a generic solution such that we do not implement
the body parsing differently for each case. .
- We may develop many different iteration tags and most of them will need the (extremely nifty) field substitution feature, and we do not want to implement
the related substitution logic more than once.
10.5.2 The design
To attain these goals, we distribute the implementation of the field substitution into
the following units:
- Body parsing— This part of our solution searches for field references and
identifies them. We'll implement this functionality in
IterationTagSupport, our iteration tag superclass. This will make all tags derived from IterationTagSupport
capable of performing field substitution. .
- Field fetching— This is the part of our solution that retrieves a field's value
when one is found. Whenever
IterationTagSupport parses and identifies a
field reference, it will use an object that implements an interface we'll call FieldGetter.
This interface will allow us to get the value of the referenced
field from the current iterator. Since FieldGetter will be an interface, we
can create many different implementations of it, such as one that fetches a
database column value, or another that gets bean properties. This will
become clearer when we see the code.
- Setting the
FieldGetter— Combining the first two portions of our design, we see that any specialized implementation of IterationTagSupport will
need a specialized version FieldGetter, corresponding to the type of objects the iterator contains. The specialized iteration tag will know the type of
objects that it exposes as iterators and will therefore know what type of FieldGetter to use. If no FieldGetter is used, the tag will not implement
any field substitution, hence avoiding the associated performance costs from parsing the body. This accomplishes our previously mentioned goal of making
the field substitution optional for performance reasons.
This design should accomplish all our defined goals. Our abstract design will become
much more comprehensible as we look at our implementation and an example.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|