|
|
|
Contents: |
|
|
|
Related content: |
|
|
|
Subscriptions: |
|
|
| Convert scriptlets to custom tags for better JSP
code
Brett
McLaughlin (mailto:brett@oreilly.com?cc=&subject=Intro
to taglibs) Author, O'Reilly and Associates 23 July 2003
Scriptlets are good for fast-and-dirty
coding, but in the long run you need a less cluttered solution for your
JSP pages. In this installment of JSP best practices, Brett
McLaughlin shows you how to convert a scriptlet into a JSP custom tag,
add it to a custom tag library, and begin using it in your JSP
development.
In the last
installment of JSP best practices, you learned a
scriptlet-based technique for adding last-modification time stamps to your
JavaServer Pages (JSP) files. Unfortunately, scriptlets introduce more
long-term complexity to your pages than they offer in terms of short-term
benefit. They interweave all sorts of HTML with Java code, which makes
debugging and authoring tricky. They aren't reusable, which often leads
developers to cut-and-paste between JSP pages, which in turn leads to
multiple versions of the same piece of code. And they make error reporting
difficult, since JSP pages have no clean-cut way to spit out script
errors.
So this time we'll devise a better solution. In this installment,
you'll learn the basics of converting a scriptlet to a custom tag and
setting it up for use in your JSP development projects.
Why taglibs? A tag
library is a library of tags that can be used in your JSP pages. JSP
containers comes with a small, default tag library. A custom tag
library is a library that has been put together for a specific use or
purpose. Developers working together in a team might create very specific
custom tag libraries for individual projects, as well as a more general
one for ongoing use.
JSP tags replace scriptlets and alleviate all the headaches that come
with them. For example, you might see tags like this:
<store:shoppingCart id="1097629"/>
|
or this:
Each tag contains a reference to a Java class but keeps that code
exactly where it belongs: out of the page and in a compiled class
file.
From scriptlets to
tags The first step in creating a custom tag is to decide
how you want it to be used, what you will call it, and what (if any)
attributes it should allow or require. In the case of the time-stamp tag,
our needs are pretty simple: we want a simple tag that outputs the
last-modification date of a page.
Because no attributes are required the tag can look something like
<site-utils:lastModified />
|
The name and prefix of the tag are the same: site-utils .
The element's content is empty, meaning no child elements are allowed
within it. After you've defined the tag, the next step is to implement its
behavior.
Implementing
behavior The first step to implementing tag behavior is to
move our scriptlet code from the previous installment into a Java class
(LastModifiedTag ), as shown in Listing 1: Listing 1. Creating a time-stamp tag
package com.newInstance.site.tags;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.tagext.TagSupport;
public class LastModifiedTag extends TagSupport {
public int doEndTag() {
try {
HttpServletRequest request =
(HttpServletRequest)pageContext.getRequest();
String path = pageContext.getServletContext().getRealPath(
request.getServletPath());
File file = new File(path);
DateFormat formatter = DateFormat.getDateInstance(
DateFormat.LONG);
pageContext.getOut().println(
formatter.format(new Date(file.lastModified())));
} catch (IOException ignored) { }
return EVAL_PAGE;
}
}
|
The code in this method should look familiar; it's essentially the same
time stamp code we worked with in the previous installment. Because no
user input is required, and the tag has no attributes or nested content,
the only new method we need to worry about is doEndTag() ,
which is where the tag can output content (in this case the
last-modification date) to a JSP page.
Other changes in Listing 1 have to do with the code being a JSP tag
rather than a scriptlet operating within a page. All JSP tags, for
example, should extend the JSP class
javax.servlet.jsp.tagext.TagSupport , which provides the basic
framework for JSP tags. You might also notice that the tag returns
EVAL_PAGE . EVAL_PAGE is a pre-defined integer
constant that instructs the container to process the rest of the page.
Another option would be to use SKIP_PAGE , which aborts
processing for the rest of the page. You need only to use
SKIP_PAGE if you are passing off control to another page,
such as when you forward or redirect the user. The rest of the details are
specific to the time stamp itself.
Next, we compile this class and place the LastModifiedTag.class file in
a WEB-INF/classes directory, within its proper path hierarchy. This path
should match the package name of the tag, replacing the dots
(. ) in the package name with slashes (/ ). In our
case, the directory path is the base (WEB-INF/classes) plus the hierarchy,
com/newInstance/site/tags. If you had a tag called
foo.bar.tag.MyTag , it would go in
WEB-INF/classes/foo/bar/tag. This path hierarchy ensures that the Web
container can locate the class whenever it is called upon to load the
tag.
Creating a TLD The
next step is to create a tag library descriptor (TLD) file. The TLD
describes your tag library to the container and any JSP pages that may use
it. Listing 2 shows a fairly standard TLD, containing only one tag. The
length and complexity of your TLD file will grow as you add more tags to
the library. Listing 2. A tag library
descriptor
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2/EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>site-utils</short-name>
<uri>http://www.newInstance.com/taglibs/site-utils</uri>
<tag>
<name>lastModified</name>
<tag-class>com.newInstance.site.tags.LastModifiedTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
|
The information at the top of the TLD file applies to the entire tag
library. In this case, I've supplied a version (useful for tracking which
version of a library JSP authors have, especially if you modify the
library often); the JSP version the library depends on; a recommended
prefix for the library; and the URI that the library is known by. Notice
that I have used the prefix short-name as part of my URI,
making it easy to visually connect the prefix to the library URI.
The rest of the information applies to a specific tag, denoted with the
tag element. I've specified the name of the tag, the class
for the tag (which should be compiled and in-place for container loading),
and finally whether the tag has any nested content. In this case, it does
not, so the "empty" value is used.
Save this file and place it in your WEB-INF/tlds directory (you may
have to create this directory in your container). I saved mine as
site-utils.tld, again creating a clear link between the library's URI,
suggested prefix, and the TLD file itself. The final step in making your
library available is to let your Web application know how to connect the
URI in a JSP page, requesting usage of a tag library, with this specific
library. This is done through the web.xml file for your application.
Listing 3 shows a very simple web.xml fragment, which does just this for
our tag library: Listing 3. Linking a URI to a tag
library
<taglib>
<taglib-uri>http://www.newInstance.com/taglibs/site-utils</taglib-uri>
<taglib-location>/WEB-INF/tlds/site-utils.tld</taglib-location>
</taglib>
|
Wrapping up If you've
followed along with each step so far, you should now be able to reference
your new tag in a JSP page. Listing 4 shows our new-and-improved
footer.jsp, completely devoid of scriptlets or references to JSP pages
that have scriptlets: Listing 4. Using the new tag
library
<%@ taglib prefix="site-utils"
uri="http://www.newInstance.com/taglibs/site-utils" %>
</td>
<td width="16" align="left" valign="top"> </td>
</tr>
<!-- End main content -->
<!-- Begin footer section -->
<tr>
<td width="91" align="left" valign="top" bgcolor="#330066"> </td>
<td align="left" valign="top"> </td>
<td class="footer" align="left" valign="top"><div align="center"><br>
© 2003
<a href="mailto:webmaster@newInstance.com">Brett McLaughlin</a><br>
Last Updated: <site-utils:lastModified />
</div></td>
<td align="left" valign="top"> </td>
<td width="141" align="right" valign="top" bgcolor="#330066"> </td>
</tr>
</table>
<!-- End footer section -->
|
After seeing how JSTL worked in previous installments (see "Update
your JSP pages with JSTL" and "Import
content to your Web site"), the next step should be clear to you: we
reference the tag library using the URI from the web.xml file, assign it a
prefix (the short-name from the TLD is always the best
choice), and then use the library just like any other JSP tag. The result
is a cleaner, better JSP page, which works just as well as it did when
scriptlets were involved.
In the next installment, we'll extend the functionality of our current,
rather simple, custom tag. Until then, see you online.
Resources
About the
author Brett McLaughlin has been working in computers since the
Logo days (remember the little triangle?). He currently specializes
in building application infrastructure using Java and Java-related
technologies. He has spent the last several years implementing these
infrastructures at Nextel Communications and Allegiance Telecom Inc.
Brett is one of the co-founders of the Java Apache project Turbine,
which builds a reusable component architecture for Web application
development using Java servlets. He is also a contributor of the
EJBoss project, an open source EJB application server, and Cocoon,
an open source XML Web-publishing engine. Contact Brett at brett@oreilly.com. |
|
|