The Java EE 5 Tutorial

Chapter 5 JavaServer Pages Technology

JavaServer Pages (JSP) technology allows you to easily create web content that has both static and dynamic components. JSP technology makes available all the dynamic capabilities of Java Servlet technology but provides a more natural approach to creating static content.

The main features of JSP technology are as follows:

JSP technology also contains an API that is used by developers of web containers, but this API is not covered in this tutorial.

What Is a JSP Page?

A JSP page is a text document that contains two types of text: static data, which can be expressed in any text-based format (such as HTML, SVG, WML, and XML), and JSP elements, which construct dynamic content.

The recommended file extension for the source file of a JSP page is .jsp. The page can be composed of a top file that includes other files that contain either a complete JSP page or a fragment of a JSP page. The recommended extension for the source file of a fragment of a JSP page is .jspf.

The JSP elements in a JSP page can be expressed in two syntaxes, standard and XML, though any given file can use only one syntax. A JSP page in XML syntax is an XML document and can be manipulated by tools and APIs for XML documents. This chapter and Chapters Chapter 7, JavaServer Pages Standard Tag Library through Chapter 9, Scripting in JSP Pages document only the standard syntax. The XML syntax is covered in Chapter 6, JavaServer Pages Documents.

A Simple JSP Page Example

The web page in Figure 5–1 is a form that allows you to select a locale and displays the date in a manner appropriate to the locale.

Figure 5–1 Localized Date Form

Screen capture of localized date form. Locale drop-down
shows Lithuanian. Get Date button displays the date, "Antradienis, 2004, Kovo
16."

The source code for this example is in the tut-install/javaeetutorial5/examples/web/date/ directory. The JSP page, index.jsp, appears below; it is a typical mixture of static HTML markup and JSP elements. If you have developed web pages, you are probably familiar with the HTML document structure statements (<head>, <body>, and so on) and the HTML statements that create a form (<form>) and a menu (<select>).

The lines in bold in the example code contain the following types of JSP constructs:

Here is the JSP page:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core
"
         prefix="c" %>
<%@ taglib uri="/functions" prefix="f" %>
<html>
<head><title>Localized Dates</title></head>
<body bgcolor="white">
<jsp:useBean id="locales" scope="application"
    class="mypkg.MyLocales"/>

<form name="localeForm" action="index.jsp" method="post">
<c:set var="selectedLocaleString" value="${param.locale}" />
<c:set var="selectedFlag"
     value="${!empty selectedLocaleString}" />
<b>Locale:</b>
<select name=locale>
<c:forEach var="localeString" items="${locales.localeNames}" >
<c:choose>
    <c:when test="${selectedFlag}">
        <c:choose>
            <c:when
                 test="${f:equals(selectedLocaleString, localeString)}" >
                <option selected>${localeString}</option>
            </c:when>
            <c:otherwise>
                <option>${localeString}</option>
            </c:otherwise>
        </c:choose>
    </c:when>
    <c:otherwise>
        <option>${localeString}</option>
    </c:otherwise>
</c:choose>
</c:forEach>
</select>
<input type="submit" name="Submit" value="Get Date">
</form>

<c:if test="${selectedFlag}" >
    <jsp:setProperty name="locales"
        property="selectedLocaleString"
        value="${selectedLocaleString}" />
    <jsp:useBean id="date" class="mypkg.MyDate"/>
    <jsp:setProperty name="date" property="locale"
        value="${locales.selectedLocale}"/>
    <b>Date: </b>${date.date}</c:if>
</body>
</html>

    To deploy the date application with NetBeans IDE, follow these steps:

  1. Start the Application Server.

  2. In NetBeans IDE, select File->Open Project.

  3. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/web/
  4. Select the date folder.

  5. Select the Open as Main Project check box.

  6. Click Open Project.

  7. In the Projects tab, right-click the date project, and select Undeploy and Deploy.

    To deploy the date application with the Ant tool, follow these steps:

  1. In a terminal window, go to tut-install/javaeetutorial5/examples/web/date/.

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/date/build/ directory, and create a WAR file.

  3. Start the Application Server.

  4. Type ant deploy.

    To run the example, do the following:

  1. Set the character encoding in your browser to UTF-8.

  2. Open your browser to http://localhost:8080/date.

  3. You will see a combo box whose entries are locales. Select a locale and click Get Date. You will see the date expressed in a manner appropriate for that locale.

Some of the characters might not display properly if you don’t have the appropriate language files installed on your machine. Consult the user guide or online help for your operating system to determine how you can install these language files.

The Example JSP Pages

To illustrate JSP technology, this chapter rewrites each servlet in the Duke’s Bookstore application introduced in The Example Servlets as a JSP page (see Table 5–1).

Table 5–1 Duke’s Bookstore Example JSP Pages

Function 

JSP Pages 

Enter the bookstore. 

bookstore.jsp

Create the bookstore banner. 

banner.jsp

Browse the books offered for sale. 

bookcatalog.jsp

Add a book to the shopping cart. 

bookcatalog.jsp and bookdetails.jsp

Get detailed information on a specific book. 

bookdetails.jsp

Display the shopping cart. 

bookshowcart.jsp

Remove one or more books from the shopping cart. 

bookshowcart.jsp

Buy the books in the shopping cart. 

bookcashier.jsp

Receive an acknowledgment for the purchase. 

bookreceipt.jsp

The data for the bookstore application is still maintained in a database and is accessed through tut-install/javaeetutorial5/examples/web/bookstore2/src/java/com/sun/bookstore2/database/BookDBAO.java. However, the JSP pages access BookDBAO through the JavaBeans component tut-install/javaeetutorial5/examples/web/bookstore2/src/java/com/sun/bookstore2/database/BookDB.java. This class allows the JSP pages to use JSP elements designed to work with JavaBeans components (see JavaBeans Component Design Conventions).

The implementation of the database bean follows. The bean has two instance variables: the current book and the data access object.

package database;
public class BookDB {
    private String bookId = "0";
    private BookDBAO database = null;

    public BookDB () throws Exception {
    }
    public void setBookId(String bookId) {
        this.bookId = bookId;
    }
    public void setDatabase(BookDAO database) {
        this.database = database;
    }
    public Book getBook()
         throws Exception {
        return (Book)database.getBook(bookId);
    }
    ...
}

This version of the Duke’s Bookstore application is organized along the Model-View-Controller (MVC) architecture. The MVC architecture is a widely used architectural approach for interactive applications that distributes functionality among application objects so as to minimize the degree of coupling between the objects. To achieve this, it divides applications into three layers: model, view, and controller. Each layer handles specific tasks and has responsibilities to the other layers:


Note –

When employed in a web application, the MVC architecture is often referred to as a Model-2 architecture. The bookstore example discussed in Chapter 4, Java Servlet Technology, which intermixes presentation and business logic, follows what is known as a Model-1 architecture. The Model-2 architecture is the recommended approach to designing web applications.


In addition, this version of the application uses several custom tags from the JavaServer Pages Standard Tag Library (JSTL), described in Chapter 7, JavaServer Pages Standard Tag Library:

Custom tags are the preferred mechanism for performing a wide variety of dynamic processing tasks, including accessing databases, using enterprise services such as email and directories, and implementing flow control. In earlier versions of JSP technology, such tasks were performed with JavaBeans components in conjunction with scripting elements (discussed in Chapter 9, Scripting in JSP Pages). Although still available in JSP 2.0 technology, scripting elements tend to make JSP pages more difficult to maintain because they mix presentation and logic, something that is discouraged in page design. Custom tags are introduced in Using Custom Tags and described in detail in Chapter 8, Custom Tags in JSP Pages.

