Documente Academic
Documente Profesional
Documente Cultură
.................
Advanced search
IBM home | Products & services | Support & downloads | My account
Learn the ins and outs of custom tag library communication Contents:
Brief overview
Jeff K. Wilson (wilsonje@us.ibm.com)
E-business architect, IBM Controlling presentation
January 2002 logic, not just style
JavaServer Pages technology serves a crucial function for Web developers, but many Benefits and examples
don't leverage its full power. Author Jeff Wilson, e-business architect (and member of
Example custom tags
the esteemed DragonSlayers team at IBM), shows you how to customize JSP tags to get
even more out of this technology. Using the techniques he details in this article, you can Wrapup
add more complex logic to your JSPs, take firmer control of data display, and share data Resources
among tags -- all without having to teach your front-end Web developers how to write
Java code. The article includes sample tags and tag-handling classes to give you a feel About the author
for how it all works. Share your thoughts on this article with the author and other readers Rate this article
in the discussion forum by clicking Discuss at the top or bottom of the article.
If you are involved with Web development at all, you're well aware of the fact that Web-based Related content:
applications today require more dynamically generated content and personalized data than ever JSP taglibs: Better usability
before. Architecting a user-friendly interface means that the front-end developer must not only by design
be proficient in the skills of visual design but also in managing and utilizing the flow of
content. Also in the Java zone:
Tutorials
Custom JSP tags give those front-end developers the means to control how data is processed in
back-end Java components without requiring any Java code in the JSP page. Tools and products
Code and components
In this article, we will be focusing on how custom tags communicate with each other, and how
combining them increases reusability and flexibility. We will also walk through a few Articles
examples.
Brief overview of custom tags
Custom tags are more advanced and flexible than typical JSP tags like <jsp:useBean .../> and
<jsp:getProperty .../>. One key benefit that custom tags have over typical JSP tags is that by using custom tags,
JSP developers can pass input through by placing data either in tag attributes or between opening and closing tags.
Custom JSP tags are composed of three parts:
● The JSP page that the tag is used in
● The tag library descriptor, an XML file that groups tags into a "library" and describes the specifics about each tag,
such as its attributes, the tag handle name, short name, and so forth
Custom tags can be configured to run their processes based on the input supplied through a tag's attributes, eliminating the
need for embedded Java code within the JSP page.
Let's look at an example. Listing 1 shows a shopping cart tag that produces one table row for every product selected by a
user:
Listing 1. Shopping cart tag
In this case, the tag handler class expects both HTML and the user's ID to be passed in as a template for the resulting output
(a table row, in this case). The various $_product... references will be replaced by actual values from the products
looped through in the tag handler -- the Java class that implements the tag.
This demonstrates another key benefit of custom tags: Java programmers don't need to know how to format the data before
sending it back to the client. Additionally, as new pages are developed that require data that is similar in content but
formatted differently, or as the look of current pages change, the Java components won't need updating.
Controlling presentation logic, not just style
Another very important advantage of custom tags is their ability to communicate with other tags on the same page. With
traditional JSP tags, developers can set properties to control the behavior of a JavaBean component, but the bean simply does
what it does on its own. By breaking down processes into smaller components, JSP developers can mix and match custom
tags to build more complex processes for greater control of dynamic content.
Using the output of one custom tag as the input for another increases the tags' reusability. For instance, in our previous
example, the user shopping cart tag held all the information about the products purchased. A better design might have the
user tag hold only product IDs and let another tag -- a product tag -- manage the product data as needed. Once you separate
out the process that collects the details of a product, you have a product tag that can be used with other tags for other
purposes.
This produces an object-oriented approach to controlling the dynamic data that is retrieved -- and front-end developers can
follow this approach without knowing any programming.
The code in Listing 2 shows this approach in action. Also, notice that the user's shopping list tag implements another tag,
called error:setErrorTemplate. If no products are found in this example, we might want to show an error message.
It's easy to see that the two-column table needed for our product list won't be that appropriate for an error message.
Listing 2. Object-oriented approach
The tag handler class can be designed to handle alternate formatting under certain predefined circumstances. This is a good
example of how JSP developers can control the logical flow of the data without using if statements or other Java code in the
JSP page. With the custom tag, the JSP developer can decide how to determine what gets displayed, not just how it is
displayed.
In another situation, the same product data tag can be reused with other tags that list products. Notice in Listing 3 that not
only does another tag (<products:getProductData category="fitness">) initiate the list, but the output will
be formatted differently, because different HTML is passed into the tag.
Listing 3. Product data tag used with product list
No special setup or coding is required to put one tag within another. A tag can be nested in one place and on its own in
another. Some tags, of course, will be designed to be nested within others, but nothing is explicitly required to declare a tag
as nestable.
You can think of HTML table, table row, and table cell tags as nested tags. An example of shared data in table tags is the
table's background color (the bgcolor attribute). If the background is set in the table tag <table
bgcolor="blue">...</table>, all the rows and cells will be set to blue unless the bgcolor attribute is overridden
by an individual tag (for example, <table bgcolor="blue">...<td
bgcolor="red">...</td>...</table>).
In its most basic implementation, the evaluated inner tag may simply be body input for the outer tag. However, a nested tag
might also reference the tags that enclose it (such as parent tags and grandparent tags), allowing linked classes to call each
If the current tag was not enclosed in a tag whose tag handler was the class specified (TableTag.class, in this case) or if
getParent() was called and it had no parent at all, both methods would return null.
Referencing tags with IDs
Another way to share data is to register a class with an ID that can then be retrieved by another tag's handler class. Using this
method, a JSP developer cannot simply set an ID in any custom tag if the tag is not specifically programmed to accept it.
An ID property is already declared within TagSupport for this very purpose and available to any tag handler class.
However, to use the ID property to store the object for other tags to access, two steps must be taken:
1. An ID attribute must be specified in the tag library descriptor (the required node can be set to either true or false).
2. The tag handler must specifically set itself to an attribute of the pageContext.
Sharing tag objects with registered IDs may be necessary if the tags cannot easily be nested.
Let's refer back to our example of a user's shopping cart. Consider that the <user:getUserShoppingList .../> in
Listing 4 below holds various information about a shopping list, including a method that returns a list of product IDs called
getProductIds(). Somewhere else in the JSP page, the <products:getProductData> ...
</products:getProductData> tag will take a list of product IDs, retrieve product details for each product, and
format them before sending them back to the client.
The user:getUserShoppingList tag will execute and store itself as an attribute of the pageContext named
userShoppingList. The product:getProductData tag will retrieve the value of the attribute and call the method
getProductIds() from the getUserShoppingList object.
Listing 4. getUserShoppingList
The tag library descriptor for the tag getUserShoppingList might look like Listing 5:
Listing 5. Library descriptor for getUserShoppingList
<tag>
<name>getUserShoppingList</name>
<tagclass>com.taglib.UserShoppingListTag</tagclass>
<bodycontent>JSP</bodycontent>
<attribute>
<name>userId</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
The getShoppingList tag handler would contain the following line once the tag completed all of its processing (perhaps
in the doEndTag() method):
pageContext.setAttribute(getId(),this);
getId() retrieves the ID set in the tag (userShoppingList) and this refers to the entire class itself.
Once the userShoppingList tag is stored in the pageContext, the getProductData tag handler class can access
it using the ID passed into it with the productData attribute. The handler class of the getProductData tag will use
that ID (retrieved with the method getProductData()) to find the attribute in the pageContext and cast it back into a
UserShoppingListTag object. The code in Listing 6 declares a List called productList and calls the user class
method getProductIds() to extract the product list.
Listing 6. Extracting a product list
UserShoppingListTag userShoppingList =
(UserShoppingListTag)pageContext.getAttribute(getProductData());
List productList = (List)userShoppingList.getProductIds();
This technique would work for shopping list tags and others, like a tag that calls sale items or products from a given
category.
If the data were stored in a session, it would like this:
<HTML>
<HEAD>
<TITLE>Custom Tag Communication</TITLE>
</HEAD>
<BODY bgcolor="#ffffff">
<!-- SET THE LOGIN HTML BASED ON WHETHER OR NOT THE USER IS LOGGED IN -->
<!-- ONE OF THE NESTED NODES WILL BE DISPLAYED ACCORDINGLY -->
<goforit:nestedLogin userDataID="user">
<goforit:isLoggedIn>
<!-- THE HTML IN THIS NODE IS DISPLAYED IF THE USER IS LOGGED IN -->
</goforit:isLoggedIn>
<goforit:notLoggedIn>
<!-- THE HTML IN THIS NODE IS DISPLAYED IF THE USER IS NOT LOGGED IN -->
</goforit:notLoggedIn>
<goforit:loginFailure>
<!-- THE HTML IN THIS NODE IS DISPLAYED IF THERE WAS A LOGIN ERROR -->
</goforit:loginFailure>
</goforit:nestedLogin>
</BODY>
</HTML>
<tag>
<name>getUserData</name>
<tagclass>com.taglibrarycommunication.taglib.GetUserDataTag</tagclass>
<info></info>
<bodycontent>JSP</bodycontent>
<attribute>
<name>id</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
<tag>
<name>nestedLogin</name>
<tagclass>com.taglibrarycommunication.taglib.NestedLoginTag</tagclass>
<info></info>
<bodycontent>JSP</bodycontent>
<attribute>
<name>userDataID</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
session = pageContext.getSession();
return SKIP_BODY;
}
NestedLoginTag
This class, shown in Listing 11, determines which of three properties are returned to the client, based on whether or not the
user is logged in or if there is an error. The values of these three properties are determined by other tags nested within the
class in the JSP page. NestedLoginTag determines which tag to display by first pulling in the user registered to the
pageContext in the previous tag. It then attempts to retrieve the username and any error that might have occurred. If both
are blank, it assumes that the user has not logged in. If the error message is not blank, clearly an error occurred. If the user's
name was set, the user was successfully logged in.
Listing 11. NestedLoginTag
...
if (getUserName()!="" &&
getLoginError()==""){
// IF userName IS SET PERSON IS LOGGED IN
pageContext.getOut().print(getIsLoggedInHTML());
} else {
if (getLoginError()=="")
// IF NO userName SET BUT NO loginError SHOW LOGIN
pageContext.getOut().print(getNotLoggedInHTML());
else
// IF loginError SHOW LOGIN AND ERROR
pageContext.getOut().print(getLogInFailureHTML());
if (parent != null){
BodyContent bc = getBodyContent();
String body = bc.getString();
GetUserDataTag userData =
(GetUserDataTag) pageContext.getAttribute(getUserDataID());
...
if (userData.getUserName() !=null){
pageContext.getOut().print(userData.getUserName());
}
Wrapup
JSP pages separate client-side display from server-side logic, and put the power of Java technology at the disposal of Web
designers who may not be Java programmers. By using custom tags, you can give more choices to developers working on
both tiers of a Web application, and impose an object-oriented approach on Web developers that will encourage the reuse of
code modules and tags. Once you've examined the sample tag library included with this article, you should be ready to start
using custom tags with your own applications.
Resources
● Participate in the discussion forum on this article by clicking Discuss at the top or bottom of the article.
● You can download all the code for this article to help you get started on your own custom tag library.
● In "JSP taglibs: Better usability by design" (developerWorks, December 2001), Noel J. Bergman teaches you how to
get the most out of the Java taglib facility.
● Using VisualAge for Java and WebSphere Studio? Find out how to integrate JSPs and custom tags into your projects
in this article from the WebSphere developer domain.
● If you're using custom tag libraries with VisualAge for Java, this article can show you how to fully unit-test your code.
● JSPTags.com offers a directory of resources related to JavaServer Pages, with an emphasis on JSP tag libraries.
● This article, " Custom JSP Tags and JSP Tag Libraries" at the Lotus Developer Network, offers a good overview of
implementing custom tags.
● Apache maintains Jakarta Taglibs, an open-source repository for JSP custom tag libraries.
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)
Send us your comments or click Discuss to share your comments with others.
Submit feedback