Tag Languages, EL & JSTL
— print (last updated: Oct 21, 2009) print

Select font size:
Tag languages are systems of XML-like tag structures which are meant to substitute for, minimize, or possibly eliminate JSP "scripting", i.e., actual Java code introduced through JSP tags: <% ... %>

The sample application in this document requires two new JAR files. You can use these directly, or use NetBeans' built-in JSTL library.

EL

EL, or more formally, the unimaginatively named United Expression Language is a script-like language built into JSP. The common structure is that its expressions are all of the form:
${... some EL expression ...}
Without anything else, it provides simple script-like ways of creating expressions using either: The first sample script illustrates the basic properties:

bean.Sample
package bean; import java.util.*; public class Sample { private String[] names = {"jim", "karen", "joe"}; private Map<String, Integer> ages = new LinkedHashMap<String, Integer>(); private List<Integer> ids = new ArrayList<Integer>(); private int count = 0; @Override public String toString() { return "This is a Sample bean"; } public Sample() { ages.put("kevin", 22); ages.put("fred", 15); ages.put("john", 30); ids.add(33); ids.add(18); ids.add(57); } public String[] getNames() { return names; } public Map<String, Integer> getAges() { return ages; } public List<Integer> getIds() { return ids; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }

el-samples.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>EL samples</title> </head> <body> <h2>EL Samples</h2> <jsp:useBean id="sample" scope="request" class="bean.Sample" /> sample: ${sample}<br /> count: ${sample.count}<br /> ids: ${sample.ids}<br /> ages: ${sample.ages}<br /> ids[0]: ${sample.ids[0]}<br /> names[0]: ${sample.names[0]}<br /> ages['karen']: ${sample.ages['karen']}<br /> <br /> param.xx: ${param.xx}<br /> <form action=""><input type="hidden" name="xx" value="999" /> <input type="submit" value = "ClickMe"/> </form> </body> </html>
Note the jsp:useBean usage:
<jsp:useBean id="sample" scope="request" class="bean.Sample" />
We need the sample bean, but only for the execution of the single GET request. There would be no difference if we were to use scope="session" so far, because we did not modify any of the Bean state.

Observe some of the key points:
  1. We use Bean properties, i.e., those names exposed by public get/set methods. In particular, we only need a getter to do what we've done so far.
  2. EL treats all list/map accesses via the array-like [..] operations, replacing the ".get" operations for collection data structures
  3. The EL object param, with usage param.xx acts like the request.getParameter("xx") operation. For a multivalued parameter, say "yy", use the paramValues object, with usage like paramValues.yy corresponding to request.getParameterValues("yy").

JSTL overview

JSTL stands for the Java Server Pages Standard Tag Library. This library provides a set of XML-tags which are meant to use in conjunction with EL expressions to replace JSP scripting. Refer to these hyperlinks for documentation.
Sun JSTL site: http://java.sun.com/products/jsp/jstl/
Docs on Sun site: http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/
Apache Jakarta TagLib home page: http://jakarta.apache.org/taglibs/
Docs on Computer Science server: http://www.cs.wcupa.edu/docs/tld
Download the documentation: jstl-1_1-mr2-spec-tlddoc.zip
The JSTL tags are those described in the table below. We have omitted the sql tags since we don't want to use SQL operations directly in JSP. Using a tag groups is effected by the addition of one of the following respective tag statements below.
c:   <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
fn:  <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
fmt: <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
xml: <%@taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> 
The uri identifies the tag set. The tag prefix can be set by the user, but the ones here are standard.

c: core fmt: formatting fn: functions x: xml
c:catch
c:choose
c:forEach
c:forTokens
c:if
c:import
c:otherwise
c:out
c:param
c:redirect
c:remove
c:set
c:url
c:when

fmt:bundle
fmt:formatDate
fmt:formatNumber
fmt:message
fmt:param
fmt:parseDate
fmt:parseNumber
fmt:requestEncoding
fmt:setBundle
fmt:setLocale
fmt:setTimeZone
fmt:timeZone

fn:contains()
fn:containsIgnoreCase()
fn:endsWith()
fn:escapeXml()
fn:indexOf()
fn:join()
fn:length()
fn:replace()
fn:split()
fn:startsWith()
fn:substring()
fn:substringAfter()
fn:substringBefore()
fn:toLowerCase()
fn:toUpperCase()
fn:trim()
x:choose
x:forEach
x:if
x:otherwise
x:out
x:param
x:parse
x:set
x:transform
x:when

JSTL usage

These and other tag systems are used in JSP in one of two forms:
<tagPrefix:tagType attribute1="VALUE1" ...
or, as functions to create expressions:
tagPrefix:function(arg1,arg2,...)
As in XML, tags can be complete, using a single tag ending with "/>", or in pairs, containing a content terminated by a matching ending tag </tagPrefix:tagType>. Some example of the common usages of the "c" tags are these:
<c:out value="EL-EXPRESSION" />
<c:set var="x" value="EL-EXPRESSION" />
<c:if test="EL-EXPRESSION" >  ...  </c:if>
<c:forEach var="x" items="EL-EXPRESSION" > ... </c:forEach>
EL is meant to be used in conjuction with JSTL to yield the fullest usage. In particular, EL variables can also be created in a number of ways, typically as temporary variables needed to effect some operation such as iteration. In order to iterate over an array, list, map, or set, the c:forEach tag pair serves our interests. Iteration with c:forEach treats arrays, lists and sets identically. For example, this code will iteratively print the elements:
<!-- L represents either an array, list or set -->
<c:forEach var="x" items="${L}" > 
  ${x}
</c:forEach>
When using a map, the iteration generates Map.Entry pairs. Using the getKey and getValue functions the structure of the JSTL code to iteratively print the key/value pairs looks like this:
<!-- M is a map -->
<c:forEach var="x" items="${M}" > 
  ${x.key}: ${x.value}
</c:forEach>

Other JSTL core tags

The c:set tag can be used to initialize an EL variable directly with
<c:set var="str" value="..." />
When used on a bean the c:set tag, along with property call the setter for that property, e.g.
<c:set target="${sample}" property="count" value="5" />
Going further, we can remove an initialized bean using the JSTL c:remove tag:
<c:remove var="mb" />
We've seen that EL expressions can be printed by the syntax:
${str}    
This will print the raw output, which could cause problems if there are HTML-special characters. A safer way uses the fn:escapeXml function:
${fn:escapeXml(str)}
The c:out tag provides an alternative way to dump to output where the default behavior is to do an escaping of HTML:
<c:out value="${str}" />   is the same as   ${fn:escapeXml(str)}
<c:out value="${str}" escapeXml="false" />    is the same as   ${str}
The c:if tag generates a choice situation with a syntax like:
<c:if test="${EL_BOOLEAN_EXPRESSION}" > ... </c:if>
The EL_BOOLEAN_EXPRESSION uses the usual boolean operators with simplifications and additions as mentioned above. If-else structures are based on the c:choose/c:when/c:otherwise tags:
<c:choose>
  <c:when test="${EL_EXPR1}"> ... </c:when>
  <c:when test="${EL_EXPR2}"> ... </c:when>
  ...
  <c:otherwise> ... </c:otherwise>
</c:choose>
Other useful tags which we'll see in later applications are:
c:redirect   redirect to a URL
c:import     import the URL contents, accessed by a variable

Sample Usage

The second sample script illustrates some basic properties of JSTL in conjunction with EL

jstl-samples.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSTL samples</title> </head> <body> <h2>JSTL Samples</h2> <jsp:useBean id="sample" scope="request" class="bean.Sample" /> <jsp:useBean id="samplesess" scope="session" class="bean.Sample" /> sample.names:<br /> <c:forEach var="name" items="${sample.names}" > &nbsp; ${name} <br /> </c:forEach> <br /> sample.names: ${fn:join( sample.names, ", " )} <br /><br /> sample.ids: <c:forEach var="id" items="${sample.ids}" >${id} </c:forEach> <br /><br /> sample.ages:<br /> <c:forEach var="pair" items="${sample.ages}" > &nbsp; ${pair.key} => ${pair.value} <br /> </c:forEach> <br /> <c:set var="firstid" value="${sample.ids[0]}" /> firstid: <c:out value="${firstid}" /> <br /><br /> sample.count: <c:out value="${sample.count}" /> <br /> <c:set var="newcount" value="${sample.count + 1}" /> <c:set target="${sample}" property="count" value="${newcount}" /> after update, sample.count: <c:out value="${sample.count}" /> <br /><br /> samplesess.count: <c:out value="${samplesess.count}" /> <br /> <c:set var="newcount" value="${samplesess.count + 1}" /> <c:set target="${samplesess}" property="count" value="${newcount}" /> after update, samplesess.count: <c:out value="${samplesess.count}" /> <br /><br /> <c:if test="${samplesess.count > 5}" > samplesess.count is greater than 5, reinitialize <c:remove var="samplesess" /> </c:if> </body> </html>

Custom EL functions

To avoid JSP code sections, Java classes and functions must be accessible through the tag system. Beans provide a limited way of doing so with "get/set" member functions, but this does not cover all programming needs. The fn tags provide some utility functions, but we must be able to extend this ourselves.

Towards this end, JSP provides a means to add your own tag libraries using a combination of Java classes and Tag Library Definition (TLD) files. Both XML-like tags and EL function tags can be added, but it's much easier to create user-defined EL function tags. The utility functions used must be static functions. For example, suppose we want to use the function defined in this class in an EL expression.

mytaglib/MyFunctions.java
package mytaglib; public class MyFunctions { public static boolean contains(java.util.Set set, String target) { return set.contains(target); } public static java.util.Set keySet(java.util.Map map) { return map.keySet(); } }
The glue connecting this function to a tag is the XML file mytags.tld in the /WEB-INF/ directory

WEB-INF/mytags.tld
<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"> <tlib-version>1.0</tlib-version> <short-name>mytags</short-name> <uri>/WEB-INF/mytags</uri> <function> <name>keySet</name> <function-class>mytaglib.MyFunctions</function-class> <function-signature> java.util.Set keySet(java.util.Map) </function-signature> </function> <function> <name>contains</name> <function-class>mytaglib.MyFunctions</function-class> <function-signature> boolean contains(java.util.Set,java.lang.String) </function-signature> </function> <tag> <name>currenttime</name> <tag-class>mytaglib.CurrentTime</tag-class> <attribute> <name>color</name> <required>false</required> <!-- this is the default --> </attribute> <body-content>empty</body-content> </tag> </taglib>
This file defines a uri by which it is accessed and a set of function prototypes in XML format. Each function has a tag name, the class it belongs to and the actual function prototype within this class. The necessary specification within the JSP file is something like this:
<%@taglib prefix="my" uri="/WEB-INF/mytags"%>
The prefix chosen specifies how the function will be referenced within the EL syntax — it can be anything you want, so long as it doesn't conflict with another tag set. In this case the function will be prefaced by my: as in this example:
<c:if test="${my:contains(someSet,someValue)}" > ... </c:if>
An example of the usage of these two functions is presented at the end of the document after the discussion of custom tags. The TLD file above also contains a tag element which we'll discuss below.

We also note that NetBeans has an menu item to automatically generate a TLD skeleton, whereas Eclipse does not appear to have one (although there is probably some way to acquire this functionality).

Custom Tags

The heart of JSTL and other tag systems is, of course, the ability to create XML-like tags which provide high-level programming functionality. We'll refer to this table for the Java code needed to create such a tag:

Tag Methods and Return Values
methodwhen calledreturn valuemeaning
doStartTag() Called once when start tag is processed. Used for initializing the tag, and for complete tag processing. SKIP_BODY Body of the tag must be empty.
EVAL_BODY_INCLUDE Body of the tag must be present and will be evaluated.
EVAL_BODY_BUFFERED Body of the tag is output to a memory buffer to be processed later.
doInitBody() Only for tags with body. Called once after doStartTag(), before the body of tag is processed. Used for additional tag initializations. void  
doAfterBody() Only for iteration/body tags. Called after body has been processed before doEndTag(). EVAL_BODY_AGAIN doAfterBody() will be called again
SKIP_BODY End of processing of tag body
doEndTag() Only for body tags. Called once after body has been processed. EVAL_PAGE Evaluate the rest of the page.
SKIP_PAGE Skip the rest of the page after this tag.
release() Called when tag processing is finished in order to release unused resources (which may be cached). void  

Custom tags are created and managed in two places: The associated Java class processes the tag by activating one or more standard methods. Keep in mind: The TLD file specifies the tag element with various subelements:
  <tag>
    <name>XML TAG NAME</name>
    <tag-class>ASSOCIATED JAVA CLASS</tag-class>
    <body-content>(empty,JSP) WHAT'S IN THE BODY OF THE TAG</body-content>
    <attribute>
      <name>ATTRIBUTE NAME</name>
      <required>(true or false) IS IT REQUIRED?</required>
      <rtexprvalue>(true or false) CAN IT BE AN EL-EXPRESSION?</rtexprvalue>
      <description>OPTIONAL DESCRIPTION</description>
    </attribute>
  </tag>

With respect to attributes, only the name element is needed. The required and rtexprvalue attributes are false if not present.

Sample tag

We'll create a simple tag which inserts the current timestamp into a JSP document, possibly colorized by a color choice. The usage will be:
<mytaglib:currenttime color="SOME-COLOR" />
Observe the tag element in the mytags.tld file:
  <tag>
    <name>currenttime</name>
    <tag-class>mytaglib.CurrentTime</tag-class>
    <attribute>
      <name>color</name>
      <required>false</required>  <!-- this is the default -->
    </attribute>
    <body-content>empty</body-content>
  </tag>

Here is the Java support class:

mytaglib.CurrentTime
package mytaglib; import java.io.*; import java.util.*; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class CurrentTime extends TagSupport { private String color; public void setColor(String color) { this.color = color; } public void release() { color = null; } @Override public int doStartTag() throws JspException { JspWriter out = pageContext.getOut(); Date today = new Date(); try { if (color == null) { out.print(today); } else { out.print("<span style='color:" + color + "'>" + today + "</span>"); } } catch (IOException x) { throw new JspException(x.getMessage()); } return SKIP_BODY; } }

Sample usage

Finally we illustrate usages of both our custom functions and our custom tag:

custom-functions-tags.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="my" uri="/WEB-INF/mytags"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <jsp:useBean id="sample" scope="request" class="bean.Sample" /> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Custom EL Functions and Tags</title> </head> <body> <h1>Custom EL Functions and Tags</h1> agenames = ${my:keySet(sample.ages)} <br /> <c:set var="agenames" value="${my:keySet(sample.ages)}" /> agenames contains "john": ${my:contains(agenames,"john")} <br /> agenames contains "tricia": ${my:contains(agenames,"tricia")} <br /> <br /> <my:currenttime color="red" /> </body> </html>


© Robert M. Kline