Finally, this version of the example contains an applet to generate a dynamic digital clock in the banner. See Including an Applet for a description of the JSP element that generates HTML for downloading the applet.

    To deploy and run the application using NetBeans IDE, follow these steps:

  1. Perform all the operations described in Accessing Databases from Web Applications.

  2. In NetBeans IDE, select File->Open Project.

  3. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/web/
  4. Select the bookstore2 folder.

  5. Select the Open as Main Project check box and the Open Required Projects check box.

  6. Click Open Project.

  7. In the Projects tab, right-click the bookstore2 project, and select Undeploy and Deploy.

  8. To run the application, open the bookstore URL http://localhost:8080/bookstore2/books/bookstore.

    To deploy and run the application using Ant, follow these steps:

  1. In a terminal window, go to tut-install/javaeetutorial5/examples/web/bookstore2/.

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore2/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore2/dist/ directory.

  3. Start the Application Server.

  4. Perform all the operations described in Creating a Data Source in the Application Server.

  5. To deploy the example, type ant deploy. The deploy target outputs a URL for running the application. Ignore this URL, and instead use the one shown in the next step.

  6. To run the application, open the bookstore URL http://localhost:8080/bookstore2/books/bookstore.

To learn how to configure the example, refer to the deployment descriptor (the web.xml file), which includes the following configurations:

Figure 5–2 shows the bookcatalog.jsp page from the Duke’s Bookstore application. This page displays a list of all the books that are available for purchase.

Figure 5–2 Book Catalog

Screen capture of Duke's Bookstore book catalog, with
titles, authors, prices, and "Add to Cart" links. Titles are links to book
details.

See Troubleshooting Duke's Bookstore Database Problems for help with diagnosing common problems related to the database server. If the messages in your pages appear as strings of the form ??? Key ???, the likely cause is that you have not provided the correct resource bundle base name as a context parameter.

The Life Cycle of a JSP Page

A JSP page services requests as a servlet. Thus, the life cycle and many of the capabilities of JSP pages (in particular the dynamic aspects) are determined by Java Servlet technology. You will notice that many sections in this chapter refer to classes and methods described in Chapter 4, Java Servlet Technology.

When a request is mapped to a JSP page, the web container first checks whether the JSP page’s servlet is older than the JSP page. If the servlet is older, the web container translates the JSP page into a servlet class and compiles the class. During development, one of the advantages of JSP pages over servlets is that the build process is performed automatically.

Translation and Compilation

During the translation phase each type of data in a JSP page is treated differently. Static data is transformed into code that will emit the data into the response stream. JSP elements are treated as follows:

In the Application Server, the source for the servlet created from a JSP page named pageName is in this file:


domain-dir/generated/jsp/j2ee-modules/WAR-NAME/pageName_jsp.java

For example, the source for the index page (named index.jsp) for the date localization example discussed at the beginning of the chapter would be named:


domain-dir/generated/jsp/j2ee-modules/date/index_jsp.java

Both the translation and the compilation phases can yield errors that are observed only when the page is requested for the first time. If an error is encountered during either phase, the server will return JasperException and a message that includes the name of the JSP page and the line where the error occurred.

    After the page has been translated and compiled, the JSP page’s servlet (for the most part) follows the servlet life cycle described in Servlet Life Cycle:

  1. If an instance of the JSP page’s servlet does not exist, the container:

    1. Loads the JSP page’s servlet class

    2. Instantiates an instance of the servlet class

    3. Initializes the servlet instance by calling the jspInit method

  2. The container invokes the _jspService method, passing request and response objects.

If the container needs to remove the JSP page’s servlet, it calls the jspDestroy method.

Execution

You can control various JSP page execution parameters by using page directives. The directives that pertain to buffering output and handling errors are discussed here. Other directives are covered in the context of specific page-authoring tasks throughout the chapter.

Buffering

When a JSP page is executed, output written to the response object is automatically buffered. You can set the size of the buffer using the following page directive:

<%@ page buffer="none|xxxkb" %>

A larger buffer allows more content to be written before anything is actually sent back to the client, thus providing the JSP page with more time to set appropriate status codes and headers or to forward to another web resource. A smaller buffer decreases server memory load and allows the client to start receiving data more quickly.

Handling JSP Page Errors

Any number of exceptions can arise when a JSP page is executed. To specify that the web container should forward control to an error page if an exception occurs, include the following page directive at the beginning of your JSP page:

<%@ page errorPage="file-name" %>

The Duke’s Bookstore application page tut-install/javaeetutorial5/examples/web/bookstore2/web/template/preludeErrorPage.jspf contains the directive:

<%@ page errorPage="errorpage.jsp"%>

The following page directive at the beginning of tut-install/javaeetutorial5/examples/web/bookstore2/web/error/errorpage.jsp indicates that it is serving as an error page:

<%@ page isErrorPage="true" %>

This directive makes an object of type javax.servlet.jsp.ErrorData available to the error page so that you can retrieve, interpret, and possibly display information about the cause of the exception in the error page. You access the error data object in an EL (see Unified Expression Language) expression by way of the page context. Thus, ${pageContext.errorData.statusCode} retrieves the status code, and ${pageContext.errorData.throwable} retrieves the exception. You can retrieve the cause of the exception using this expression:

${pageContext.errorData.throwable.cause}

For example, the error page for Duke’s Bookstore is as follows:

<%@ page isErrorPage="true" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
     prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"
     prefix="fmt" %>
<html>
<head>
<title><fmt:message key="ServerError"/></title>
</head>
<body bgcolor="white">
<h3>
<fmt:message key="ServerError"/>
</h3>
<p>
: ${pageContext.errorData.throwable.cause}
</body>
</html>

Note –

You can also define error pages for the WAR that contains a JSP page. If error pages are defined for both the WAR and a JSP page, the JSP page’s error page takes precedence.


Creating Static Content

You create static content in a JSP page simply by writing it as if you were creating a page that consisted only of that content. Static content can be expressed in any text-based format, such as HTML, Wireless Markup Language (WML), and XML. The default format is HTML. If you want to use a format other than HTML, at the beginning of your JSP page you include a page directive with the contentType attribute set to the content type. The purpose of the contentType directive is to allow the browser to correctly interpret the resulting content. So if you wanted a page to contain data expressed in WML, you would include the following directive:

<%@ page contentType="text/vnd.wap.wml"%>

A registry of content type names is kept by the IANA at http://www.iana.org/assignments/media-types/.

Response and Page Encoding

You also use the contentType attribute to specify the encoding of the response. For example, the date application specifies that the page should be encoded using UTF-8, an encoding that supports almost all locales, using the following page directive:

<%@ page contentType="text/html; charset=UTF-8" %>

If the response encoding weren’t set, the localized dates would not be rendered correctly.

To set the source encoding of the page itself, you would use the following page directive:

<%@ page pageEncoding="UTF-8" %>

You can also set the page encoding of a set of JSP pages. The value of the page encoding varies depending on the configuration specified in the JSP configuration section of the web application deployment descriptor (see Declaring Page Encodings).

Creating Dynamic Content

You create dynamic content by accessing Java programming language object properties.

Using Objects within JSP Pages

You can access a variety of objects, including enterprise beans and JavaBeans components, within a JSP page. JSP technology automatically makes some objects available, and you can also create and access application-specific objects.

Using Implicit Objects

Implicit objects are created by the web container and contain information related to a particular request, page, session, or application. Many of the objects are defined by the Java servlet technology underlying JSP technology and are discussed at length in Chapter 4, Java Servlet Technology. The section Implicit Objects explains how you access implicit objects using the JSP expression language.

Using Application-Specific Objects

When possible, application behavior should be encapsulated in objects so that page designers can focus on presentation issues. Objects can be created by developers who are proficient in the Java programming language and in accessing databases and other services. The main way to create and use application-specific objects within a JSP page is to use JSP standard tags (discussed in JavaBeans Components) to create JavaBeans components and set their properties, and EL expressions to access their properties. You can also access JavaBeans components and other objects in scripting elements, which are described in Chapter 9, Scripting in JSP Pages.

Using Shared Objects

The conditions affecting concurrent access to shared objects (described in Controlling Concurrent Access to Shared Resources) apply to objects accessed from JSP pages that run as multithreaded servlets. You can use the following page directive to indicate how a web container should dispatch multiple client requests:

<%@ page isThreadSafe="true|false" %>

When the isThreadSafe attribute is set to true, the web container can choose to dispatch multiple concurrent client requests to the JSP page. This is the default setting. If using true, you must ensure that you properly synchronize access to any shared objects defined at the page level. This includes objects created within declarations, JavaBeans components with page scope, and attributes of the page context object (see Implicit Objects).

