[ Team LiB ] Previous Section Next Section

Core Tag Library

The Core tag library contains tags for getting, setting, and displaying attribute values; executing tags conditionally; and iterating through collections.

General-Purpose Tags

The general-purpose tags let you add and remove variables, display variable values, and enclose a group of tags within a try-catch block.

The <c:out> Tag

The <c:out> tag displays the result of an expression, similar to the way <%= %> works. There are three main differences between <c:out> and <%= %>. First, the <c:out> tag lets you use the simpler "." notation to access properties. To access customer.address.street from <%= %>, the expression would be <%= customer.getAddress().getStreet() %>. The equivalent <c:out> tag is <c:out value="customer.address.street"/>. The second difference is that the <c:out> tag can automatically escape XML tags so they aren't evaluated as actual tags. For example, if you want to display the string <hello> in an XML file, you must either use &lt;hello&gt; or <[CDATA[<hello>]]>. The <c:out> tag includes an attribute called escapeXML, which, if true, automatically escapes the text to prevent it from being evaluated as XML; for example,


<c:out value="customer.address.street" escapeXML="true"/>

The third difference between <c:out> and <%= %> is the most significant. The <c:out> tag lets you specify a default value to display if the result of the value expression is null. When you use <%= %> to display a null value, it prints out the word null. The <c:out> tag lets you specify a value such as N/A or None or even just a blank to display for null values. You can specify the default value two ways. First, you can use the default attribute, like this:


<c:out value="customer.address.street" default="N/A"/>

The second option is to specify the default value as the content of the <c:out> tag:


<c:out value="customer.address.street">
    No address available
</c:out>

The <c:out> tag can be used to display default values for the results from other tag operations. For example, the <fmt:formatDate> tag allows you to store a formatted date in a variable. If the date is null, the value of the variable is null. Although <fmt:formatDate> doesn't have a default attribute, you can use <c:out> to display the formatted date with a default value:


<fmt:formatDate var="dateVar" value="${dueDate}/>
<c:out value="${dateVar}" default="No due date specified"/>
The <c:set> Tag

The <c:set> attribute lets you create new variables that hold the results of an EL expression. There are two basic variations of <c:set>, each with two ways to specify a value. First, you can set a particular variable with the form


<c:set var="variableName" value="expression"/>

In this case, the <c:set> tag evaluates the value expression and assigns it to a variable named by the var attribute. The following expression is an example of this:


<c:set var="custAddr" value="${customer.address}"/>

Rather than using the value attribute, you can also use the body content of the <c:set> tag to specify the value. The interesting thing about specifying a value in the body tag is that you can use other tags, such as <c:out>, in the body; for example,


<c:set var="custAddr>
   <c:out value="${customer.address.street}"/><p>
   <c:out value="${customer.address.city}"/>
   <c:out value="${customer.address.state}"/>,
   <c:out value="${customer.address.zip}"/>
</c:set>

By default, the scope of a variable in <c:set> is the page scope. You can explicitly specify the scope with the scope attribute. For example, to store the custAddr variable under the session scope, use


<c:set var="custAddr" scope="session" value="${customer.address}"/>

The <c:set> tag also lets you set individual property values by following this form:


<c:set target="bean-or-map-variable" property="propertyName"
    value="expression"/>

In this case, the target attribute is an expression that must return either a JavaBean or a map. For example, the following code snippet stores a HashMap in the request object, then sets a property value in the HashMap by using <c:set>:


<%
    request.setAttribute("mymap", new java.util.HashMap());
%>
<c:set target="${mymap}" property="myvalue" value="12345"/>
<c:out value="${mymap.myvalue}"/>

Again, you can use either the value attribute or the body content to set the property's value.

If the value expression evaluates to null and you use the var attribute, the variable is removed from the scope (either the scope specified by the scope attribute or the first scope where the variable was found). When you use the target or property attributes when value is null, if the target is a HashMap, the property is removed from the map; and if the target is a JavaBean, the property is set to null.

