The Java EE 5 Tutorial

Flow Control Tags

To execute flow control logic, a page author must generally resort to using scriptlets. For example, the following scriptlet is used to iterate through a shopping cart:

<%
     Iterator i = cart.getItems().iterator();
    while (i.hasNext()) {
        ShoppingCartItem item =
            (ShoppingCartItem)i.next();
        ...
%>
        <tr>
        <td align="right" bgcolor="#ffffff">
         ${item.quantity}
        </td>
        ...
<%
     }
 %>

Flow control tags eliminate the need for scriptlets. The next two sections have examples that demonstrate the conditional and iterator tags.

Conditional Tags

The if tag allows the conditional execution of its body according to the value of the test attribute. The following example from tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp tests whether the request parameter Add is empty. If the test evaluates to true, the page queries the database for the book record identified by the request parameter and adds the book to the shopping cart:

<c:if test="${!empty param.Add}">
    <c:set var="bid" value="${param.Add}"/>
    <jsp:useBean id="bid"  type="java.lang.String" />
     <sql:query var="books"
         dataSource="${applicationScope.bookDS}">
        select * from PUBLIC.books where id = ?
        <sql:param value="${bid}" />
    </sql:query>
    <c:forEach var="bookRow" begin="0" items="${books.rows}">
         <jsp:useBean id="bookRow" type="java.util.Map" />
        <jsp:useBean id="addedBook"
            class="database.Book" scope="page" />
    ...
    <% cart.add(bid, addedBook); %>
...
</c:if>

The choose tag performs conditional block execution by the embedded when subtags. It renders the body of the first when tag whose test condition evaluates to true. If none of the test conditions of nested when tags evaluates to true, then the body of an otherwise tag is evaluated, if present.

For example, the following sample code shows how to render text based on a customer’s membership category.

<c:choose>
     <c:when test="${customer.category == ’trial’}" >
         ...
     </c:when>
     <c:when test="${customer.category == ’member’}" >
         ...
     </c:when>
         <c:when test="${customer.category == ’preferred’}" >
         ...
     </c:when>
     <c:otherwise>
         ...
     </c:otherwise>
 </c:choose>

The choose, when, and otherwise tags can be used to construct an if-then-else statement as follows:

<c:choose>
     <c:when test="${count == 0}" >
         No records matched your selection.
     </c:when>
     <c:otherwise>
         ${count} records matched your selection.
     </c:otherwise>
 </c:choose>

Iterator Tags

The forEach tag allows you to iterate over a collection of objects. You specify the collection using the items attribute, and the current item is available through a variable named by the var attribute.

A large number of collection types are supported by forEach, including all implementations of java.util.Collection and java.util.Map. If the items attribute is of type java.util.Map, then the current item will be of type java.util.Map.Entry, which has the following properties:

Arrays of objects as well as arrays of primitive types (for example, int) are also supported. For arrays of primitive types, the current item for the iteration is automatically wrapped with its standard wrapper class (for example, Integer for int, Float for float, and so on).

Implementations of java.util.Iterator and java.util.Enumeration are supported, but they must be used with caution. Iterator and Enumeration objects can't be reset, so they should not be used within more than one iteration tag. Finally, java.lang.String objects can be iterated over if the string contains a list of comma-separated values (for example: Monday,Tuesday,Wednesday,Thursday,Friday).

Here’s the shopping cart iteration from the preceding section, now with the forEach tag:

<c:forEach var="item" items="${sessionScope.cart.items}">
    ...
    <tr>
         <td align="right" bgcolor="#ffffff">
         ${item.quantity}
    </td>
    ...
</c:forEach>

The forTokens tag is used to iterate over a collection of tokens separated by a delimiter.

Similarly to the value attribute of the c:set tag (see Variable Support Tags), the items attribute of forEach and forTokens can also take a deferred value expression so that JavaServer Faces tags can be included within these tags.

As described in Variable Support Tags, JavaServer Faces technology (see Chapter 10, JavaServer Faces Technology) supports a multiphase life cycle. Therefore, any JavaServer Faces component tags that are included in the forEach tag or the forTokens tag must have access to the variable referenced by the items attribute at different phases of the life cycle, not just during the rendering phase. Consider the following code:

<c:forEach var="book" items="#{BooksBean.books}">
    ...
    <h:inputText id="quantity" value="#{book.quantity}"/>
    ...
</c:forEach>

The items attribute uses a deferred value expression, which means that the book variable it references is available not only during the rendering phase of the JavaServer Faces life cycle but also during the later stages of the life cycle. Therefore, whatever values the user enters into the quantity component tags are updated to the external data object during the appropriate stage of the life cycle.

If the expression referenced by the items attribute used immediate evaluation syntax then the book variable would be available only when the component is rendered during the render response phase. This would prevent the values the user enters into the components from being converted, validated, or updated to the external data object during the later phases of the life cycle. The JavaServer Faces version of Duke’s Bookstore includes a forEach tag on its tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp page.