If isThreadSafe is set to false, requests are dispatched one at a time in the order they were received, and access to page-level objects does not have to be controlled. However, you still must ensure that access is properly synchronized to attributes of the application or session scope objects and to JavaBeans components with application or session scope. Furthermore, it is not recommended to set isThreadSafe to false. The JSP page’s generated servlet will implement the javax.servlet.SingleThreadModel interface, and because the Servlet 2.4 specification deprecates SingleThreadModel, the generated servlet will contain deprecated code.

Unified Expression Language

The primary new feature of JSP 2.1 is the unified expression language (unified EL), which represents a union of the expression language offered by JSP 2.0 and the expression language created for JavaServer Faces technology (see Chapter 10, JavaServer Faces Technology) version 1.0.

The expression language introduced in JSP 2.0 allows page authors to use simple expressions to dynamically read data from JavaBeans components. For example, the test attribute of the following conditional tag is supplied with an EL expression that compares the number of items in the session-scoped bean named cart with 0.

<c:if test="${sessionScope.cart.numberOfItems > 0}">
  ...
</c:if>

As explained in The Life Cycle of a JSP Page, JSP supports a simple request/response life cycle, during which a page is executed and the HTML markup is rendered immediately. Therefore, the simple, read-only expression language offered by JSP 2.0 was well suited to the needs of JSP applications.

JavaServer Faces technology, on the other hand, features a multiphase life cycle designed to support its sophisticated UI component model, which allows for converting and validating component data, propagating component data to objects, and handling component events. To facilitate these functions, JavaServer Faces technology introduced its own expression language that included the following functionality:

See Using the Unified EL to Reference Backing Beans for more information on how to use the unified EL in JavaServer Faces applications.

These two expression languages have been unified for a couple reasons. One reason is so that page authors can mix JSP content with JavaServer Faces tags without worrying about conflicts caused by the different life cycles these technologies support. Another reason is so that other JSP-based technologies could make use of the additional features similarly to the way JavaServer Faces technology uses them. In fact, although the standard JSP tags and static content continue to use only those features present in JSP 2.0, authors of JSP custom tags can create tags that take advantage of the new set of features in the unified expression language.

To summarize, the new, unified expression language allows page authors to use simple expressions to perform the following tasks:

The unified EL also allows custom tag developers to specify which of the following kinds of expressions that a custom tag attribute will accept:

Finally, the unified EL also provides a pluggable API for resolving expressions so that application developers can implement their own resolvers that can handle expressions not already supported by the unified EL.

This section gives an overview of the unified expression language features by explaining the following topics:

Immediate and Deferred Evaluation Syntax

The unified EL supports both immediate and deferred evaluation of expressions. Immediate evaluation means that the JSP engine evaluates the expression and returns the result immediately when the page is first rendered. Deferred evaluation means that the technology using the expression language can employ its own machinery to evaluate the expression sometime later during the page’s life cycle, whenever it is appropriate to do so.

Those expressions that are evaluated immediately use the ${} syntax, which was introduced with the JSP 2.0 expression language. Expressions whose evaluation is deferred use the #{} syntax, which was introduced by JavaServer Faces technology.

Because of its multiphase life cycle, JavaServer Faces technology uses deferred evaluation expressions. During the life cycle, component events are handled, data is validated, and other tasks are performed, all done in a particular order. Therefore, it must defer evaluation of expressions until the appropriate point in the life cycle.

Other technologies using the unified EL might have different reasons for using deferred expressions.

Immediate Evaluation

All expressions using the ${} syntax are evaluated immediately. These expressions can only be used within template text or as the value of a JSP tag attribute that can accept runtime expressions.

The following example shows a tag whose value attribute references an immediate evaluation expression that gets the total price from the session-scoped bean named cart:

<fmt:formatNumber value="${sessionScope.cart.total}"/>

The JSP engine evaluates the expression, ${sessionScope.cart.total}, converts it, and passes the returned value to the tag handler.

Immediate evaluation expressions are always read-only value expressions. The expression shown above can only get the total price from the cart bean; it cannot set the total price.

Deferred Evaluation

Deferred evaluation expressions take the form #{expr} and can be evaluated at other phases of a page life cycle as defined by whatever technology is using the expression. In the case of JavaServer Faces technology, its controller can evaluate the expression at different phases of the life cycle depending on how the expression is being used in the page.

The following example shows a JavaServer Faces inputText tag, which represents a text field component into which a user enters a value. The inputText tag’s value attribute references a deferred evaluation expression that points to the name property of the customer bean.

<h:inputText id="name" value="#{customer.name}" />

For an initial request of the page containing this tag, the JavaServer Faces implementation evaluates the #{customer.name} expression during the render response phase of the life cycle. During this phase, the expression merely accesses the value of name from the customer bean, as is done in immediate evaluation.

For a postback, the JavaServer Faces implementation evaluates the expression at different phases of the life cycle, during which the value is retrieved from the request, validated, and propagated to the customer bean.

As shown in this example, deferred evaluation expressions can be value expressions that can be used to both read and write data. They can also be method expressions. Value expressions (both immediate and deferred) and method expressions are explained in the next section.

Value and Method Expressions

The unified EL defines two kinds of expressions: value expressions and method expressions. Value expressions can either yield a value or set a value. Method expressions reference methods that can be invoked and can return a value.

Value Expressions

Value expressions can be further categorized into rvalue and lvalue expressions. Rvalue expressions are those that can read data, but cannot write it. Lvalue expressions can both read and write data.

All expressions that are evaluated immediately use the ${} delimiters and are always rvalue expressions. Expressions whose evaluation can be deferred use the #{} delimiters and can act as both rvalue and lvalue expressions. Consider these two value expressions:

<taglib:tag value="${customer.name}" />
<taglib:tag value="#{customer.name}" />

The former uses immediate evaluation syntax, whereas the latter uses deferred evaluation syntax. The first expression accesses the name property, gets its value, and the value is added to the response and rendered on the page. The same thing can happen with the second expression. However, the tag handler can defer the evaluation of this expression to a later time in the page life cycle, if the technology using this tag allows it.

In the case of JavaServer Faces technology, the latter tag’s expression is evaluated immediately during an initial request for the page. In this case, this expression acts as an rvalue expression. During a postback, this expression can be used to set the value of the name property with user input. In this situation, the expression acts as an lvalue expression.

Referencing Objects Using Value Expressions

Both rvalue and lvalue expressions can refer to the following objects and their properties or attributes:

See Implicit Objects for more detail on the implicit objects available with JSP technology.

To refer to these objects, you write an expression using a variable name with which you created the object. The following expression references a JavaBeans component called customer.

${customer}

The web container evaluates a variable that appears in an expression by looking up its value according to the behavior of PageContext.findAttribute(String), where the String argument is the name of the variable. For example, when evaluating the expression ${customer}, the container will look for customer in the page, request, session, and application scopes and will return its value. If customer is not found, null is returned. A variable that matches one of the implicit objects described in Implicit Objects will return that implicit object instead of the variable’s value.

You can alter the way variables are resolved with a custom EL resolver, which is a new feature of the unified EL. For instance, you can provide an EL resolver that intercepts objects with the name customer, so that ${customer} returns a value in the EL resolver instead. However, you cannot override implicit objects in this way. See EL Resolvers for more information on EL resolvers.

You can set the variable name, customer, when you declare the bean. See Creating and Using a JavaBeans Component for information on how to declare a JavaBeans component for use in your JSP pages.

To declare beans in JavaServer Faces applications, you use the managed bean facility. See Backing Beans for information on how to declare beans for use in JavaServer Faces applications.

When referencing an enum constant with an expression, you use a String literal. For example, consider this Enum class:

public enum Suit {hearts, spades, diamonds, clubs}

To refer to the Suit constant, Suit.hearts with an expression, you use the String literal, "hearts". Depending on the context, the String literal is converted to the enum constant automatically. For example, in the following expression in which mySuit is an instance of Suit, "hearts" is first converted to a Suit.hearts before it is compared to the instance.

${mySuit == "hearts"}

Referring to Object Properties Using Value Expressions