Also, the <c:set> tag performs any necessary type conversions. If a property type is int or double, for example, the <c:set> tag tries to convert a string value to an int or a double.

Listing 17.1 shows a simple example of <c:set> and <c:out>.

Listing 17.1 Source Code for coutdemo.jsp
<%@ page import="java.util.HashMap" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
<body>
<%
    HashMap person = new HashMap();
    person.put("address", new HashMap());
    request.setAttribute("fred", person);
    ((HashMap) person.get("address")).
        put("street", "123 Blah Blahlevard");
%>
<c:out value="${fred.address.street}"/>
<c:set target="${fred.address}" property="city" value="Blahse"/>
<c:out value="${fred.address.city}"/>
<c:set var="cityName">The city value is
    <c:out value="${fred.address.city}"/>.</c:set>
<p>
CityName=<c:out value="${cityName}"/>
<c:set target="${fred}" property="name" value="Fred Fredrickson"/>
<p><c:out value="${fred.name}"/>
</body>
</html>
The <c:remove> Tag

The <c:remove> tag removes a variable from either a specified scope or the first scope where the variable is found (if no scope is specified). For example, to remove the variable custAddr from the session scope, use


<c:remove var="custAddr" scope="session"/>
The <c:catch> Tag

The <c:catch> tag lets you surround a set of tags by a try-catch block. One of the main reasons for using this tag is that you may evaluate some expressions that result in a NullPointerException. For example, if you have the expression customer.address.street and the address property is null, you will get a NullPointerException; for example,


<c:catch>
   <c:out value="${customer.address.street}"/><p>
   <c:out value="${customer.address.city}"/>
   <c:out value="${customer.address.state}"/>,
   <c:out value="${customer.address.zip}"/>
</c:catch>

If you need to access the exception itself, you can use the var attribute to specify a variable name to hold the exception. Unlike <c:set> tag, you can't specify a scope for the exception attribute—it always has a scope of page. The following code provides an example:


<c:catch var="exc">
   <c:out value="${customer.name.first}"/>
</c:catch>

Conditional Tags

The conditional tags make it easy for you to display text under only certain conditions.

The <c:if> Tag

The <c:if> tag evaluates an expression and displays its body content only if the expression evaluates to true. For example, the following displays an address only if customer.address is not null:


<c:if test="${customer.address != null}">
   <c:out value="${customer.address.street}"/><p>
</c:if>

You can also use the empty operator to test for null:


<c:if test="${!empty customer.address">
   <c:out value="${customer.address.street}"/><p>
</c:if>

When you use <c:if> to evaluate an expression, you can store the evaluation's result into a variable by using the var attribute (and optionally the scope attribute):


<c:if test="${!empty customer.address}" var="custNotNull"
    scope="session">
   <c:out value="${customer.address.street}"/><p>
</c:if>

If you don't specify a scope, the default is the page scope. You can use <c:if> to evaluate an expression and set a value without specifying any body content:


<c:if test="${!empty customer.address}" var="custNotNull"/>

This is equivalent to the following expression:


<c:set var="custNotNull" value="${!empty customer.address}"/>
The <c:choose> Tag

The <c:choose> tag works like a Java switch statement in that it lets you choose between a number of alternatives. Where the switch statement has case statements, the <c:choose> tag has <c:when> tags. In a switch statement, you can specify a default clause to specify a default action in case none of the cases match. The <c:choose> equivalent of default is <c:otherwise>, for example,


<c:choose>
    <c:when test="${emp.salary <= 0}">
        Sorry, no pay for you!
    </c:when>
    <c:when test="${emp.salary < 10000}>
        I'm going to have to ask you to
        come in on Saturday...
    </c:when>
    <c:otherwise>
        Yes sir! Whatever you say, sir!
    </c:otherwise>
</c:when>

