JSP Standard Tag Library eases Webpage development

Learn how JSTL improves upon JSP for simpler Webpage implementation

The 1996 introduction of Java servlets made Java a reasonable choice for dynamic Webpage development. The subsequent debut of JavaServer Pages (JSP) followed by the inclusion of support for JSP tags were logical evolutionary steps toward fast, maintainable Java Webpage implementation. But the mid-2002 release of JSTL (JSP Standard Tag Library) represents perhaps the biggest step yet in speeding and simplifying the development process further.

In this article, I explain JSTL's capabilities and cover everything you need to get started with JSTL. It's assumed you have a basic understanding of Java, JSP, XML, and setting up a Web container. If you're not comfortable with these topics, you might want to browse the background references in Resources. Additional assumed knowledge is described in the XML and SQL sections below.

Installing JSTL support

For our JSTL installation example, we use Tomcat 4.1 (although any servlet container that supports the Servlet 2.3 and JSP 1.2 specifications should work). First, download Tomcat and follow the setup instructions. (Note that JSTL requires a JSP 1.2 Web container.)

Start Tomcat with tomcat4 start and load the index.html page to make sure Tomcat is alive and well.

Next, you'll need to install JSTL support. You can download JSTL support from the Jakarta Website then follow these steps:

  1. Download the JSTL archive (binaries not source) from the Jakarta Website. Unzip/untar the file.
  2. Copy the jar files you've extracted to common/lib in your Tomcat installation (although you won't need all the jar files for our project). This makes the JSTL jar files available to any of your Web applications.
  3. For any Web application for which you want to use JSTL, copy the .tld files to the WEB-INF directory in your Web application.
  4. For your JSTL Web application, edit your web.xml file and add the following entries:

      <taglib>
        <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
        <taglib-location>/WEB-INF/fmt.tld</taglib-location>
      </taglib>
      <taglib>
        <taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
        <taglib-location>/WEB-INF/c.tld</taglib-location>
      </taglib>
      <taglib>
        <taglib-uri>http://java.sun.com/jstl/sql</taglib-uri>
        <taglib-location>/WEB-INF/sql.tld</taglib-location>
      </taglib>
      <taglib>
        <taglib-uri>http://java.sun.com/jstl/x</taglib-uri>
        <taglib-location>/WEB-INF/x.tld</taglib-location>
      </taglib>
    

    These entries let your Web application use the expression language (EL) versions of the JSTL tag libraries. Position of these entries matters! If you're not sure where to put them, the definitive guide to web.xml options and ordering is defined in the document type definition (DTD) at: http://java.sun.com/j2ee/dtds/web-app_2_2.dtd.

  5. When you create a JSP page that uses JSTL, put it in your Web application's main directory, just like other JSP and HTML pages. You can name this page whatever you want, but it should have a .jsp extension.

The basics

First, all JSTL pages are also JSP pages. JSTL is just a superset of JSP functionality.

Also, all JSTL tags are valid XML. That means if you treat the context of a page outside the JSTL tags as template text (which will normally be HTML), the remaining JSTL tags must parse as valid XML. This has some important implications, most of which are good.

JSTL provides a set of four standard tag libraries (core, internationalization/format, XML, and SQL) and support for an EL. A primary design goal for JSTL and the EL was to simplify Webpage development and implementation.

In this article, we follow the JSTL specification's naming convention and refer to JSTL tags as actions. A JSTL tag corresponds to some action; calling them actions explicitly remind us that they add dynamic behavior to an otherwise static page.

The JSTL tag library comes in two versions: one lets you plug in the standard JSP expressions you've used in the past, such as <%= . . . %>, and one uses a JSTL EL. I further discuss EL support in JSTL below.

EL support

To understand the current state of EL support in JSTL, let's examine how the relevant specifications have been handled. The Java Specification Request (JSR) expert group members decided, for good reasons, that an expression language specification should be part of the JSP, not the JSTL, specification. Complete specification of an expression language will be part of the JSP 2.0 specification. Since JSTL 1.0 was finalized before JSP 1.3, the JSTL authors had to make an educated guess (which will probably turn out to be quite good) on an EL support implementation for JSTL 1.0. A JSTL maintenance release will coincide with finalization of the JSP 1.3 specification and will contain any tweaks to the EL required for consistency with the final JSP 1.3 specification.

The bottom line is that the EL described here may change a bit in an upcoming JSTL release. However, any changes will likely be small.

The EL simply defines a powerful language for expressing simple expressions in a syntax that's easy to learn. It has the flavor of a cross between JavaScript and the better parts of Perl. EL expressions, combined with JSTL tags from the four standard tag libraries, provide a large, flexible feature set.

All EL expressions are enclosed by ${ }. Expressions in JSTL are always part of attribute values in JSTL tags. The expressions may be the only part of the attribute or may be combined and embedded in string literals. JSTL attributes may also contain simple string literals. In the following JSTL, we show each of these cases in a c:out action, which is an action from the core library that spews the contents of its value attribute to the JSP's output:

<c:out value="${anExpression}"/>
<c:out value="literalText${anExpression}${anotherExpression}"/>
<c:out value="literalText"/>

The EL also defines a set of rules for coercing values in an expression to a type that corresponds to the context in which the values are used. We won't cover these rules in detail here; however, the approach is very similar to that defined in Perl. (As with most things Perl, this approach works reasonably well, but, on occasion, gives results the language happily accepts, but may not be quite what you expect.)

The EL provides support for accessing object properties and collection elements, a set of implicit objects, and using relational, logical, and arithmetic operators. For indexed properties, including arrays and java.util.List classes, elements can be accessed with syntax like the following:

${alist[4]}
${aList[someVariable]}

