Skip to main content

Practical JSTL, Part 1

October 7, 2003


If you have heard about the JSP Standard Tag Library (JSTL) but aren't quite sure of how to make the
best use of it, this first of two excerpts from the JSTL: Practical Guide for JSP Programmers provides an introduction to the technology. The JSTL allows page authors to make use of easy-to-learn, easy-to-use standard actions for common ways we deal
with presentation. The book has just been released, and comes with free
download of all code examples used throughout. Each standard action is covered with a detailed
explanation and includes a code sample, so you can start using the JSTL

This will be a two-part series. This set of excerpts from the book
offers a functional overview and takes a look at the expression
language and some of the actions available in the Core tag
library. Next time, we'll take a look at
what the standard actions provided in the other tag libraries.


JSTL is the JSP Standard Tag Library. The JSTL came about under JSR-52
of the Java Community Process (JCP). The specification can be found at
the JCP site. JSR-52
covers the creation of a standard tag library for JavaServer Pages and allows this library to
be available to all compliant JSP containers. These tag libraries
provide a wide range of custom action functionality that most JSP
authors have found themselves in need of in the past. Having a defined
specification for how the functionality is implemented means that a
page author can learn these custom actions once and then use and reuse
them on all future products on all application containers that support
the specification. Using the JSTL will not only make your JSPs more
readable and maintainable, but will allow you to concentrate on good
design and implementation practices in your pages. We can finally take
the "custom" out of custom action and replace it with
"standard." No
more creating your own iteration action for the tenth
time. Additionally, your favorite Integrated Development Environment
(IDE) that supports JSP authoring will now support these standard
actions and can assist the JSP page author in rapid development.

Functional Overview

The JSTL encapsulates common functionality that a typical JSP author
would encounter. This set of common functionality has come about
through the input of the various members of the expert group. Since
this expert group has a good cross-section of JSP authors and users,
the actions provided in the JSTL should suit a wide audience. The JSTL
is a set of custom actions that is based on the JSP 1.2 and servlet
2.3 specifications. While the JSTL is commonly referred to as a single
tag library, it is actually composed of four separate tag libraries:

  • Core
  • XML manipulation
  • SQL
  • Internationalization and formatting

These libraries are defined by the Tag Library Descriptor (TLD) files. Using
separate TLDs to expose the tags, the functionality for each set of
actions is apparent and makes more sense. Using separate TLDs also
allows each library to have its own namespace. To sum up for now, the
layout of the JSTL is straightforward.

The overriding theme throughout the JSTL is simplifying the life of the page author. The page author
is the person who builds the JSP pages. There has always been a need
(although not a requirement) that the page authors have some
understanding of a programming language (usually Java) in order to
create complex pages. This dilemma is what has hampered the true role
separation between the JSP page author and the Java programmer. Using
the tags provided in the JSTL, we are closer to reaching that clean
division of labor. The functional areas in the JSTL help page authors
identify what type of functionality they need, and where they can find

Using the Expression Language

Before we dive into the various functional areas in the JSTL, we
should start with the expression language. This is one of the most
important features of the
JSTL and is a prominent feature of the JSP 2.0 specification. The
expression language (EL) allows for a much simpler syntax for the
page author to manipulate application data. Currently the EL in
the JSTL can only be used with tag attribute values, primarily in
actions that reside in the Core tag library. It is possible to use the
EL within template text if you are working with the JSP 2.0
specification. Expressions in template text are not supported if you
are using JSTL 1.0 with JSP 1.2.

What it means to use EL in attributes
can be shown in the following example:

<c:if test="${book.orderQuantity > book.inStock}">
The book <c:out value="${book.title}"/> is currently out of stock.

Using the <c:if> conditional tag (which we'll
talk about in
detail shortly), we can use the EL in the test attribute to determine if we
can order a book that is currently in stock. If the book is not in
stock, we can access the book object by using the EL and
assigning that to the value attribute. Anyone who has worked with JSPs
before can certainly appreciate the ease of use and coding simplification
made possible with the EL. If you are working with JSP 2.0, this sample
could also be written using the expression in the template text:

<c:if test="${book.orderQuantity >book.inStock}">
The book ${book.title} is currently out of stock.

Keep in mind that when using an identifier (like book,
for example)
with the EL, it is the same thing as if you had done
PageContext.findAttribute(identifier). The identifier itself can
reside in any of the known JSP scopes. This includes
request, session, or
application scope. If the identifier isn't found in any
scope, then a null value is returned.

Implicit Objects Available in the EL

There are quite a few implicit objects exposed through the EL. These
objects allow for access to any variables that are held in the
particular JSP scopes. Objects include pageScope,
requestScope, sessionScope, and
applicationScope. All of these xScope
objects are Maps that map the respective scope attribute
names to their values. Using the implicit objects param
and paramValues, it is also
possible to access HTTP request parameters. This holds true for
request header information, as well as for using the implicit objects
header and headerValues.

The param and header objects are
Maps that map the parameter or header
name to a String. This is similar to doing a
ServletRequest.getParameter(String name) or
ServletRequest.getHeader(String name). The
paramValues and headerValues
are Maps that map parameter and header names to a
String[] of all
values for that parameter or header. Again, this is as if you had made
ServletRequest.getParameterValues(String name) or
ServletRequest.getHeaders(String) calls.

The initParam gives access to context initialization
parameters, while cookie exposes cookies received in the
request. The implicit object
pageContext gives access to all properties associated with the
PageContext of a JSP page, such as the
HttpServletRequest, ServletContext,
and HttpSession objects and their properties.