As you can see, the <c:choose> tag makes up for the lack of a <c:else> in the <c:if> tag. The <c:choose> tag looks for the first <c:when> tag that evaluates to true. Although it is possible for multiple <c:when> clauses to evaluate to true, only the first one that evaluates to true is processed. See the following code as an example:


<c:choose>
   <c:when test="${emp.firstName == 'John' &&
      emp.lastName == "Smith"}>
         Hello John!
   </c:when>
   <c:when test="${emp.lastName == "Smith"}">
      Hello, Mr. Smith!
   </c:when>
</c:choose>

In this case, for the name John Smith, even though the name matches both <c:when> clauses, the code displays only "Hello John!" but not "Hello, Mr. Smith."

Iterator Tags

The iterator tags iterate through collections or tokens, or for a fixed number of times. Not only do the tags perform looping functions, but they can also return a loop status variable as well as store the current member of the collection in a variable.

The <c:forEach> Tag

The <c:forEach> tag can iterate for a fixed number of times, similar to a Java for loop, and can also iterate over a collection of items. In both cases, the optional var attribute specifies the variable that holds the current loop variable. When iterating for a fixed number of times, the loop variable is the numeric loop index. When iterating through a collection, the loop variable is the current member of the collection.

To iterate a fixed number of times, specify start and end attributes. You can also specify a step attribute to indicate how much to increment the loop index each time. The default step value is 1. For example, to loop 10 times, use the following:


<c:forEach var="i" start="1" end="10">
   Item <c:out value="${i}/><p>
</c:forEach>

To iterate through a collection, use the items attribute to specify the collection. The items attribute must be an EL expression that evaluates to an object that implements the Collection interface:


<c:forEach var="emp" items="employees">
   Employee: <c:out value="${emp.name}"/>
</c:forEach/>

You can also use the start, end, and step attributes in conjunction with collections to iterate through only a specific part of a collection.

The <c:forTokens> Tag

The <c:forTokens> tag takes a string of tokens separated by one or more delimiters and splits them into individual tokens. The items attribute specifies the string to tokenize and the delimiters attribute specifies a list of delimiters (similar to the way java.util.StringTokenizer works). For example:


<c:forTokens items="moe,larry,curly" delimiters=","
   var="stooge">
   <c:out value="${stooge}/><p>
</c:forTokens>

As with the <c:forEach> tag, you can specify start, end, and step to iterate through only a portion of the tokens.

Loop Status

Both the <c:forEach> and <c:forTokens> tags can provide a loop status variable that lets you examine various aspects of the loop. In both tags, you supply a variable name with the varStatus attribute. The value stored in the varStatus attribute implements the LoopTagStatus interface.

The LoopTagStatus interface provides the methods shown in Table 17.1.

Table 17.1. LoopTagStatus Interface Methods

Method

Description

Object getCurrent()

