Many of us have been working with the Java Server Pages technology for quite some time and have become familiar with custom tags. Custom tags have made working with JSPs not only easier, but also more efficient.
If a custom tag has been created, tested, and debugged, then it only is logical that, as a developer, you want to grab the golden ring of OOD: reusable components. Working with custom tags is one avenue to explore in the world of reuse. But wouldn't it be better, more efficient, and easier if there was a set of standard tags that solved common problems? Do we really need ten different ways to iterate, or to do conditional processing?
Enter the JSP Standard Tag Library, also known as JSTL. The base design philosophy of JSTL is to provide page authors with a script-free environment. I say, bottoms up to that.
JSTL is still in early access release, but that doesn't mean that you shouldn't start paying attention to it. JSTL is being developed under the Java Community Process, in the JSR-052 expert group. The purpose of JSTL is to work towards a common and standard set of custom tags. There are currently many tag libraries available for download from various vendors, as well as from open source projects such as the Jakarta Taglibs project. In fact, a JSP 1.2/Servlet 2.3-compliant reference implementation of JSTL is being hosted under the Taglibs project. You can run this reference implementation under Tomcat, but you'll need to use Tomcat 4.
Remember, this is still an early-access release, so there's always the chance that things will change slightly. The tags provided in JSTL will be able to be used within any JSP-compliant container. The advantage of using JSTL over a vendor-specific tag library is, obviously, that you won't be bound to a specific vendor's container.
Ready for a look at the wizard behind the curtain?
A tag library is a set of actions that encapsulate functionality. These tags are then used within JSP pages. JSTL provides a wide variety of functionality that can be broken down into specific functional areas. While JSTL is a single taglib, it is exposed through multiple Tag Library Descriptors (TLDs). This is done primarily for convenience (so that tags are in their appropriate functional area), but also so that each TLD can have its own namespace, or prefix. These four areas are:
Core (with a URI of http://java.sun.com/jstl/ea/core and a prefix of
c): provides the core JSTL tags, such as those that perform iteration, conditional processing, and expression language support. Access tags provided in this TLD by placing
< %@ taglib prefix="c" uri="http://java.sun.com/jstl/ea/core" %> at the top of your JSP.
XML processing (with a URI of http://java.sun.com/jstl/ea/xml and a prefix of
x): provides tags that allow parsing and XSL transformation of XML documents.
I18N-capable formatting (with a URI of http://java.sun.com/jstl/ea/fmt and a prefix of
fmt): provides tags that support I18N and localized formatting and parsing.
Database access (SQL) (with a URI of http://java.sun.com/jstl/ea/sql and a prefix of
sql: provides tags that allow direct database access from within JSPs.
One other point to mention about the JSTL tag libraries is that there are actually two versions each of the majority of the tags. One set takes advantage of the new expression language, and the other doesn't; the tags that don't make use of an expression language use request-time expressions. This is useful if you want the flexibility provided by the standard tags but don't want to use the expression language support yet. To access these tag libraries, simply append
-rt to the end of the taglib URI like so:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/ea/core-rt" %>
Let's take an overview look at the various tags in the functional areas outlined above.
One of core tags is
<forEach>, which provides iteration functionality: it iterates over most collections. It can be used with ranges or primitives, and it also can provide a detailed status of the iteration.
<forTokens> works like
<forEach>, except that it is applied to strings of tokens and takes an extra attribute called
delims that allows for the delimiter to be specified. You can have more than one delimiter specified.
Also in the core functional area are the conditional tags. JSTL supports a simple conditional
<if> tag along with a collection of tags such as
<otherwise>. These tags support mutually exclusive conditionals. By using these tags, you can implement if/else structures. In its API, JSTL also exposes the abstract class
ConditionalTagSupport, to facilitate the implementation of custom conditional tags that leverage the standard conditional behavior defined in JSTL.
Expression language (EL) support is an important feature of JSTL that we'll talk about in more detail in the next section. It is also part of the core functionality. JSTL provides a few tags to facilitate the use of expression language.
<c:expr> prints out the value of a particular expression in the current EL, similar to the way that the scriptlet expression (
<%= ... %=>) syntax prints out the value of a expression in the scripting language (usually Java).
<c:set> lets you set a scoped attribute (e.g., a value in the request, page, session, or application scopes) with the value of an expression. There is also the
<c:declare> tag. In order for JSTL tags to collaborate with custom tags that only accept
<c:declare> tag must be used to create a scripting variable.
While JSP supports the
jsp:include tag, this standard action is limited because it only supports relative URLs. JSTL introduces the
c:import tag, which lets you retrieve absolute URLs. You can use
c:import to retrieve information from the Web using HTTP URLs, or from a file server using an FTP URL. You are even able to specify a foreign context, and that can come in handy sometimes.
Formatting data is one of the key tasks in many JSP pages. JSTL introduces tags to support data formatting and parsing for such things as dates and numbers. Using
<fmt:message>, you can easily specify locale information for determining which resource bundles to use. These tags can also be used to support parameterized content using the
<fmt:messageArg> tag. It's possible to use these tags very easily in your internationalized applications.
Using the XML processing tags provided in JSTL, you can manipulate XML from your JSP pages. This includes document parsing using
<x:parse> and using the
<x:expr> tag to specify XPath to select content, as well as performing XSLT transformations from within your JSP pages by using the
<x:transform> tag. You can also use
<x:foreach> to iterate over XML nodes.
You can easily access relational databases using SQL actions. By using various tags available (including
<sql:query>), you can do transaction-based database access. It is questionable, as a Java architect, why you would want to provide tags that mix presentation and data tier access. In theory, projects should be based on clean MVC architectures; however, page authors often face a different reality out there in the real world, and the need simply cannot be ignored. It is not encouraged to access the data tier in JSP pages, but if a page author must go that route (for whatever reason), doing so with a set of standard tags seems to be the lesser evil. I strongly feel that these SQL tags should only be used in prototyping or very simple applications, if at all. You really should be separating your presentation and logic tiers, especially a data tier.
One of the key features of JSTL is that it supports an expression language. An expression language leverages the fact that JSP-scoped attributes are the privileged way to communicate information from the business logic to the JSP pages. Why is this important? Well, think about how we have to do this now. If you are using JavaBeans or their properties with a custom tag, you must either have request-time expressions or make use of other functionality, such as the powerful tags that are provided with frameworks like Jakarta Struts. By using expression language in the tag, it's possible to provide values for an attribute of a tag and manipulate it in simple ways, without having to use scriptlets or request-time expression values. This sounds like something that might (or should) just be in the JSP specification, and maybe at some point it will be. But for now, it's part of the JSTL.
In order to be able to support both the scripting (
rtexprvalues) and the expression language (
elexprvalues) worlds, JSTL has the concept of twin tag libraries: one that supports the expression language, and one that supports request-time expression values. It's assumed that most developers will use the EL-based tag libraries; however, it's still possible for scripting page authors to use JSTL with
rtexprvalues. Using the
rtexprvalues will provide the benefit of type safety and performance via the request-time based tag libraries (their URI simply has the
-rt suffix appended).
For example, if we assume that we have an object bound in our page called
cd, we can use a expression to get the value of the artist property.
<c:if test="$cd.artist == 'Madonna'"> ... </c:if>
Notice that the expression starts with a
$ symbol. This is because something is needed to indicate that the string should be evaluated (and is not a static string). Most of the expression languages available in JSTL make use of a special symbol (usually the
$ character) to indicate this.
It's important to note that the whole idea of expression languages is being carefully watched and evaluated by the expert group. Because of this, you should think of it as more experimental than the rest of the JSTL. The community feedback will most likely determine whether it stays in the final version of the JSTL.
It is also possible that you can use JSTL as a base for developing your own custom tags. Some abstract classes are provided that can assist with rapid development of tags and promote integration of your own custom tags with JSTLs tag set.
For instance, you can build your own custom tags that make use of the JSTL's EL mechanism. By extending
javax.servlet.jsp.jstl.core.ConditionalTagSupport, you can write a conditional tag by simply implementing a single method that returns a boolean value corresponding with your tag's desired conditional behavior. Similarly,
javax.servlet.jsp.jstl.core.IteratorTagSupport lets you easily implement iteration tags. The handlers for the
<forTokens> tags extend this class and thus implement the
javax.servlet.jsp.jstl.core.IteratorTag interface, which provides a well-defined mechanism for iteration tags to communicate with custom subtags you may write.
There are a number of samples provided with the
standard-examples application that might prove helpful. Not only are samples of the tags provided, but there are also samples that induce errors, so that you can get familiar with what some of the errors mean. This application is part of the early access download. You can just drop the
standards-example.war file into the
webapps directory of Tomcat and access it in your browser at http://127.0.0.1:8080/standard-examples/.
With the early access release of JSTL and the reference implementation provided on the Jakarta site, there is good reason to take a few minutes and explore what's going to be available. It remains to be seen how the expression language support will play out in the community. While some might welcome it, I can see how other people might feel that it is just introducing another way to have code still involved on your JSPs. The spec was scheduled to go into public review on March 12, 2002. The more developers who have a chance to play with the JSTL before the spec is final, the better it will suit the development community. So download JSTL, give it a spin, and go have yourself a good old custom tag time.
In the next article in this JSTL series, we'll look at the practical use of some of the tags. Stay tuned.
Sue Spielman is an associate editor for ONJava.com, covering JSP and Servlets technologies. She is also President and Senior Consulting Engineer for Switchback Software LLC.
Read more JSP and Servlets columns.
Return to ONJava.com.
Copyright © 2009 O'Reilly Media, Inc.