To refer to properties of a bean or an Enum instance, items of a collection, or attributes of an implicit object, you use the . or [] notation, which is similar to the notation used by ECMAScript.

So, if you wanted to reference the name property of the customer bean, you could use either the expression ${customer.name} or the expression ${customer["name"]}. The part inside the square brackets is a String literal that is the name of the property to reference.

You can use double or single quotes for the String literal. You can also combine the [] and . notations, as shown here:

${customer.address["street"]}

Properties of an enum can also be referenced in this way. However, as with JavaBeans component properties, the Enum class’s properties must follow JavaBeans component conventions. This means that a property must at least have an accessor method called get<Property> (where <Property> is the name of the property) so that an expression can reference it.

For example, say you have an Enum class that encapsulates the names of the planets of our galaxy and includes a method to get the mass of a planet. You can use the following expression to reference the method getMass of the Planet Enum class:

${myPlanet.mass}

If you are accessing an item in an array or list, you must use either a literal value that can be coerced to int or the [] notation with an int and without quotes. The following examples could all resolve to the same item in a list or array, assuming that socks can be coerced to int:

In contrast, an item in a Map can be accessed using a string literal key; no coercion is required:

${customer.orders["socks"]}

An rvalue expression also refers directly to values that are not objects, such as the result of arithmetic operations and literal values, as shown by these examples:

The unified expression language defines the following literals:

You can also write expressions that perform operations on an enum constant. For example, consider the following Enum class:

public enum Suit {club, diamond, heart, spade }

After declaring an enum constant called mySuit, you can write the following expression to test if mySuit is spade:

${mySuit == "spade"}

When the EL resolving mechanism resolves this expression it will invoke the valueOf method of the Enum class with the Suit class and the spade type, as shown here:

mySuit.valueOf(Suit.class, "spade"}

See JavaBeans Components for more information on using expressions to reference JavaBeans components and their properties.

Where Value Expressions Can Be Used

Value expressions using the ${} delimiters can be used in the following places:

The value of an expression in static text is computed and inserted into the current output. Here is an example of an expression embedded in static text:

<some:tag>
    some text ${expr} some text
</some:tag>

If the static text appears in a tag body, note that an expression will not be evaluated if the body is declared to be tagdependent (see Tags with Attributes).

Lvalue expressions can only be used in tag attributes that can accept lvalue expressions.

There are three ways to set a tag attribute value using either an rvalue or lvalue expression:

All expressions used to set attribute values are evaluated in the context of an expected type. If the result of the expression evaluation does not match the expected type exactly, a type conversion will be performed. For example, the expression ${1.2E4} provided as the value of an attribute of type float will result in the following conversion:

Float.valueOf("1.2E4").floatValue()