Returns the current loop object (the collection member, token, or index (if performing a fixed-length loop).

int getIndex()

Returns the current loop index, starting at 0. Even for a fixed loop, the index is 0 the first time through, regardless of the loop's start value.

int getCount()

Returns the count of the iteration, starting at 1. The count is really just index + 1.

boolean isFirst()

Returns true if this is the first member of the collection, token list, or fixed list of numbers.

boolean isLast()

Returns true if this is the last member of the collection, token list, or fixed list of numbers.

Integer getBegin()

Returns the value specified by the begin attribute.

Integer getEnd()

Returns the value specified by the end attribute.

Integer getStep()

Returns the value specified by the step attribute.

URL-Related Tags

JSTL provides several tags for handling URLs and accessing Web resources. URLs can be difficult to work with when you must worry about URL rewriting (to insert the session ID when the browser doesn't support cookies), URL encoding of parameters, and referencing resources from a separate servlet context within the same servlet container.

The <c:url> Tag

The <c:url> tag formats a URL into a string and stores it into a variable. The <c:url> tag automatically performs URL rewriting when necessary. The var attribute specifies the variable that will contain the formatted URL. The optional scope attribute specifies the scope of the variable (page is the default). The value attribute specifies the URL to be formatted:


<c:url var="trackURL" value="/tracking.html"/>

If the browser doesn't support cookies, the resulting URL will include a parameter containing the session ID. The URL may be a relative URL such as form.html, a context-relative URL such as /welcome.jsp, or an absolute URL such as http://www.wutka.com/data.xml or ftp://ftp.wutka.com/data.xml, although, as a security precaution, the URL is only rewritten for relative URLs.

To specify a context-relative URL within a separate servlet context within the same servlet container, specify the other context with the context attribute. For example, suppose you have installed a Web application in your servlet container with a context of "/tracking". To access a URL within the "/tracking" context, you can use this:


<c:url var="trackURL" value="/track.jsp" context="/tracking"/>

You can include parameters in the formatted URL by putting <c:param> tags inside the <c:url> tag. The <c:param> tag does any necessary URL encoding. Within a <c:param> tag, the name attribute indicates the parameter name, and the value attribute indicates the parameter value:


<c:url value="/track.jsp" var="trackingURL">
   <c:param name="trackingId" value="1234"/>
   <c:param name="reportType" value="summary"/>
</c:url>
The <c:import> Tag

The <c:import> tag is similar to the <jsp:import> tag, but it is much more powerful. For example, the <jsp:import> tag usually just imports resources from within the same servlet container. The <c:import> tag can import data from other servers as well as from within the same container. Also, the <jsp:import> tag automatically inserts the imported content directly into the JSP. Although the <c:import> tag can automatically insert content, it can also return the content as either a string or a reader.

The only required attribute in the <c:import> tag is url, which specifies the URL to be imported. As with the <c:url> tag, the URL may be a relative URL, a context-relative URL, or an absolute URL.

The advantage of specifying the alternate context instead of just using an absolute URL is that the <c:import> tag can use a RequestDispatcher to access the URL rather than using the URL class. The RequestDispatcher is more efficient than the URL class because it doesn't go through as many layers of processing.

To retrieve the contents of a URL as a string, use the var attribute to specify a variable that will contain the string and, optionally, a scope of page, request, session, or application via the scope attribute. As usual, the default scope is page. If necessary, you can specify a character encoding as well with the charEncoding attribute.

The following sequence of tags retrieves the contents of a URL as a string, and then displays the string:


<c:import var="data" url="/data.xml"/>
<c:out value="${data}/>

The previous two tags are essentially equivalent to the following tag, except that the previous tags leave the contents of the URL in a variable called data:


<c:import url="/data.xml"/>

The varReader attribute specifies the name of a variable that will contain a reader that reads the contents of the URL. Again, you can specify a scope with the scope attribute and a character encoding with the charEncoding attribute:


<c:import url="/data.xml" varReader="dataReader" scope="session"/>

You can use the <c:param> tag within a <c:import> tag, except in the case where you use the varReader tag to obtain a reader. The reason you can't use <c:param> with a reader is that the <c:import> tag creates the reader immediately—that is, before it processes the <c:param> tags. Because the <c:param> tags modify the URL, however, this means that the <c:import> tag needs to access a URL containing the parameters before it actually processes the <c:param> tags.

If you need to pass parameters to a <c:import> tag, use the <c:url> tag to create the URL first:


<c:url value="/track.jsp" var="trackingURL">
   <c:param name="trackingId" value="1234"/>
   <c:param name="reportType" value="summary"/>
</c:url>
<c:import url="${trackingURL}"/>
The <c:redirect> Tag

The <c:redirect> tag redirects the browser to an alternate URL. The advantage of using <c:redirect> rather than response.sendRedirect is that <c:redirect> automatically performs URL rewriting, it supports context-relative URLs, and it supports the <c:param> tag.

The url parameter specifies the URL to redirect to, and the optional context attribute specifies a context for a context-relative URL. The following code is an example:


<c:redirect url="http://www.wutka.com"/>
    [ Team LiB ] Previous Section Next Section