Let's look at a couple of samples to drive the usage of the
objects home:

  • ${pageContext.request.servletPath} will return the servlet path obtained from the HttpServletRequest.

  • ${sessionScope.loginId} will return the session-scoped attribute named
    LoginId, or null if the attribute is not found.

  • ${param.bookId} will return the String value of the bookId parameter, or null if it is not found.

  • ${paramValues.bookId} will return the String[] containing all values
    of the bookId parameter, or null if it is not found. Using paramValues
    is particularly useful if you have a form with checkboxes or if, for some other reason, a parameter might have multiple values, as with a multiselect box.

The EL operations are necessary to handle data manipulations. All of
the Java standard and common operators are available. Functionality is
included in the EL for relational, arithmetic, and logical operators.

Automatic Type Conversion

Automatic type conversion is a very convenient feature of the EL,
in that a full set of coercions between various object and primitive
types is supported. Coercion means that the page author isn't
responsible for converting parameters into the appropriate objects or
primitives. The JSTL defines appropriate conversions and default
values. For example, a String parameter from a request
will be coerced to the appropriate object or primitive.

If we are dealing with A, which is an item or object,
the coercion rules supplied by the JSTL will be applied for each given
type. These coercions are done under the covers for you by the
implementation, but it is always a good idea to understand how (and in
what order) the rules are being applied. For this reason, the coercion
rules from the JSTL 1.0 specification are included in the book's JSTL
Reference section so that you can review them if you want.

Let's look at Example 1. If we have a variable called
myInteger and
want to use the value in an expression as a number, we simply declare
a variable with the value using <c:set>. If a
parameter that represents the month is passed in the request as a
String, the value of the
month variable will be correct because the String will be
coerced to
the correct type when used. If the value of the parameter does not
parse correctly to a number -- say, the value is September
instead of 9 -- then an exception will be thrown. Having
automatic type
conversions can save unnecessary exceptions from happening.

Example 1. Performing a Coercion

<c:set var="myInteger"value="${param.month}"/>
The value of myInteger is:<c:out value="${myInteger}"/>
Perform a multiplication operation to show that the type is correct:
<c:out value="${myInteger *2}"/>

If the coercion is not possible, the exception might look something
like this:

javax.servlet.ServletException: An error occurred while evaluating
custom action attribute "value" with value "${myInteger *2}": An
exception occurred trying to convert String "September" to type

Keep in mind that it's possible to use <c:catch>
to prevent a complete exception stack trace from being displayed to
the user. The page author can
handle an unexpected value more in a user-friendly way, perhaps
informing the user of the type of data that is expected, or providing a
sample of the format of data required by the user. A more graceful
handling of an error is shown in Example 2.

Example 2. Friendly Handling of a Coercion Error

<c:catch var="coercionError">
The value of myInteger is:<c:out value="${myInteger}"/>
Perform a multiplication operation to show that the type is
correct:<c:out value="${myInteger *2}"/>
<c:if test="${not empty coercionError}">
<b>The value of month is supposed to be a number.</b>
Here 's more information on the error:
<br><font color="#FF0000"><c:out value="${coercionError}"/>

Working with the Core Actions

The set of tags that are available in the Core tag library come into
play for probably most anything you will be doing in your JSPs. Let's
walk through code samples to see how we use each of the tags provided
in this library.

The Core area comprises four distinct functional sections:

  • General-purpose actions that are used to manipulate the scoped
    variables that might be found within a JSP. These general-purpose
    actions also encompass error handling.
  • Conditional actions used for doing conditional processing within a
  • Iterator actions that make it easy to iterate through collections of
  • URL-related actions for dealing with URL resources in a JSP.

Writing Output to the JspWriter

There are four general-purpose tags. The <c:out>
tag is probably the tag that you will see the most. It is used to output to
the current JspWriter. This is similar to using the JSP
expression <%=scripting language expression %>
to write dynamic data to the client.

The value to be written to the JspWriter is specified
as a value attribute. You can use expressions in the value
attribute. This allows
for the resulting evaluation to be sent to the JspWriter.
The <c:out>
tag can perform XML character-entity encoding for
<, >, &, ", and '. This
means that a < will be automatically encoded to
&lt;. The book includes a table of the XML entity
values that are used for encoding the characters.
Therefore, it's possible also to use this encoding capability to
encode any HTML, such as <br>, so that the angle
brackets appear correctly. This capability is controlled by the
escapeXml attribute. It defaults to true.

It should be obvious that:

The title of the book you just purchased is
<c:out value="${sessionScope.bookInfo.title}">

is much easier to read (and write) than:

<%@page import=""%>
<%BookInfo bookInfo =(BookInfo)session.getAttribute"
The title of the book you just purchased is

In another example, we might want to output some data values that have
been stored in a scoped variable called myData. The value
of myData is
"<b>I love to ride my bicycle</b>".
There are HTML
tags included in the string that we want to make sure are rendered
correctly, with the string bolded. To ensure that the data is displayed
to the user correctly, we would use:

<c:out value=${myData}escapeXml="false"/>

With escapeXml set to false, our users see the correct
display with the text bolded.

Otherwise, they just see the characters <b> displayed with the text, as
shown in Figure 1.

The two displays are shown as they would appear if you were to view
the source of the resulting file in your browser. The first output is
using the default value of escapeXml, while the second output shows
the result of using escapeXml set to false. With escapeXml
defaulting to true:

&lt;b&gt;I love to ride my bicycle&lt;/b&gt;

With escapeXml set to false:

<b>I love to ride my bicycle</b>

Figure 1
Figure 1. escapeXML sample

I hope that you've found these brief excerpts to be
helpful and applicable to your development. In the next excerpt, we'll
get a taste for many of the standard actions provided in the
International and Formatting, XML, and SQL tag libraries.

Sue Spielman is president and senior consulting engineer for Switchback Software LLC , author of a number of books, and a speaker on various Java topics around the country.
Related Topics >> Web Development Tools   |