See section 1.18 of the JavaServer Pages 2.1 Expression Language Specification (available from http://jcp.org/aboutJava/communityprocess/final/jsr245/) for the complete type conversion rules.

Method Expressions

Another feature of the unified expression language is its support of deferred method expressions. A method expression is used to invoke an arbitrary public method, which can return a result. A similar feature of the unified EL is functions. Method expressions differ from functions in many ways. Functions explains more about the differences between functions and method expressions.

Method expressions primarily benefit JavaServer Faces technology, but they are available to any technology that can support the unified expression language. Let’s take a look at how JavaServer Faces technology employs method expressions.

In JavaServer Faces technology, a component tag represents a UI component on a page. The component tag uses method expressions to invoke methods that perform some processing for the component. These methods are necessary for handling events that the components generate and validating component data, as shown in this example:

<h:form>
    <h:inputText
         id="name"
        value="#{customer.name}"
        validator="#{customer.validateName}"/>
    <h:commandButton
        id="submit"
        action="#{customer.submit}" />
</h:form>

The inputText tag displays a UIInput component as a text field. The validator attribute of this inputText tag references a method, called validateName, in the bean, called customer. The TLD (see Tag Library Descriptors) that defines the inputText tag specifies what signature the method referred to by the validator attribute must have. The same is true of the customer.submit method referenced by the action attribute of the commandButton tag. The TLD specifies that the submit method must return an Object instance that specifies which page to navigate to next after the button represented by the commandButton tag is clicked.

The validation method is invoked during the process validation phase of the life cycle, whereas the submit method is invoked during the invoke application phase of the life cycle. Because a method can be invoked during different phases of the life cycle, method expressions must always use the deferred evaluation syntax.

Similarly to lvalue expressions, method expressions can use the . and [] operators. For example, #{object.method} is equivalent to #{object["method"]}. The literal inside the [] is coerced to String and is used to find the name of the method that matches it. Once the method is found, it is invoked or information about the method is returned.

Method expressions can be used only in tag attributes and only in the following ways:

Defining a Tag Attribute Type

As explained in the previous section, all kinds of expressions can be used in tag attributes. Which kind of expression and how that expression is evaluated (whether immediately or deferred) is determined by the type attribute of the tag’s definition in the TLD (see Tag Library Descriptors) file that defines the tag.

If you plan to create custom tags (see Chapter 8, Custom Tags in JSP Pages), you need to specify for each tag in the TLD what kind of expression it accepts. Table 5–2 shows the three different kinds of tag attributes that accept EL expressions, and gives examples of expressions they accept and the type definitions of the attributes that must be added to the TLD. You cannot use #{} syntax for a dynamic attribute, meaning an attribute that accepts dynamically-calculated values at runtime. Section 2.3.2 of the JavaServer Pages 2.1 specification refers to these attributes. Neither can you use the ${} syntax for a deferred attribute.

Table 5–2 Definitions of Tag Attributes That Accept EL Expressions

Attribute Type 

Example Expression 

Type Attribute Definition 

dynamic 

"literal"

<rtexprvalue>true</rtexprvalue>

${literal}

<rtexprvalue>true</rtexprvalue>

deferred value 

"literal"

<deferred-value>
   <type>java.lang.String</type>
</deferred-value>

#{customer.age}

<deferred-value>
   <type>int</type>
</deferred-value>

deferred method 

"literal"

<deferred-method>
   <method-signature>
      java.lang.String submit()
   </method-signature>
<deferred-method>

#{customer.calcTotal}

<deferred-method>
   <method-signature>
      double calcTotal(int, double)
   </method-signature>
</deferred-method>

In addition to the tag attribute types shown in Table 5–2, you can also define an attribute to accept both dynamic and deferred expressions. In this case, the tag attribute definition contains both an rtexprvalue definition set to true and either a deferred-value or deferred-method definition.

Deactivating Expression Evaluation

Because the patterns that identify EL expressions, ${ } and #{ }, were not reserved in the JSP specifications before JSP 2.0, there might exist applications in which such patterns are intended to pass through verbatim. To prevent the patterns from being evaluated, you can deactivate EL evaluation using one of the following methods:

To escape the #{ or ${ characters in the page, you use the \ character as follows:

some text \#{ some more\${ text
<my:tag someAttribute="sometext\#{more\${text" />

Another way to deactivate EL evaluation is by using a JSP property group to either allow the #{ characters as a String literal using the deferred-syntax-allowed-as-literal subelement, or to treat all expressions as literals using the el-ignored subelement:

<jsp-property-group>
    <deferred-syntax-allowed-as-literal>
        true
    </deferred-syntax-allowed-as-literal>
</jsp-property-group>

or

<jsp-property-group>
    <el-ignored>true</el-ignored>
</jsp-property-group>

Finally, you can configure the page with the page directive to either accept the #{ characters as String literals with the deferredSyntaxAllowedAsLiteral attribute, or to ignore all EL expressions using the isELIgnored attribute:

<%@page ... deferredSyntaxAllowedAsLiteral="true" %>

or

<%@ page isELIgnored ="true" %>

The valid values of these attributes are true and false. If isELIgnored is true, EL expressions are ignored when they appear in static text or tag attributes. If it is false, EL expressions are evaluated by the container only if the attribute has rtexprvalue set to true or the expression is a deferred expression.

The default value of isELIgnored varies depending on the version of the web application deployment descriptor. The default mode for JSP pages delivered with a Servlet 2.4 descriptor is to evaluate EL expressions; this automatically provides the default that most applications want. The default mode for JSP pages delivered using a descriptor from Servlet 2.3 or before is to ignore EL expressions; this provides backward compatibility.

Literal Expressions

A literal expression evaluates to the text of the expression, which is of type String. It does not use the ${} or #{} delimiters.

If you have a literal expression that includes the reserved ${} or #{} syntax, you need to escape these characters as follows.

When a literal expression is evaluated, it can be converted to another type. Table 5–3 shows examples of various literal expressions and their expected types and resulting values.

Table 5–3 Literal Expressions

Expression 

Expected Type 

Result 

Hi

String

Hi

true

Boolean

Boolean.TRUE

42

int

42

Literal expressions can be evaluated immediately or deferred and can be either value or method expressions. At what point a literal expression is evaluated depends on where it is being used. If the tag attribute that uses the literal expression is defined as accepting a deferred value expression, then the literal expression references a value and is evaluated at a point in the life cycle that is determined by where the expression is being used and to what it is referring.

In the case of a method expression, the method that is referenced is invoked and returns the specified String literal. The commandButton tag of the Guess Number application uses a literal method expression as a logical outcome to tell the JavaServer Faces navigation system which page to display next. See Navigation Model for more information on this example.

Resolving Expressions

The unified EL introduces a new, pluggable API for resolving expressions. The main pieces of this API are:

Most application developers will not need to use these classes directly unless they plan to write their own custom EL resolvers. Those writing JavaServer Faces custom components will definitely need to use ValueExpression and MethodExpression. This section details how expressions are resolved for the benefit of these developers. It does not explain how to create a custom resolver. For more information on creating custom resolvers, see the article The Unified Expression Language, Ryan Lubke et al., located at http://java.sun.com/products/jsp/reference/techart/unifiedEL.html. You can also refer to Request Processing, which explains how the Duke’s Bank application uses a custom resolver.

Process of Expression Evaluation

When a value expression that is included in a page is parsed during an initial request for the page, a ValueExpression object is created to represent the expression. Then, the ValueExpression object’s getValue method is invoked. This method will in turn invoke the getValue method of the appropriate resolver. A similar process occurs during a postback when setValue is called if the expression is an lvalue expression.

In the case of a method expression, a BeanELResolver is used to find the object that implements the method to be invoked or queried. Similarly to the process for evaluating value expressions, when a method expression is encountered, a MethodExpression object is created. Subsequently, either the invoke or getMethodInfo method of the MethodExpression object is called. This method in turn invokes the BeanELResolver object’s getValue method. The getMethodInfo is mostly for use by tools.

After a resolver completes resolution of an expression, it sets the propertyResolved flag of the ELContext to true so that no more resolvers are consulted.

EL Resolvers

At the center of the EL machinery is the extensible ELResolver class. A class that implements ELResolver defines how to resolve expressions referring to a particular type of object or property. In terms of the following expression, a BeanELResolver instance is called the first time to find the base object, employee, which is a JavaBeans component. Once the resolver finds the object, it is called again to resolve the property, lName of the employee object.

${employee.lName}

The unified EL includes a set of standard resolver implementations. Table 5–4 lists these standard resolvers and includes example expressions that they can resolve.

Table 5–4 Standard EL Resolvers

Resolver 

Example Expression 

Description 

ArrayELResolver

${myArray[1]}

Returns the value at index 1 in the array called myArray

BeanELResolver

${employee.lName}

Returns the value of the lName property of the employee bean

ListELResolver

${myList[5]}

Returns the value at index 5 of myList list

MapELResolver

${myMap.someKey}

Returns the value stored at the key, someKey, in the Map, myMap

ResourceBundleELResolver

${myRB.myKey}

Returns the message at myKey in the resource bundle called myRB

Depending on the technology using the unified EL, other resolvers might be available. In addition, application developers can add their own implementations of ELResolver to support resolution of expressions not already supported by the unified EL by registering them with an application.

All of the standard and custom resolvers available to a particular application are collected in a chain in a particular order. This chain of resolvers is represented by a CompositeELResolver instance. When an expression is encountered, the CompositeELResolver instance iterates over the list of resolvers and consults each resolver until it finds one that can handle the expression.

If an application is using JSP technology, the chain of resolvers includes the ImplicitObjectELResolver and the ScopedAttributeELResolver. These are described in the following section.

See section JSP 2.9 of the JavaServer Pages 2.1 specification to find out the order in which resolvers are chained together in a CompositeELResolver instance.

To learn how to create a custom EL resolver, see The Unified Expression Language .

Implicit Objects

The JSP expression language defines a set of implicit objects:

JSP 2.1 provides two EL resolvers to handle expressions that reference these objects: ImplicitObjectELResolver and ScopedAttributeELResolver.

A variable that matches one of the implicit objects is evaluated by ImplicitObjectResolver, which returns the implicit object. This resolver only handles expressions with a base of null. What this means for the following expression is that the ImplicitObjectResolver resolves the sessionScope implicit object only. Once the implicit object is found, the MapELResolver instance resolves the profile attribute because the profile object represents a map.

${sessionScope.profile}

ScopedAttributeELResolver evaluates a single object that is stored in scope. Like ImplicitObjectELResolver, it also only evaluates expressions with a base of null. This resolver essentially looks for an object in all of the scopes until it finds it, according to the behavior of PageContext.findAttribute(String). For example, when evaluating the expression ${product}, the resolver will look for product in the page, request, session, and application scopes and will return its value. If product is not found, null is returned.

When an expression references one of the implicit objects by name, the appropriate object is returned instead of the corresponding attribute. For example, ${pageContext} returns the PageContext object, even if there is an existing pageContext attribute containing some other value.

Operators

In addition to the . and [] operators discussed in Value and Method Expressions, the JSP expression language provides the following operators, which can be used in rvalue expressions only:

The precedence of operators highest to lowest, left to right is as follows:

Reserved Words

The following words are reserved for the JSP expression language and should not be used as identifiers.

and

or

not

eq

ne

lt

gt

le

ge

true

false

null

instanceof

empty

div

mod

Note that many of these words are not in the language now, but they may be in the future, so you should avoid using them.

Examples of EL Expressions

Table 5–5 contains example EL expressions and the result of evaluating them.

Table 5–5 Example Expressions

EL Expression 

Result 

${1 > (4/2)}

false

${4.0 >= 3}

true

${100.0 == 100}

true

${(10*10) ne 100}

false

${'a' < 'b'}

true

${'hip' gt 'hit'}

false

${4 > 3}

true

${1.2E4 + 1.4}

12001.4

${3 div 4}

0.75

${10 mod 4}

2

${!empty param.Add}

False if the request parameter named Add is null or an empty string.

${pageContext.request.contextPath}

The context path. 

${sessionScope.cart.numberOfItems}

The value of the numberOfItems property of the session-scoped attribute named cart.

${param['mycom.productId']}

The value of the request parameter named mycom.productId.

${header["host"]}

The host. 

${departments[deptName]}

The value of the entry named deptName in the departments map.

${requestScope[’javax.servlet.forward.servlet_path’]}

The value of the request-scoped attribute named javax.servlet.forward.servlet_path.

#{customer.lName}

Gets the value of the property lName from the customer bean during an initial request. Sets the value of lName during a postback.

#{customer.calcTotal}

The return value of the method calcTotal of the customer bean.

Functions

The JSP expression language allows you to define a function that can be invoked in an expression. Functions are defined using the same mechanisms as custom tags (see Using Custom Tags and Chapter 8, Custom Tags in JSP Pages).

At first glance, functions seem similar to method expressions, but they are different in the following ways:

Using Functions

Functions can appear in static text and tag attribute values.

To use a function in a JSP page, you use a taglib directive to import the tag library containing the function. Then you preface the function invocation with the prefix declared in the directive.

For example, the date example page index.jsp imports the /functions library and invokes the function equals in an expression:

<%@ taglib prefix="f" uri="/functions"%>
...
        <c:when
            test="${f:equals(selectedLocaleString,
                localeString)}" >

In this example, the expression referencing the function is using immediate evaluation syntax. A page author can also use deferred evaluation syntax to reference a function in an expression, assuming that the attribute that is referencing the function can accept deferred expressions.