Both JavaBean properties and java.util.Map elements (which represent a set of name/value pairs) can be accessed using one of the following ways. In the first two expressions below, we can access a property named aProperty in a JavaBean or a Map entry with the key aProperty. In the third expression (note I've left out the quotes), we access an element in anObject with a name held in the variable aVariableContainingPropertyName:

${anObject.aProperty}
${anObject["aPropertyName"]}
${anObject[aVariableContainingPropertyName]}

There are a number of implicit varibles defined in the EL:

  • pageContext: the pageContext object for that Webpage
  • pageScope, requestScope, sessionScope, and applicationScope: these are Map collections that map variable names in each of these scopes to values
  • param and paramValues: parameters passed with the page request; same as in JSP
  • header and headerValues: headers passed with the page request; same as in JSP
  • cookie: Map that maps cookie names to a particular cookie object

The EL defines a full set of operators that corresponds closely to those you're familiar with in Java. Arithmetic operators include +, -, *, / (or div), and % (or mod). Relational operators include ==, !=, <, >, <=, >=, which correspond to eq, ne, lt, gt, le, and ge, respectively. I won't elaborate on these operators because they are all self-explanatory.

JSTL tag libraries

Now that I've covered some basics and looked at EL syntax, I can discuss the four JSTL tag libraries specifically. I discuss the core library most since it's the one you'll certainly use; but I'll also cover the rest in enough detail to get you started.

First, though, I should talk more about the JSTL tag libraries' two flavors. I mentioned above that each JSTL tag library comes in two versions: one that supports expressions in the EL and one that supports standard JSP expressions. When you import any tag library into a JSP page, you define a prefix that designates a namespace corresponding to the tags in that library.

The four standard tag libraries, with their JSTL spec-defined prefix conventions, are listed below. Note that you could define your own prefixes, but there is absolutely no good reason for this.

Four standard tag libraries

LibraryEL library prefixRequest-time (RT) library prefix
Corecc_rt
Internationalization/formatfmtfmt_rt
SQL/DB supportsqlsql_rt
XMLxx_rt

To use the EL core tag library in your page (you're really just giving your page visibility into the namespace defined in the library), include the following example directive at the top of your page:

<%@ taglib prefix="c" uri=http://java.sun.com/jstl/core %>

To use the tags in that core library, prefix each tag in your page with the prefix you've designated in your include statement:

<c:out value="${anExpression}"/>

The core tag library

Let's examine the core tag library in more detail. We look at the most commonly used functionality first.

Displaying/setting values and exception handling

The core library's most basic tag is the c:out tag, which displays an EL expression's value in a page. An example expression that uses c:out might look like this:

 We have <c:out value="${applicationScope.product.inventoryCount}" escapeXml="true" default="0"  /> of those items in stock.

In the above, the value attribute is the expression we send to the page output. I've also shown the optional escapeXml attribute, which specifies whether XML characters (<, >, &, and .) should convert to corresponding character entity codes (so they show up as those characters in an HTML page), and the default attribute, which is used if the EL can't evaluate the value or the value evaluates to null.

Note that when EL support is fully implemented in JSP 2.0, you won't need to use the c:out action; you can just embed JSP expressions directly in the page.

Another commonly used core action is c:set, which sets a variable in a page. You can use c:set in two ways. The first way sets the variable defined in the var attribute to the value defined in the value attribute, as shown below:

<c:set var="customerID" value="$param:customerNumber" scope="session" />

The optional scope attribute above specifies that we want to set the variable customerID in the session scope; if scope is not specified, it defaults to page scope.

Another powerful usage of c:set assigns the contents of the c:set tag's body to a specified variable:

<c:set var="cellContents">
<td>
<c:out value="${myCell}"/>
</td>
</c:set>

In the above example, a c:set action defines a variable named cellContents (in page scope) that holds the contents defined in the tag's body. In this case, the body defines an HTML table cell element. The c:out action in the body is evaluated, and that evaluation's results are included in the string literal in the body.

As you might expect, JSTL has made exception handling a bit easier. In typical JSP pages, you have two approaches for handling exceptions: try/catch blocks in scriptlet code embedded directly in the page or with a JSP errorPage directive that provides a nice catch-all way to handle any possible exception on a page. JSTL offers a good alternative with the c:catch action, which provides an effective way to handle exceptions with a bit more granularity without embedding Java code in your pages. A c:catch action might look like this:

<c:catch>
     <!--. . . some set of nested JSTL tags below which would be hit on an exception-->
</c:catch>

The c:catch action has an optional attribute, a variable that references a thrown exception.

You're less likely to use the c:remove tag. This tag has attributes for a variable name and a scope, and removes the specified variable from the specified scope.

Flow control

Let's move on to JSTL's flow control and conditional tags. If you've used conditional and flow control statements in any language, conceptually there's not much new here.

The c:if action handles simple conditional tests. The Boolean expression's value in the test attribute is evaluated; if true, the body's contents are evaluated. In the action below, we also show the optional var attribute that stores the test results for later use in the page (or elsewhere, if the other optional scope attribute is specified):

<c:if test="${status.totalVisits == 1000000}" var="visits">
   You are the millionth visitor to our site!  Congratulations!
</c:if>

Below we show JSTL's support for switching logic with c:choose, c:when, and c:otherwise. A set of c:when actions may be included within a choose tag; if any of the expressions in the c:when blocks evaluate to true, the following tests in the c:choose action are not evaluated. If none of the tests in the c:when blocks evaluate to true, c:otherwise action's contents, if present, are evaluated:

1 2 3 Page 1
Page 1 of 3
InfoWorld Technology of the Year Awards 2023. Now open for entries!