If an attribute references a function with a deferred expression then the function is not invoked immediately; rather, it is invoked whenever the underlying technology using the function determines it should be invoked.

Defining Functions

To define a function, program it as a public static method in a public class. The mypkg.MyLocales class in the date example defines a function that tests the equality of two Strings as follows:

package mypkg;
public class MyLocales {

    ...
    public static boolean equals( String l1, String l2 ) {
        return l1.equals(l2);
    }
}

Then map the function name as used in the EL expression to the defining class and function signature in a TLD (see Chapter 8, Custom Tags in JSP Pages). The following functions.tld file in the date example maps the equals function to the class containing the implementation of the function equals and the signature of the function:

<function>
    <name>equals</name>
    <function-class>mypkg.MyLocales</function-class>
    <function-signature>boolean equals( java.lang.String,
        java.lang.String )</function-signature>
</function>

No two functions within a tag library can have the same name.

JavaBeans Components

JavaBeans components are Java classes that can be easily reused and composed together into applications. Any Java class that follows certain design conventions is a JavaBeans component.

JavaServer Pages technology directly supports using JavaBeans components with standard JSP language elements. You can easily create and initialize beans and get and set the values of their properties.

JavaBeans Component Design Conventions

JavaBeans component design conventions govern the properties of the class and govern the public methods that give access to the properties.

A JavaBeans component property can be:

A property does not have to be implemented by an instance variable. It must simply be accessible using public methods that conform to the following conventions:

In addition to the property methods, a JavaBeans component must define a constructor that takes no parameters.

The Duke’s Bookstore application JSP pages bookstore.jsp, bookdetails.jsp, catalog.jsp, and showcart.jsp, all located at tut-install/javaeetutorial5/examples/web/bookstore2/web, use the tut-install/javaeetutorial5/examples/web/bookstore2/src/java/com/sun/bookstore2/database/BookDB.java JavaBeans component.

BookDB provides a JavaBeans component front end to the access object BookDBAO. The JSP pages showcart.jsp and cashier.jsp access the bean tut-install/javaeetutorial5/examples/web/bookstore/src/com/sun/bookstore/cart/ShoppingCart.java, which represents a user’s shopping cart.

The BookDB bean has two writable properties, bookId and database, and three readable properties: bookDetails, numberOfBooks, and books. These latter properties do not correspond to any instance variables but rather are a function of the bookId and database properties.

package database;
public class BookDB {
    private String bookId = "0";
    private BookDBAO database = null;
    public BookDB () {
    }
    public void setBookId(String bookId) {
    this.bookId = bookId;
    }
    public void setDatabase(BookDBAO database) {
    this.database = database;
    }
    public Book getBook() throws
         BookNotFoundException {
        return (Book)database.getBook(bookId);
     }
    public List getBooks() throws BooksNotFoundException {
        return database.getBooks();
    }
    public void buyBooks(ShoppingCart cart)
         throws OrderException {
        database.buyBooks(cart);
    }
    public int getNumberOfBooks() throws BooksNotFoundException {
        return database.getNumberOfBooks();
    }
}

Creating and Using a JavaBeans Component

To declare that your JSP page will use a JavaBeans component, you use a jsp:useBean element. There are two forms:

<jsp:useBean id="beanName"
    class="fully-qualified-classname" scope="scope"/>

and

<jsp:useBean id="beanName"
    class="fully-qualified-classname" scope="scope">
    <jsp:setProperty .../>
</jsp:useBean>

The second form is used when you want to include jsp:setProperty statements, described in the next section, for initializing bean properties.

The jsp:useBean element declares that the page will use a bean that is stored within and is accessible from the specified scope, which can be application, session, request, or page. If no such bean exists, the statement creates the bean and stores it as an attribute of the scope object (see Using Scope Objects). The value of the id attribute determines the name of the bean in the scope and the identifier used to reference the bean in EL expressions, other JSP elements, and scripting expressions (see Chapter 9, Scripting in JSP Pages). The value supplied for the class attribute must be a fully qualified class name. Note that beans cannot be in the unnamed package. Thus the format of the value must be package-name.class-name.

The following element creates an instance of mypkg.myLocales if none exists, stores it as an attribute of the application scope, and makes the bean available throughout the application by the identifier locales:

<jsp:useBean id="locales" scope="application"
    class="mypkg.MyLocales"/>

Setting JavaBeans Component Properties

The standard way to set JavaBeans component properties in a JSP page is by using the jsp:setProperty element. The syntax of the jsp:setProperty element depends on the source of the property value. Table 5–6 summarizes the various ways to set a property of a JavaBeans component using the jsp:setProperty element.


Note –

    Syntax rules of attribute values used in this table:

  1. beanName must be the same as that specified for the id attribute in a useBean element.

  2. There must be a setPropName method in the JavaBeans component.

  3. paramName must be a request parameter name.


Table 5–6 Valid Bean Property Assignments from String Values

Value Source 

Element Syntax 

String constant 

<jsp:setProperty name="beanName"
   property="propName" value="string-constant"/>

Request parameter 

<jsp:setProperty name="beanName"
   property="propName" param="paramName"/>

Request parameter name that matches bean property 

<jsp:setProperty name="beanName"
   property="propName"/>
<jsp:setProperty name="beanName"
   property="*"/>

Expression 

<jsp:setProperty name="beanName"
   property="propName" value="expression"/>
<jsp:setProperty name="beanName"
   property="propName" >
   <jsp:attribute name="value">
      expression
   </jsp:attribute>
</jsp:setProperty>

A property set from a constant string or request parameter must have one of the types listed in Table 5–7. Because constants and request parameters are strings, the web container automatically converts the value to the property’s type; the conversion applied is shown in the table.

String values can be used to assign values to a property that has a PropertyEditor class. When that is the case, the setAsText(String) method is used. A conversion failure arises if the method throws an IllegalArgumentException.

The value assigned to an indexed property must be an array, and the rules just described apply to the elements.

You use an expression to set the value of a property whose type is a compound Java programming language type. The type returned from an expression must match or be castable to the type of the property.

Table 5–7 Valid Property Value Assignments from String Values

Property Type 

Conversion on String Value 

Bean Property 

Uses setAsText(string-literal)

boolean or Boolean

As indicated in java.lang.Boolean.valueOf(String)

byte or Byte

As indicated in java.lang.Byte.valueOf(String)

char or Character

As indicated in java.lang.String.charAt(0)

double or Double

As indicated in java.lang.Double.valueOf(String)

int or Integer

As indicated in java.lang.Integer.valueOf(String)

float or Float

As indicated in java.lang.Float.valueOf(String)

long or Long

As indicated in java.lang.Long.valueOf(String)

short or Short

As indicated in java.lang.Short.valueOf(String)

Object

new String(string-literal)

The Duke’s Bookstore application demonstrates how to use the setProperty element to set the current book from a request parameter in the database bean in tut-install/javaeetutorial5/examples/web/bookstore2/web/books/bookdetails.jsp:

<c:set var="bid" value="${param.bookId}"/>
<jsp:setProperty name="bookDB" property="bookId"
    value="${bid}" />

The following fragment from the page tut-install/javaeetutorial5/examples/web/bookstore2/web/books/bookshowcart.jsp illustrates how to initialize a BookDB bean with a database object. Because the initialization is nested in a useBean element, it is executed only when the bean is created.

<jsp:useBean id="bookDB" class="database.BookDB" scope="page">
    <jsp:setProperty name="bookDB" property="database"
         value="${bookDBAO}" />
</jsp:useBean>

Retrieving JavaBeans Component Properties

The main way to retrieve JavaBeans component properties is by using the unified EL expressions. Thus, to retrieve a book title, the Duke’s Bookstore application uses the following expression:

${bookDB.bookDetails.title}

Another way to retrieve component properties is to use the jsp:getProperty element. This element converts the value of the property into a String and inserts the value into the response stream:

<jsp:getProperty name="beanName" property="propName"/>

Note that beanName must be the same as that specified for the id attribute in a useBean element, and there must be a getPropName method in the JavaBeans component. Although the preferred approach to getting properties is to use an EL expression, the getProperty element is available if you need to disable expression evaluation.

Using Custom Tags

Custom tags are user-defined JSP language elements that encapsulate recurring tasks. Custom tags are distributed in a tag library, which defines a set of related custom tags and contains the objects that implement the tags.

Custom tags have the syntax

<prefix:tag attr1="value" ... attrN="value" />

or

<prefix:tag attr1="value" ... attrN="value" >
     body</prefix:tag>

where prefix distinguishes tags for a library, tag is the tag identifier, and attr1 ... attrN are attributes that modify the behavior of the tag.

To use a custom tag in a JSP page, you must

See Chapter 8, Custom Tags in JSP Pages for detailed information on the different types of tags and how to implement tags.

Declaring Tag Libraries

To declare that a JSP page will use tags defined in a tag library, you include a taglib directive in the page before any custom tag from that tag library is used. If you forget to include the taglib directive for a tag library in a JSP page, the JSP compiler will treat any invocation of a custom tag from that library as static data and will simply insert the text of the custom tag call into the response.

<%@ taglib prefix="tt" [tagdir=/WEB-INF/tags/dir | uri=URI ] %>

The prefix attribute defines the prefix that distinguishes tags defined by a given tag library from those provided by other tag libraries.

If the tag library is defined with tag files (see Encapsulating Reusable Content Using Tag Files), you supply the tagdir attribute to identify the location of the files. The value of the attribute must start with /WEB-INF/tags/. A translation error will occur if the value points to a directory that doesn’t exist or if it is used in conjunction with the uri attribute.

The uri attribute refers to a URI that uniquely identifies the tag library descriptor (TLD), a document that describes the tag library (see Tag Library Descriptors).

Tag library descriptor file names must have the extension .tld. TLD files are stored in the WEB-INF directory or subdirectory of the WAR file, or in the META-INF directory or subdirectory of a tag library packaged in a JAR. You can reference a TLD directly or indirectly.

The following taglib directive directly references a TLD file name:

<%@ taglib prefix="tlt" uri="/WEB-INF/iterator.tld"%>

This taglib directive uses a short logical name to indirectly reference the TLD:

<%@ taglib prefix="tlt" uri="/tlt"%>

The iterator example defines and uses a simple iteration tag. The JSP pages use a logical name to reference the TLD.

    To deploy and run the iterator application with NetBeans IDE, follow these steps:

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/web/
  3. Select the iterator folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. In the Projects tab, right-click the iterator project, and select Undeploy and Deploy.

  7. To run the application, open the bookstore URL http://localhost:8080/iterator.

    To deploy and run the iterator application with Ant, follow these steps:

  1. In a terminal window, go to tut-install/javaeetutorial5/examples/web/iterator/.

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/iterator/build/ directory, and create a WAR file.

  3. Start the Application Server.

  4. Type ant deploy.

  5. To run the example, open your browser to http://localhost:8080/iterator.

To learn how to configure the example, refer to the deployment descriptor, which includes the following configurations:

The absolute URIs for the JSTL library are as follows:

When you reference a tag library with an absolute URI that exactly matches the URI declared in the taglib element of the TLD (see Tag Library Descriptors), you do not have to add the taglib element to web.xml; the JSP container automatically locates the TLD inside the JSTL library implementation.

Including the Tag Library Implementation

In addition to declaring the tag library, you also must make the tag library implementation available to the web application. There are several ways to do this. Tag library implementations can be included in a WAR in an unpacked format: Tag files are packaged in the /WEB-INF/tag/ directory, and tag handler classes are packaged in the /WEB-INF/classes/ directory of the WAR. Tag libraries already packaged into a JAR file are included in the /WEB-INF/lib/ directory of the WAR. Finally, an application server can load a tag library into all the web applications running on the server. For example, in the Application Server, the JSTL TLDs and libraries are distributed in the archive appserv-jstl.jar in as-install/lib/. This library is automatically loaded into the classpath of all web applications running on the Application Server, so you don’t need to add it to your web application.

The iterator tag library is implemented with tag handlers. Therefore, its implementation classes are packaged in the /WEB-INF/classes/ directory.

Reusing Content in JSP Pages

There are many mechanisms for reusing JSP content in a JSP page. Three mechanisms that can be categorized as direct reuse are discussed here:

An indirect method of content reuse occurs when a tag file is used to define a custom tag that is used by many web applications. Tag files are discussed in the section Encapsulating Reusable Content Using Tag Files in Chapter 8, Custom Tags in JSP Pages.

The include directive is processed when the JSP page is translated into a servlet class. The effect of the directive is to insert the text contained in another file (either static content or another JSP page) into the including JSP page. You would probably use the include directive to include banner content, copyright information, or any chunk of content that you might want to reuse in another page. The syntax for the include directive is as follows:

<%@ include file="filename" %>

For example, all the Duke’s Bookstore application pages could include the file banner.jspf, which contains the banner content, by using the following directive:

<%@ include file="banner.jspf" %>

Another way to do a static include is to use the prelude and coda mechanisms described in Defining Implicit Includes. This is the approach used by the Duke’s Bookstore application.

Because you must put an include directive in each file that reuses the resource referenced by the directive, this approach has its limitations. Preludes and codas can be applied only to the beginnings and ends of pages. For a more flexible approach to building pages out of content chunks, see A Template Tag Library.

The jsp:include element is processed when a JSP page is executed. The include action allows you to include either a static or a dynamic resource in a JSP file. The results of including static and dynamic resources are quite different. If the resource is static, its content is inserted into the calling JSP file. If the resource is dynamic, the request is sent to the included resource, the included page is executed, and then the result is included in the response from the calling JSP page. The syntax for the jsp:include element is:

<jsp:include page="includedPage" />

The hello1 application discussed in Packaging Web Modules uses the following statement to include the page that generates the response:

<jsp:include page="response.jsp"/>

Transferring Control to Another Web Component

The mechanism for transferring control to another web component from a JSP page uses the functionality provided by the Java Servlet API as described in Accessing a Session. You access this functionality from a JSP page by using the jsp:forward element:

<jsp:forward page="/main.jsp" />

Note that if any data has already been returned to a client, the jsp:forward element will fail with an IllegalStateException.

jsp:param Element

When an include or forward element is invoked, the original request object is provided to the target page. If you wish to provide additional data to that page, you can append parameters to the request object by using the jsp:param element:

<jsp:include page="..." >
    <jsp:param name="param1" value="value1"/>
</jsp:include>

When jsp:include or jsp:forward is executed, the included page or forwarded page will see the original request object, with the original parameters augmented with the new parameters and new values taking precedence over existing values when applicable. For example, if the request has a parameter A=foo and a parameter A=bar is specified for forward, the forwarded request will have A=bar,foo. Note that the new parameter has precedence.

The scope of the new parameters is the jsp:include or jsp:forward call; that is, in the case of an jsp:include the new parameters (and values) will not apply after the include.

Including an Applet

You can include an applet or a JavaBeans component in a JSP page by using the jsp:plugin element. This element generates HTML that contains the appropriate client-browser-dependent construct (<object> or <embed>) that will result in the download of the Java Plug-in software (if required) and the client-side component, and in the subsequent execution of any client-side component. The syntax for the jsp:plugin element is as follows:

<jsp:plugin
     type="bean|applet"
     code="objectCode"
     codebase="objectCodebase"
     { align="alignment" }
     { archive="archiveList" }
     { height="height" }
     { hspace="hspace" }
     { jreversion="jreversion" }
     { name="componentName" }
     { vspace="vspace" }
     { width="width" }
     { nspluginurl="url" }
     { iepluginurl="url" } >
     { <jsp:params>
         { <jsp:param name="paramName" value= paramValue" /> }+
    </jsp:params> }
     { <jsp:fallback> arbitrary-text </jsp:fallback> }
 </jsp:plugin>

The jsp:plugin tag is replaced by either an <object> or an <embed> tag as appropriate for the requesting client. The attributes of the jsp:plugin tag provide configuration data for the presentation of the element as well as the version of the plug-in required. The nspluginurl and iepluginurl attributes override the default URL where the plug-in can be downloaded.

The jsp:params element specifies parameters to the applet or JavaBeans component. The jsp:fallback element indicates the content to be used by the client browser if the plug-in cannot be started (either because <object> or <embed> is not supported by the client or because of some other problem).

If the plug-in can start but the applet or JavaBeans component cannot be found or started, a plug-in-specific message will be presented to the user, most likely a pop-up window reporting a ClassNotFoundException.

The Duke’s Bookstore page /template/prelude.jspf creates the banner that displays a dynamic digital clock generated by DigitalClock (see Figure 5–3).

Figure 5–3 Duke’s Bookstore with Applet

Screen capture of Duke's Bookstore with "Web Components
for Web Developers" recommendation, "Start Shopping" link and date and time
applet.

Here is the jsp:plugin element that is used to download the applet:

<jsp:plugin
     type="applet"
     code="DigitalClock.class"
     codebase="/bookstore2"
     jreversion="1.4"
     align="center" height="25" width="300"
    nspluginurl="http://java.sun.com/j2se/1.4.2/download.html"
     iepluginurl="http://java.sun.com/j2se/1.4.2/download.html" >
    <jsp:params>
        <jsp:param name="language"
            value="${pageContext.request.locale.language}" />
        <jsp:param name="country"
            value="${pageContext.request.locale.country}" />
        <jsp:param name="bgcolor" value="FFFFFF" />
        <jsp:param name="fgcolor" value="CC0066" />
    </jsp:params>
    <jsp:fallback>
        <p>Unable to start plugin.</p>
    </jsp:fallback>
</jsp:plugin>

Setting Properties for Groups of JSP Pages

It is possible to specify certain properties for a group of JSP pages:

A JSP property group is defined by naming the group and specifying one or more URL patterns; all the properties in the group apply to the resources that match any of the URL patterns. If a resource matches URL patterns in more than one group, the pattern that is most specific applies.

    To define a property group in a deployment descriptor using NetBeans IDE, follow these steps:

  1. In NetBeans IDE, expand your project’s folder in the Projects pane.

  2. Expand the Web Pages node and then the WEB-INF node.

  3. Double-click web.xml to open it in the editor pane.

  4. Click Pages at the top of the editor pane.

  5. Click Add JSP Property Group.

  6. In the Add JSP Property Group dialog:

    1. Enter a name for the JSP property group in the Display Name field.

    2. Enter a URL pattern (a regular expression, such as *.jsp) or click Browse to indicate to which page or set of pages to apply the properties specified by the JSP property group.

    3. Click OK.

    Instead of performing the preceding steps, you can define a JSP property group by editing the XML by hand using NetBeans IDE by doing the following:

  1. Perform steps 1 through 3 in the preceding set of steps.

  2. Click XML at the top of the editor pane.

  3. Include a jsp-config element if the deployment descriptor doesn’t already have one.

  4. Add a jsp-property-group element inside the jsp-config element.

  5. Add a display-name element inside the jsp-property-group element and give it a name.

  6. Add a url-pattern element inside the jsp-property-group element and give it a URL pattern (a regular expression, such as *.jsp).

The following sections discuss the properties and explain how they are interpreted for various combinations of group properties, individual page directives, and web application deployment descriptor versions.

Deactivating EL Expression Evaluation

Each JSP page has a default mode for EL expression evaluation. The default value varies depending on the version of the web application deployment descriptor. The default mode for JSP pages delivered with a Servlet 2.4 descriptor is to evaluate EL expressions; this automatically provides the default that most applications want. The default mode for JSP pages delivered using a descriptor from Servlet 2.3 or before is to ignore EL expressions; this provides backward compatibility. For tag files (see Encapsulating Reusable Content Using Tag Files), the default is to always evaluate expressions.

You can override the default mode through the isELIgnored attribute of the page directive in JSP pages and through the isELIgnored attribute of the tag directive in tag files. You can also explicitly change the default mode by doing one of the following:

Table 5–8 summarizes the EL evaluation settings for JSP pages.

Table 5–8 EL Evaluation Settings for JSP Pages

JSP Configuration 

Page Directive isELIgnored

EL Encountered 

Unspecified 

Unspecified 

Evaluated if 2.4 web.xml

Ignored if <= 2.3 web.xml

false

Unspecified 

Evaluated 

true

Unspecified 

Ignored 

Overridden by page directive 

false

Evaluated 

Overridden by page directive 

true

Ignored 

Table 5–9 summarizes the EL evaluation settings for tag files.

Table 5–9 EL Evaluation Settings for Tag Files

Tag Directive isELIgnored

EL Encountered 

Unspecified 

Evaluated 

false

Evaluated 

true

Ignored 

Declaring Page Encodings

You set the page encoding of a group of JSP pages using the JSP property group configuration in the deployment descriptor by doing one of the following:

A translation-time error results if you define the page encoding of a JSP page with one value in the JSP configuration element and then give it a different value in a pageEncoding directive.

Defining Implicit Includes

You can implicitly include preludes and codas for a group of JSP pages by adding items to the Include Preludes and Codas lists. Their values are context-relative paths that must correspond to elements in the web application. When the elements are present, the given paths are automatically included (as in an include directive) at the beginning and end, respectively, of each JSP page in the property group. When there is more than one include or coda element in a group, they are included in the order they appear. When more than one JSP property group applies to a JSP page, the corresponding elements will be processed in the same order as they appear in the JSP configuration section.

    For example, the Duke’s Bookstore application uses the files /template/prelude.jspf and /template/coda.jspf to include the banner and other boilerplate in each screen. To add these files to the Duke’s Bookstore property group using the deployment descriptor, follow these steps:

  1. In NetBeans IDE, expand your project’s folder in the Projects pane.

  2. Expand the Web Pages node and then the WEB-INF node.

  3. Double-click web.xml to open it in the editor pane.

  4. Click Pages at the top of the editor pane.

  5. Add a new JSP property group if you haven’t already (see Setting Properties for Groups of JSP Pages) and give it the name bookstore2 and the URL pattern *.jsp.

  6. Expand the JSP Property Group node.

  7. Click the Browse button to the right of the Include Preludes field to locate the file that you want to include at the beginning of all pages matching the pattern in the URL pattern field. In this case, you want the /template/prelude.jspf file.

  8. Click the Browse button to the right of the Include Codas field to locate the file that you want to include at the end of all pages matching the URL pattern. In this case, you want the /template/coda.jspf file.

    Instead of performing the preceding steps, you can add preludes and codas by editing the XML by hand using NetBeans IDE by doing the following:

  1. Perform steps 1 through 3 in the preceding set of steps.

  2. Click XML at the top of the editor pane.

  3. Add a new JSP property group (see Setting Properties for Groups of JSP Pages) and give it the name bookstore2 and URL pattern *.jsp.

  4. Add an include-prelude element to the jsp-property-group element and give it the name of the file to include, in this case, /template/prelude.jspf.

  5. Add an include-coda element to the jsp-property-group element and give it the name of the file to include, in this case, /template/coda.jspf.

Preludes and codas can put the included code only at the beginning and end of each file. For a more flexible approach to building pages out of content chunks, see A Template Tag Library.

Eliminating Extra White Space

White space included in the template text of JSP pages is preserved by default. This can have undesirable effects. For example, a carriage return added after a taglib directive would be added to the response output as an extra line.

If you want to eliminate the extra white space from the page, you can add a trim-directive-whitespaces element to a jsp-property-group element in the deployment descriptor and set it to true.

    To set the trim-directive-whitespaces element to true using NetBeans 5.5, do the following:

  1. Open the deployment descriptor file in the editor.

  2. Click the Pages button at the top of the editor.

  3. Select a JSP property group.

  4. Select the Trim Directive Whitespaces check box.

  5. Save the deployment descriptor.

Alternatively, a page author can set the value of the trimDirectiveWhitespaces attribute of the page directive to true or false. This will override the value specified in the deployment descriptor.

Custom tag authors can eliminate white space from the output generated by a tag file by setting the trimDirectiveWhiteSpace attribute of the tag directive to true.

Further Information about JavaServer Pages Technology

For more information on JavaServer Pages technology, see: