The Java EE 5 Tutorial

Part II The Web Tier

Part Two explores the technologies in the web tier.

Chapter 3 Getting Started with Web Applications

A web application is a dynamic extension of a web or application server. There are two types of web applications:

Web Applications

In the Java 2 platform, web components provide the dynamic extension capabilities for a web server. Web components are either Java servlets, JSP pages, or web service endpoints. The interaction between a web client and a web application is illustrated in Figure 3–1. The client sends an HTTP request to the web server. A web server that implements Java Servlet and JavaServer Pages technology converts the request into an HTTPServletRequest object. This object is delivered to a web component, which can interact with JavaBeans components or a database to generate dynamic content. The web component can then generate an HTTPServletResponse or it can pass the request to another web component. Eventually a web component generates a HTTPServletResponse object. The web server converts this object to an HTTP response and returns it to the client.

Figure 3–1 Java Web Application Request Handling

Diagram of web application request handling. Clients
and web components communicate using HttpServletRequest and HttpServletResponse.

Servlets are Java programming language classes that dynamically process requests and construct responses. JSP pages are text-based documents that execute as servlets but allow a more natural approach to creating static content. Although servlets and JSP pages can be used interchangeably, each has its own strengths. Servlets are best suited for service-oriented applications (web service endpoints are implemented as servlets) and the control functions of a presentation-oriented application, such as dispatching requests and handling nontextual data. JSP pages are more appropriate for generating text-based markup such as HTML, Scalable Vector Graphics (SVG), Wireless Markup Language (WML), and XML.

Since the introduction of Java Servlet and JSP technology, additional Java technologies and frameworks for building interactive web applications have been developed. Figure 3–2 illustrates these technologies and their relationships.

Figure 3–2 Java Web Application Technologies

Diagram of web application technologies. JavaServer Pages,
the JSP Standard Tag Library, and JavaServer Faces rest on JavaServlet technology.

Notice that Java Servlet technology is the foundation of all the web application technologies, so you should familiarize yourself with the material in Chapter 4, Java Servlet Technology even if you do not intend to write servlets. Each technology adds a level of abstraction that makes web application prototyping and development faster and the web applications themselves more maintainable, scalable, and robust.

Web components are supported by the services of a runtime platform called a web container. A web container provides services such as request dispatching, security, concurrency, and life-cycle management. It also gives web components access to APIs such as naming, transactions, and email.

Certain aspects of web application behavior can be configured when the application is installed, or deployed, to the web container. The configuration information is maintained in a text file in XML format called a web application deployment descriptor (DD). A DD must conform to the schema described in the Java Servlet Specification.

This chapter gives a brief overview of the activities involved in developing web applications. First it summarizes the web application life cycle. Then it describes how to package and deploy very simple web applications on the Application Server. It moves on to configuring web applications and discusses how to specify the most commonly used configuration parameters. It then introduces an example, Duke’s Bookstore, which illustrates all the Java EE web-tier technologies, and describes how to set up the shared components of this example. Finally it discusses how to access databases from web applications and set up the database resources needed to run Duke’s Bookstore.

Web Application Life Cycle

A web application consists of web components, static resource files such as images, and helper classes and libraries. The web container provides many supporting services that enhance the capabilities of web components and make them easier to develop. However, because a web application must take these services into account, the process for creating and running a web application is different from that of traditional stand-alone Java classes.

    The process for creating, deploying, and executing a web application can be summarized as follows:

  1. Develop the web component code.

  2. Develop the web application deployment descriptor.

  3. Compile the web application components and helper classes referenced by the components.

  4. Optionally package the application into a deployable unit.

  5. Deploy the application into a web container.

  6. Access a URL that references the web application.

Developing web component code is covered in the later chapters. Steps 2 through 4 are expanded on in the following sections and illustrated with a Hello, World-style presentation-oriented application. This application allows a user to enter a name into an HTML form (Figure 3–3) and then displays a greeting after the name is submitted (Figure 3–4).

Figure 3–3 Greeting Form

Screen capture of Duke's greeting, "Hello, my name is
Duke. What's yours?" Includes a text field for your name and Submit and Reset
buttons.

Figure 3–4 Response

Screen capture of Duke's response, "Hello, Charlie!"

The Hello application contains two web components that generate the greeting and the response. This chapter discusses two versions of the application: a JSP version called hello1, in which the components are implemented by two JSP pages (tut-install/javaeetutorial5/examples/web/hello1/web/index.jsp and tut-install/javaeetutorial5/examples/web/hello1/web/response.jsp) and a servlet version called hello2, in which the components are implemented by two servlet classes (tut-install/javaeetutorial5/examples/web/hello2/src/servlets/GreetingServlet.java and tut-install/javaeetutorial5/examples/web/hello2/src/servlets/ResponseServlet.java). The two versions are used to illustrate tasks involved in packaging, deploying, configuring, and running an application that contains web components. The section Chapter 2, Using the Tutorial Examples explains how to get the code for these examples.

After you install the tutorial bundle, the source code for the examples is in the following directories:

Web Modules

In the Java EE architecture, web components and static web content files such as images are called web resources. A web module is the smallest deployable and usable unit of web resources. A Java EE web module corresponds to a web application as defined in the Java Servlet specification.

In addition to web components and web resources, a web module can contain other files:

A web module has a specific structure. The top-level directory of a web module is the document root of the application. The document root is where JSP pages, client-side classes and archives, and static web resources, such as images, are stored.

The document root contains a subdirectory named WEB-INF, which contains the following files and directories:

If your web module does not contain any servlets, filter, or listener components then it does not need a web application deployment descriptor. In other words, if your web module only contains JSP pages and static files then you are not required to include a web.xml file. The hello1 example, first discussed in Packaging Web Modules, contains only JSP pages and images and therefore does not include a deployment descriptor.

You can also create application-specific subdirectories (that is, package directories) in either the document root or the WEB-INF/classes/ directory.

A web module can be deployed as an unpacked file structure or can be packaged in a JAR file known as a web archive (WAR) file. Because the contents and use of WAR files differ from those of JAR files, WAR file names use a .war extension. The web module just described is portable; you can deploy it into any web container that conforms to the Java Servlet Specification.

To deploy a WAR on the Application Server, the file must also contain a runtime deployment descriptor. The runtime deployment descriptor is an XML file that contains information such as the context root of the web application and the mapping of the portable names of an application’s resources to the Application Server’s resources. The Application Server web application runtime DD is named sun-web.xml and is located in the WEB-INF directory along with the web application DD. The structure of a web module that can be deployed on the Application Server is shown in Figure 3–5.

Figure 3–5 Web Module Structure

Diagram of web module structure. WEB-INF and web pages
are under the root. Under WEB-INF are descriptors and the lib, classes, and
tags directories.

Packaging Web Modules

A web module must be packaged into a WAR in certain deployment scenarios and whenever you want to distribute the web module. You package a web module into a WAR by executing the jar command in a directory laid out in the format of a web module, by using the Ant utility, or by using the IDE tool of your choice. This tutorial shows you how to use NetBeans IDE or Ant to build, package, and deploy the sample applications.

    To build the hello1 application with NetBeans IDE, follow these instructions:

  1. Select File->Open Project.

  2. In the Open Project dialog, navigate to:


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

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. In the Projects tab, right-click the hello1 project and select Build.

    To build the hello1 application using the Ant utility, follow these steps:

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

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

Deploying a WAR File

You can deploy a WAR file to the Application Server in a few ways:

All these methods are described briefly in this chapter; however, throughout the tutorial, you will use ant and NetBeans IDE for packaging and deploying.

Setting the Context Root

A context root identifies a web application in a Java EE server. You specify the context root when you deploy a web module. A context root must start with a forward slash (/) and end with a string.

In a packaged web module for deployment on the Application Server, the context root is stored in sun-web.xml.

    To edit the context root, do the following:

  1. Expand your project tree in the Projects pane of NetBeans IDE.

  2. Expand the Web Pages and WEB-INF nodes of your project.

  3. Double-click sun-web.xml.

  4. In the editor pane, click Edit As XML.

  5. Edit the context root, which is enclosed by the context-root element.

Deploying a Packaged Web Module

If you have deployed the hello1 application, before proceeding with this section, undeploy the application by following one of the procedures described in Undeploying Web Modules.

Deploying with the Admin Console

  1. Expand the Applications node.

  2. Select the Web Applications node.

  3. Click the Deploy button.

  4. Select the radio button labeled “Package file to be uploaded to the Application Server.”

  5. Type the full path to the WAR file (or click on Browse to find it), and then click the OK button.

  6. Click Next.

  7. Type the application name.

  8. Type the context root.

  9. Select the Enabled box.

  10. Click the Finish button.

Deploying with asadmin

To deploy a WAR with asadmin, open a terminal window or command prompt and execute


asadmin deploy full-path-to-war-file

Deploying with Ant

To deploy a WAR with the Ant tool, open a terminal window or command prompt in the directory where you built and packaged the WAR, and execute


ant deploy

Deploying with NetBeans IDE

    To deploy a WAR with NetBeans IDE, do the following:

  1. Select File->Open Project.

  2. In the Open Project dialog, navigate to your project and open it.

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

Testing Deployed Web Modules

Now that the web module is deployed, you can view it by opening the application in a web browser. By default, the application is deployed to host localhost on port 8080. The context root of the web application is hello1.

    To test the application, follow these steps:

  1. Open a web browser.

  2. Enter the following URL in the web address box:


    http://localhost:8080/hello1
  3. Enter your name, and click Submit.

The application should display the name you submitted as shown in Figure 3–3 and Figure 3–4.

Listing Deployed Web Modules

The Application Server provides two ways to view the deployed web modules: the Admin Console and the asadmin command.

    To use the Admin Console:

  1. Open the URL http://localhost:4848/asadmin in a browser.

  2. Expand the nodes Applications->Web Applications.

Use the asadmin command as follows:


asadmin list-components

Updating Web Modules

    A typical iterative development cycle involves deploying a web module and then making changes to the application components. To update a deployed web module, you must do the following:

  1. Recompile any modified classes.

  2. If you have deployed a packaged web module, update any modified components in the WAR.

  3. Redeploy the module.

  4. Reload the URL in the client.

Updating a Packaged Web Module

This section describes how to update the hello1 web module that you packaged.

First, change the greeting in the file tut-install/javaeetutorial5/examples/web/hello1/web/index.jsp to

<h2>Hi, my name is Duke. What’s yours?</h2>

To update the project in NetBeans IDE:

To update the project using the Ant build tool:

To view the modified module, reload the URL in the browser.

You should see the screen in Figure 3–6 in the browser.

Figure 3–6 New Greeting

Screen capture of Duke's new greeting, "Hi, my name is
Duke. What's yours?" Includes a text field for your name and Submit and Reset
buttons.

Dynamic Reloading

If dynamic reloading is enabled, you do not have to redeploy an application or module when you change its code or deployment descriptors. All you have to do is copy the changed JSP or class files into the deployment directory for the application or module. The deployment directory for a web module named context-root is domain-dir/applications/j2ee-modules/context-root. The server checks for changes periodically and redeploys the application, automatically and dynamically, with the changes.

This capability is useful in a development environment, because it allows code changes to be tested quickly. Dynamic reloading is not recommended for a production environment, however, because it may degrade performance. In addition, whenever a reload is done, the sessions at that time become invalid and the client must restart the session.

    To enable dynamic reloading, use the Admin Console:

  1. Select the Applications Server node.

  2. Select the Advanced tab.

  3. Check the Reload Enabled box to enable dynamic reloading.

  4. Enter a number of seconds in the Reload Poll Interval field to set the interval at which applications and modules are checked for code changes and dynamically reloaded.

  5. Click the Save button.

    In addition, to load new servlet files or reload deployment descriptor changes, you must do the following:

  1. Create an empty file named .reload at the root of the module:


    domain-dir/applications/j2ee-modules/context-root/.reload
  2. Explicitly update the .reload file’s time stamp each time you make these changes. On UNIX, execute


    touch .reload
    

For JSP pages, changes are reloaded automatically at a frequency set in the Reload Poll Interval field. To disable dynamic reloading of JSP pages, set the Reload Poll Interval field value to –1.

Undeploying Web Modules

You can undeploy web modules in four ways: you can use NetBeans IDE, the Admin Console, the asadmin command, or the Ant tool.

    To use NetBeans IDE:

  1. Ensure the Sun Java System Application Server is running.

  2. In the Runtime window, expand the Sun Java System Application Server instance and the node containing the application or module.

  3. Right-click the application or module and choose Undeploy.

    To use the Admin Console:

  1. Open the URL http://localhost:4848/asadmin in a browser.

  2. Expand the Applications node.

  3. Select Web Applications.

  4. Click the check box next to the module you wish to undeploy.

  5. Click the Undeploy button.

Use the asadmin command as follows:


asadmin undeploy context-root

To use the Ant tool, execute the following command in the directory where you built and packaged the WAR:


ant undeploy

Configuring Web Applications

Web applications are configured by means of elements contained in the web application deployment descriptor.

The following sections give a brief introduction to the web application features you will usually want to configure. A number of security parameters can be specified; these are covered in Chapter 30, Securing Web Applications.

In the following sections, examples demonstrate procedures for configuring the Hello, World application. If Hello, World does not use a specific configuration feature, the section gives references to other examples that illustrate how to specify the deployment descriptor element.

Mapping URLs to Web Components

When a request is received by the web container it must determine which web component should handle the request. It does so by mapping the URL path contained in the request to a web application and a web component. A URL path contains the context root and an alias:


http://host:port/context-root/alias

Setting the Component Alias

The alias identifies the web component that should handle a request. The alias path must start with a forward slash (/) and end with a string or a wildcard expression with an extension (for example, *.jsp). Since web containers automatically map an alias that ends with *.jsp, you do not have to specify an alias for a JSP page unless you wish to refer to the page by a name other than its file name.

    The hello2 application has two servlets that need to be mapped in the web.xml file. You can edit a web application’s web.xml file in NetBeans IDE by doing the following:

  1. Select File->Open Project.

  2. In the Open Project dialog, navigate to:


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

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. Expand the project tree in the Projects pane.

  7. Expand the Web pages node and then the WEB-INF node in the project tree.

  8. Double-click the web.xml file inside the WEB-INF node.

The following steps describe how to make the necessary edits to the web.xml file, including how to set the display name and how to map the servlet components. Because the edits are already in the file, you can just use the steps to view the settings.

    To set the display name:

  1. Click General at the top of the editor to open the general view.

  2. Enter hello2 in the Display Name field.

    To perform the servlet mappings:

  1. Click Servlets at the top of the editor to open the servlets view.

  2. Click Add Servlet.

  3. In the Add Servlet dialog, enter GreetingServlet in the Servlet Name field.

  4. Enter servlets.GreetingServlet in the Servlet Class field.

  5. Enter /greeting in the URL Pattern field.

  6. Click OK.

  7. Repeat the preceding steps, except enter ResponseServlet as the servlet name, servlets.ResponseServlet as the servlet class, and /response as the URL pattern.

If you are not using NetBeans IDE, you can add these settings using a text editor.

    To package the example with NetBeans IDE, do the following:

  1. Select File->Open Project.

  2. In the Open Project dialog, navigate to:


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

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. In the Projects tab, right-click the hello2 project and select Build.

    To package the example with the Ant utility, do the following:

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

  2. Type ant. This target will build the WAR file and copy it to the tut-install/javaeetutorial5/examples/web/hello2/dist/ directory.

To deploy the example using NetBeans IDE, right-click on the project in the Projects pane and select Undeploy and Deploy.

To deploy the example using Ant, type ant deploy. The deploy target in this case gives you an incorrect URL to run the application. To run the application, please use the URL shown at the end of this section.

To run the application, first deploy the web module, and then open the URL http://localhost:8080/hello2/greeting in a browser.

Declaring Welcome Files

The welcome files mechanism allows you to specify a list of files that the web container will use for appending to a request for a URL (called a valid partial request) that is not mapped to a web component.

For example, suppose you define a welcome file welcome.html. When a client requests a URL such as host:port/webapp/directory, where directory is not mapped to a servlet or JSP page, the file host:port/webapp/directory/welcome.html is returned to the client.

If a web container receives a valid partial request, the web container examines the welcome file list and appends to the partial request each welcome file in the order specified and checks whether a static resource or servlet in the WAR is mapped to that request URL. The web container then sends the request to the first resource in the WAR that matches.

If no welcome file is specified, the Application Server will use a file named index.XXX, where XXX can be html or jsp, as the default welcome file. If there is no welcome file and no file named index.XXX, the Application Server returns a directory listing.

    To specify a welcome file in the web application deployment descriptor using NetBeans IDE, do the following:

  1. Open the project if you haven’t already.

  2. Expand the project’s node in the Projects pane.

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

  4. Double-click web.xml.

  5. Do one of the following, making sure that the JSP pages you specify are actually included in the WAR file:

    1. Click Pages at the top of the editor pane and enter the names of the JSP pages that act as welcome files in the Welcome Files field.

    2. Click XML at the top of the editor pane, specify the JSP pages using welcome-file elements and include these elements inside a welcome-file-list element. The welcome-file element defines the JSP page to be used as the welcome page.

      The example discussed in Encapsulating Reusable Content Using Tag Files has a welcome file.

Setting Initialization Parameters

The web components in a web module share an object that represents their application context (see Accessing the Web Context). You can pass initialization parameters to the context or to a web component.

    To add a context parameter using NetBeans IDE, do the following:

  1. Open the project if you haven’t already.

  2. Expand the project’s node in the Projects pane.

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

  4. Double-click web.xml.

  5. Click General at the top of the editor pane.

  6. Select the Context Parameters node.

  7. Click Add.

  8. In the Add Context Parameter dialog, do the following:

    1. Enter the name that specifies the context object in the Param Name field.

    2. Enter the parameter to pass to the context object in the Param Value field.

    3. Click OK.

Alternatively, you can edit the XML of the web.xml file directly by clicking XML at the top of the editor pane and using the following elements to add a context parameter:

For a sample context parameter, see the example discussed in The Example JSP Pages.

    To add a web component initialization parameter using NetBeans IDE, do the following:

  1. Open the project if you haven’t already.

  2. Expand the project’s node in the Projects pane.

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

  4. Double-click web.xml.

  5. Click Servlets at the top of the editor pane.

  6. After entering the servlet’s name, class, and URL pattern, click the Add button under the Initialization Parameters table.

  7. In the Add Initialization Parameter dialog:

    1. Enter the name of the parameter in the Param Name field.

    2. Enter the parameter’s value in the Param Value Field.

    3. Click OK.

Alternatively, you can edit the XML of the web.xml file directly by clicking XML at the top of the editor pane and using the following elements to add a context parameter:

Mapping Errors to Error Screens

When an error occurs during execution of a web application, you can have the application display a specific error screen according to the type of error. In particular, you can specify a mapping between the status code returned in an HTTP response or a Java programming language exception returned by any web component (see Handling Servlet Errors) and any type of error screen.

    To set up error mappings using NetBeans IDE, do the following:

  1. Open the project if you haven’t already.

  2. Expand the project’s node in the Projects pane.

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

  4. Double-click web.xml.

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

  6. Expand the Error Pages node.

  7. Click Add.

  8. In the Add Error Page dialog:

    1. Click Browse to locate the page that you want to act as the error page.

    2. Enter the HTTP status code that will cause the error page to be opened in the Error Code field.

    3. Enter the exception that will cause the error page to load in the Exception Type field.

    4. Click OK.

Alternatively, you can click XML at the top of the editor pane and enter the error page mapping by hand using the following elements:

You can have multiple error-page elements in your deployment descriptor. Each one of the elements identifies a different error that causes an error page to open. This error page can be the same for any number of error-page elements.


Note –

You can also define error screens for a JSP page contained in a WAR. If error screens are defined for both the WAR and a JSP page, the JSP page’s error page takes precedence. See Handling JSP Page Errors.


For a sample error page mapping, see the example discussed in The Example Servlets.

Declaring Resource References

If your web component uses objects such as enterprise beans, data sources, or web services, you use Java EE annotations to inject these resources into your application. Annotations eliminate a lot of the boilerplate lookup code and configuration elements that previous versions of Java EE required.

Although resource injection using annotations can be more convenient for the developer, there are some restrictions from using it in web applications. First, you can only inject resources into container-managed objects. This is because a container must have control over the creation of a component so that it can perform the injection into a component. As a result, you cannot inject resources into objects such as simple JavaBeans components. However, JavaServer Faces managed beans are managed by the container; therefore, they can accept resource injections.

Additionally, JSP pages cannot accept resource injections. This is because the information represented by annotations must be available at deployment time, but the JSP page is compiled after that; therefore, the annotation will not be seen when it is needed. Those components that can accept resource injections are listed in Table 3–1.

This section describes how to use a couple of the annotations supported by a servlet container to inject resources. Chapter 25, Persistence in the Web Tier describes how web applications use annotations supported by the Java Persistence API. Chapter 30, Securing Web Applications describes how to use annotations to specify information about securing web applications.

Table 3–1 Web Components That Accept Resource Injections

Component 

Interface/Class 

Servlets 

javax.servlet.Servlet

Servlet Filters 

javax.servlet.ServletFilter

Event Listeners 

javax.servlet.ServletContextListener

javax.servlet.ServletContextAttributeListener

javax.servlet.ServletRequestListener

javax.servlet.ServletRequestAttributeListener

javax.servlet.http.HttpSessionListener

javax.servlet.http.HttpSessionAttributeListener

javax.servlet.http.HttpSessionBindingListener

Taglib Listeners 

Same as above 

Taglib Tag Handlers 

javax.servlet.jsp.tagext.JspTag

Managed Beans 

Plain Old Java Objects 

Declaring a Reference to a Resource

The @Resource annotation is used to declare a reference to a resource such as a data source, an enterprise bean, or an environment entry. This annotation is equivalent to declaring a resource-ref element in the deployment descriptor.

The @Resource annotation is specified on a class, method or field. The container is responsible for injecting references to resources declared by the @Resource annotation and mapping it to the proper JNDI resources. In the following example, the @Resource annotation is used to inject a data source into a component that needs to make a connection to the data source, as is done when using JDBC technology to access a relational database:

@Resource javax.sql.DataSource catalogDS;
public getProductsByCategory() {
    // get a connection and execute the query
    Connection conn = catalogDS.getConnection();
    ..
}

The container injects this data source prior to the component being made available to the application. The data source JNDI mapping is inferred from the field name catalogDS and the type, javax.sql.DataSource.

If you have multiple resources that you need to inject into one component, you need to use the @Resources annotation to contain them, as shown by the following example:

@Resources ({
    @Resource (name="myDB" type=java.sql.DataSource),
    @Resource(name="myMQ" type=javax.jms.ConnectionFactory)
})

The web application examples in this tutorial use the Java Persistence API to access relational databases. This API does not require you to explicitly create a connection to a data source. Therefore, the examples do not use the @Resource annotation to inject a data source. However, this API supports the @PersistenceUnit and @PersistenceContext annotations for injecting EntityManagerFactory and EntityManager instances, respectively. Chapter 25, Persistence in the Web Tier describes these annotations and the use of the Java Persistence API in web applications.

Declaring a Reference to a Web Service

The @WebServiceRef annotation provides a reference to a web service. The following example shows uses the @WebServiceRef annotation to declare a reference to a web service. WebServiceRef uses the wsdlLocation element to specify the URI of the deployed service’s WSDL file:

...
import javax.xml.ws.WebServiceRef;
...
public class ResponseServlet extends HTTPServlet {
@WebServiceRef(wsdlLocation=
    "http://localhost:8080/helloservice/hello?wsdl")
static HelloService service;

Duke’s Bookstore Examples

In Chapters Chapter 4, Java Servlet Technology through Chapter 15, Internationalizing and Localizing Web Applications a common example, Duke’s Bookstore, is used to illustrate the elements of Java Servlet technology, JavaServer Pages technology, the JSP Standard Tag Library, and JavaServer Faces technology. The example emulates a simple online shopping application. It provides a book catalog from which users can select books and add them to a shopping cart. Users can view and modify the shopping cart. When users are finished shopping, they can purchase the books in the cart.

The Duke’s Bookstore examples share common classes and a database schema. These files are located in the directory tut-install/javaeetutorial5/examples/web/bookstore/. The common classes are packaged into a JAR. Each of the Duke’s Bookstore examples must include this JAR file in their WAR files. The process that builds and packages each application also builds and packages the common JAR file and includes it in the example WAR file.

The next section describes how to create the bookstore database tables and resources required to run the examples.

Accessing Databases from Web Applications

Data that is shared between web components and is persistent between invocations of a web application is usually maintained in a database. To maintain a catalog of books, the Duke’s Bookstore examples described in Chapters Chapter 4, Java Servlet Technology through Chapter 15, Internationalizing and Localizing Web Applications use the Java DB database included with the Application Server.

To access the data in a database, web applications use the new Java Persistence API (see Chapter 24, Introduction to the Java Persistence API). See Chapter 25, Persistence in the Web Tier to learn how the Duke’s Bookstore applications use this API to access the book data.

To run the Duke’s Bookstore applications, you need to first populate the database with the book data and create a data source in the application server. The rest of this section explains how to perform these tasks.

Populating the Example Database

    When you deploy any of the Duke’s Bookstore applications using ant deploy, the database is automatically populated at the same time. If you want to populate the database separately from the deploy task or are using NetBeans IDE to deploy the application, follow these steps:

  1. In a terminal window, go to the books directory or any one of the bookstore1 through bookstore6 example directories.

  2. Start the Java DB database server. For instructions, see Starting and Stopping the Java DB Database Server. You don’t have to do this if you are using NetBeans IDE. It starts the database server automatically.

  3. Type ant create-tables. This task runs a command to read the file tutorial.sql and execute the SQL commands contained in the file.

  4. At the end of the processing, you should see the following output:


    ...
    [sql] 181 of 181 SQL statements executed successfully

When you are running create-tables, don’t worry if you see a message that an SQL statement failed. This usually happens the first time you run the command because it always tries to delete an existing database table first before it creates a new one. The first time through, there is no table yet, of course.

Creating a Data Source in the Application Server

A DataSource object has a set of properties that identify and describe the real world data source that it represents. These properties include information such as the location of the database server, the name of the database, the network protocol to use to communicate with the server, and so on.

Data sources in the Application Server implement connection pooling. To define the Duke’s Bookstore data source, you use the installed Derby connection pool named DerbyPool.

    You create the data source using the Application Server Admin Console, following this procedure:

  1. Expand the Resources node.

  2. Expand the JDBC node.

  3. Select the JDBC Resources node.

  4. Click the New... button.

  5. Type jdbc/BookDB in the JNDI Name field.

  6. Choose DerbyPool for the Pool Name.

  7. Click OK.

Further Information about Web Applications

For more information on web applications, see:

Chapter 4 Java Servlet Technology

As soon as the web began to be used for delivering services, service providers recognized the need for dynamic content. Applets, one of the earliest attempts toward this goal, focused on using the client platform to deliver dynamic user experiences. At the same time, developers also investigated using the server platform for this purpose. Initially, Common Gateway Interface (CGI) scripts were the main technology used to generate dynamic content. Although widely used, CGI scripting technology has a number of shortcomings, including platform dependence and lack of scalability. To address these limitations, Java Servlet technology was created as a portable way to provide dynamic, user-oriented content.

What Is a Servlet?

A servlet is a Java programming language class that is used to extend the capabilities of servers that host applications accessed by means of a request-response programming model. Although servlets can respond to any type of request, they are commonly used to extend the applications hosted by web servers. For such applications, Java Servlet technology defines HTTP-specific servlet classes.

The javax.servlet and javax.servlet.http packages provide interfaces and classes for writing servlets. All servlets must implement the Servlet interface, which defines life-cycle methods. When implementing a generic service, you can use or extend the GenericServlet class provided with the Java Servlet API. The HttpServlet class provides methods, such as doGet and doPost, for handling HTTP-specific services.

This chapter focuses on writing servlets that generate responses to HTTP requests.

The Example Servlets

This chapter uses the Duke’s Bookstore application to illustrate the tasks involved in programming servlets. The source code for the bookstore application is located in the tut-install/javaeetutorial5/examples/web/bookstore1/ directory, which is created when you unzip the tutorial bundle (see Building the Examples).

Table 4–1 lists the servlets that handle each bookstore function. You can find these servlet classes in tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/. Each programming task is illustrated by one or more servlets. For example, BookDetailsServlet illustrates how to handle HTTP GET requests, BookDetailsServlet and CatalogServlet show how to construct responses, and CatalogServlet illustrates how to track session information.

Table 4–1 Duke’s Bookstore Example Servlets

Function 

Servlet 

Enter the bookstore 

BookStoreServlet

Create the bookstore banner 

BannerServlet

Browse the bookstore catalog 

CatalogServlet

Put a book in a shopping cart 

CatalogServlet,

BookDetailsServlet

Get detailed information on a specific book 

BookDetailsServlet

Display the shopping cart 

ShowCartServlet

Remove one or more books from the shopping cart 

ShowCartServlet

Buy the books in the shopping cart 

CashierServlet

Send an acknowledgment of the purchase 

ReceiptServlet

The data for the bookstore application is maintained in a database and accessed through the database access class database.BookDBAO. The database package also contains the class Book which represents a book. The shopping cart and shopping cart items are represented by the classes cart.ShoppingCart and cart.ShoppingCartItem, respectively.

    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 bookstore1 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 bookstore1 project, and select Undeploy and Deploy.

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

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

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

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore1/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore1/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/bookstore1/bookstore.

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

Troubleshooting Duke's Bookstore Database Problems

The Duke’s Bookstore database access object returns the following exceptions:

Because you have specified an error page, you will see the message


The application is unavailable. Please try later.

If you don’t specify an error page, the web container generates a default page containing the message


A Servlet Exception Has Occurred

and a stack trace that can help you diagnose the cause of the exception. If you use errorpage.html, you will have to look in the server log to determine the cause of the exception.

Servlet Life Cycle

The life cycle of a servlet is controlled by the container in which the servlet has been deployed. When a request is mapped to a servlet, the container performs the following steps.

  1. If an instance of the servlet does not exist, the web container

    1. Loads the servlet class.

    2. Creates an instance of the servlet class.

    3. Initializes the servlet instance by calling the init method. Initialization is covered in Initializing a Servlet.

  2. Invokes the service method, passing request and response objects. Service methods are discussed in Writing Service Methods.

If the container needs to remove the servlet, it finalizes the servlet by calling the servlet’s destroy method. Finalization is discussed in Finalizing a Servlet.

Handling Servlet Life-Cycle Events

You can monitor and react to events in a servlet’s life cycle by defining listener objects whose methods get invoked when life-cycle events occur. To use these listener objects you must define and specify the listener class.

Defining the Listener Class

You define a listener class as an implementation of a listener interface. Table 4–2 lists the events that can be monitored and the corresponding interface that must be implemented. When a listener method is invoked, it is passed an event that contains information appropriate to the event. For example, the methods in the HttpSessionListener interface are passed an HttpSessionEvent, which contains an HttpSession.

Table 4–2 Servlet Life-Cycle Events

Object 

Event 

Listener Interface and Event Class 

Web context (see Accessing the Web Context)

Initialization and destruction 

javax.servlet.ServletContextListener and

ServletContextEvent

Attribute added, removed, or replaced 

javax.servlet.ServletContextAttributeListener and

ServletContextAttributeEvent

Session (See Maintaining Client State)

Creation, invalidation, activation, passivation, and timeout 

javax.servlet.http.HttpSessionListener, javax.servlet.http.HttpSessionActivationListener, and

HttpSessionEvent

Attribute added, removed, or replaced 

javax.servlet.http.HttpSessionAttributeListener and

HttpSessionBindingEvent

Request 

A servlet request has started being processed by web components 

javax.servlet.ServletRequestListener and

ServletRequestEvent

Attribute added, removed, or replaced 

javax.servlet.ServletRequestAttributeListener and

ServletRequestAttributeEvent

The tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/listeners/ContextListener class creates and removes the database access and counter objects used in the Duke’s Bookstore application. The methods retrieve the web context object from ServletContextEvent and then store (and remove) the objects as servlet context attributes.

import database.BookDBAO;
import javax.servlet.*;
import util.Counter;

import javax.ejb.*;
import javax.persistence.*;

public final class ContextListener
    implements ServletContextListener {
    private ServletContext context = null;

    @PersistenceUnit
    EntityManagerFactory emf;

    public void contextInitialized(ServletContextEvent event) {
        context = event.getServletContext();
        try {
            BookDBAO bookDB = new BookDBAO(emf);
            context.setAttribute("bookDB", bookDB);
        } catch (Exception ex) {
            System.out.println(
                "Couldn’t create database: " + ex.getMessage());
        }
        Counter counter = new Counter();
        context.setAttribute("hitCounter", counter);
        counter = new Counter();
        context.setAttribute("orderCounter", counter);
    }

    public void contextDestroyed(ServletContextEvent event) {
        context = event.getServletContext();
        BookDBAO bookDB = context.getAttribute("bookDB");
        bookDB.remove();
        context.removeAttribute("bookDB");
        context.removeAttribute("hitCounter");
        context.removeAttribute("orderCounter");
    }
}

Specifying Event Listener Classes

You specify an event listener class using the listener element of the deployment descriptor. Review The Example Servlets for information on how to specify the ContextListener listener class.

    You can specify an event listener using the deployment descriptor editor of NetBeans IDE by doing the following:

  1. Expand your application’s project node.

  2. Expand the project’s Web Pages and WEB-INF nodes.

  3. Double-click web.xml.

  4. Click General at the top of the web.xml editor.

  5. Expand the Web Application Listeners node.

  6. Click Add.

  7. In the Add Listener dialog, click Browse to locate the listener class.

  8. Click OK.

Handling Servlet Errors

Any number of exceptions can occur when a servlet executes. When an exception occurs, the web container generates a default page containing the message


A Servlet Exception Has Occurred

But you can also specify that the container should return a specific error page for a given exception. Review the deployment descriptor file included with the example to learn how to map the exceptions exception.BookNotFound, exception.BooksNotFound, and exception.OrderException returned by the Duke’s Bookstore application to errorpage.html.

See Mapping Errors to Error Screens for instructions on how to specify error pages using NetBeans IDE.

Sharing Information

Web components, like most objects, usually work with other objects to accomplish their tasks. There are several ways they can do this. They can use private helper objects (for example, JavaBeans components), they can share objects that are attributes of a public scope, they can use a database, and they can invoke other web resources. The Java Servlet technology mechanisms that allow a web component to invoke other web resources are described in Invoking Other Web Resources.

Using Scope Objects

Collaborating web components share information by means of objects that are maintained as attributes of four scope objects. You access these attributes using the [get|set]Attribute methods of the class representing the scope. Table 4–3 lists the scope objects.

Table 4–3 Scope Objects

Scope Object 

Class 

Accessible From 

Web context 

javax.servlet.ServletContext

Web components within a web context. See Accessing the Web Context.

Session 

javax.servlet.http.HttpSession

Web components handling a request that belongs to the session. See Maintaining Client State.

Request 

subtype of javax.servlet.ServletRequest

Web components handling the request. 

Page 

javax.servlet.jsp.JspContext

The JSP page that creates the object. See Using Implicit Objects.

Figure 4–1 shows the scoped attributes maintained by the Duke’s Bookstore application.

Figure 4–1 Duke’s Bookstore Scoped Attributes

Diagram of Duke's Bookstore scoped attributes. Session
attributes are currency and cart, web context attributes are hitCounter, bookDB,
orderCounter.

Controlling Concurrent Access to Shared Resources

In a multithreaded server, it is possible for shared resources to be accessed concurrently. In addition to scope object attributes, shared resources include in-memory data (such as instance or class variables) and external objects such as files, database connections, and network connections.

Concurrent access can arise in several situations:

When resources can be accessed concurrently, they can be used in an inconsistent fashion. To prevent this, you must control the access using the synchronization techniques described in the Threads lesson in The Java Tutorial, Fourth Edition, by Sharon Zakhour et al. (Addison-Wesley, 2006).

The preceding section showed five scoped attributes shared by more than one servlet: bookDB, cart, currency, hitCounter, and orderCounter. The bookDB attribute is discussed in the next section. The cart, currency, and counters can be set and read by multiple multithreaded servlets. To prevent these objects from being used inconsistently, access is controlled by synchronized methods. For example, here is the Counter class, located at tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/util/:

public class Counter {
    private int counter;
    public Counter() {
        counter = 0;
    }
    public synchronized int getCounter() {
        return counter;
    }
    public synchronized int setCounter(int c) {
        counter = c;
        return counter;
    }
    public synchronized int incCounter() {
        return(++counter);
    }
}

Accessing Databases

Data that is shared between web components and is persistent between invocations of a web application is usually maintained by a database. Web components use the Java Persistence API to access relational databases. The data for Duke’s Bookstore is maintained in a database and is accessed through the database access class tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/database/BookDBAO. For example, ReceiptServlet invokes the BookDBAO.buyBooks method to update the book inventory when a user makes a purchase. The buyBooks method invokes buyBook for each book contained in the shopping cart, as shown in the following code.

public void buyBooks(ShoppingCart cart) throws OrderException{

    Collection items = cart.getItems();
    Iterator i = items.iterator();
    
    try {
        while (i.hasNext()) {
            ShoppingCartItem sci = (ShoppingCartItem)i.next();
            Book bd = (Book)sci.getItem();
            String id = bd.getBookId();
            int quantity = sci.getQuantity();
            buyBook(id, quantity);
        }
    } catch (Exception ex) {
        throw new OrderException("Commit failed: " +
            ex.getMessage());
     }
}

public void buyBook(String bookId, int quantity)
     throws OrderException {

    try {
        Book requestedBook = em.find(Book.class, bookId);
        
        if (requestedBook != null) {
            int inventory = requestedBook.getInventory();
            if ((inventory - quantity) >= 0) {
                int newInventory = inventory - quantity;
                requestedBook.setInventory(newInventory);
            } else{
                throw new OrderException("Not enough of "
                     + bookId + " in stock to complete order.");
            }
        }
    } catch (Exception ex) {
        throw new OrderException("Couldn’t purchase book: "
             + bookId + ex.getMessage());
    }
}

To ensure that the order is processed in its entirety, the call to buyBooks is wrapped in a single transaction. In the following code, the calls to the begin and commit methods of UserTransaction mark the boundaries of the transaction. The call to the rollback method of UserTransaction undoes the effects of all statements in the transaction so as to protect the integrity of the data.

try {
    utx.begin();
    bookDB.buyBooks(cart);
    utx.commit();
} catch (Exception ex) {
    try {
        utx.rollback();
    } catch(Exception e) {
        System.out.println("Rollback failed: "+e.getMessage());
    }
    System.err.println(ex.getMessage());
    orderCompleted = false;}
}

Initializing a Servlet

After the web container loads and instantiates the servlet class and before it delivers requests from clients, the web container initializes the servlet. To customize this process to allow the servlet to read persistent configuration data, initialize resources, and perform any other one-time activities, you override the init method of the Servlet interface. A servlet that cannot complete its initialization process should throw UnavailableException.

All the servlets that access the bookstore database (BookStoreServlet, CatalogServlet, BookDetailsServlet, and ShowCartServlet) initialize a variable in their init method that points to the database access object created by the web context listener:

public class CatalogServlet extends HttpServlet {
    private BookDBAO bookDB;
    public void init() throws ServletException {
        bookDB = (BookDBAO)getServletContext().
            getAttribute("bookDB");
        if (bookDB == null) throw new
            UnavailableException("Couldn’t get database.");
    }
}

Writing Service Methods

The service provided by a servlet is implemented in the service method of a GenericServlet, in the doMethod methods (where Method can take the value Get, Delete, Options, Post, Put, or Trace) of an HttpServlet object, or in any other protocol-specific methods defined by a class that implements the Servlet interface. In the rest of this chapter, the term service method is used for any method in a servlet class that provides a service to a client.

The general pattern for a service method is to extract information from the request, access external resources, and then populate the response based on that information.

For HTTP servlets, the correct procedure for populating the response is to first retrieve an output stream from the response, then fill in the response headers, and finally write any body content to the output stream. Response headers must always be set before the response has been committed. Any attempt to set or add headers after the response has been committed will be ignored by the web container. The next two sections describe how to get information from requests and generate responses.

Getting Information from Requests

A request contains data passed between a client and the servlet. All requests implement the ServletRequest interface. This interface defines methods for accessing the following information:

For example, in CatalogServlet the identifier of the book that a customer wishes to purchase is included as a parameter to the request. The following code fragment illustrates how to use the getParameter method to extract the identifier:

String bookId = request.getParameter("Add");
if (bookId != null) {
    Book book = bookDB.getBook(bookId);

You can also retrieve an input stream from the request and manually parse the data. To read character data, use the BufferedReader object returned by the request’s getReader method. To read binary data, use the ServletInputStream returned by getInputStream.

HTTP servlets are passed an HTTP request object, HttpServletRequest, which contains the request URL, HTTP headers, query string, and so on.

An HTTP request URL contains the following parts:


http://[host]:[port][request-path]?[query-string]

The request path is further composed of the following elements:

If the context path is /catalog and for the aliases listed in Table 4–4, Table 4–5 gives some examples of how the URL will be parsed.

Table 4–4 Aliases

Pattern 

Servlet 

/lawn/*

LawnServlet

/*.jsp

JSPServlet

Table 4–5 Request Path Elements

Request Path 

Servlet Path 

Path Info 

/catalog/lawn/index.html

/lawn

/index.html

/catalog/help/feedback.jsp

/help/feedback.jsp

null

Query strings are composed of a set of parameters and values. Individual parameters are retrieved from a request by using the getParameter method. There are two ways to generate query strings:

Constructing Responses

A response contains data passed between a server and the client. All responses implement the ServletResponse interface. This interface defines methods that allow you to:

HTTP response objects, HttpServletResponse, have fields representing HTTP headers such as the following:

In Duke’s Bookstore, BookDetailsServlet generates an HTML page that displays information about a book that the servlet retrieves from a database. The servlet first sets response headers: the content type of the response and the buffer size. The servlet buffers the page content because the database access can generate an exception that would cause forwarding to an error page. By buffering the response, the servlet prevents the client from seeing a concatenation of part of a Duke’s Bookstore page with the error page should an error occur. The doGet method then retrieves a PrintWriter from the response.

To fill in the response, the servlet first dispatches the request to BannerServlet, which generates a common banner for all the servlets in the application. This process is discussed in Including Other Resources in the Response. Then the servlet retrieves the book identifier from a request parameter and uses the identifier to retrieve information about the book from the bookstore database. Finally, the servlet generates HTML markup that describes the book information and then commits the response to the client by calling the close method on the PrintWriter.

public class BookDetailsServlet extends HttpServlet {
     ...
     public void doGet (HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        ...
        // set headers before accessing the Writer
        response.setContentType("text/html");
        response.setBufferSize(8192);
        PrintWriter out = response.getWriter();

        // then write the response
        out.println("<html>" +
            "<head><title>+
            messages.getString("TitleBookDescription")
            +</title></head>");

        // Get the dispatcher; it gets the banner to the user
        RequestDispatcher dispatcher =
            getServletContext().
            getRequestDispatcher("/banner");
        if (dispatcher != null)
            dispatcher.include(request, response);

        // Get the identifier of the book to display
        String bookId = request.getParameter("bookId");
        if (bookId != null) {
            // and the information about the book
            try {
                Book bd =
                    bookDB.getBook(bookId);
                ...
                // Print the information obtained
                out.println("<h2>" + bd.getTitle() + "</h2>" +
                ...
            } catch (BookNotFoundException ex) {
                response.resetBuffer();
                throw new ServletException(ex);
            }
        }
        out.println("</body></html>");
        out.close();
    }
}

BookDetailsServlet generates a page that looks like Figure 4–2.

Figure 4–2 Book Details

Screen capture of book details. Shows "Web Servers for
Fun and Profit" author, review, and price, with links "Add to Cart" and "Continue
Shopping."

Filtering Requests and Responses

A filter is an object that can transform the header and content (or both) of a request or response. Filters differ from web components in that filters usually do not themselves create a response. Instead, a filter provides functionality that can be “attached” to any kind of web resource. Consequently, a filter should not have any dependencies on a web resource for which it is acting as a filter; this way it can be composed with more than one type of web resource.

The main tasks that a filter can perform are as follows:

Applications of filters include authentication, logging, image conversion, data compression, encryption, tokenizing streams, XML transformations, and so on.

You can configure a web resource to be filtered by a chain of zero, one, or more filters in a specific order. This chain is specified when the web application containing the component is deployed and is instantiated when a web container loads the component.

In summary, the tasks involved in using filters are

Programming Filters

The filtering API is defined by the Filter, FilterChain, and FilterConfig interfaces in the javax.servlet package. You define a filter by implementing the Filter interface.

The most important method in this interface is doFilter, which is passed request, response, and filter chain objects. This method can perform the following actions:

In addition to doFilter, you must implement the init and destroy methods. The init method is called by the container when the filter is instantiated. If you wish to pass initialization parameters to the filter, you retrieve them from the FilterConfig object passed to init.

The Duke’s Bookstore application uses the filters HitCounterFilter and OrderFilter, located at tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/filters/, to increment and log the value of counters when the entry and receipt servlets are accessed.

In the doFilter method, both filters retrieve the servlet context from the filter configuration object so that they can access the counters stored as context attributes. After the filters have completed application-specific processing, they invoke doFilter on the filter chain object passed into the original doFilter method. The elided code is discussed in the next section.

public final class HitCounterFilter implements Filter {
    private FilterConfig filterConfig = null;

    public void init(FilterConfig filterConfig)
         throws ServletException {
        this.filterConfig = filterConfig;
    }
    public void destroy() {
        this.filterConfig = null;
    }
    public void doFilter(ServletRequest request,
        ServletResponse response, FilterChain chain)
         throws IOException, ServletException {
        if (filterConfig == null)
            return;
        StringWriter sw = new StringWriter();
        PrintWriter writer = new PrintWriter(sw);
        Counter counter = (Counter)filterConfig.
            getServletContext().
            getAttribute("hitCounter");
        writer.println();
        writer.println("===============");
        writer.println("The number of hits is: " +
            counter.incCounter());
        writer.println("===============");
        // Log the resulting string
        writer.flush();
        System.out.println(sw.getBuffer().toString());
        ...
        chain.doFilter(request, wrapper);
        ...
    }
}

Programming Customized Requests and Responses

There are many ways for a filter to modify a request or response. For example, a filter can add an attribute to the request or can insert data in the response. In the Duke’s Bookstore example, HitCounterFilter inserts the value of the counter into the response.

A filter that modifies a response must usually capture the response before it is returned to the client. To do this, you pass a stand-in stream to the servlet that generates the response. The stand-in stream prevents the servlet from closing the original response stream when it completes and allows the filter to modify the servlet’s response.

To pass this stand-in stream to the servlet, the filter creates a response wrapper that overrides the getWriter or getOutputStream method to return this stand-in stream. The wrapper is passed to the doFilter method of the filter chain. Wrapper methods default to calling through to the wrapped request or response object. This approach follows the well-known Wrapper or Decorator pattern described in Design Patterns, Elements of Reusable Object-Oriented Software, by Erich Gamma et al. (Addison-Wesley, 1995). The following sections describe how the hit counter filter described earlier and other types of filters use wrappers.

To override request methods, you wrap the request in an object that extends ServletRequestWrapper or HttpServletRequestWrapper. To override response methods, you wrap the response in an object that extends ServletResponseWrapper or HttpServletResponseWrapper.

HitCounterFilter wraps the response in a tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/filters/CharResponseWrapper. The wrapped response is passed to the next object in the filter chain, which is BookStoreServlet. Then BookStoreServlet writes its response into the stream created by CharResponseWrapper. When chain.doFilter returns, HitCounterFilter retrieves the servlet’s response from PrintWriter and writes it to a buffer. The filter inserts the value of the counter into the buffer, resets the content length header of the response, and then writes the contents of the buffer to the response stream.

PrintWriter out = response.getWriter();
CharResponseWrapper wrapper = new CharResponseWrapper(
    (HttpServletResponse)response);
chain.doFilter(request, wrapper);
CharArrayWriter caw = new CharArrayWriter();
caw.write(wrapper.toString().substring(0,
    wrapper.toString().indexOf("</body>")-1));
caw.write("<p>\n<center>" +
     messages.getString("Visitor") + "<font color=’red’>" +
     counter.getCounter() + "</font></center>");
caw.write("\n</body></html>");
response.setContentLength(caw.toString().getBytes().length);
out.write(caw.toString());
out.close();

public class CharResponseWrapper extends
    HttpServletResponseWrapper {
    private CharArrayWriter output;
    public String toString() {
        return output.toString();
    }
    public CharResponseWrapper(HttpServletResponse response){
        super(response);
        output = new CharArrayWriter();
    }
    public PrintWriter getWriter(){
        return new PrintWriter(output);
    }
}

Figure 4–3 shows the entry page for Duke’s Bookstore with the hit counter.

Figure 4–3 Duke’s Bookstore with Hit Counter

Screen capture of Duke's Bookstore with "Web Components
for Web Developers" recommendation, "Start Shopping" link and "You are visitor
number 2."

Specifying Filter Mappings

A web container uses filter mappings to decide how to apply filters to web resources. A filter mapping matches a filter to a web component by name, or to web resources by URL pattern. The filters are invoked in the order in which filter mappings appear in the filter mapping list of a WAR. You specify a filter mapping list for a WAR in its deployment descriptor, either with NetBeans IDE or by coding the list by hand with XML.

    To declare the filter and map it to a web resource using NetBeans IDE, do the following:

  1. Expand the application’s project node in the Project pane.

  2. Expand the Web Pages and WEB-INF nodes under the project node.

  3. Double-click web.xml.

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

  5. Expand the Servlet Filters node in the editor pane.

  6. Click Add Filter Element to map the filter to a web resource by name or by URL pattern.

  7. In the Add Servlet Filter dialog, enter the name of the filter in the Filter Name field.

  8. Click Browse to locate the servlet class to which the filter applies. You can include wildcard characters so that you can apply the filter to more than one servlet.

  9. Click OK.

    To constrain how the filter is applied to requests, do the following:

  1. Expand the Filter Mappings node in the Filters tab of the editor pane.

  2. Select the filter from the list of filters.

  3. Click Add.

  4. In the Add Filter Mapping dialog, select one of the following dispatcher types:

    • REQUEST: Only when the request comes directly from the client

    • FORWARD: Only when the request has been forwarded to a component (see Transferring Control to Another Web Component)

    • INCLUDE: Only when the request is being processed by a component that has been included (see Including Other Resources in the Response)

    • ERROR: Only when the request is being processed with the error page mechanism (see Handling Servlet Errors)

      You can direct the filter to be applied to any combination of the preceding situations by selecting multiple dispatcher types. If no types are specified, the default option is REQUEST.

    You can declare, map, and constrain the filter by editing the XML in the web application deployment descriptor directly by following these steps:

  1. While in the web.xml editor pane in NetBeans IDE, click XML at the top of the editor pane.

  2. Declare the filter by adding a filter element right after the display-name element. The filter element creates a name for the filter and declares the filter’s implementation class and initialization parameters.

  3. Map the filter to a web resource by name or by URL pattern using the filter-mapping element:

    1. Include a filter-name element that specifies the name of the filter as defined by the filter element.

    2. Include a servlet-name element that specifies to which servlet the filter applies. The servlet-name element can include wildcard characters so that you can apply the filter to more than one servlet.

  4. Constrain how the filter will be applied to requests by specifying one of the enumerated dispatcher options (described in step 4 of the preceding set of steps) with the dispatcher element and adding the dispatcher element to the filter-mapping element.

    You can direct the filter to be applied to any combination of the preceding situations by including multiple dispatcher elements. If no elements are specified, the default option is REQUEST.

If you want to log every request to a web application, you map the hit counter filter to the URL pattern /*. Table 4–6 summarizes the filter definition and mapping list for the Duke’s Bookstore application. The filters are matched by servlet name, and each filter chain contains only one filter.

Table 4–6 Duke’s Bookstore Filter Definition and Mapping List

Filter 

Class 

Servlet 

HitCounterFilter

filters.HitCounterFilter

BookStoreServlet

OrderFilter

filters.OrderFilter

ReceiptServlet

You can map a filter to one or more web resources and you can map more than one filter to a web resource. This is illustrated in Figure 4–4, where filter F1 is mapped to servlets S1, S2, and S3, filter F2 is mapped to servlet S2, and filter F3 is mapped to servlets S1 and S2.

Figure 4–4 Filter-to-Servlet Mapping

Diagram of filter-to-servlet mapping with filters F1-F3
and servlets S1-S3. F1 filters S1-S3, then F2 filters S2, then F3 filters
S1 and S2.

Recall that a filter chain is one of the objects passed to the doFilter method of a filter. This chain is formed indirectly by means of filter mappings. The order of the filters in the chain is the same as the order in which filter mappings appear in the web application deployment descriptor.

When a filter is mapped to servlet S1, the web container invokes the doFilter method of F1. The doFilter method of each filter in S1’s filter chain is invoked by the preceding filter in the chain by means of the chain.doFilter method. Because S1’s filter chain contains filters F1 and F3, F1’s call to chain.doFilter invokes the doFilter method of filter F3. When F3’s doFilter method completes, control returns to F1’s doFilter method.

Invoking Other Web Resources

Web components can invoke other web resources in two ways: indirectly and directly. A web component indirectly invokes another web resource when it embeds a URL that points to another web component in content returned to a client. In the Duke’s Bookstore application, most web components contain embedded URLs that point to other web components. For example, ShowCartServlet indirectly invokes the CatalogServlet through the following embedded URL:

/bookstore1/catalog

A web component can also directly invoke another resource while it is executing. There are two possibilities: The web component can include the content of another resource, or it can forward a request to another resource.

To invoke a resource available on the server that is running a web component, you must first obtain a RequestDispatcher object using the getRequestDispatcher("URL") method.

You can get a RequestDispatcher object from either a request or the web context; however, the two methods have slightly different behavior. The method takes the path to the requested resource as an argument. A request can take a relative path (that is, one that does not begin with a /), but the web context requires an absolute path. If the resource is not available or if the server has not implemented a RequestDispatcher object for that type of resource, getRequestDispatcher will return null. Your servlet should be prepared to deal with this condition.

Including Other Resources in the Response

It is often useful to include another web resource (for example, banner content or copyright information) in the response returned from a web component. To include another resource, invoke the include method of a RequestDispatcher object:

include(request, response);

If the resource is static, the include method enables programmatic server-side includes. If the resource is a web component, the effect of the method is to send the request to the included web component, execute the web component, and then include the result of the execution in the response from the containing servlet. An included web component has access to the request object, but it is limited in what it can do with the response object:

The banner for the Duke’s Bookstore application is generated by BannerServlet. Note that both doGet and doPost are implemented because BannerServlet can be dispatched from either method in a calling servlet.

public class BannerServlet extends HttpServlet {
     public void doGet (HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
            output(request, response);
    }
    public void doPost (HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
            output(request, response);
}

private void output(HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("<body bgcolor=\"#ffffff\">" +
        "<center>" + "<hr> <br> &nbsp;" + "<h1>" +
        "<font size=\"+3\" color=\"#CC0066\">Duke’s </font>" +
        <img src=\"" + request.getContextPath() +
        "/duke.books.gif\">" +
         "<font size=\"+3\" color=\"black\">Bookstore</font>" +
        "</h1>" + "</center>" + "<br> &nbsp; <hr> <br> ");
    }
}

Each servlet in the Duke’s Bookstore application includes the result from BannerServlet using the following code:

RequestDispatcher dispatcher =
    getServletContext().getRequestDispatcher("/banner");
if (dispatcher != null)
    dispatcher.include(request, response);
}

Transferring Control to Another Web Component

In some applications, you might want to have one web component do preliminary processing of a request and have another component generate the response. For example, you might want to partially process a request and then transfer to another component depending on the nature of the request.

To transfer control to another web component, you invoke the forward method of a RequestDispatcher. When a request is forwarded, the request URL is set to the path of the forwarded page. The original URI and its constituent parts are saved as request attributes javax.servlet.forward.[request-uri|context-path|servlet-path|path-info|query-string]. The tut-install/javaeetutorial5/examples/web/bookstore2/src/java/com/sun/bookstore2/dispatcher/Dispatcher servlet, used by a version of the Duke’s Bookstore application described in The Example JSP Pages, saves the path information from the original URL, retrieves a RequestDispatcher from the request, and then forwards to the JSP page, tut-install/javaeetutorial5/examples/web/bookstore3/web/template/template.jsp.

public class Dispatcher extends HttpServlet {
    public void doGet(HttpServletRequest request,
         HttpServletResponse response) {
        RequestDispatcher dispatcher = request.
            getRequestDispatcher("/template.jsp");
        if (dispatcher != null)
            dispatcher.forward(request, response);
    }
    public void doPost(HttpServletRequest request,
     ...
}

The forward method should be used to give another resource responsibility for replying to the user. If you have already accessed a ServletOutputStream or PrintWriter object within the servlet, you cannot use this method; doing so throws an IllegalStateException.

Accessing the Web Context

The context in which web components execute is an object that implements the ServletContext interface. You retrieve the web context using the getServletContext method. The web context provides methods for accessing:

The web context is used by the Duke’s Bookstore filters HitCounterFilter and OrderFilter, which are discussed in Filtering Requests and Responses. Each filter stores a counter as a context attribute. Recall from Controlling Concurrent Access to Shared Resources that the counter’s access methods are synchronized to prevent incompatible operations by servlets that are running concurrently. A filter retrieves the counter object using the context’s getAttribute method. The incremented value of the counter is recorded in the log.

public final class HitCounterFilter implements Filter {
    private FilterConfig filterConfig = null;
    public void doFilter(ServletRequest request,
        ServletResponse response, FilterChain chain)
         throws IOException, ServletException {
        ...
        StringWriter sw = new StringWriter();
        PrintWriter writer = new PrintWriter(sw);
        ServletContext context = filterConfig.
            getServletContext();
        Counter counter = (Counter)context.
            getAttribute("hitCounter");
        ...
        writer.println("The number of hits is: " +
            counter.incCounter());
        ...
        System.out.println(sw.getBuffer().toString());
        ...
    }
}

Maintaining Client State

Many applications require that a series of requests from a client be associated with one another. For example, the Duke’s Bookstore application saves the state of a user’s shopping cart across requests. Web-based applications are responsible for maintaining such state, called a session, because HTTP is stateless. To support applications that need to maintain state, Java Servlet technology provides an API for managing sessions and allows several mechanisms for implementing sessions.

Accessing a Session

Sessions are represented by an HttpSession object. You access a session by calling the getSession method of a request object. This method returns the current session associated with this request, or, if the request does not have a session, it creates one.

Associating Objects with a Session

You can associate object-valued attributes with a session by name. Such attributes are accessible by any web component that belongs to the same web context and is handling a request that is part of the same session.

The Duke’s Bookstore application stores a customer’s shopping cart as a session attribute. This allows the shopping cart to be saved between requests and also allows cooperating servlets to access the cart. CatalogServlet adds items to the cart; ShowCartServlet displays, deletes items from, and clears the cart; and CashierServlet retrieves the total cost of the books in the cart.

public class CashierServlet extends HttpServlet {
     public void doGet (HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {

        // Get the user’s session and shopping cart
        HttpSession session = request.getSession();
        ShoppingCart cart =
            (ShoppingCart)session.
                getAttribute("cart");
         ...
        // Determine the total price of the user’s books
        double total = cart.getTotal();

Notifying Objects That Are Associated with a Session

Recall that your application can notify web context and session listener objects of servlet life-cycle events (Handling Servlet Life-Cycle Events). You can also notify objects of certain events related to their association with a session such as the following:

Session Management

Because there is no way for an HTTP client to signal that it no longer needs a session, each session has an associated timeout so that its resources can be reclaimed. The timeout period can be accessed by using a session’s [get|set]MaxInactiveInterval methods.

    You can also set the timeout period in the deployment descriptor using NetBeans IDE:

  1. Open the web.xml file in the web.xml editor.

  2. Click General at the top of the editor.

  3. Enter an integer value in the Session Timeout field. The integer value represents the number of minutes of inactivity that must pass before the session times out.

To ensure that an active session is not timed out, you should periodically access the session by using service methods because this resets the session’s time-to-live counter.

When a particular client interaction is finished, you use the session’s invalidate method to invalidate a session on the server side and remove any session data. The bookstore application’s ReceiptServlet is the last servlet to access a client’s session, so it has the responsibility to invalidate the session:

public class ReceiptServlet extends HttpServlet {
     public void doPost(HttpServletRequest request,
                    HttpServletResponse response)
                     throws ServletException, IOException {
        // Get the user’s session and shopping cart
        HttpSession session = request.getSession();
        // Payment received -- invalidate the session
        session.invalidate();
        ...

Session Tracking

A web container can use several methods to associate a session with a user, all of which involve passing an identifier between the client and the server. The identifier can be maintained on the client as a cookie, or the web component can include the identifier in every URL that is returned to the client.

If your application uses session objects, you must ensure that session tracking is enabled by having the application rewrite URLs whenever the client turns off cookies. You do this by calling the response’s encodeURL(URL) method on all URLs returned by a servlet. This method includes the session ID in the URL only if cookies are disabled; otherwise, it returns the URL unchanged.

The doGet method of ShowCartServlet encodes the three URLs at the bottom of the shopping cart display page as follows:

out.println("<p> &nbsp; <p><strong><a href=\"" +
    response.encodeURL(request.getContextPath() +
        "/bookcatalog") +
        "\">" + messages.getString("ContinueShopping") +
        "</a> &nbsp; &nbsp; &nbsp;" +
        "<a href=\"" +
    response.encodeURL(request.getContextPath() +
        "/bookcashier") +
        "\">" + messages.getString("Checkout") +
        "</a> &nbsp; &nbsp; &nbsp;" +
        "<a href=\"" +
     response.encodeURL(request.getContextPath() +
        "/bookshowcart?Clear=clear") +
        "\">" + messages.getString("ClearCart") +
        "</a></strong>");

If cookies are turned off, the session is encoded in the Check Out URL as follows:


http://localhost:8080/bookstore1/cashier;jsessionid=c0o7fszeb1

If cookies are turned on, the URL is simply


http://localhost:8080/bookstore1/cashier

Finalizing a Servlet

When a servlet container determines that a servlet should be removed from service (for example, when a container wants to reclaim memory resources or when it is being shut down), the container calls the destroy method of the Servlet interface. In this method, you release any resources the servlet is using and save any persistent state. The following destroy method releases the database object created in the init method described in Initializing a Servlet:

public void destroy() {
    bookDB = null;
}

All of a servlet’s service methods should be complete when a servlet is removed. The server tries to ensure this by calling the destroy method only after all service requests have returned or after a server-specific grace period, whichever comes first. If your servlet has operations that take a long time to run (that is, operations that may run longer than the server’s grace period), the operations could still be running when destroy is called. You must make sure that any threads still handling client requests complete; the remainder of this section describes how to do the following:

Tracking Service Requests

To track service requests, include in your servlet class a field that counts the number of service methods that are running. The field should have synchronized access methods to increment, decrement, and return its value.

public class ShutdownExample extends HttpServlet {
    private int serviceCounter = 0;
    ...
    // Access methods for serviceCounter
    protected synchronized void enteringServiceMethod() {
        serviceCounter++;
    }
    protected synchronized void leavingServiceMethod() {
        serviceCounter--;
    }
    protected synchronized int numServices() {
        return serviceCounter;
    }
}

The service method should increment the service counter each time the method is entered and should decrement the counter each time the method returns. This is one of the few times that your HttpServlet subclass should override the service method. The new method should call super.service to preserve the functionality of the original service method:

protected void service(HttpServletRequest req,
                    HttpServletResponse resp)
                    throws ServletException,IOException {
    enteringServiceMethod();
    try {
        super.service(req, resp);
    } finally {
        leavingServiceMethod();
    }
}

Notifying Methods to Shut Down

To ensure a clean shutdown, your destroy method should not release any shared resources until all the service requests have completed. One part of doing this is to check the service counter. Another part is to notify the long-running methods that it is time to shut down. For this notification, another field is required. The field should have the usual access methods:

public class ShutdownExample extends HttpServlet {
    private boolean shuttingDown;
    ...
    //Access methods for shuttingDown
    protected synchronized void setShuttingDown(boolean flag) {
        shuttingDown = flag;
    }
    protected synchronized boolean isShuttingDown() {
        return shuttingDown;
    }
}

Here is an example of the destroy method using these fields to provide a clean shutdown:

public void destroy() {
    /* Check to see whether there are still service methods /*
    /* running, and if there are, tell them to stop. */
    if (numServices() > 0) {
        setShuttingDown(true);
    }

    /* Wait for the service methods to stop. */
    while(numServices() > 0) {
        try {
            Thread.sleep(interval);
        } catch (InterruptedException e) {
        }
    }
}

Creating Polite Long-Running Methods

The final step in providing a clean shutdown is to make any long-running methods behave politely. Methods that might run for a long time should check the value of the field that notifies them of shutdowns and should interrupt their work, if necessary.

public void doPost(...) {
    ...
    for(i = 0; ((i < lotsOfStuffToDo) &&
         !isShuttingDown()); i++) {
        try {
            partOfLongRunningOperation(i);
        } catch (InterruptedException e) {
            ...
        }
    }
}

Further Information about Java Servlet Technology

For more information on Java Servlet technology, see:

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:

Chapter 6 JavaServer Pages Documents

A JSP document is a JSP page written in XML syntax as opposed to the standard syntax described in Chapter 5, JavaServer Pages Technology. Because it is written in XML syntax, a JSP document is also an XML document and therefore gives you all the benefits offered by the XML standard:

In addition to these benefits, the XML syntax gives the JSP page author less complexity and more flexibility. For example, a page author can use any XML document as a JSP document. Also, elements in XML syntax can be used in JSP pages written in standard syntax, allowing a gradual transition from JSP pages to JSP documents.

This chapter gives you details on the benefits of JSP documents and uses a simple example to show you how easy it is to create a JSP document.

You can also write tag files in XML syntax. This chapter covers only JSP documents. Writing tag files in XML syntax will be addressed in a future release of the tutorial.

The Example JSP Document

This chapter uses the Duke’s Bookstore application, version bookstore5, and the books application to demonstrate how to write JSP pages in XML syntax. The JSP pages of the bookstore5 application use the JSTL XML tags (see XML Tag Library) to manipulate the book data from an XML stream. The books application contains the JSP document books.jspx, which accesses the book data from the database and converts it into the XML stream. The bookstore5 application accesses this XML stream to get the book data.

These applications show how easy it is to generate XML data and stream it between web applications. The books application can be considered the application hosted by the book warehouse’s server. The bookstore5 application can be considered the application hosted by the book retailer’s server. In this way, the customer of the bookstore web site sees the list of books currently available, according to the warehouse’s database.

The source for the Duke’s Bookstore application is located in the tut-install/javaeetutorial5/examples/web/bookstore5/ directory, which is created when you unzip the tutorial bundle (see Chapter 2, Using the Tutorial Examples).

    To deploy the books 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 books 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 books project, and select Undeploy and Deploy.

    To deploy the books application using the Ant utility, follow these steps:

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

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

  3. To deploy the application, type ant deploy.

    To deploy and run the bookstore5 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 bookstore5 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 bookstore5 project, and select Undeploy and Deploy.

  8. To run the applications, open the bookstore URL http://localhost:8080/bookstore5/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/bookstore5/.

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore5/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore5/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 applications, open the bookstore URL http://localhost:8080/bookstore5/books/bookstore.

To learn how to configure the bookstore5 example, refer to the web.xml file, which includes the following configurations:

To learn how to configure the books example, refer to the web.xml file, which includes the following configurations:

Creating a JSP Document

A JSP document is an XML document and therefore must comply with the XML standard. Fundamentally, this means that a JSP document must be well formed, meaning that each start tag must have a corresponding end tag and that the document must have only one root element. In addition, JSP elements included in the JSP document must comply with the XML syntax.

Much of the standard JSP syntax is already XML-compliant, including all the standard actions. Those elements that are not compliant are summarized in Table 6–1 along with the equivalent elements in XML syntax. As you can see, JSP documents are not much different from JSP pages. If you know standard JSP syntax, you will find it easy to convert your current JSP pages to XML syntax and to create new JSP documents.

Table 6–1 Standard Syntax Versus XML Syntax

Syntax Elements 

Standard Syntax 

XML Syntax 

Comments 

<%--.. --%>

<!-- .. -->

Declarations 

<%! ..%>

<jsp:declaration> .. </jsp:declaration>

Directives 

<%@ include .. %>

<jsp:directive.include .. />

<%@ page .. %>

<jsp:directive.page .. />

<%@ taglib .. %>

xmlns:prefix="tag library URL"

Expressions 

<%= ..%>

<jsp:expression> .. </jsp:expression>

Scriptlets 

<% ..%>

<jsp:scriptlet> .. </jsp:scriptlet>

To illustrate how simple it is to transition from standard syntax to XML syntax, let’s convert a simple JSP page to a JSP document. The standard syntax version is as follows:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
     prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions"
     prefix="fn" %>
<html>
    <head><title>Hello</title></head>
    <body bgcolor="white">
        <img src="duke.waving.gif">
         <h2>My name is Duke. What is yours?</h2>
         <form method="get">
            <input type="text" name="username" size="25">
            <p></p>
            <input type="submit" value="Submit">
            <input type="reset" value="Reset">
        </form>
        <jsp:useBean id="userNameBean" class="hello.UserNameBean"
                 scope="request"/>
        <jsp:setProperty name="userNameBean" property="name"
                 value="${param.username}" />
        <c:if test="${fn:length(userNameBean.name) > 0}" >
            <%@include file="response.jsp" %>
        </c:if>
    </body>
</html>

Here is the same page in XML syntax:

<html
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions" >
    <head><title>Hello</title></head>
    <body bgcolor="white" />
    <img src="duke.waving.gif" />
     <h2>My name is Duke. What is yours?</h2>
     <form method="get">
        <input type="text" name="username" size="25" />
        <p></p>
        <input type="submit" value="Submit" />
        <input type="reset" value="Reset" />
    </form>
    <jsp:useBean id="userNameBean" class="hello.UserNameBean"
         scope="request"/>
    <jsp:setProperty name="userNameBean" property="name"
         value="${param.username}" />
    <c:if test="${fn:length(userNameBean.name) gt 0}" >
        <jsp:directive.include="response.jsp" />
    </c:if>
    </body>
</html>

As you can see, a number of constructs that are legal in standard syntax have been changed to comply with XML syntax:

With only these few small changes, when you save the file with a .jspx extension, this page is a JSP document.

Using the example described in The Example JSP Document, the rest of this chapter gives you more details on how to transition from standard syntax to XML syntax. It explains how to use XML namespaces to declare tag libraries, include directives, and create static and dynamic content in your JSP documents. It also describes jsp:root and jsp:output, two elements that are used exclusively in JSP documents.

Declaring Tag Libraries

This section explains how to use XML namespaces to declare tag libraries.

In standard syntax, the taglib directive declares tag libraries used in a JSP page. Here is an example of a taglib directive:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

This syntax is not allowed in JSP documents. To declare a tag library in a JSP document, you use the xmlns attribute, which is used to declare namespaces according to the XML standard:

...
xmlns:c="http://java.sun.com/jsp/jstl/core"
...

The value that identifies the location of the tag library can take three forms:

The URN of the form urn:jsptld:path points to one tag library packaged with the application:

xmlns:u="urn:jsptld:/WEB-INF/tlds/my.tld"

The URN of the form urn:jsptagdir:path must start with /WEB-INF/tags/ and identifies tag extensions (implemented as tag files) installed in the /WEB-INF/tags/ directory or a subdirectory of it:

xmlns:u="urn:jsptagdir:/WEB-INF/tags/mytaglibs/"

You can include the xmlns attribute in any element in your JSP document, just as you can in an XML document. This capability has many advantages:

The books.jspx page declares the tag libraries it uses with the xmlns attributes in the root element, books:

<books
    xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
>

In this way, all elements within the books element have access to these tag libraries.

As an alternative, you can scope the namespaces:

<books>
...
    <jsp:useBean xmlns:jsp="http://java.sun.com/JSP/Page"
                        id="bookDB"
                         class="database.BookDB"
                         scope="page">
         <jsp:setProperty name="bookDB"
                         property="database" value="${bookDBAO}" />
    </jsp:useBean>
    <c:forEach xmlns:c="http://java.sun.com/jsp/jstl/core"
                    var="book" begin="0" items="${bookDB.books}">
                    ...
    </c:forEach>
</books>

In this way, the tag library referenced by the jsp prefix is available only to the jsp:useBean element and its subelements. Similarly, the tag library referenced by the c prefix is only available to the c:forEach element.

Scoping the namespaces also allows you to override the prefix. For example, in another part of the page, you could bind the c prefix to a different namespace or tag library. In contrast, the jsp prefix must always be bound to http://java.sun.com/JSP/Page, the JSP namespace.

Including Directives in a JSP Document

Directives are elements that relay messages to the JSP container and affect how it compiles the JSP page. The directives themselves do not appear in the XML output.

There are three directives: include, page, and taglib. The taglib directive is covered in the preceding section.

The jsp:directive.page element defines a number of page-dependent properties and communicates these to the JSP container. This element must be a child of the root element. Its syntax is

<jsp:directive.page page-directive-attr-list />

The page-directive-attr-list is the same list of attributes that the <@ page ...> directive has. These are described in Chapter 5, JavaServer Pages Technology. All the attributes are optional. Except for the import and pageEncoding attributes, there can be only one instance of each attribute in an element, but an element can contain more than one attribute.

An example of a page directive is one that tells the JSP container to load an error page when it throws an exception. You can add this error page directive to the books.jspx page:

<books xmlns:jsp="http://java.sun.com/JSP/Page">
    <jsp:directive.page errorPage="errorpage.jsp" />
    ...
</books>

If there is an error when you try to execute the page (perhaps when you want to see the XML output of books.jspx), the error page is accessed.

The jsp:directive.include element is used to insert the text contained in another file (either static content or another JSP page) into the including JSP document. You can place this element anywhere in a document. Its syntax is:

<jsp:directive.include file="relativeURLspec" />

The XML view of a JSP document does not contain jsp:directive.include elements; rather the included file is expanded in place. This is done to simplify validation.

Suppose that you want to use an include directive to add a JSP document containing magazine data inside the JSP document containing the books data. To do this, you can add the following include directive to books.jspx, assuming that magazines.jspx generates the magazine XML data.

<jsp:root version="2.0" >
    <books ...>
    ...
    </books>
    <jsp:directive.include file="magazine.jspx" />
</jsp:root>

Note that jsp:root is required because otherwise books.jspx would have two root elements: <books> and <magazines>. The output generated from books.jspx will be a sequence of XML documents: one with <books> and the other with <magazines> as its root element.

The output of this example will not be well-formed XML because of the two root elements, so the client might refuse to process it. However, it is still a legal JSP document.

In addition to including JSP documents in JSP documents, you can also include JSP pages written in standard syntax in JSP documents, and you can include JSP documents in JSP pages written in standard syntax. The container detects the page you are including and parses it as either a standard syntax JSP page or a JSP document and then places it into the XML view for validation.

Creating Static and Dynamic Content

This section explains how to represent static text and dynamic content in a JSP document. You can represent static text in a JSP document using uninterpreted XML tags or the jsp:text element. The jsp:text element passes its content through to the output.

If you use jsp:text, all white space is preserved. For example, consider this example using XML tags:

<books>
    <book>
        Web Servers for Fun and Profit
    </book>
</books>

The output generated from this XML has all white space removed:

<books><book>
        Web Servers for Fun and Profit
</book></books>

If you wrap the example XML with a <jsp:text> tag, all white space is preserved. The white space characters are #x20, #x9, #xD, and #xA.

You can also use jsp:text to output static data that is not well formed. The ${counter} expression in the following example would be illegal in a JSP document if it were not wrapped in a jsp:text tag.

<c:forEach var="counter" begin="1" end="${3}">
    <jsp:text>${counter}</jsp:text>
</c:forEach>

This example will output


123

The jsp:text tag must not contain any other elements. Therefore, if you need to nest a tag inside jsp:text, you must wrap the tag inside CDATA.

You also need to use CDATA if you need to output some elements that are not well-formed. The following example requires CDATA wrappers around the blockquote start and end tags because the blockquote element is not well formed. This is because the blockquote element overlaps with other elements in the example.

<c:forEach var="i" begin="1" end="${x}">
    <![CDATA[<blockquote>]]>
</c:forEach>
...
<c:forEach var="i" begin="1" end="${x}">
    <![CDATA[</blockquote>]]>
</c:forEach>

Just like JSP pages, JSP documents can generate dynamic content using expressions language (EL) expressions, scripting elements, standard actions, and custom tags. The books.jspx document uses EL expressions and custom tags to generate the XML book data.

As shown in this snippet from books.jspx, the c:forEach JSTL tag iterates through the list of books and generates the XML data stream. The EL expressions access the JavaBeans component, which in turn retrieves the data from the database:

<c:forEach var="book" begin="0" items="${bookDB.books}">
    <book id="${book.bookId}" >
        <surname>${book.surname}</surname>
        <firstname>${book.firstName}</firstname>
        <title>${book.title}</title>
        <price>${book.price}</price>
        <year>${book.year}</year>
        <description>${book.description}</description>
        <inventory>${book.inventory}</inventory>
    </book>
</c:forEach>

When using the expression language in your JSP documents, you must substitute alternative notation for some of the operators so that they will not be interpreted as XML markup. Table 6–2 enumerates the more common operators and their alternative syntax in JSP documents.

Table 6–2 EL Operators and JSP Document-Compliant Alternative Notation

EL Operator 

JSP Document Notation 

<

lt

>

gt

<=

le

>=

ge

!=

ne

You can also use EL expressions with jsp:element to generate tags dynamically rather than hard code them. This example could be used to generate an HTML header tag with a lang attribute:

<jsp:element name="${content.headerName}"
         xmlns:jsp="http://java.sun.com/JSP/Page">
    <jsp:attribute name="lang">${content.lang}</jsp:attribute>
    <jsp:body>${content.body}</jsp:body>
</jsp:element>

The name attribute identifies the generated tag’s name. The jsp:attribute tag generates the lang attribute. The body of the jsp:attribute tag identifies the value of the lang attribute. The jsp:body tag generates the body of the tag. The output of this example jsp:element could be

<h1 lang="fr">Heading in French</h1>

As shown in Table 6–1, scripting elements (described in Chapter 9, Scripting in JSP Pages) are represented as XML elements when they appear in a JSP document. The only exception is a scriptlet expression used to specify a request-time attribute value. Instead of using <%=expr %>, a JSP document uses %= expr % to represent a request-time attribute value.

The three scripting elements are declarations, scriptlets, and expressions.

A jsp:declaration element declares a scripting language construct that is available to other scripting elements. A jsp:declaration element has no attributes and its body is the declaration itself. Its syntax is

<jsp:declaration> declaration goes here </jsp:declaration>

A jsp:scriptlet element contains a Java program fragment called a scriptlet. This element has no attributes, and its body is the program fragment that constitutes the scriptlet. Its syntax is

<jsp:scriptlet> code fragment goes here </jsp:scriptlet>

The jsp:expression element inserts the value of a scripting language expression, converted into a string, into the data stream returned to the client. A jsp:expression element has no attributes and its body is the expression. Its syntax is

<jsp:expression> expression goes here </jsp:expression>

Using the jsp:root Element

The jsp:root element represents the root element of a JSP document. A jsp:root element is not required for JSP documents. You can specify your own root element, enabling you to use any XML document as a JSP document. The root element of the books.jspx example JSP document is books.

Although the jsp:root element is not required, it is still useful in these cases:

The version attribute is the only required attribute of the jsp:root element. It specifies the JSP specification version that the JSP document is using.

The jsp:root element can also include xmlns attributes for specifying tag libraries used by the other elements in the page.

The books.jspx page does not need a jsp:root element and therefore doesn’t include one. However, suppose that you want to generate two XML documents from books.jspx: one that lists books and another that lists magazines (assuming magazines are in the database). This example is similar to the one in the section Including Directives in a JSP Document. To do this, you can use this jsp:root element:

<jsp:root
     xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0" >
    <books>...</books>
    <magazines>...</magazines>
</jsp:root>

Notice in this example that jsp:root defines the JSP namespace because both the books and the magazines elements use the elements defined in this namespace.

Using the jsp:output Element

The jsp:output element specifies the XML declaration or the document type declaration in the request output of the JSP document.

The XML declaration and document type declaration that are declared by the jsp:output element are not interpreted by the JSP container. Instead, the container simply directs them to the request output.

To illustrate this, here is an example of specifying a document type declaration with jsp:output:

<jsp:output doctype-root-element="books"
                    doctype-system="books.dtd" />

The resulting output is:

<!DOCTYPE books SYSTEM "books.dtd" >

Specifying the document type declaration in the jsp:output element will not cause the JSP container to validate the JSP document against the books.dtd.

If you want the JSP document to be validated against the DTD, you must manually include the document type declaration within the JSP document, just as you would with any XML document.

Table 6–3 shows all the jsp:output attributes. They are all optional, but some attributes depend on other attributes occurring in the same jsp:output element, as shown in the table. The rest of this section explains more about using jsp:output to generate an XML declaration and a document type declaration.

Table 6–3 jsp:output Attributes

Attribute 

What It Specifies 

omit-xml-declaration

A value of true or yes omits the XML declaration. A value of false or no generates an XML declaration.

doctype-root-element

Indicates the root element of the XML document in the DOCTYPE. Can be specified only if doctype-system is specified.

doctype-system

Specifies that a DOCTYPE is generated in output and gives the SYSTEM literal.

doctype-public

Specifies the value for the Public ID of the generated DOCTYPE. Can be specified only if doctype-system is specified.

Generating XML Declarations

Here is an example of an XML declaration:

<?xml version="1.0" encoding="UTF-8" ?>

This declaration is the default XML declaration. It means that if the JSP container is generating an XML declaration, this is what the JSP container will include in the output of your JSP document.

Neither a JSP document nor its request output is required to have an XML declaration. In fact, if the JSP document is not producing XML output then it shouldn’t have an XML declaration.

The JSP container will not include the XML declaration in the output when either of the following is true:

The JSP container will include the XML declaration in the output when either of the following is true:

The books.jspx JSP document does not include a jsp:root action nor a jsp:output. Therefore, the default XML declaration is generated in the output.

Generating a Document Type Declaration

A document type declaration (DTD) defines the structural rules for the XML document in which the document type declaration occurs. XML documents are not required to have a DTD associated with them. In fact, the books example does not include one.

This section shows you how to use the jsp:output element to add a document type declaration to the XML output of books.jspx. It also shows you how to enter the document type declaration manually into books.jspx so that the JSP container will interpret it and validate the document against the DTD.

As shown in Table 6–3, the jsp:output element has three attributes that you use to generate the document type declaration:

The rules for using the attributes are as follows:

This syntax notation summarizes these rules:

<jsp:output (omit-xmldeclaration=
    "yes"|"no"|"true"|"false"){doctypeDecl} />
doctypeDecl:=    (doctype-root-element="rootElement"
        doctype-public="PublicLiteral"
    doctype-system="SystemLiteral")
    | (doctype-root-element="rootElement"
    doctype-system="SystemLiteral")

Suppose that you want to reference a DTD, called books.DTD, from the output of the books.jspx page. The DTD would look like this:

<!ELEMENT books (book+) >
<!ELEMENT book (surname, firstname, title, price, year,
                         description, inventory) >
<!ATTLIST book id CDATA #REQUIRED >
<!ELEMENT surname (#PCDATA) >
<!ELEMENT firstname (#PCDATA) >
<!ELEMENT title (#PCDATA) >
<!ELEMENT price (#PCDATA) >
<!ELEMENT year (#PCDATA) >
<!ELEMENT description (#PCDATA) >
<!ELEMENT inventory (#PCDATA) >

To add a document type declaration that references the DTD to the XML request output generated from books.jspx, include this jsp:output element in books.jspx:

<jsp:output doctype-root-element="books"
         doctype-system="books.DTD" />

With this jsp:output action, the JSP container generates this document type declaration in the request output:

<!DOCTYPE books SYSTEM "books.DTD" />

The jsp:output need not be located before the root element of the document. The JSP container will automatically place the resulting document type declaration before the start of the output of the JSP document.

Note that the JSP container will not interpret anything provided by jsp:output. This means that the JSP container will not validate the XML document against the DTD. It only generates the document type declaration in the XML request output. To see the XML output, run http://localhost:8080/books/books.jspx in your browser after you have updated books.WAR with books.DTD and the jsp:output element. When using some browsers, you might need to view the source of the page to actually see the output.

Directing the document type declaration to output without interpreting it is useful in situations when another system receiving the output expects to see it. For example, two companies that do business by means of a web service might use a standard DTD, against which any XML content exchanged between the companies is validated by the consumer of the content. The document type declaration tells the consumer what DTD to use to validate the XML data that it receives.

For the JSP container to validate books.jspx against book.DTD, you must manually include the document type declaration in the books.jspx file rather than use jsp:output. However, you must add definitions for all tags in your DTD, including definitions for standard elements and custom tags, such as jsp:useBean and c:forEach. You also must ensure that the DTD is located in the domain-dir/config/ directory so that the JSP container will validate the JSP document against the DTD.

Identifying the JSP Document to the Container

A JSP document must be identified as such to the web container so that the container interprets it as an XML document. There are three ways to do this:

Chapter 7 JavaServer Pages Standard Tag Library

The JavaServer Pages Standard Tag Library (JSTL) encapsulates core functionality common to many JSP applications. Instead of mixing tags from numerous vendors in your JSP applications, JSTL allows you to employ a single, standard set of tags. This standardization allows you to deploy your applications on any JSP container supporting JSTL and makes it more likely that the implementation of the tags is optimized.

JSTL has tags such as iterators and conditionals for handling flow control, tags for manipulating XML documents, internationalization tags, tags for accessing databases using SQL, and commonly used functions.

This chapter demonstrates JSTL through excerpts from the JSP version of the Duke’s Bookstore application discussed in the earlier chapters. It assumes that you are familiar with the material in the Using Custom Tags section of Chapter 5, JavaServer Pages Technology.

This chapter does not cover every JSTL tag, only the most commonly used ones. Please refer to the reference pages at http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/index.html for a complete list of the JSTL tags and their attributes.

The Example JSP Pages

This chapter illustrates JSTL using excerpts from the JSP version of the Duke’s Bookstore application discussed in Chapter 5, JavaServer Pages Technology. Here, they are rewritten to replace the JavaBeans component database access object with direct calls to the database using the JSTL SQL tags. For most applications, it is better to encapsulate calls to a database in a bean. JSTL includes SQL tags for situations where a new application is being prototyped and the overhead of creating a bean may not be warranted.

The source for the Duke’s Bookstore application is located in the tut-install/javaeetutorial5/examples/web/bookstore4/ directory created when you unzip the tutorial bundle (see Chapter 2, Using the Tutorial Examples).

    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 bookstore4 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 bookstore4 project, and select Undeploy and Deploy.

  8. To run the application, open the bookstore URL http://localhost:8080/bookstore4/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/bookstore4/.

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore4/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore4/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/bookstore4/books/bookstore.

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

See Troubleshooting Duke's Bookstore Database Problems for help with diagnosing common problems.

Using JSTL

JSTL includes a wide variety of tags that fit into discrete functional areas. To reflect this, as well as to give each area its own namespace, JSTL is exposed as multiple tag libraries. The URIs for the libraries are as follows:

Table 7–1 summarizes these functional areas along with the prefixes used in this tutorial.

Table 7–1 JSTL Tags

Area 

Subfunction 

Prefix 

Core

Variable support 

c

Flow control 

URL management 

Miscellaneous 

XML

Core 

x

Flow control 

Transformation 

I18N

Locale 

fmt

Message formatting 

Number and date formatting 

Database

SQL 

sql

Functions

Collection length 

fn

String manipulation 

Thus, the tutorial references the JSTL core tags in JSP pages by using the following taglib directive:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

In addition to declaring the tag libraries, tutorial examples access the JSTL API and implementation. In the Application Server, the JSTL TLDs and libraries are distributed in the archive as-install/lib/appserv-jstl.jar. 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.

Tag Collaboration

Tags usually collaborate with their environment in implicit and explicit ways. Implicit collaboration is done by means of a well-defined interface that allows nested tags to work seamlessly with the ancestor tag that exposes that interface. The JSTL conditional tags employ this mode of collaboration.

Explicit collaboration happens when a tag exposes information to its environment. JSTL tags expose information as JSP EL variables; the convention followed by JSTL is to use the name var for any tag attribute that exports information about the tag. For example, the forEach tag exposes the current item of the shopping cart it is iterating over in the following way:

<c:forEach var="item" items="${sessionScope.cart.items}">
    ...
</c:forEach>

In situations where a tag exposes more than one piece of information, the name var is used for the primary piece of information being exported, and an appropriate name is selected for any other secondary piece of information exposed. For example, iteration status information is exported by the forEach tag through the attribute status.

When you want to use an EL variable exposed by a JSTL tag in an expression in the page’s scripting language (see Chapter 9, Scripting in JSP Pages), you use the standard JSP element jsp:useBean to declare a scripting variable.

For example, tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookshowcart.jsp removes a book from a shopping cart using a scriptlet. The ID of the book to be removed is passed as a request parameter. The value of the request parameter is first exposed as an EL variable (to be used later by the JSTL sql:query tag) and then is declared as a scripting variable and passed to the cart.remove method:

<c:set var="bookId" value="${param.Remove}"/>
<jsp:useBean id="bookId" type="java.lang.String" />
<% cart.remove(bookId); %>
<sql:query var="books"
     dataSource="${applicationScope.bookDS}">
    select * from PUBLIC.books where id = ?
    <sql:param value="${bookId}" />
</sql:query>

Core Tag Library

Table 7–2 summarizes the core tags, which include those related to variables and flow control, as well as a generic way to access URL-based resources whose content can then be included or processed within the JSP page.

Table 7–2 Core Tags

Area 

Function 

Tags 

Prefix 

Core

Variable support 

remove
set

c

Flow control 

choose
    when
    otherwise
forEach
forTokens
if

URL management 

import
    param
redirect
    param
url
    param

Miscellaneous 

catch
out

Variable Support Tags

The set tag sets the value of an EL variable or the property of an EL variable in any of the JSP scopes (page, request, session, or application). If the variable does not already exist, it is created.

The JSP EL variable or property can be set either from the attribute value:

<c:set var="foo" scope="session" value="..."/>

or from the body of the tag:

<c:set var="foo">
     ...
 </c:set>

For example, the following sets an EL variable named bookID with the value of the request parameter named Remove:

<c:set var="bookId" value="${param.Remove}"/>

To remove an EL variable, you use the remove tag. When the bookstore JSP page tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookreceipt.jsp is invoked, the shopping session is finished, so the cart session attribute is removed as follows:

<c:remove var="cart" scope="session"/>

The value attribute of the set tag can also take a deferred value expression (See Immediate and Deferred Evaluation Syntax) so that JavaServer Faces component tags can access the value at the appropriate stage of the page life cycle.

JavaServer Faces technology (see Chapter 10, JavaServer Faces Technology) supports a multiphase life cycle, which includes separate phases for rendering components, validating data, updating model values, and performing other tasks. What this means is that any JavaServer Faces component tags that reference the value set by the set tag must have access to this value at different phases of the life cycle, not just during the rendering phase. Consider the following code:

<c:set var="bookId" scope="page" value="#{BooksBean.books}"/>
...
<h:inputText id="bookId" value="#{bookId}"/>
...

The value attribute of the c:set tag uses a deferred value expression, which means that the bookId 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 value the user enters into the bookId component tag is updated to the external data object during the appropriate stage of the life cycle.

If the expression referenced by the value attribute used immediate evaluation syntax then the bookId variable would be available only when the component is rendered during the render response phase. This would prevent the value the user enters into the component from being converted, validated, or updated to the external data object during the later phases of the life cycle.

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.

URL Tags

The jsp:include element provides for the inclusion of static and dynamic resources in the same context as the current page. However, jsp:include cannot access resources that reside outside the web application, and it causes unnecessary buffering when the resource included is used by another element.

In the following example, the transform element uses the content of the included resource as the input of its transformation. The jsp:include element reads the content of the response and writes it to the body content of the enclosing transform element, which then rereads exactly the same content. It would be more efficient if the transform element could access the input source directly and thereby avoid the buffering involved in the body content of the transform tag.

<acme:transform>
    <jsp:include page="/exec/employeesList"/>
<acme:transform/>

The import tag is therefore the simple, generic way to access URL-based resources, whose content can then be included and or processed within the JSP page. For example, in XML Tag Library, import is used to read in the XML document containing book information and assign the content to the scoped variable xml:

<c:import url="/books.xml" var="xml" />
<x:parse doc="${xml}" var="booklist"
     scope="application" />

The param tag, analogous to the jsp:param tag (see jsp:param Element), can be used with import to specify request parameters.

Session Tracking discusses how an application must rewrite URLs to enable session tracking whenever the client turns off cookies. You can use the url tag to rewrite URLs returned from a JSP page. The tag includes the session ID in the URL only if cookies are disabled; otherwise, it returns the URL unchanged. Note that this feature requires that the URL be relative. The url tag takes param subtags to include parameters in the returned URL. For example, tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp rewrites the URL used to add a book to the shopping cart as follows:

<c:url var="url" value="/catalog" >
    <c:param name="Add" value="${bookId}" />
</c:url>
<p><strong><a href="${url}">

The redirect tag sends an HTTP redirect to the client. The redirect tag takes param subtags for including parameters in the returned URL.

Miscellaneous Tags

The catch tag provides a complement to the JSP error page mechanism. It allows page authors to recover gracefully from error conditions that they can control. Actions that are of central importance to a page should not be encapsulated in a catch; in this way their exceptions will propagate instead to an error page. Actions with secondary importance to the page should be wrapped in a catch so that they never cause the error page mechanism to be invoked.

The exception thrown is stored in the variable identified by var, which always has page scope. If no exception occurred, the scoped variable identified by var is removed if it existed. If var is missing, the exception is simply caught and not saved.

The out tag evaluates an expression and outputs the result of the evaluation to the current JspWriter object. The syntax and attributes are as follows:

<c:out value="value" [escapeXml="{true|false}"]
     [default="defaultValue"] />

If the result of the evaluation is a java.io.Reader object, then data is first read from the Reader object and then written into the current JspWriter object. The special processing associated with Reader objects improves performance when a large amount of data must be read and then written to the response.

If escapeXml is true, the character conversions listed in Table 7–3 are applied.

Table 7–3 Character Conversions

Character 

Character Entity Code 

<

&lt;

>

&gt;

&

&amp;

&#039;

"

&#034;

XML Tag Library

The JSTL XML tag set is listed in Table 7–4.

Table 7–4 XML Tags

Area 

Function 

Tags 

Prefix 

XML 

Core 

out
parse
set

x

Flow control 

choose
    when
    otherwise
forEach
if

Transformation 

transform
    param

A key aspect of dealing with XML documents is to be able to easily access their content. XPath (see http://java.sun.com/webservices/jaxp/), a W3C recommendation since 1999, provides an easy notation for specifying and selecting parts of an XML document. In the JSTL XML tags, XPath expressions specified using the select attribute are used to select portions of XML data streams. Note that XPath is used as a local expression language only for the select attribute. This means that values specified for select attributes are evaluated using the XPath expression language but that values for all other attributes are evaluated using the rules associated with the JSP 2.0 expression language.

In addition to the standard XPath syntax, the JSTL XPath engine supports the following scopes to access web application data within an XPath expression:

These scopes are defined in exactly the same way as their counterparts in the JSP expression language discussed in Implicit Objects. Table 7–5 shows some examples of using the scopes.

Table 7–5 Example XPath Expressions

XPath Expression 

Result 

$sessionScope:profile

The session-scoped EL variable named profile

$initParam:mycom.productId

The String value of the mycom.productId context parameter

The XML tags are illustrated in another version (bookstore5) of the Duke’s Bookstore application. This version replaces the database with an XML representation of the bookstore database, which is retrieved from another web application. The directions for building and deploying this version of the application are in The Example JSP Document.

Core Tags

The core XML tags provide basic functionality to easily parse and access XML data.

The parse tag parses an XML document and saves the resulting object in the EL variable specified by attribute var. In bookstore5, the XML document is parsed and saved to a context attribute in tut-install/javaeetutorial5/examples/web/bookstore5/web/books/parsebooks.jsp, which is included by all JSP pages that need access to the document:

<c:if test="${applicationScope:booklist == null}" >
     <c:import url="${initParam.booksURL}" var="xml" />
    <x:parse doc="${xml}" var="booklist" scope="application" />
</c:if>

The set and out tags parallel the behavior described in Variable Support Tags and Miscellaneous Tags for the XPath local expression language. The set tag evaluates an XPath expression and sets the result into a JSP EL variable specified by attribute var. The out tag evaluates an XPath expression on the current context node and outputs the result of the evaluation to the current JspWriter object.

The JSP page tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookdetails.jsp selects a book element whose id attribute matches the request parameter bookId and sets the abook attribute. The out tag then selects the book’s title element and outputs the result.

<x:set var="abook"
    select="$applicationScope.booklist/
        books/book[@id=$param:bookId]" />
    <h2><x:out select="$abook/title"/></h2>

As you have just seen, x:set stores an internal XML representation of a node retrieved using an XPath expression; it doesn’t convert the selected node into a String and store it. Thus, x:set is primarily useful for storing parts of documents for later retrieval.

If you want to store a String, you must use x:out within c:set. The x:out tag converts the node to a String, and c:set then stores the String as an EL variable. For example, tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookdetails.jsp stores an EL variable containing a book price, which is later provided as the value of a fmt tag, as follows:

<c:set var="price">
    <x:out select="$abook/price"/>
</c:set>
<h4><fmt:message key="ItemPrice"/>:
     <fmt:formatNumber value="${price}" type="currency"/>

The other option, which is more direct but requires that the user have more knowledge of XPath, is to coerce the node to a String manually by using XPath’s string function.

<x:set var="price" select="string($abook/price)"/>

Flow Control Tags

The XML flow control tags parallel the behavior described in Flow Control Tags for XML data streams.

The JSP page tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp uses the forEach tag to display all the books contained in booklist as follows:

<x:forEach var="book"
     select="$applicationScope:booklist/books/*">
    <tr>
        <c:set var="bookId">
            <x:out select="$book/@id"/>
        </c:set>=
        <td bgcolor="#ffffaa">
             <c:url var="url"
            value="/bookdetails" >
                <c:param name="bookId" value="${bookId}" />
                <c:param name="Clear" value="0" />
            </c:url>
            <a href="${url}">
            <strong><x:out select="$book/title"/>&nbsp;
            </strong></a></td>
         <td bgcolor="#ffffaa" rowspan=2>
             <c:set var="price">
                <x:out select="$book/price"/>
            </c:set>
            <fmt:formatNumber value="${price}" type="currency"/>
             &nbsp;
        </td>
         <td bgcolor="#ffffaa" rowspan=2>
         <c:url var="url" value="/catalog" >
            <c:param name="Add" value="${bookId}" />
        </c:url>
         <p><strong><a href="${url}">&nbsp;
            <fmt:message key="CartAdd"/>&nbsp;</a>
        </td>
    </tr>
     <tr>
         <td bgcolor="#ffffff">
         &nbsp;&nbsp;<fmt:message key="By"/> <em>
            <x:out select="$book/firstname"/>&nbsp;
            <x:out select="$book/surname"/></em></td></tr>
</x:forEach>

Transformation Tags

The transform tag applies a transformation, specified by an XSLT stylesheet set by the attribute xslt, to an XML document, specified by the attribute doc. If the doc attribute is not specified, the input XML document is read from the tag’s body content.

The param subtag can be used along with transform to set transformation parameters. The attributes name and value are used to specify the parameter. The value attribute is optional. If it is not specified, the value is retrieved from the tag’s body.

Internationalization Tag Library

Chapter 15, Internationalizing and Localizing Web Applications covers how to design web applications so that they conform to the language and formatting conventions of client locales. This section describes tags that support the internationalization of JSP pages.

JSTL defines tags for setting the locale for a page, creating locale-sensitive messages, and formatting and parsing data elements such as numbers, currencies, dates, and times in a locale-sensitive or customized manner. Table 7–6 lists the tags.

Table 7–6 Internationalization Tags

Area 

Function 

Tags 

Prefix 

I18N 

Setting Locale 

setLocale
requestEncoding

fmt

Messaging 

bundle
message
    param
setBundle

Number and Date Formatting 

formatNumber
formatDate
parseDate
parseNumber
setTimeZone
timeZone

JSTL I18N tags use a localization context to localize their data. A localization context contains a locale and a resource bundle instance. To specify the localization context at deployment time, you define the context parameter javax.servlet.jsp.jstl.fmt.localizationContext, whose value can be a javax.servlet.jsp.jstl.fmt.LocalizationContext or a String. A String context parameter is interpreted as a resource bundle base name. For the Duke’s Bookstore application, the context parameter is the String messages.BookstoreMessages. When a request is received, JSTL automatically sets the locale based on the value retrieved from the request header and chooses the correct resource bundle using the base name specified in the context parameter.

Setting the Locale

The setLocale tag is used to override the client-specified locale for a page. The requestEncoding tag is used to set the request’s character encoding, in order to be able to correctly decode request parameter values whose encoding is different from ISO-8859-1.

Messaging Tags

By default, the capability to sense the browser locale setting is enabled in JSTL. This means that the client determines (through its browser setting) which locale to use, and allows page authors to cater to the language preferences of their clients.

The setBundle and bundle Tags

You can set the resource bundle at runtime with the JSTL fmt:setBundle and fmt:bundle tags. fmt:setBundle is used to set the localization context in a variable or configuration variable for a specified scope. fmt:bundle is used to set the resource bundle for a given tag body.

The message Tag

The message tag is used to output localized strings. The following tag from tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp is used to output a string inviting customers to choose a book from the catalog.

<h3><fmt:message key="Choose"/></h3>

The param subtag provides a single argument (for parametric replacement) to the compound message or pattern in its parent message tag. One param tag must be specified for each variable in the compound message or pattern. Parametric replacement takes place in the order of the param tags.

Formatting Tags

JSTL provides a set of tags for parsing and formatting locale-sensitive numbers and dates.

The formatNumber tag is used to output localized numbers. The following tag from tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookshowcart.jsp is used to display a localized price for a book.

<fmt:formatNumber value="${book.price}" type="currency"/>

Note that because the price is maintained in the database in dollars, the localization is somewhat simplistic, because the formatNumber tag is unaware of exchange rates. The tag formats currencies but does not convert them.

Analogous tags for formatting dates (formatDate) and for parsing numbers and dates (parseNumber, parseDate) are also available. The timeZone tag establishes the time zone (specified with the value attribute) to be used by any nested formatDate tags.

In tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookreceipt.jsp, a “pretend” ship date is created and then formatted with the formatDate tag:

<jsp:useBean id="now" class="java.util.Date" />
<jsp:setProperty name="now" property="time"
     value="${now.time + 432000000}" />
<fmt:message key="ShipDate"/>
 <fmt:formatDate value="${now}" type="date"
    dateStyle="full"/>.

SQL Tag Library

The JSTL SQL tags for accessing databases listed in Table 7–7 are designed for quick prototyping and simple applications. For production applications, database operations are normally encapsulated in JavaBeans components.

Table 7–7 SQL Tags

Area 

Function 

Tags 

Prefix 

Database 

Setting the data source 

setDataSource

sql

SQL 

query
    dateParam
    param
transaction
update
    dateParam
    param

The setDataSource tag allows you to set data source information for the database. You can provide a JNDI name or DriverManager parameters to set the data source information. All of the Duke’s Bookstore pages that have more than one SQL tag use the following statement to set the data source:

<sql:setDataSource dataSource="jdbc/BookDB" />

The query tag performs an SQL query that returns a result set. For parameterized SQL queries, you use a nested param tag inside the query tag.

In tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp, the value of the Add request parameter determines which book information should be retrieved from the database. This parameter is saved as the attribute name bid and is passed to the param tag.

<c:set var="bid" value="${param.Add}"/>
<sql:query var="books" >
    select * from PUBLIC.books where id = ?
    <sql:param value="${bid}" />
</sql:query>

The update tag is used to update a database row. The transaction tag is used to perform a series of SQL statements atomically.

The JSP page tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookreceipt.jsp uses both tags to update the database inventory for each purchase. Because a shopping cart can contain more than one book, the transaction tag is used to wrap multiple queries and updates. First, the page establishes that there is sufficient inventory; then the updates are performed.

<c:set var="sufficientInventory" value="true" />
<sql:transaction>
    <c:forEach var="item" items="${sessionScope.cart.items}">
        <c:set var="book" value="${item.item}" />
        <c:set var="bookId" value="${book.bookId}" />

        <sql:query var="books"
             sql="select * from PUBLIC.books where id = ?" >
            <sql:param value="${bookId}" />
        </sql:query>
        <jsp:useBean id="inventory"
            class="database.BookInventory" />
        <c:forEach var="bookRow" begin="0"
            items="${books.rowsByIndex}">
            <jsp:useBean id="bookRow"  type="java.lang.Object[]" />
            <jsp:setProperty name="inventory" property="quantity"
                value="${bookRow[7]}" />

            <c:if test="${item.quantity > inventory.quantity}">
                <c:set var="sufficientInventory" value="false" />
                <h3><font color="red" size="+2">
                <fmt:message key="OrderError"/>
                 There is insufficient inventory for
                 <i>${bookRow[3]}</i>.</font></h3>
            </c:if>
        </c:forEach>
    </c:forEach>

    <c:if test="${sufficientInventory == ’true’}" />
        <c:forEach var="item" items="${sessionScope.cart.items}">
          <c:set var="book" value="${item.item}" />
          <c:set var="bookId" value="${book.bookId}" />

            <sql:query var="books"
                 sql="select * from PUBLIC.books where id = ?" >
                <sql:param value="${bookId}" />
            </sql:query>

            <c:forEach var="bookRow" begin="0"
                items="${books.rows}">    
                          <sql:update var="books" sql="update PUBLIC.books set
                    inventory = inventory - ? where id = ?" >
                    <sql:param value="${item.quantity}" />
                    <sql:param value="${bookId}" />
                </sql:update>
            </c:forEach>
        </c:forEach>
        <h3><fmt:message key="ThankYou"/>
            ${param.cardname}.</h3><br>
      </c:if>
</sql:transaction>

query Tag Result Interface

The Result interface is used to retrieve information from objects returned from a query tag.

public interface Result
    public String[] getColumnNames();
    public int getRowCount()
    public Map[] getRows();
    public Object[][] getRowsByIndex();
    public boolean isLimitedByMaxRows();

For complete information about this interface, see the API documentation for the JSTL packages.

The var attribute set by a query tag is of type Result. The getRows method returns an array of maps that can be supplied to the items attribute of a forEach tag. The JSTL expression language converts the syntax ${result.rows} to a call to result.getRows. The expression ${books.rows} in the following example returns an array of maps.

When you provide an array of maps to the forEach tag, the var attribute set by the tag is of type Map. To retrieve information from a row, use the get("colname") method to get a column value. The JSP expression language converts the syntax ${map.colname} to a call to map.get("colname"). For example, the expression ${book.title} returns the value of the title entry of a book map.

The Duke’s Bookstore page tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookdetails.jsp retrieves the column values from the book map as follows.

<c:forEach var="book" begin="0" items="${books.rows}">
    <h2>${book.title}</h2>
    &nbsp;<fmt:message key="By"/> <em>${book.firstname}
    ${book.surname}</em>&nbsp;&nbsp;
    (${book.year})<br> &nbsp; <br>
    <h4><fmt:message key="Critics"/></h4>
    <blockquote>${book.description}</blockquote>
    <h4><fmt:message key="ItemPrice"/>:
     <fmt:formatNumber value="${book.price}" type="currency"/>
     </h4>
</c:forEach>

The following excerpt from tut-install/javaeetutorial5/examples/web/bookstore4/web/books/bookcatalog.jsp uses the Row interface to retrieve values from the columns of a book row using scripting language expressions. First, the book row that matches a request parameter (bid) is retrieved from the database. Because the bid and bookRow objects are later used by tags that use scripting language expressions to set attribute values and by a scriptlet that adds a book to the shopping cart, both objects are declared as scripting variables using the jsp:useBean tag. The page creates a bean that describes the book, and scripting language expressions are used to set the book properties from book row column values. Then the book is added to the shopping cart.

You might want to compare this version of bookcatalog.jsp to the versions in Chapter 5, JavaServer Pages Technology and Chapter 8, Custom Tags in JSP Pages that use a book database JavaBeans component.

<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.rowsByIndex}">
     <jsp:useBean id="bid"  type="java.lang.String" />
    <jsp:useBean id="bookRow" type="java.lang.Object[]" />
    <jsp:useBean id="addedBook" class="database.Book"
        scope="page" >
        <jsp:setProperty name="addedBook" property="bookId"
            value="${bookRow[0]}" />
        <jsp:setProperty name="addedBook" property="surname"
            value="${bookRow[1]}" />
        <jsp:setProperty name="addedBook" property="firstName"
            value="${bookRow[2]}" />
        <jsp:setProperty name="addedBook" property="title"
            value="${bookRow[3]}" />
        <jsp:setProperty name="addedBook" property="price"
            value="${bookRow[4])}" />
        <jsp:setProperty name="addedBook" property="year"
            value="${bookRow[6]}" />
        <jsp:setProperty name="addedBook"
             property="description"
             value="${bookRow[7]}" />
        <jsp:setProperty name="addedBook" property="inventory"
            value="${bookRow[8]}" />
    </jsp:useBean>
    <% cart.add(bid, addedBook); %>
    ...
</c:forEach>

JSTL Functions

Table 7–8 lists the JSTL functions.

Table 7–8 Functions

Area 

Function 

Tags 

Prefix 

Functions 

Collection length 

length

fn

String manipulation 

toUpperCase, toLowerCase

substring, substringAfter, substringBefore

trim

replace

indexOf, startsWith, endsWith, contains, containsIgnoreCase

split, join

escapeXml

Although the java.util.Collection interface defines a size method, it does not conform to the JavaBeans component design pattern for properties and so cannot be accessed by using the JSP expression language. The length function can be applied to any collection supported by the c:forEach and returns the length of the collection. When applied to a String, it returns the number of characters in the string.

For example, the index.jsp page of the hello1 application introduced in Chapter 3, Getting Started with Web Applications uses the fn:length function and the c:if tag to determine whether to include a response page:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
     prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions"
    prefix="fn" %>
<html>
<head><title>Hello</title></head>
...
<input type="text" name="username" size="25">
<p></p>
<input type="submit" value="Submit">
<input type="reset" value="Reset">
</form>

<c:if test="${fn:length(param.username) > 0}" >
  <%@include file="response.jsp" %>
</c:if>
</body>
</html>

The rest of the JSTL functions are concerned with string manipulation:

Further Information about JSTL

For more information on JSTL, see:

Chapter 8 Custom Tags in JSP Pages

The standard JSP tags simplify JSP page development and maintenance. JSP technology also provides a mechanism for encapsulating other types of dynamic functionality in custom tags, which are extensions to the JSP language. Some examples of tasks that can be performed by custom tags include operating on implicit objects, processing forms, accessing databases and other enterprise services such as email and directories, and implementing flow control. Custom tags increase productivity because they can be reused in more than one application.

Custom tags are distributed in a tag library, which defines a set of related custom tags and contains the objects that implement the tags. The object that implements a custom tag is called a tag handler. JSP technology defines two types of tag handlers: simple and classic. Simple tag handlers can be used only for tags that do not use scripting elements in attribute values or the tag body. Classic tag handlers must be used if scripting elements are required. Simple tag handlers are covered in this chapter, and classic tag handlers are discussed in Chapter 9, Scripting in JSP Pages.

You can write simple tag handlers using the JSP language or using the Java language. A tag file is a source file containing a reusable fragment of JSP code that is translated into a simple tag handler by the web container. Tag files can be used to develop custom tags that are presentation-centric or that can take advantage of existing tag libraries, or by page authors who do not know Java. When the flexibility of the Java programming language is needed to define the tag, JSP technology provides a simple API for developing a tag handler in the Java programming language.

This chapter assumes that you are familiar with the material in Chapter 5, JavaServer Pages Technology, especially the section Using Custom Tags. For more information about tag libraries and for pointers to some freely available libraries, see http://java.sun.com/products/jsp/taglibraries/index.jsp.

What Is a Custom Tag?

A custom tag is a user-defined JSP language element. When a JSP page containing a custom tag is translated into a servlet, the tag is converted to operations on a tag handler. The web container then invokes those operations when the JSP page’s servlet is executed.

Custom tags have a rich set of features. They can

The Example JSP Pages

This chapter describes the tasks involved in defining simple tags. It illustrates the tasks using excerpts from the JSP version of the Duke’s Bookstore application discussed in The Example JSP Pages, rewritten here to take advantage of several custom tags:

The tutorial-template tag library defines a set of tags for creating an application template. The template is a JSP page that has placeholders for the parts that need to change with each screen. Each of these placeholders is referred to as a parameter of the template. For example, a simple template might include a title parameter for the top of the generated screen and a body parameter to refer to a JSP page for the custom content of the screen. The template is created using a set of nested tags (definition, screen, and parameter) that are used to build a table of screen definitions for Duke’s Bookstore. An insert tag to insert parameters from the table into the screen.

Figure 8–1 shows the flow of a request through the following Duke’s Bookstore web components:

Figure 8–1 Request Flow through Duke’s Bookstore Components

Diagram shows how a request is routed through a servlet
and two JSP pages to the Book DB, then a response is routed through a JSP
page to the client.

The source code for the Duke’s Bookstore application is located in the tut-install/javaeetutorial5/examples/web/bookstore3/ directory created when you unzip the tutorial bundle (see Chapter 2, Using the Tutorial Examples).

    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 bookstore3 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 bookstore3 project, and select Undeploy and Deploy.

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

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

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

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore3/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore3/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/bookstore3/bookstore.

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

To run the example, open the bookstore URL http://localhost:8080/bookstore3/bookstore.

See Troubleshooting Duke's Bookstore Database Problems for help with diagnosing common problems.

Types of Tags

Simple tags are invoked using XML syntax. They have a start tag and an end tag, and possibly a body:

<tt:tag>
    body</tt:tag>

A custom tag with no body is expressed as follows:

<tt:tag /> or <tt:tag></tt:tag>

Tags with Attributes

A simple tag can have attributes. Attributes customize the behavior of a custom tag just as parameters customize the behavior of a method. There are three types of attributes:

Simple Attributes

Simple attributes are evaluated by the container before being passed to the tag handler. Simple attributes are listed in the start tag and have the syntax attr="value". You can set a simple attribute value from a String constant, or an expression language (EL) expression, or by using a jsp:attribute element (see jsp:attribute Element). The conversion process between the constants and expressions and attribute types follows the rules described for JavaBeans component properties in Setting JavaBeans Component Properties.

The Duke’s Bookstore page tut-install/javaeetutorial5/examples/web/bookstore3/web/bookcatalog.jsp calls the catalog tag, which has two attributes. The first attribute, a reference to a book database object, is set by an EL expression. The second attribute, which sets the color of the rows in a table that represents the bookstore catalog, is set with a String constant.

<sc:catalog bookDB ="${bookDB}" color="#cccccc">

Fragment Attributes

A JSP fragment is a portion of JSP code passed to a tag handler that can be invoked as many times as needed. You can think of a fragment as a template that is used by a tag handler to produce customized content. Thus, unlike a simple attribute which is evaluated by the container, a fragment attribute is evaluated by a tag handler during tag invocation.

To declare a fragment attribute, you use the fragment attribute of the attribute directive (see Declaring Tag Attributes in Tag Files) or use the fragment subelement of the attribute TLD element (see Declaring Tag Attributes for Tag Handlers). You define the value of a fragment attribute by using a jsp:attribute element. When used to specify a fragment attribute, the body of the jsp:attribute element can contain only static text and standard and custom tags; it cannot contain scripting elements (see Chapter 9, Scripting in JSP Pages).

JSP fragments can be parameterized by means of expression language (EL) variables in the JSP code that composes the fragment. The EL variables are set by the tag handler, thus allowing the handler to customize the fragment each time it is invoked (see Declaring Tag Variables in Tag Files, and Declaring Tag Variables for Tag Handlers).

The catalog tag discussed earlier accepts two fragments: normalPrice, which is displayed for a product that’s full price, and onSale, which is displayed for a product that’s on sale.

<sc:catalog bookDB ="${bookDB}" color="#cccccc">
    <jsp:attribute name="normalPrice">
        <fmt:formatNumber value="${price}" type="currency"/>
  </jsp:attribute>
    <jsp:attribute name="onSale">
        <strike><fmt:formatNumber value="${price}"
            type="currency"/></strike><br/>
        <font color="red"><fmt:formatNumber value="${salePrice}"
            type="currency"/></font>
    </jsp:attribute>
</sc:catalog>

The tag executes the normalPrice fragment, using the values for the price EL variable, if the product is full price. If the product is on sale, the tag executes the onSale fragment using the price and salePrice variables.

Dynamic Attributes

A dynamic attribute is an attribute that is not specified in the definition of the tag. Dynamic attributes are used primarily by tags whose attributes are treated in a uniform manner but whose names are not necessarily known at development time.

For example, this tag accepts an arbitrary number of attributes whose values are colors and outputs a bulleted list of the attributes colored according to the values:

<colored:colored color1="red" color2="yellow" color3="blue"/>

You can also set the value of dynamic attributes using an EL expression or using the jsp:attribute element.

Deferred Value

A deferred value attribute is one that accepts deferred value expressions, which are described in Value Expressions.

Deferred Method

A deferred method attribute is one that accepts deferred method expressions, which are described in Method Expressions.

Dynamic Attribute or Deferred Expression

This kind of attribute can accept a String literal, a scriptlet expression, or an EL expression, including deferred expressions.

jsp:attribute Element

The jsp:attribute element allows you to define the value of a tag attribute in the body of an XML element instead of in the value of an XML attribute.

For example, the Duke’s Bookstore template page screendefinitions.jsp uses jsp:attribute to use the output of fmt:message to set the value of the value attribute of tt:parameter:

...
<tt:screen id="/bookcatalog">
    <tt:parameter name="title" direct="true">
        <jsp:attribute name="value" >
            <fmt:message key="TitleBookCatalog"/>
        </jsp:attribute>
    </tt:parameter>
    <tt:parameter name="banner" value="/template/banner.jsp"
        direct="false"/>
    <tt:parameter name="body" value="/bookcatalog.jsp"
        direct="false"/>
</tt:screen>
...

jsp:attribute accepts a name attribute and a trim attribute. The name attribute identifies which tag attribute is being specified. The optional trim attribute determines whether or not white space appearing at the beginning and end of the element body should be discarded. By default, the leading and trailing white space is discarded. The white space is trimmed when the JSP page is translated. If a body contains a custom tag that produces leading or trailing white space, that white space is preserved regardless of the value of the trim attribute.

An empty body is equivalent to specifying "" as the value of the attribute.

The body of jsp:attribute is restricted according to the type of attribute being specified:

Tags with Bodies

A simple tag can contain custom and core tags, HTML text, and tag-dependent body content between the start tag and the end tag.

In the following example, the Duke’s Bookstore application page tut-install/javaeetutorial5/examples/web/bookstore3/web/bookshowcart.jsp uses the JSTL c:if tag to print the body if the request contains a parameter named Clear:

<c:if test="${param.Clear}">
    <font color="#ff0000" size="+2"><strong>
     You just cleared your shopping cart!
     </strong><br>&nbsp;<br></font>
</c:if>

jsp:body Element

You can also explicitly specify the body of a simple tag by using the jsp:body element. If one or more attributes are specified with the jsp:attribute element, then jsp:body is the only way to specify the body of the tag. If one or more jsp:attribute elements appear in the body of a tag invocation but you don’t include a jsp:body element, the tag has an empty body.

Tags That Define Variables

A simple tag can define an EL variable that can be used within the calling page. In the following example, the iterator tag sets the value of the EL variable departmentName as it iterates through a collection of department names.

<tlt:iterator var="departmentName" type="java.lang.String"
        group="${myorg.departmentNames}">
    <tr>
        <td><a href="list.jsp?deptName=${departmentName}">
            ${departmentName}</a></td>
    </tr>
</tlt:iterator>

Communication between Tags

Custom tags communicate with each other through shared objects. There are two types of shared objects: public and private.

In the following example, the c:set tag creates a public EL variable called aVariable, which is then reused by anotherTag.

<c:set var="aVariable" value="aValue" />
<tt:anotherTag attr1="${aVariable}" />

Nested tags can share private objects. In the next example, an object created by outerTag is available to innerTag. The inner tag retrieves its parent tag and then retrieves an object from the parent. Because the object is not named, the potential for naming conflicts is reduced.

<tt:outerTag>
    <tt:innerTag />
</tt:outerTag>

The Duke’s Bookstore page tut-install/javaeetutorial5/examples/web/bookstore3/web/template/template.jsp uses a set of cooperating tags that share public and private objects to define the screens of the application. These tags are described in A Template Tag Library.

Encapsulating Reusable Content Using Tag Files

A tag file is a source file that contains a fragment of JSP code that is reusable as a custom tag. Tag files allow you to create custom tags using JSP syntax. Just as a JSP page gets translated into a servlet class and then compiled, a tag file gets translated into a tag handler and then compiled.

The recommended file extension for a tag file is .tag. As is the case with JSP files, the tag can be composed of a top file that includes other files that contain either a complete tag or a fragment of a tag file. Just as the recommended extension for a fragment of a JSP file is .jspf, the recommended extension for a fragment of a tag file is .tagf.

The following version of the Hello, World application introduced in Chapter 3, Getting Started with Web Applications uses a tag to generate the response. The response tag, which accepts two attributes (a greeting string and a name) is encapsulated in response.tag:

<%@ attribute name="greeting" required="true" %>
<%@ attribute name="name" required="true" %>
<h2><font color="black">${greeting}, ${name}!</font></h2>

The highlighted line in the greeting.jsp page invokes the response tag if the length of the username request parameter is greater than 0:

<%@ taglib tagdir="/WEB-INF/tags" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
     prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions"
    prefix="fn" %>
<html>
<head><title>Hello</title></head>
<body bgcolor="white">
<img src="duke.waving.gif">
 <c:set var="greeting" value="Hello" />
 <h2>${greeting}, my name is Duke. What’s yours?</h2>
<form method="get">
<input type="text" name="username" size="25">
<p></p>
<input type="submit" value="Submit">
<input type="reset" value="Reset">
</form>

<c:if test="${fn:length(param.username) > 0}" >
    <h:response greeting="${greeting}"
        name="${param.username}"/></c:if>
</body>
</html>

    To deploy and run the hello3 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 hello3 folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

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

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

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

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

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

  3. Start the Application Server.

  4. To deploy the example, type ant deploy.

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

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

Tag File Location

Tag files can be placed in one of two locations: in the /WEB-INF/tags/ directory or subdirectory of a web application or in a JAR file (see Packaged Tag Files) in the /WEB-INF/lib/ directory of a web application. Packaged tag files require a tag library descriptor (see Tag Library Descriptors), an XML document that contains information about a library as a whole and about each tag contained in the library. Tag files that appear in any other location are not considered tag extensions and are ignored by the web container.

Tag File Directives

Directives are used to control aspects of tag file translation to a tag handler, and to specify aspects of the tag, attributes of the tag, and variables exposed by the tag. Table 8–1 lists the directives that you can use in tag files.

Table 8–1 Tag File Directives

Directive 

Description 

taglib

Identical to taglib directive (see Declaring Tag Libraries) for JSP pages.

include

Identical to include directive (see Reusing Content in JSP Pages) for JSP pages. Note that if the included file contains syntax unsuitable for tag files, a translation error will occur.

tag

Similar to the page directive in a JSP page, but applies to tag files instead of JSP pages. As with the page directive, a translation unit can contain more than one instance of the tag directive. All the attributes apply to the complete translation unit. However, there can be only one occurrence of any attribute or value defined by this directive in a given translation unit. With the exception of the import attribute, multiple attribute or value (re)definitions result in a translation error.

Also used for declaring custom tag properties such as display name. See Declaring Tags.

attribute

Declares an attribute of the custom tag defined in the tag file. See Declaring Tag Attributes in Tag Files.

variable

Declares an EL variable exposed by the tag to the calling page. See Declaring Tag Variables in Tag Files.

Declaring Tags

The tag directive is similar to the JSP page’s page directive but applies to tag files. Some of the elements in the tag directive appear in the tag element of a TLD (see Declaring Tag Handlers). Table 8–2 lists the tag directive attributes.

Table 8–2 tag Directive Attributes

Attribute 

Description 

display-name

(optional) A short name that is intended to be displayed by tools. Defaults to the name of the tag file without the extension .tag.

body-content

(optional) Provides information on the content of the body of the tag. Can be either empty, tagdependent, or scriptless. A translation error will result if JSP or any other value is used. Defaults to scriptless. See body-content Attribute.

dynamic-attributes

(optional) Indicates whether this tag supports additional attributes with dynamic names. The value identifies a scoped attribute in which to place a Map containing the names and values of the dynamic attributes passed during invocation of the tag.

A translation error results if the value of the dynamic-attributes of a tag directive is equal to the value of a name-given of a variable directive or the value of a name attribute of an attribute directive.

small-icon

(optional) Relative path, from the tag source file, of an image file containing a small icon that can be used by tools. Defaults to no small icon. 

large-icon

(optional) Relative path, from the tag source file, of an image file containing a large icon that can be used by tools. Defaults to no large icon. 

description

(optional) Defines an arbitrary string that describes this tag. Defaults to no description. 

example

(optional) Defines an arbitrary string that presents an informal description of an example of a use of this action. Defaults to no example. 

language

(optional) Carries the same syntax and semantics of the language attribute of the page directive.

import

(optional) Carries the same syntax and semantics of the import attribute of the page directive.

pageEncoding

(optional) Carries the same syntax and semantics of the page-Encoding attribute in the page directive.

isELIgnored

(optional) Carries the same syntax and semantics of the isEL-Ignored attribute of the page directive.

body-content Attribute

You specify the type of a tag’s body content using the body-content attribute:

bodycontent="empty | scriptless | tagdependent"

You must declare the body content of tags that do not accept a body as empty. For tags that have a body there are two options. Body content containing custom and standard tags and HTML text is specified as scriptless. All other types of body content (for example, SQL statements passed to the query tag) is specified as tagdependent. If no attribute is specified, the default is scriptless.

Declaring Tag Attributes in Tag Files

To declare the attributes of a custom tag defined in a tag file, you use the attribute directive. A TLD has an analogous attribute element (see Declaring Tag Attributes for Tag Handlers). Table 8–3 lists the attribute directive attributes.

Table 8–3 attribute Directive Attributes

Attribute 

Description 

description

(optional) Description of the attribute. Defaults to no description. 

name

The unique name of the attribute being declared. A translation error results if more than one attribute directive appears in the same translation unit with the same name.

A translation error results if the value of a name attribute of an attribute directive is equal to the value of the dynamic-attributes attribute of a tag directive or the value of a name-given attribute of a variable directive.

required

(optional) Whether this attribute is required (true) or optional (false). Defaults to false.

rtexprvalue

(optional) Whether the attribute’s value can be dynamically calculated at runtime by an expression. Defaults to true. When this element is set to true and the attribute definition also includes either a deferred-value or deferred-method element then the attribute accepts both dynamic and deferred expressions.

type

(optional) The runtime type of the attribute’s value. Defaults to java.lang.String.

deferredValue

(optional) Indicates whether the attribute accepts deferred value expressions. Only one of deferredValue or deferredMethod can be true. If deferredValueType is specified, the default for deferredValue is true. Causes a translation error if specified in a tag file with a JSP version less than 2.1.

deferredValueType

(optional) The type resulting from the evaluation of the attribute’s value expression. The default is java.lang.String if no type is specified. If both deferredValueType and deferredValue are specified, deferredValue must be true. If deferredValue is true, the default of deferredValueType is java.lang.Object. Causes a translation error specified in a tag file with a JSP version less than 2.1.

deferredMethod

(optional) Indicates whether the tag attribute accepts deferred method expressions. If deferredMethod and deferredMethodSignature are specified then deferredMethod must be true. The default of deferredMethod is true if deferredMethodSignature is specified, otherwise the default of deferredMethod is false. The presence of a deferred-method element in an attribute definition precludes the inclusion of a deferred-value element. Causes a translation error if specified in a tag file with a JSP version less than 2.1.

deferredMethodSignature

(optional) The signature of the method to be invoked by the expression defined by the accompanying deferredMethod attribute. If deferredMethod is true and this attribute is not specified, the method signature defaults to void methodName(). Causes a translation error if specified in a tag file with a JSP version less than 2.1.

fragment

(optional) Whether this attribute is a fragment to be evaluated by the tag handler (true) or a normal attribute to be evaluated by the container before being passed to the tag handler.

If this attribute is true:

You do not specify the rtexprvalue attribute. The container fixes the rtexprvalue attribute at true.

You do not specify the type attribute. The container fixes the type attribute at javax.servlet.jsp.tagext.JspFragment.

Defaults to false.

Declaring Tag Variables in Tag Files

Tag attributes are used to customize tag behavior much as parameters are used to customize the behavior of object methods. In fact, using tag attributes and EL variables, it is possible to emulate various types of parameters: IN, OUT, and nested.

To emulate IN parameters, use tag attributes. A tag attribute is communicated between the calling page and the tag file when the tag is invoked. No further communication occurs between the calling page and the tag file.

To emulate OUT or nested parameters, use EL variables. The variable is not initialized by the calling page but instead is set by the tag file. Each type of parameter is synchronized with the calling page at various points according to the scope of the variable. See Variable Synchronization for details.

To declare an EL variable exposed by a tag file, you use the variable directive. A TLD has an analogous variable element (see Declaring Tag Variables for Tag Handlers). Table 8–4 lists the variable directive attributes.

Table 8–4 variable Directive Attributes

Attribute 

Description 

description

(optional) An optional description of this variable. Defaults to no description. 

name-given | name-from-attribute

Defines an EL variable to be used in the page invoking this tag. Either name-given or name-from-attribute must be specified. If name-given is specified, the value is the name of the variable. If name-from-attribute is specified, the value is the name of an attribute whose (translation-time) value at the start of the tag invocation will give the name of the variable.

Translation errors arise in the following circumstances: 

1. Specifying neither name-given nor name-from-attribute or both.

2. If two variable directives have the same name-given.

3. If the value of a name-given attribute of a variable directive is equal to the value of a name attribute of an attribute directive or the value of a dynamic-attributes attribute of a tag directive.

alias

Defines a variable, local to the tag file, to hold the value of the EL variable. The container will synchronize this value with the variable whose name is given in name-from-attribute.

Required when name-from-attribute is specified. A translation error results if used without name-from-attribute.

A translation error results if the value of alias is the same as the value of a name attribute of an attribute directive or the name-given attribute of a variable directive.

variable-class

(optional) The name of the class of the variable. The default is java.lang.String.

declare

(optional) Whether or not the variable is declared. True is the default.

scope

(optional) The scope of the variable. Can be either AT_BEGIN, AT_END, or NESTED. Defaults to NESTED.

Variable Synchronization

The web container handles the synchronization of variables between a tag file and a calling page. Table 8–5 summarizes when and how each object is synchronized according to the object’s scope.

Table 8–5 Variable Synchronization Behavior

Tag File Location 

AT_BEGIN

NESTED

AT_END

Beginning 

Not sync. 

Save 

Not sync. 

Before any fragment invocation using jsp:invoke or jsp:doBody (see Evaluating Fragments Passed to Tag Files)

Tag->page 

Tag->page 

Not sync. 

End 

Tag->page 

Restore 

Tag->page 

If name-given is used to specify the variable name, then the name of the variable in the calling page and the name of the variable in the tag file are the same and are equal to the value of name-given.

The name-from-attribute and alias attributes of the variable directive can be used to customize the name of the variable in the calling page while another name is used in the tag file. When using these attributes, you set the name of the variable in the calling page from the value of name-from-attribute at the time the tag was called. The name of the corresponding variable in the tag file is the value of alias.

Synchronization Examples

The following examples illustrate how variable synchronization works between a tag file and its calling page. All the example JSP pages and tag files reference the JSTL core tag library with the prefix c. The JSP pages reference a tag file located in /WEB-INF/tags with the prefix my.

AT_BEGIN Scope

In this example, the AT_BEGIN scope is used to pass the value of the variable named x to the tag’s body and at the end of the tag invocation.

<%-- callingpage.jsp --%>
<c:set var="x" value="1"/>
${x} <%-- (x == 1) --%>
<my:example>
    ${x} <%-- (x == 2) --%>
</my:example>
${x} <%-- (x == 4) --%>
<%-- example.tag --%>
<%@ variable name-given="x" scope="AT_BEGIN" %>
${x} <%-- (x == null) --%>
<c:set var="x" value="2"/>
<jsp:doBody/>
${x} <%-- (x == 2) --%>
<c:set var="x" value="4"/>
NESTED Scope

In this example, the NESTED scope is used to make a variable named x available only to the tag’s body. The tag sets the variable to 2, and this value is passed to the calling page before the body is invoked. Because the scope is NESTED and because the calling page also had a variable named x, its original value, 1, is restored when the tag completes.

<%-- callingpage.jsp --%>
<c:set var="x" value="1"/>
${x} <%-- (x == 1) --%>
<my:example>
    ${x} <%-- (x == 2) --%>
</my:example>
${x} <%-- (x == 1) --%>
<%-- example.tag --%>
<%@ variable name-given="x" scope="NESTED" %>
${x} <%-- (x == null) --%>
<c:set var="x" value="2"/>
<jsp:doBody/>
${x} <%-- (x == 2) --%>
<c:set var="x" value="4"/>
AT_END Scope

In this example, the AT_END scope is used to return a value to the page. The body of the tag is not affected.

<%-- callingpage.jsp --%>
<c:set var="x" value="1"/>
${x} <%-- (x == 1) --%>
<my:example>
    ${x} <%-- (x == 1) --%>
</my:example>
${x} <%-- (x == 4) --%>
<%-- example.tag --%>
<%@ variable name-given="x" scope="AT_END" %>
${x} <%-- (x == null) --%>
<c:set var="x" value="2"/>
<jsp:doBody/>
${x} <%-- (x == 2) --%>
<c:set var="x" value="4"/>
AT_BEGIN and name-from-attribute

In this example the AT_BEGIN scope is used to pass an EL variable to the tag’s body and make to it available to the calling page at the end of the tag invocation. The name of the variable is specified by the value of the attribute var. The variable is referenced by a local name, result, in the tag file.

<%-- callingpage.jsp --%>
<c:set var="x" value="1"/>
${x} <%-- (x == 1) --%>
<my:example var="x">
    ${x} <%-- (x == 2) --%>
    ${result} <%-- (result == null) --%>
    <c:set var="result" value="invisible"/>
</my:example>
${x} <%-- (x == 4) --%>
${result} <%-- (result == ”invisible’) --%>
<%-- example.tag --%>
<%@ attribute name="var" required="true" rtexprvalue="false"%>
<%@ variable alias="result" name-from-attribute="var"
    scope="AT_BEGIN" %>
${x} <%-- (x == null) --%>
${result} <%-- (result == null) --%>
<c:set var="x" value="ignored"/>
<c:set var="result" value="2"/>
<jsp:doBody/>
${x} <%-- (x == ”ignored’) --%>
${result} <%-- (result == 2) --%>
<c:set var="result" value="4"/>

Evaluating Fragments Passed to Tag Files

When a tag file is executed, the web container passes it two types of fragments: fragment attributes and the tag body. Recall from the discussion of fragment attributes that fragments are evaluated by the tag handler as opposed to the web container. Within a tag file, you use the jsp:invoke element to evaluate a fragment attribute and use the jsp:doBody element to evaluate a tag file body.

The result of evaluating either type of fragment is sent to the response or is stored in an EL variable for later manipulation. To store the result of evaluating a fragment to an EL variable, you specify the var or varReader attribute. If var is specified, the container stores the result in an EL variable of type String with the name specified by var. If varReader is specified, the container stores the result in an EL variable of type java.io.Reader, with the name specified by varReader. The Reader object can then be passed to a custom tag for further processing. A translation error occurs if both var and varReader are specified.

An optional scope attribute indicates the scope of the resulting variable. The possible values are page (default), request, session, or application. A translation error occurs if you use this attribute without specifying the var or varReader attribute.

Custom Tag Examples

This section introduces examples that demonstrate using custom tags.

Simple Attribute Example

The Duke’s Bookstore shipDate tag, defined in tut-install/javaeetutorial5/examples/web/bookstore3/web/WEB-INF/tags/shipDate.tag, is a custom tag that has a simple attribute. The tag generates the date of a book order according to the type of shipping requested.

<%@ taglib prefix="sc" tagdir="/WEB-INF/tags" %>
<h3><fmt:message key="ThankYou"/> ${param.cardname}.</h3><br>
<fmt:message key="With"/>
 <em><fmt:message key="${param.shipping}"/></em>,
  <fmt:message key="ShipDateLC"/>
<sc:shipDate shipping="${param.shipping}" />

The tag determines the number of days until shipment from the shipping attribute passed to it by the page tut-install/javaeetutorial5/examples/web/bookstore3/web/bookreceipt.jsp. From the number of days, the tag computes the ship date. It then formats the ship date.

<%@ attribute name="shipping" required="true" %>

<jsp:useBean id="now" class="java.util.Date" />
<jsp:useBean id="shipDate" class="java.util.Date" />
<c:choose>
  <c:when test="${shipping == ’QuickShip’}">
    <c:set var="days" value="2" />
  </c:when>
  <c:when test="${shipping == ’NormalShip’}">
    <c:set var="days" value="5" />
  </c:when>
  <c:when test="${shipping == ’SaverShip’}">
     <c:set var="days" value="7" />
  </c:when>
</c:choose>
<jsp:setProperty name="shipDate" property="time"
    value="${now.time + 86400000 * days}" />
<fmt:formatDate value="${shipDate}" type="date"
    dateStyle="full"/>.<br><br>

Simple and Fragment Attribute and Variable Example

The Duke’s Bookstore catalog tag, defined in tut-install/javaeetutorial5/examples/web/bookstore3/web/WEB-INF/tags/catalog.tag, is a custom tag with simple and fragment attributes and variables. The tag renders the catalog of a book database as an HTML table. The tag file declares that it sets variables named price and salePrice using variable directives. The fragment normalPrice uses the variable price, and the fragment onSale uses the variables price and salePrice. Before the tag invokes the fragment attributes using the jsp:invoke element, the web container passes values for the variables back to the calling page.

<%@ attribute name="bookDB" required="true"
    type="database.BookDB" %>
<%@ attribute name="color" required="true" %>
<%@ attribute name="normalPrice" fragment="true" %>
<%@ attribute name="onSale" fragment="true" %>

<%@ variable name-given="price" %>
 <%@ variable name-given="salePrice" %>

<center>
<table>
<c:forEach var="book" begin="0" items="${bookDB.books}">
    <tr>
    <c:set var="bookId" value="${book.bookId}" />
    <td bgcolor="${color}">
         <c:url var="url" value="/bookdetails" >
            <c:param name="bookId" value="${bookId}" />
        </c:url>
        <a href="${url}"><
            strong>${book.title}&nbsp;</strong></a></td>
     <td bgcolor="${color}" rowspan=2>
    <c:set var="salePrice" value="${book.price * .85}" />
    <c:set var="price" value="${book.price}" />
    <c:choose>
        <c:when test="${book.onSale}" >
            <jsp:invoke fragment="onSale" />
        </c:when>
        <c:otherwise>
            <jsp:invoke fragment="normalPrice"/>
        </c:otherwise>
    </c:choose>

    &nbsp;</td>

 ...
</table>
</center>

The page bookcatalog.jsp invokes the catalog tag that has the simple attributes bookDB, which contains catalog data, and color, which customizes the coloring of the table rows. The formatting of the book price is determined by two fragment attributes, normalPrice and onSale, that are conditionally invoked by the tag according to data retrieved from the book database.

<sc:catalog bookDB ="${bookDB}" color="#cccccc">
    <jsp:attribute name="normalPrice">
        <fmt:formatNumber value="${price}" type="currency"/>
    </jsp:attribute>
    <jsp:attribute name="onSale">
        <strike>
        <fmt:formatNumber value="${price}" type="currency"/>
        </strike><br/>
        <font color="red">
        <fmt:formatNumber value="${salePrice}" type="currency"/>
        </font>
    </jsp:attribute>
</sc:catalog>

The screen produced by tut-install/javaeetutorial5/examples/web/bookstore3/web/bookcatalog.jsp is shown in Figure 8–2. You can compare it to the version in Figure 5–2.

Figure 8–2 Book Catalog

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

Dynamic Attribute Example

The following code implements the tag discussed in Dynamic Attributes. An arbitrary number of attributes whose values are colors are stored in a Map named by the dynamic-attributes attribute of the tag directive. The JSTL forEach tag is used to iterate through the Map and the attribute keys and colored attribute values are printed in a bulleted list.

<%@ tag dynamic-attributes="colorMap"%>
<ul>
<c:forEach var="color" begin="0" items="${colorMap}">
    <li>${color.key} =
         <font color="${color.value}">${color.value}</font></li>
</c:forEach>
</ul>

Tag Library Descriptors

If you want to redistribute your tag files or implement your custom tags with tag handlers written in Java, you must declare the tags in a tag library descriptor (TLD). A tag library descriptor is an XML document that contains information about a library as a whole and about each tag contained in the library. TLDs are used by a web container to validate the tags and by JSP page development tools.

Tag library descriptor file names must have the extension .tld and must be packaged 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. If a tag is implemented as a tag file and is packaged in /WEB-INF/tags/ or a subdirectory, a TLD will be generated automatically by the web container, though you can provide one if you wish.

Most containers set the JSP version of this automatically generated TLD (called an implicit TLD) to 2.0. Therefore, in order to take advantage of JSP 2.1 features, you must provide a TLD that sets the JSP version to 2.1 if you don’t have a TLD already. This TLD must be named implicit.tld and placed into the same directory as the tag files.

You set the JSP version using the version attribute of the root taglib element that of the TLD, as shown here:

<taglib
    xsi:schemaLocation=
    "http://java.sun.com/xml/ns/javaee web-
        jsptaglibrary_2_1.xsd"
    xmlns="http://java.sun.com/xml/ns/javaee"|
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     version="2.1">

Table 8–6 lists the subelements of the taglib element.

Table 8–6 taglib Subelements

Element 

Description 

description

(optional) A string describing the use of the tag library. 

display-name

(optional) Name intended to be displayed by tools. 

icon

(optional) Icon that can be used by tools. 

tlib-version

The tag library’s version. 

short-name

(optional) Name that could be used by a JSP page-authoring tool to create names with a mnemonic value. 

uri

A URI that uniquely identifies the tag library. 

validator

See validator Element.

listener

See listener Element.

tag-file | tag

Declares the tag files or tags defined in the tag library. See Declaring Tag Files and Declaring Tag Handlers. A tag library is considered invalid if a tag-file element has a name subelement with the same content as a name subelement in a tag element.

function

Zero or more EL functions (see Functions) defined in the tag library.

tag-extension

(optional) Extensions that provide extra information about the tag library for tools. 

Top-Level Tag Library Descriptor Elements

This section describes some top-level TLD elements. Subsequent sections describe how to declare tags defined in tag files, how to declare tags defined in tag handlers, and how to declare tag attributes and variables.

validator Element

This element defines an optional tag library validator that can be used to validate the conformance of any JSP page importing this tag library to its requirements. Table 8–7 lists the subelements of the validator element.

Table 8–7 validator Subelements

Element 

Description 

validator-class

The class implementing javax.servlet.jsp.tagext.TagLibraryValidator

init-param

(optional) Initialization parameters 

listener Element

A tag library can specify some classes that are event listeners (see Handling Servlet Life-Cycle Events). The listeners are listed in the TLD as listener elements, and the web container will instantiate the listener classes and register them in a way analogous to that of listeners defined at the WAR level. Unlike WAR-level listeners, the order in which the tag library listeners are registered is undefined. The only subelement of the listener element is the listener-class element, which must contain the fully qualified name of the listener class.

Declaring Tag Files

Although not required for tag files, providing a TLD allows you to share the tag across more than one tag library and lets you import the tag library using a URI instead of the tagdir attribute.

tag-file TLD Element

A tag file is declared in the TLD using a tag-file element. Its subelements are listed in Table 8–8.

Table 8–8 tag-file Subelements

Element 

Description 

description

(optional) A description of the tag. 

display-name

(optional) Name intended to be displayed by tools. 

icon

(optional) Icon that can be used by tools. 

name

The unique tag name. 

path

Where to find the tag file implementing this tag, relative to the root of the web application or the root of the JAR file for a tag library packaged in a JAR. This must begin with /WEB-INF/tags/ if the tag file resides in the WAR, or /META-INF/tags/ if the tag file resides in a JAR.

example

(optional) Informal description of an example use of the tag. 

tag-extension

(optional) Extensions that provide extra information about the tag for tools. 

Unpackaged Tag Files

Tag files placed in a subdirectory of /WEB-INF/tags/ do not require a TLD file and don’t have to be packaged. Thus, to create reusable JSP code, you simply create a new tag file and place the code inside it.

The web container generates an implicit tag library for each directory under and including /WEB-INF/tags/. There are no special relationships between subdirectories; they are allowed simply for organizational purposes. For example, the following web application contains three tag libraries:

/WEB-INF/tags/
/WEB-INF/tags/a.tag
/WEB-INF/tags/b.tag
/WEB-INF/tags/foo/
/WEB-INF/tags/foo/c.tag
/WEB-INF/tags/bar/baz/
/WEB-INF/tags/bar/baz/d.tag

The implicit TLD for each library has the following values:

So, for the example, the implicit TLD for the /WEB-INF/tags/bar/baz/ directory would be as follows:

<taglib>
    <tlib-version>1.0</tlib-version>
    <short-name>bar-baz</short-name>
    <tag-file>
        <name>d</name>
        <path>/WEB-INF/tags/bar/baz/d.tag</path>
    </tag-file>
</taglib>

Despite the existence of an implicit tag library, a TLD in the web application can still create additional tags from the same tag files. To accomplish this, you add a tag-file element with a path that points to the tag file.

Packaged Tag Files

Tag files can be packaged in the /META-INF/tags/ directory in a JAR file installed in the /WEB-INF/lib/ directory of the web application. Tags placed here are typically part of a reusable library of tags that can be used easily in any web application.

Tag files bundled in a JAR require a tag library descriptor. Tag files that appear in a JAR but are not defined in a TLD are ignored by the web container.

When used in a JAR file, the path subelement of the tag-file element specifies the full path of the tag file from the root of the JAR. Therefore, it must always begin with /META-INF/tags/.

Tag files can also be compiled into Java classes and bundled as a tag library. This is useful when you wish to distribute a binary version of the tag library without the original source. If you choose this form of packaging, you must use a tool that produces portable JSP code that uses only standard APIs.

Declaring Tag Handlers

When tags are implemented with tag handlers written in Java, each tag in the library must be declared in the TLD with a tag element. The tag element contains the tag name, the class of its tag handler, information on the tag’s attributes, and information on the variables created by the tag (see Tags That Define Variables).

Each attribute declaration contains an indication of whether the attribute is required, whether its value can be determined by request-time expressions, the type of the attribute, and whether the attribute is a fragment. Variable information can be given directly in the TLD or through a tag extra info class. Table 8–9 lists the subelements of the tag element.

Table 8–9 tag Subelements

Element 

Description 

description

(optional) A description of the tag. 

display-name

(optional) name intended to be displayed by tools. 

icon

(optional) Icon that can be used by tools. 

name

The unique tag name. 

tag-class

The fully qualified name of the tag handler class. 

tei-class

(optional) Subclass of javax.servlet.jsp.tagext.TagExtraInfo. See Declaring Tag Variables for Tag Handlers.

body-content

The body content type. See body-content Element.

variable

(optional) Declares an EL variable exposed by the tag to the calling page. See Declaring Tag Variables for Tag Handlers.

attribute

Declares an attribute of the custom tag. See Declaring Tag Attributes for Tag Handlers.

dynamic-attributes

Whether the tag supports additional attributes with dynamic names. Defaults to false. If true, the tag handler class must implement the javax.servlet.jsp.tagext.DynamicAttributes interface.

example

(optional) Informal description of an example use of the tag. 

tag-extension

(optional) Extensions that provide extra information about the tag for tools. 

body-content Element

You specify the type of body that is valid for a tag by using the body-content element. This element is used by the web container to validate that a tag invocation has the correct body syntax and is used by page-composition tools to assist the page author in providing a valid tag body. There are three possible values:

Declaring Tag Attributes for Tag Handlers

For each tag attribute, you must specify whether the attribute is required, whether the value can be determined by an expression, the type of the attribute in an attribute element (optional), and whether the attribute is a fragment. If the rtexprvalue element is true or yes, then the type element defines the return type expected from any expression specified as the value of the attribute. For static values, the type is always java.lang.String. An attribute is specified in a TLD in an attribute element. Table 8–10 lists the subelements of the attribute element.

Table 8–10 attribute Subelements

Element 

Description 

description

(optional) A description of the attribute. 

name

The unique name of the attribute being declared. A translation error results if more than one attribute element appears in the same tag with the same name.

required

(optional) Whether the attribute is required. The default is false.

rtexprvalue

(optional) Whether the attribute’s value can be dynamically calculated at runtime by an EL expression. The default is false. When this element is set to true and the attribute definition also includes either a deferred-value or deferred-method element then the attribute accepts both dynamic and deferred expressions.

type

(optional) The runtime type of the attribute’s value. Defaults to java.lang.String if not specified.

fragment

(optional) Whether this attribute is a fragment to be evaluated by the tag handler (true) or a normal attribute to be evaluated by the container before being passed to the tag handler.

If this attribute is true:

You do not specify the rtexprvalue attribute. The container fixes the rtexprvalue attribute at true.

You do not specify the type attribute. The container fixes the type attribute at javax.servlet.jsp.tagext.JspFragment.

Defaults to false.

deferred-value

(optional) Indicates that the tag attribute accepts deferred value expressions. This element includes an optional type child element, which indicates the type of object to which the expression resolves. If no type element is included, the type is java.lang.Object. Either the deferred-value or deferred-method element (but not both) can be defined for the same attribute.

deferred-method

(optional) Indicates that the tag attribute accepts deferred method expressions. This element includes an optional method-signature child element, which indicates the signature of the method that the expression invokes. If no method signature is defined, the method signature default is void methodName(). Either the deferred-value or deferred-method element (but not both) can be defined for the same attribute.

If a tag attribute is not required, a tag handler should provide a default value.

The tag element for a tag that outputs its body if a test evaluates to true declares that the test attribute is required and that its value can be set by a runtime expression.

<tag>
    <name>present</name>
         <tag-class>condpkg.IfSimpleTag</tag-class>
    <body-content>scriptless</body-content>
    ...
    <attribute>
        <name>test</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    ...
</tag>

Declaring Tag Variables for Tag Handlers

The example described in Tags That Define Variables defines an EL variable departmentName:

    <tlt:iterator var="departmentName" type="java.lang.String"
            group="${myorg.departmentNames}">
        <tr>
            <td><a href="list.jsp?deptName=${departmentName}">
                ${departmentName}</a></td>
        </tr>
    </tlt:iterator>

When the JSP page containing this tag is translated, the web container generates code to synchronize the variable with the object referenced by the variable. To generate the code, the web container requires certain information about the variable:

There are two ways to provide this information: by specifying the variable TLD subelement or by defining a tag extra info class and including the tei-class element in the TLD (see TagExtraInfo Class). Using the variable element is simpler but less dynamic. With the variable element, the only aspect of the variable that you can specify at runtime is its name (with the name-from-attribute element). If you provide this information in a tag extra info class, you can also specify the type of the variable at runtime.

Table 8–11 lists the subelements of the variable element.

Table 8–11 variable Subelements

Element 

Description 

description

(optional) A description of the variable. 

name-given | name-from-attribute

Defines an EL variable to be used in the page invoking this tag. Either name-given or name-from-attribute must be specified. If name-given is specified, the value is the name of the variable. If name-from-attribute is specified, the value is the name of an attribute whose (translation-time) value at the start of the tag invocation will give the name of the variable.

Translation errors arise in the following circumstances: 

  • Specifying neither name-given nor name-from-attribute or both.

  • If two variable elements have the same name-given.

variable-class

(optional) The fully qualified name of the class of the object. java.lang.String is the default.

declare

(optional) Whether or not the object is declared. True is the default. A translation error results if both declare and fragment are specified.

scope

(optional) The scope of the variable defined. Can be either AT_BEGIN, AT_END, or NESTED (see Table 8–12). Defaults to NESTED.

Table 8–12 summarizes a variable’s availability according to its declared scope.

Table 8–12 Variable Availability

Value 

Availability 

NESTED

Between the start tag and the end tag. 

AT_BEGIN

From the start tag until the scope of any enclosing tag. If there’s no enclosing tag, then to the end of the page. 

AT_END

After the end tag until the scope of any enclosing tag. If there’s no enclosing tag, then to the end of the page. 

You can define the following variable element for the tlt:iterator tag:

<tag>
    <variable>
        <name-given>var</name-given>
        <variable-class>java.lang.String</variable-class>
        <declare>true</declare>
        <scope>NESTED</scope>
    </variable>
</tag>

Programming Simple Tag Handlers

The classes and interfaces used to implement simple tag handlers are contained in the javax.servlet.jsp.tagext package. Simple tag handlers implement the SimpleTag interface. Interfaces can be used to take an existing Java object and make it a tag handler. For most newly created handlers, you would use the SimpleTagSupport classes as a base class.

The heart of a simple tag handler is a single method, doTag, which is invoked when the end element of the tag is encountered. Note that the default implementation of the doTag method of SimpleTagSupport does nothing.

A tag handler has access to an API that allows it to communicate with the JSP page. The entry point to the API is the JSP context object (javax.servlet.jsp.JspContext). The JspContext object provides access to implicit objects. PageContext extends JspContext with servlet-specific behavior. Through these objects, a tag handler can retrieve all the other implicit objects (request, session, and application) that are accessible from a JSP page. If the tag is nested, a tag handler also has access to the handler (called the parent) that is associated with the enclosing tag.

Including Tag Handlers in Web Applications

Tag handlers can be made available to a web application in two basic ways. The classes implementing the tag handlers can be stored in an unpacked form in the /WEB-INF/classes/ subdirectory of the web application. Alternatively, if the library is distributed as a JAR, it is stored in the /WEB-INF/lib/ directory of the web application.

How Is a Simple Tag Handler Invoked?

The SimpleTag interface defines the basic protocol between a simple tag handler and a JSP page’s servlet. The JSP page’s servlet invokes the setJspContext, setParent, and attribute setting methods before calling doStartTag.

ATag t = new ATag();
t.setJSPContext(...);
t.setParent(...);
t.setAttribute1(value1);
t.setAttribute2(value2);
...
t.setJspBody(new JspFragment(...))
t.doTag();

The following sections describe the methods that you need to develop for each type of tag introduced in Types of Tags.

Tag Handlers for Basic Tags

The handler for a basic tag without a body must implement the doTag method of the SimpleTag interface. The doTag method is invoked when the end element of the tag is encountered.

The basic tag discussed in the first section, <tt:basic />, would be implemented by the following tag handler:

public HelloWorldSimpleTag extends SimpleTagSupport {
    public void doTag() throws JspException, IOException {
        getJspContext().getOut().write("Hello, world.");
    }
}

Tag Handlers for Tags with Attributes

This section describes how to define attributes for a tag handler and how to validate attribute values.

Defining Attributes in a Tag Handler

For each tag attribute, you must define a set method in the tag handler that conforms to the JavaBeans architecture conventions. For example, consider the tag handler for the JSTL c:if tag:

<c:if test="${Clear}">

This tag handler contains the following method:

public void setTest(boolean test) {
    this.test = test;
}

As shown by the preceding example, the name of the attribute must match the name of the set method.

Attribute Validation

The documentation for a tag library should describe valid values for tag attributes. When a JSP page is translated, a web container will enforce any constraints contained in the TLD element for each attribute.

The attributes passed to a tag can also be validated at translation time using the validate method of a class derived from TagExtraInfo. This class is also used to provide information about variables defined by the tag (see TagExtraInfo Class).

The validate method is passed the attribute information in a TagData object, which contains attribute-value tuples for each of the tag’s attributes. Because the validation occurs at translation time, the value of an attribute that is computed at request time will be set to TagData.REQUEST_TIME_VALUE.

The tag <tt:twa attr1="value1"/> has the following TLD attribute element:

<attribute>
    <name>attr1</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
</attribute>

This declaration indicates that the value of attr1 can be determined at runtime.

The following validate method checks whether the value of attr1 is a valid Boolean value. Note that because the value of attr1 can be computed at runtime, validate must check whether the tag user has chosen to provide a runtime value.

public class TwaTEI extends TagExtraInfo {
    public ValidationMessage[] validate(TagData data) {
        Object o = data.getAttribute("attr1");
        if (o != null && o != TagData.REQUEST_TIME_VALUE) {
            if (((String)o).toLowerCase().equals("true") ||
                 ((String)o).toLowerCase().equals("false") )
                 return null;
            else
                return new ValidationMessage(data.getId(),
                    "Invalid boolean value.");
        }
        else
            return null;
    }
}

Setting Dynamic Attributes

Simple tag handlers that support dynamic attributes must declare that they do so in the tag element of the TLD (see Declaring Tag Handlers). In addition, your tag handler must implement the setDynamicAttribute method of the DynamicAttributes interface. For each attribute specified in the tag invocation that does not have a corresponding attribute element in the TLD, the web container calls setDynamicAttribute, passing in the namespace of the attribute (or null if in the default namespace), the name of the attribute, and the value of the attribute. You must implement the setDynamicAttribute method to remember the names and values of the dynamic attributes so that they can be used later when doTag is executed. If the setDynamicAttribute method throws an exception, the doTag method is not invoked for the tag, and the exception must be treated in the same manner as if it came from an attribute setter method.

The following implementation of setDynamicAttribute saves the attribute names and values in lists. Then, in the doTag method, the names and values are echoed to the response in an HTML list.

private ArrayList keys = new ArrayList();
private ArrayList values = new ArrayList();

public void setDynamicAttribute(String uri,
     String localName, Object value ) throws JspException {
    keys.add( localName );
    values.add( value );
}

public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();
    for( int i = 0; i < keys.size(); i++ ) {
        String key = (String)keys.get( i );
        Object value = values.get( i );
        out.println( "<li>" + key + " = " + value + "</li>" );
    }
}

Setting Deferred Value Attributes and Deferred Method Attributes

For each tag attribute that accepts a deferred value expression or a deferred method expression, the tag handler must have a method to access the value of the attribute.

The methods that access the value of a deferred value attribute method must accept a ValueExpression object. The methods that access the value of a deferred method attribute must accept a MethodExpression object. These methods take the form setXXX, where XXX is the name of the attribute.

The following example shows a method that can be used to access the value of a deferred value attribute called attributeName:

private javax.el.ValueExpression attributeName = null;

public void setAttributeName(
    javax.el.ValueExpression attributeName)
 {
    this.attributeName = attributeName;
}

Deferred value attributes and deferred method attributes are primarily used by JavaServer Faces technology. See Getting the Attribute Values for an example of creating a tag handler that processes these attributes for a JavaServer Faces application.

If you have an attribute that is both dynamic and deferred (meaning that the tag attribute definition accepts a deferred expression and has rtexprvalue set to true), then the setX method that accesses this value must accept an Object instance and test if the Object instance is a deferred value expression, as shown in this pseudocode:

public void setAttr(Object obj) {
    if (obj instance of ValueExpression) {
        // this is a deferred expression
    else {
        // this is an rtexpression
    }
}

Tag Handlers for Tags with Bodies

A simple tag handler for a tag with a body is implemented differently depending on whether or not the tag handler needs to manipulate the body. A tag handler manipulates the body when it reads or modifies the contents of the body.

Tag Handler Does Not Manipulate the Body

If a tag handler needs simply to evaluate the body, it gets the body using the getJspBody method of SimpleTag and then evaluates the body using the invoke method.

The following tag handler accepts a test parameter and evaluates the body of the tag if the test evaluates to true. The body of the tag is encapsulated in a JSP fragment. If the test is true, the handler retrieves the fragment using the getJspBody method. The invoke method directs all output to a supplied writer or, if the writer is null, to the JspWriter returned by the getOut method of the JspContext associated with the tag handler.

public class IfSimpleTag extends SimpleTagSupport {
    private boolean test;
    public void setTest(boolean test) {
        this.test = test;
    }
    public void doTag() throws JspException, IOException {
        if(test){
            getJspBody().invoke(null);
        }
    }
}

Tag Handler Manipulates the Body

If the tag handler needs to manipulate the body, the tag handler must capture the body in a StringWriter. The invoke method directs all output to a supplied writer. Then the modified body is written to the JspWriter returned by the getOut method of the JspContext. Thus, a tag that converts its body to uppercase could be written as follows:

public class SimpleWriter extends SimpleTagSupport {
    public void doTag() throws JspException, IOException {
        StringWriter sw = new StringWriter();
        jspBody.invoke(sw);
        jspContext().
            getOut().println(sw.toString().toUpperCase());
    }
}

Tag Handlers for Tags That Define Variables

Similar communication mechanisms exist for communication between JSP page and tag handlers as for JSP pages and tag files.

To emulate IN parameters, use tag attributes. A tag attribute is communicated between the calling page and the tag handler when the tag is invoked. No further communication occurs between the calling page and the tag handler.

To emulate OUT or nested parameters, use variables with availability AT_BEGIN, AT_END, or NESTED. The variable is not initialized by the calling page but instead is set by the tag handler.

For AT_BEGIN availability, the variable is available in the calling page from the start tag until the scope of any enclosing tag. If there’s no enclosing tag, then the variable is available to the end of the page. For AT_END availability, the variable is available in the calling page after the end tag until the scope of any enclosing tag. If there’s no enclosing tag, then the variable is available to the end of the page. For nested parameters, the variable is available in the calling page between the start tag and the end tag.

When you develop a tag handler you are responsible for creating and setting the object referenced by the variable into a context that is accessible from the page. You do this by using the JspContext().setAttribute(name, value) or JspContext.setAttribute(name,value,scope) method. You retrieve the page context using the getJspContext method of SimpleTag.

Typically, an attribute passed to the custom tag specifies the name of the variable and the value of the variable is dependent on another attribute. For example, the iterator tag introduced in Chapter 5, JavaServer Pages Technology retrieves the name of the variable from the var attribute and determines the value of the variable from a computation performed on the group attribute.

public void doTag() throws JspException, IOException {
    if (iterator == null)
        return;
    while (iterator.hasNext()) {
        getJspContext().setAttribute(var, iterator.next());
        getJspBody().invoke(null);
    }
}
public void setVar(String var) {
    this.var = var;
}
public void setGroup(Collection group) {
    this.group = group;
    if(group.size() > 0)
        iterator = group.iterator();
}

The scope that a variable can have is summarized in Table 8–13. The scope constrains the accessibility and lifetime of the object.

Table 8–13 Scope of Objects

Name 

Accessible From 

Lifetime 

page

Current page 

Until the response has been sent back to the user or the request is passed to a new page 

request

Current page and any included or forwarded pages 

Until the response has been sent back to the user 

session

Current request and any subsequent request from the same browser (subject to session lifetime) 

The life of the user’s session 

application

Current and any future request in the same web application 

The life of the application 

TagExtraInfo Class

Declaring Tag Variables for Tag Handlers discussed how to provide information about tag variables in the tag library descriptor. This section describes another approach: defining a tag extra info class. You define a tag extra info class by extending the class javax.servlet.jsp.tagext.TagExtraInfo. A TagExtraInfo must implement the getVariableInfo method to return an array of VariableInfo objects containing the following information:

The web container passes a parameter of type javax.servlet.jsp.tagext.TagData to the getVariableInfo method, which contains attribute-value tuples for each of the tag’s attributes. These attributes can be used to provide the VariableInfo object with an EL variable’s name and class.

The following example demonstrates how to provide information about the variable created by the iterator tag in a tag extra info class. Because the name (var) and class (type) of the variable are passed in as tag attributes, they can be retrieved using the data.getAttributeString method and can be used to fill in the VariableInfo constructor. To allow the variable var to be used only within the tag body, you set the scope of the object to NESTED.

package iterator;
public class IteratorTEI extends TagExtraInfo {
    public VariableInfo[] getVariableInfo(TagData data) {
        String type = data.getAttributeString("type");
        if (type == null)
            type = "java.lang.Object";
        return new VariableInfo[] {
            new VariableInfo(data.getAttributeString("var"),
            type,
            true,
            VariableInfo.NESTED)
        };
    }
}

The fully qualified name of the tag extra info class defined for an EL variable must be declared in the TLD in the tei-class subelement of the tag element. Thus, the tei-class element for IteratorTei would be as follows:

<tei-class>
    iterator.IteratorTEI
</tei-class>

Cooperating Tags

Tags cooperate by sharing objects. JSP technology supports two styles of object sharing.

The first style requires that a shared object be named and stored in the page context (one of the implicit objects accessible to JSP pages as well as tag handlers). To access objects created and named by another tag, a tag handler uses the pageContext.getAttribute(name,scope) method.

In the second style of object sharing, an object created by the enclosing tag handler of a group of nested tags is available to all inner tag handlers. This form of object sharing has the advantage that it uses a private namespace for the objects, thus reducing the potential for naming conflicts.

To access an object created by an enclosing tag, a tag handler must first obtain its enclosing tag by using the static method SimpleTagSupport.findAncestorWithClass(from,class) or the SimpleTagSupport.getParent method. The former method should be used when a specific nesting of tag handlers cannot be guaranteed. After the ancestor has been retrieved, a tag handler can access any statically or dynamically created objects. Statically created objects are members of the parent. Private objects can also be created dynamically. Such privately named objects would have to be managed by the tag handler; one approach would be to use a Map to store name-object pairs.

The following example illustrates a tag handler that supports both the named approach and the private object approach to sharing objects. In the example, the handler for a query tag checks whether an attribute named connectionId has been set. If the connectionId attribute has been set, the handler retrieves the connection object from the page context. Otherwise, the tag handler first retrieves the tag handler for the enclosing tag and then retrieves the connection object from that handler.

public class QueryTag extends SimpleTagSupport {
    public int doTag() throws JspException {
        String cid = getConnectionId();
        Connection connection;
        if (cid != null) {
        // there is a connection id, use it
            connection =(Connection)pageContext.
                getAttribute(cid);
        } else {
            ConnectionTag ancestorTag =
                (ConnectionTag)findAncestorWithClass(this,
                    ConnectionTag.class);
            if (ancestorTag == null) {
                throw new JspTagException("A query without
                    a connection attribute must be nested
                    within a connection tag.");
            }
            connection = ancestorTag.getConnection();
            ...
        }
    }
}

The query tag implemented by this tag handler can be used in either of the following ways:

<tt:connection cid="con01" ... >
     ...
 </tt:connection>
<tt:query id="balances" connectionId="con01">
     SELECT account, balance FROM acct_table
         where customer_number = ?
    <tt:param value="${requestScope.custNumber}" />
</tt:query>

<tt:connection ... >
    <tt:query cid="balances">
         SELECT account, balance FROM acct_table
         where customer_number = ?
        <tt:param value="${requestScope.custNumber}" />
    </tt:query>
</tt:connection>

The TLD for the tag handler uses the following declaration to indicate that the connectionId attribute is optional:

<tag>
    ...
    <attribute>
        <name>connectionId</name>
        <required>false</required>
    </attribute>
</tag>

Tag Handler Examples

The simple tags described in this section demonstrate solutions to two recurring problems in developing JSP applications: minimizing the amount of Java programming in JSP pages and ensuring a common look and feel across applications. In doing so, they illustrate many of the styles of tags discussed in the first part of the chapter.

An Iteration Tag

Constructing page content that is dependent on dynamically generated data often requires the use of flow control scripting statements. By moving the flow control logic to tag handlers, flow control tags reduce the amount of scripting needed in JSP pages. Iteration is a very common flow control function and is easily handled by a custom tag.

The discussion on using tag libraries in Chapter 5, JavaServer Pages Technology introduced a tag library containing an iterator tag. The tag retrieves objects from a collection stored in a JavaBeans component and assigns them to an EL variable. The body of the tag retrieves information from the variable. As long as elements remain in the collection, the iterator tag causes the body to be reevaluated. The tag in this example is simplified to make it easy to demonstrate how to program a custom tag. web applications requiring such functionality should use the JSTL forEach tag, which is discussed in Iterator Tags.

JSP Page

The index.jsp page invokes the iterator tag to iterate through a collection of department names. Each item in the collection is assigned to the departmentName variable.

<%@ taglib uri="/tlt" prefix="tlt" %>
<html>
    <head>
    <title>Departments</title>
    </head>
    <body bgcolor="white">
    <jsp:useBean id="myorg" class="myorg.Organization"/>
    <table border=2 cellspacing=3 cellpadding=3>
        <tr>
            <td><b>Departments</b></td>
        </tr>
    <tlt:iterator var="departmentName" type="java.lang.String"
            group="${myorg.departmentNames}">
        <tr>
            <td><a href="list.jsp?deptName=${departmentName}">
                ${departmentName}</a></td>
        </tr>
    </tlt:iterator>
    </table>
    </body>
</html>

Tag Handler

The collection is set in the tag handler by means of the group attribute. The tag handler retrieves an element from the group and passes the element back to the page in the EL variable whose name is determined by the var attribute. The variable is accessed in the calling page using the JSP expression language. After the variable is set, the tag body is evaluated with the invoke method.

public void doTag() throws JspException, IOException {
    if (iterator == null)
        return;
    while (iterator.hasNext()) {
        getJspContext().setAttribute(var, iterator.next());
        getJspBody().invoke(null);
    }
}
public void setVar(String var) {
    this.var = var;
}
public void setGroup(Collection group) {
    this.group = group;
    if(group.size() > 0)
        iterator = group.iterator();
}

A Template Tag Library

A template provides a way to separate the common elements that are part of each screen from the elements that change with each screen of an application. Putting all the common elements together into one file makes it easier to maintain and enforce a consistent look and feel in all the screens. It also makes development of individual screens easier because the designer can focus on portions of a screen that are specific to that screen while the template takes care of the common portions.

The template is a JSP page that has placeholders for the parts that need to change with each screen. Each of these placeholders is referred to as a parameter of the template. For example, a simple template might include a title parameter for the top of the generated screen and a body parameter to refer to a JSP page for the custom content of the screen.

The template uses a set of nested tags (definition, screen, and parameter) to define a table of screen definitions and uses an insert tag to insert parameters from a screen definition into a specific application screen.

JSP Pages

The template for the Duke’s Bookstore example, tut-install/javaeetutorial5/examples/web/bookstore3/web/template/template.jsp, is shown next. This page includes a JSP page that creates the screen definition and then uses the insert tag to insert parameters from the definition into the application screen.

<%@ taglib uri="/tutorial-template" prefix="tt" %>
<%@ page errorPage="/template/errorinclude.jsp" %>
<%@ include file="/template/screendefinitions.jsp" %>
<html>
<head>
<title>
<tt:insert definition="bookstore" parameter="title"/>
</title>
</head>
<body  bgcolor="#FFFFFF">
  <tt:insert definition="bookstore" parameter="banner"/>
<tt:insert definition="bookstore" parameter="body"/>
<center><em>Copyright &copy; 2004 Sun Microsystems, Inc. </em></center>
</body>
</html>

The tut-install/javaeetutorial5/examples/web/bookstore3/web/template/screendefinitions.jspf page creates a definition for the screen specified by the request attribute javax.servlet.forward.servlet_path:

<tt:definition name="bookstore"
screen="${requestScope
    [’javax.servlet.forward.servlet_path’]}">
    <tt:screen id="/bookstore">
    <tt:parameter name="title" value="Duke’s Bookstore"
        direct="true"/>
    <tt:parameter name="banner" value="/template/banner.jsp"
        direct="false"/>
    <tt:parameter name="body" value="/bookstore.jsp"
        direct="false"/>
    </tt:screen>
    <tt:screen id="/bookcatalog">
    <tt:parameter name="title" direct="true">
      <jsp:attribute name="value" >
        <fmt:message key="TitleBookCatalog"/>
      </jsp:attribute>
    </tt:parameter>
    <tt:parameter name="banner" value="/template/banner.jsp"
        direct="false"/>
        <tt:parameter name="body" value="/bookcatalog.jsp"
        direct="false"/>
    </tt:screen>
    ...
</tt:definition>

The template is instantiated by the Dispatcher servlet. Dispatcher first gets the requested screen. Dispatcher performs business logic and updates model objects based on the requested screen. For example, if the requested screen is /bookcatalog, Dispatcher determines whether a book is being added to the cart based on the value of the Add request parameter. It sets the price of the book if it’s on sale, and then adds the book to the cart. Finally, the servlet dispatches the request to template.jsp:

public class Dispatcher extends HttpServlet {
    @Resource
    UserTransaction utx;

    public void doGet(HttpServletRequest request,
        HttpServletResponse response) {
        String bookId = null;
        Book book = null;
        String clear = null;
        BookDBAO bookDBAO =
            (BookDBAO)getServletContext().
                getAttribute("bookDBAO");
        HttpSession session = request.getSession();
        String selectedScreen = request.getServletPath();
        ShoppingCart cart = (ShoppingCart)session.
            getAttribute("cart");
        if (cart == null) {
            cart = new ShoppingCart();
            session.setAttribute("cart", cart);
        }
        if (selectedScreen.equals("/bookcatalog")) {
            bookId = request.getParameter("Add");
            if (!bookId.equals("")) {
                try {
                    book = bookDBAO.getBook(bookId);
                    if ( book.getOnSale() ) {
                        double sale = book.getPrice() * .85;
                        Float salePrice = new Float(sale);
                        book.setPrice(salePrice.floatValue());
                    }
                    cart.add(bookId, book);
                } catch (BookNotFoundException ex) {
                    // not possible
                }
            }
        } else if (selectedScreen.equals("/bookshowcart")) {
            bookId =request.getParameter("Remove");
            if (bookId != null) {
                cart.remove(bookId);
            }
             clear = request.getParameter("Clear");
            if (clear != null && clear.equals("clear")) {
                cart.clear();
            }
        } else if (selectedScreen.equals("/bookreceipt")) {
        // Update the inventory
            try {
                utx.begin();
                bookDBAO.buyBooks(cart);
                utx.commit();
            } catch (Exception ex) {
                try {
                    utx.rollback();
                    request.getRequestDispatcher(
                        "/bookordererror.jsp").
                        forward(request, response);
                } catch(Exception e) {
                        System.out.println(
                            "Rollback failed: "+e.getMessage());
                        e.printStackTrace();
                }
            }
        }
        try {
            request.
                getRequestDispatcher(
                "/template/template.jsp").
                forward(request, response);
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    public void doPost(HttpServletRequest request,
        HttpServletResponse response) {
             request.setAttribute("selectedScreen",
            request.getServletPath());
        try {
            request.
                getRequestDispatcher(
                "/template/template.jsp").
                forward(request, response);
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }
}

Tag Handlers

The template tag library contains four tag handlers (DefinitionTag, ScreenTag, ParameterTag, and InsertTag) that demonstrate the use of cooperating tags. DefinitionTag, ScreenTag, and ParameterTag constitute a set of nested tag handlers that share private objects. DefinitionTag creates a public object named bookstore that is used by InsertTag.

In doTag, tut-install/javaeetutorial5/examples/web/bookstore3/src/java/com/sun/bookstore3/template/DefinitionTag.java creates a private object named screens that contains a hash table of screen definitions. A screen definition consists of a screen identifier and a set of parameters associated with the screen. These parameters are loaded when the body of the definition tag, which contains nested screen and parameter tags, is invoked. DefinitionTag creates a public object of class tut-install/javaeetutorial5/examples/web/bookstore3/src/java/com/sun/bookstore3/template/Definition.java, selects a screen definition from the screens object based on the URL passed in the request, and uses this screen definition to initialize a public Definition object.

public int doTag() {
    try {
        screens = new HashMap();
        getJspBody().invoke(null);
        Definition definition = new Definition();
        PageContext context = (PageContext)getJspContext();
        ArrayList params = (ArrayList) screens.get(screenId);
        Iterator ir = null;
        if (params != null) {
            ir = params.iterator();
            while (ir.hasNext())
                definition.setParam((Parameter)ir.next());
        // put the definition in the page context
        context.setAttribute(definitionName, definition,
             context.APPLICATION_SCOPE);
        }
    }

The table of screen definitions is filled in by ScreenTag and ParameterTag from text provided as attributes to these tags. Table 8–14 shows the contents of the screen definitions hash table for the Duke’s Bookstore application.

Table 8–14 Screen Definitions

Screen ID 

Title 

Banner 

Body 

/bookstore

Duke’s Bookstore

/banner.jsp

/bookstore.jsp

/bookcatalog

Book Catalog

/banner.jsp

/bookcatalog.jsp

/bookdetails

Book Description

/banner.jsp

/bookdetails.jsp

/bookshowcart

Shopping Cart

/banner.jsp

/bookshowcart.jsp

/bookcashier

Cashier

/banner.jsp

/bookcashier.jsp

/bookreceipt

Receipt

/banner.jsp

/bookreceipt.jsp

If the URL passed in the request is /bookstore, the Definition object contains the items from the first row of Table 8–14 (see Table 8–15).

Table 8–15 Definition Object Contents for URL /bookstore

Title 

Banner 

Body 

Duke’s Bookstore

/banner.jsp

/bookstore.jsp

The parameters for the URL /bookstore are shown in Table 8–16. The parameters specify that the value of the title parameter, Duke’s Bookstore, should be inserted directly into the output stream, but the values of banner and body should be included dynamically.

Table 8–16 Parameters for the URL /bookstore

Parameter Name 

Parameter Value 

isDirect

title

Duke’s Bookstore

true

banner

/banner.jsp

false

body

/bookstore.jsp

false

tut-install/javaeetutorial5/examples/web/bookstore3/src/java/com/sun/bookstore3/template/InsertTag.java inserts parameters of the screen definition into the response. The doTag method retrieves the definition object from the page context and then inserts the parameter value. If the parameter is direct, it is directly inserted into the response; otherwise, the request is sent to the parameter, and the response is dynamically included into the overall response.

public void doTag() throws JspTagException {    
    Definition definition = null;
    Parameter parameter = null;
    boolean directInclude = false;
    PageContext context = (PageContext)getJspContext();

        // get the definition from the page context
    definition = (Definition)context.getAttribute(
        definitionName, context.APPLICATION_SCOPE);
        // get the parameter
    if (parameterName != null && definition != null)
        parameter = (Parameter)
            definition.getParam(parameterName);

    if (parameter != null)
        directInclude = parameter.isDirect();

    try {
        // if parameter is direct, print to out
        if (directInclude && parameter  != null)
            context.getOut().print(parameter.getValue());
        // if parameter is indirect,
                 include results of dispatching to page
         else {
            if ((parameter != null) &&
                 (parameter.getValue() !=  null))
            context.include(parameter.getValue());
        }
    } catch (Exception ex) {
          throw new JspTagException(ex.getMessage());
    }
}

Chapter 9 Scripting in JSP Pages

JSP scripting elements allow you to use Java programming language statements in your JSP pages. Scripting elements are typically used to create and access objects, define methods, and manage the flow of control. Many tasks that require the use of scripts can be eliminated by using custom tag libraries, in particular the JSP Standard Tag Library. Because one of the goals of JSP technology is to separate static data from the code needed to dynamically generate content, very sparing use of JSP scripting is recommended. Nevertheless, there may be some circumstances that require its use.

There are three ways to create and use objects in scripting elements:

This chapter briefly describes the syntax and usage of JSP scripting elements.

The Example JSP Pages

This chapter illustrates JSP scripting elements using webclient, a version of the hello1 example introduced in Chapter 3, Getting Started with Web Applications that accesses a web service.

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

  1. Build and deploy the JAX-WS web service MyHelloService described in Building, Packaging, and Deploying the Service.

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

  3. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/jaxws/
  4. Select the webclient 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 webclient project, and select Undeploy and Deploy.

  8. To run the application, open the bookstore URL http://localhost:8080/webclient/greeting.

    To deploy and run the webclient example using ant, follow these steps:

  1. Build and deploy the JAX-WS web service MyHelloService described in Building, Packaging, and Deploying the Service.

  2. In a terminal window, go to tut-install/javaeetutorial5/examples/jaxws/webclient/.

  3. Run ant. This target will spawn any necessary compilations, will copy files to the tut-install/javaeetutorial5/examples/jaxws/webclient/build/ directory, will create a WAR file, and will copy it to the tut-install/javaeetutorial5/examples/jaxws/webclient/dist directory.

  4. Start the Application Server.

  5. To deploy the example using ant, run the following command:

    ant deploy

  6. To run the example, open your browser to http://localhost:8080/webclient/greeting.

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

Using Scripting

JSP technology allows a container to support any scripting language that can call Java objects. If you wish to use a scripting language other than the default, java, you must specify it in the language attribute of the page directive at the beginning of a JSP page:

<%@ page language="scripting-language" %>

Because scripting elements are converted to programming language statements in the JSP page’s servlet class, you must import any classes and packages used by a JSP page. If the page language is java, you import a class or package with the import attribute of the page directive:

<%@ page import="fully-qualified-classname, packagename.*" %>

The webclient JSP page response.jsp uses the following page directive to import the classes needed to access the service classes:

<%@ page import=
    "helloservice.endpoint.HelloService,
        helloservice.endpoint.Hello" %>

Disabling Scripting

By default, scripting in JSP pages is valid. Because scripting can make pages difficult to maintain, some JSP page authors or page authoring groups may want to follow a methodology in which scripting elements are not allowed.

You can disable scripting for a group of JSP pages in an application in one of two ways:

For information on how to define a group of JSP pages, see Setting Properties for Groups of JSP Pages. When scripting is invalid, it means that scriptlets, scripting expressions, and declarations will produce a translation error if present in any of the pages in the group. Table 9–1 summarizes the scripting settings and their meanings.

Table 9–1 Scripting Settings

JSP Configuration 

Scripting Encountered 

Unspecified 

Valid 

false

Valid 

true

Translation Error 

JSP Declarations

A JSP declaration is used to declare variables and methods in a page’s scripting language. The syntax for a declaration is as follows:

<%! scripting-language-declaration %>

When the scripting language is the Java programming language, variables and methods in JSP declarations become declarations in the JSP page’s servlet class.

Initializing and Finalizing a JSP Page

You can customize the initialization process to allow the JSP page to read persistent configuration data, initialize resources, and perform any other one-time activities; to do so, you override the jspInit method of the JspPage interface. You release resources using the jspDestroy method. The methods are defined using JSP declarations.

For example, an older version of the Duke’s Bookstore application retrieved the object that accesses the bookstore database from the context and stored a reference to the object in the variable bookDBAO in the jspInit method. The variable definition and the initialization and finalization methods jspInit and jspDestroy were defined in a declaration:

<%!
private BookDBAO bookDBAO;
public void jspInit() {    
bookDBAO =
    (BookDBAO)getServletContext().getAttribute("bookDB");
    if (bookDBAO == null)
        System.out.println("Couldn’t get database.");
}
%>

When the JSP page was removed from service, the jspDestroy method released the BookDBAO variable.

<%!
public void jspDestroy() {
    bookDBAO = null;
}
%>

JSP Scriptlets

A JSP scriptlet is used to contain any code fragment that is valid for the scripting language used in a page. The syntax for a scriptlet is as follows:

<%
    scripting-language-statements
%>

When the scripting language is set to java, a scriptlet is transformed into a Java programming language statement fragment and is inserted into the service method of the JSP page’s servlet. A programming language variable created within a scriptlet is accessible from anywhere within the JSP page.

In the web service version of the hello1 application, greeting.jsp contains a scriptlet to retrieve the request parameter named username and test whether it is empty. If the if statement evaluates to true, the response page is included. Because the if statement opens a block, the HTML markup would be followed by a scriptlet that closes the block.

<%
    String username = request.getParameter("username");
    if ( username != null && username.length() > 0 ) {
%>
    <%@include file="response.jsp" %>
<%
    }
%>

JSP Expressions

A JSP expression is used to insert the value of a scripting language expression, converted into a string, into the data stream returned to the client. When the scripting language is the Java programming language, an expression is transformed into a statement that converts the value of the expression into a String object and inserts it into the implicit out object.

The syntax for an expression is as follows:

<%= scripting-language-expression %>

Note that a semicolon is not allowed within a JSP expression, even if the same expression has a semicolon when you use it within a scriptlet.

In the web service version of the hello1 application, response.jsp contains the following scriptlet, which gets the proxy that implements the service endpoint interface. It then invokes the sayHello method on the proxy, passing the user name retrieved from a request parameter:

<%
    String resp = null;
    try {
        Hello hello = new HelloService().getHelloPort();
        resp = hello.sayHello(request.getParameter("username"));
    } catch (Exception ex) {
        resp = ex.toString();
    }
%>

A scripting expression is then used to insert the value of resp into the output stream:

<h2><font color="black"><%= resp %>!</font></h2>

Programming Tags That Accept Scripting Elements

Tags that accept scripting elements in attribute values or in the body cannot be programmed as simple tags; they must be implemented as classic tags. The following sections describe the TLD elements and JSP tag extension API specific to classic tag handlers. All other TLD elements are the same as for simple tags.

TLD Elements

You specify the character of a classic tag’s body content using the body-content element:

<body-content>empty | JSP | tagdependent</body-content>

You must declare the body content of tags that do not have a body as empty. For tags that have a body, there are two options. Body content containing custom and core tags, scripting elements, and HTML text is categorized as JSP. All other types of body content (for example, SQL statements passed to the query tag) are labeled tagdependent.

Tag Handlers

The classes and interfaces used to implement classic tag handlers are contained in the javax.servlet.jsp.tagext package. Classic tag handlers implement either the Tag, the IterationTag, or the BodyTag interface. Interfaces can be used to take an existing Java object and make it a tag handler. For newly created classic tag handlers, you can use the TagSupport and BodyTagSupport classes as base classes. These classes and interfaces are contained in the javax.servlet.jsp.tagext package.

Tag handler methods defined by the Tag and BodyTag interfaces are called by the JSP page’s servlet at various points during the evaluation of the tag. When the start element of a custom tag is encountered, the JSP page’s servlet calls methods to initialize the appropriate handler and then invokes the handler’s doStartTag method. When the end element of a custom tag is encountered, the handler’s doEndTag method is invoked for all but simple tags. Additional methods are invoked in between when a tag handler needs to manipulate the body of the tag. For further information, see Tags with Bodies. To provide a tag handler implementation, you must implement the methods, summarized in Table 9–2, that are invoked at various stages of processing the tag.

Table 9–2 Tag Handler Methods

Tag Type 

Interface 

Methods 

Basic 

Tag

doStartTag, doEndTag

Attributes 

Tag

doStartTag, doEndTag, setAttribute1,...,N, release

Body 

Tag

doStartTag, doEndTag, release

Body, iterative evaluation 

IterationTag

doStartTag, doAfterBody, doEndTag, release

Body, manipulation 

BodyTag

doStartTag, doEndTag, release, doInitBody, doAfterBody

A tag handler has access to an API that allows it to communicate with the JSP page. The entry points to the API are two objects: the JSP context (javax.servlet.jsp.JspContext) for simple tag handlers and the page context (javax.servlet.jsp.PageContext) for classic tag handlers. JspContext provides access to implicit objects. PageContext extends JspContext with HTTP-specific behavior. A tag handler can retrieve all the other implicit objects (request, session, and application) that are accessible from a JSP page through these objects. In addition, implicit objects can have named attributes associated with them. Such attributes are accessed using [set|get]Attribute methods.

If the tag is nested, a tag handler also has access to the handler (called the parent) associated with the enclosing tag.

How Is a Classic Tag Handler Invoked?

The Tag interface defines the basic protocol between a tag handler and a JSP page’s servlet. It defines the life cycle and the methods to be invoked when the start and end tags are encountered.

The JSP page’s servlet invokes the setPageContext, setParent, and attribute-setting methods before calling doStartTag. The JSP page’s servlet also guarantees that release will be invoked on the tag handler before the end of the page.

Here is a typical tag handler method invocation sequence:

ATag t = new ATag();
t.setPageContext(...);
t.setParent(...);
t.setAttribute1(value1);
t.setAttribute2(value2);
t.doStartTag();
t.doEndTag();
t.release();

The BodyTag interface extends Tag by defining additional methods that let a tag handler access its body. The interface provides three new methods:

A typical invocation sequence is as follows:

t.doStartTag();
out = pageContext.pushBody();
t.setBodyContent(out);
// perform any initialization needed after body content is set
t.doInitBody();
t.doAfterBody();
// while doAfterBody
 returns EVAL_BODY_AGAIN
 we
 // iterate body evaluation
...
t.doAfterBody();
t.doEndTag();
out = pageContext.popBody();
t.release();

Tags with Bodies

A tag handler for a tag with a body is implemented differently depending on whether or not the tag handler needs to manipulate the body. A tag handler manipulates the body when it reads or modifies the contents of the body.

Tag Handler Does Not Manipulate the Body

If the tag handler does not need to manipulate the body, the tag handler should implement the Tag interface. If the tag handler implements the Tag interface and the body of the tag needs to be evaluated, the doStartTag method must return EVAL_BODY_INCLUDE; otherwise it should return SKIP_BODY.

If a tag handler needs to iteratively evaluate the body, it should implement the IterationTag interface. The tag handler should return EVAL_BODY_AGAIN from the doAfterBody method if it determines that the body needs to be evaluated again.

Tag Handler Manipulates the Body

If the tag handler needs to manipulate the body, the tag handler must implement BodyTag (or must be derived from BodyTagSupport).

When a tag handler implements the BodyTag interface, it must implement the doInitBody and the doAfterBody methods. These methods manipulate body content passed to the tag handler by the JSP page’s servlet.

A BodyContent object supports several methods to read and write its contents. A tag handler can use the body content’s getString or getReader method to extract information from the body, and the writeOut(out) method to write the body contents to an out stream. The writer supplied to the writeOut method is obtained using the tag handler’s getPreviousOut method. This method is used to ensure that a tag handler’s results are available to an enclosing tag handler.

If the body of the tag needs to be evaluated, the doStartTag method must return EVAL_BODY_BUFFERED; otherwise, it should return SKIP_BODY.

doInitBody Method

The doInitBody method is called after the body content is set but before it is evaluated. You generally use this method to perform any initialization that depends on the body content.

doAfterBody Method

The doAfterBody method is called after the body content is evaluated. doAfterBody must return an indication of whether to continue evaluating the body. Thus, if the body should be evaluated again, as would be the case if you were implementing an iteration tag, doAfterBody should return EVAL_BODY_AGAIN; otherwise, doAfterBody should return SKIP_BODY.

The following example reads the content of the body (which contains an SQL query) and passes it to an object that executes the query. Because the body does not need to be reevaluated, doAfterBody returns SKIP_BODY.

public class QueryTag extends BodyTagSupport {
    public int doAfterBody() throws JspTagException {
        BodyContent bc = getBodyContent();
        // get the bc as string
        String query = bc.getString();
        // clean up
        bc.clearBody();
        try {
            Statement stmt = connection.createStatement();
            result = stmt.executeQuery(query);
        } catch (SQLException e) {
            throw new JspTagException("QueryTag: " +
                 e.getMessage());
        }
        return SKIP_BODY;
    }
}

release Method

A tag handler should reset its state and release any private resources in the release method.

Cooperating Tags

Tags cooperate by sharing objects. JSP technology supports two styles of object sharing.

The first style requires that a shared object be named and stored in the page context (one of the implicit objects accessible to JSP pages as well as tag handlers). To access objects created and named by another tag, a tag handler uses the pageContext.getAttribute(name,scope) method.

In the second style of object sharing, an object created by the enclosing tag handler of a group of nested tags is available to all inner tag handlers. This form of object sharing has the advantage that it uses a private namespace for the objects, thus reducing the potential for naming conflicts.

To access an object created by an enclosing tag, a tag handler must first obtain its enclosing tag using the static method TagSupport.findAncestorWithClass(from,class) or the TagSupport.getParent method. The former method should be used when a specific nesting of tag handlers cannot be guaranteed. After the ancestor has been retrieved, a tag handler can access any statically or dynamically created objects. Statically created objects are members of the parent. Private objects can also be created dynamically. Such objects can be stored in a tag handler using the setValue method and can be retrieved using the getValue method.

The following example illustrates a tag handler that supports both the named approach and the private object approach to sharing objects. In the example, the handler for a query tag checks whether an attribute named connectionId has been set. If the connection attribute has been set, the handler retrieves the connection object from the page context. Otherwise, the tag handler first retrieves the tag handler for the enclosing tag and then retrieves the connection object from that handler.

public class QueryTag extends BodyTagSupport {
    public int doStartTag() throws JspException {
        String cid = getConnectionId();
        Connection connection;
        if (cid != null) {
        // there is a connection id, use it
            connection =(Connection)pageContext.
                getAttribute(cid);
        } else {
            ConnectionTag ancestorTag =
                (ConnectionTag)findAncestorWithClass(this,
                    ConnectionTag.class);
            if (ancestorTag == null) {
                throw new JspTagException("A query without
                    a connection attribute must be nested
                    within a connection tag.");
            }
            connection = ancestorTag.getConnection();
            ...
        }
    }
}

The query tag implemented by this tag handler can be used in either of the following ways:

<tt:connection cid="con01" ... >
     ...
 </tt:connection>
<tt:query id="balances" connectionId="con01">
     SELECT account, balance FROM acct_table
         where customer_number = ?
    <tt:param value="${requestScope.custNumber}" />
</tt:query>

<tt:connection ... >
    <tt:query cid="balances">
         SELECT account, balance FROM acct_table
         where customer_number = ?
        <tt:param value="${requestScope.custNumber}" />
    </tt:query>
</tt:connection>

The TLD for the tag handler use the following declaration to indicate that the connectionId attribute is optional:

<tag>
    ...
    <attribute>
        <name>connectionId</name>
        <required>false</required>
    </attribute>
</tag>

Tags That Define Variables

The mechanisms for defining variables in classic tags are similar to those described in Chapter 8, Custom Tags in JSP Pages. You must declare the variable in a variable element of the TLD or in a tag extra info class. Use PageContext().setAttribute(name,value) or PageContext.setAttribute(name,value,scope) methods in the tag handler to create or update an association between a name that is accessible in the page context and the object that is the value of the variable. For classic tag handlers, Table 9–3 illustrates how the availability of a variable affects when you may want to set or update the variable’s value.

Table 9–3 Variable Availability

Value 

Availability 

In Methods 

NESTED

Between the start tag and the end tag 

doStartTag, doInitBody, and doAfterBody

AT_BEGIN

From the start tag until the end of the page 

doStartTag, doInitBody, doAfterBody, and doEndTag

AT_END

After the end tag until the end of the page 

doEndTag

A variable defined by a custom tag can also be accessed in a scripting expression. For example, the web service described in the preceding section can be encapsulated in a custom tag that returns the response in a variable named by the var attribute, and then var can be accessed in a scripting expression as follows:

<ws:hello var="response"
         name="<%=request.getParameter("username")%>" />
<h2><font color="black"><%= response %>!</font></h2>

Remember that in situations where scripting is not allowed (in a tag body where the body-content is declared as scriptless and in a page where scripting is specified to be invalid), you wouldn’t be able to access the variable in a scriptlet or an expression. Instead, you would have to use the JSP expression language to access the variable.

Chapter 10 JavaServer Faces Technology

JavaServer Faces technology is a server-side user interface component framework for Java technology-based web applications.

The main components of JavaServer Faces technology are as follows:

The well-defined programming model and tag libraries significantly ease the burden of building and maintaining web applications with server-side UIs. With minimal effort, you can

JavaServer Faces Technology User Interface

As shown in Figure 10–1, the user interface you create with JavaServer Faces technology (represented by myUI in the graphic) runs on the server and renders back to the client.

Figure 10–1 The UI Runs on the Server

Diagram shows a browser accessing the myform.jsp page
using an HTTP Request and the server sending the rendered the HTML page using
an HTTP Response.

The JSP page, myform.jsp, is a JavaServer Faces page, which is a JSP page that includes JavaServer Faces tags. It expresses the user interface components by using custom tags defined by JavaServer Faces technology. The UI for the web application (represented by myUI in the figure) manages the objects referenced by the JSP page. These objects include

This chapter gives an overview of JavaServer Faces technology. After going over some of the primary benefits of using JavaServer Faces technology and explaining what a JavaServer Faces application is, it describes a simple application and specifies which part of the application the developers of each role work on. It then describes the UI component model, the navigation model, and the backing bean features supported by JavaServer Faces technology. Finally, this chapter uses a page from a simple application to summarize the life cycle of a JavaServer Faces page.

JavaServer Faces Technology Benefits

One of the greatest advantages of JavaServer Faces technology is that it offers a clean separation between behavior and presentation. Web applications built using JSP technology achieve this separation in part. However, a JSP application cannot map HTTP requests to component-specific event handling nor manage UI elements as stateful objects on the server, as a JavaServer Faces application can. JavaServer Faces technology allows you to build web applications that implement the finer-grained separation of behavior and presentation that is traditionally offered by client-side UI architectures.

The separation of logic from presentation also allows each member of a web application development team to focus on his or her piece of the development process, and it provides a simple programming model to link the pieces. For example, page authors with no programming expertise can use JavaServer Faces technology UI component tags to link to server-side objects from within a web page without writing any scripts.

Another important goal of JavaServer Faces technology is to leverage familiar UI-component and web-tier concepts without limiting you to a particular scripting technology or markup language. Although JavaServer Faces technology includes a JSP custom tag library for representing components on a JSP page, the JavaServer Faces technology APIs are layered directly on top of the Servlet API, as shown in Figure 3–2. This layering of APIs enables several important application use cases, such as using another presentation technology instead of JSP pages, creating your own custom components directly from the component classes, and generating output for various client devices.

Most importantly, JavaServer Faces technology provides a rich architecture for managing component state, processing component data, validating user input, and handling events.

What Is a JavaServer Faces Application?

For the most part, a JavaServer Faces application is like any other Java web application. A typical JavaServer Faces application includes the following pieces:

A JavaServer Faces application that includes JSP pages also uses the standard tag libraries defined by JavaServer Faces technology for representing UI components and other objects on the page.

A Simple JavaServer Faces Application

This section describes the general steps involved in developing a simple JavaServer Faces application from the perspective of different development roles. These roles are:

This application is quite simple, and so it does not include any custom components. See chapter Writing a Method to Handle a Value-Change Event to learn about the responsibilities of a component writer.

Steps in the Development Process

Developing a simple JavaServer Faces application usually requires these tasks:

The example used in this section is the guessNumber application, located in the tut-install/javaeetutorial5/examples/web/ directory. It asks you to guess a number between 0 and 10, inclusive. The second page tells you whether you guessed correctly. The example also checks the validity of your input. The system log prints Duke’s number. Figure 10–2 shows what the first page looks like.

Figure 10–2 The greeting.jsp Page of the guessNumber Application

Screen capture of Duke asking you to guess a number between
1 and 10, with a text field and a Submit button.

The source for the guessNumber application is located in the tut-install/javaeetutorial5/examples/web/guessNumber/ directory created when you unzip the tutorial bundle (see Chapter 2, Using the Tutorial Examples).

    To build, package, deploy, and run this example using 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 guessNumber folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

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

  7. To run the application, open the URL http://localhost:8080/guessNumber in a browser.

    To build, package, and deploy this example using Ant, follow these steps:

  1. Go to tut-install/javaeetutorial5/examples/web/guessNumber/.

  2. Type ant.

  3. Start the Application Server.

  4. Type ant deploy.

  5. To run the application, open the URL http://localhost:8080/guessNumber in a browser.

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

Mapping the FacesServlet Instance

All JavaServer Faces applications must include a mapping to the FacesServlet instance in their deployment descriptors. The FacesServlet instance accepts incoming requests, passes them to the life cycle for processing, and initializes resources. The following piece of the guessNumber example’s deployment descriptor performs the mapping to the FacesServlet instance:

<servlet>
    <display-name>FacesServlet</display-name>
    <servlet-name>FacesServlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>FacesServlet</servlet-name>
    <url-pattern>/guess/*</url-pattern>
</servlet-mapping>

The mapping to FacesServlet shown above uses a prefix mapping to identify a JSP page as having JavaServer Faces components. Because of this, the URL to the first JSP page of the application must include the mapping. To accomplish this, the guessNumber example includes an HTML page that has the URL to the first JSP page:

<a href="guess/greeting.jsp">

See Identifying the Servlet for Life Cycle Processing for more information on how to map the FacesServlet instance.

Creating the Pages

Creating the pages is the page author’s responsibility. This task involves laying out UI components on the pages, mapping the components to beans, and adding tags that register converters, validators, or listeners onto the components.

In this section you will build the tut-install/javaeetutorial5/examples/examples/web/guessNumber/web/greeting.jsp page, the first page of the guessNumber application. As with any JSP page, you’ll need to add the usual HTML and HEAD tags to the page:

<HTML xmlns="http://www.w3.org/1999/xhtml"xml:lang="en">
    <HEAD> <title>Hello</title> </HEAD>    
    ...
</HTML>

You’ll also need a page directive that specifies the content type:

<%@ page contentType="application/xhtml+xml" %>

Declaring the Tag Libraries

In order to use JavaServer Faces components in JSP pages, you need to give your pages access to the two standard tag libraries, the HTML component tag library and the core tag library using taglib declarations:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http:.//java.sun.com/jsf/core" prefix="f" %>

The first taglib declaration declares the HTML component tag library with a prefix, h. All component tags in the page have this prefix. The core tag library is declared with the prefix f. All core tags in the page have this prefix.

User Interface Component Model includes a table that lists all the component tags included with JavaServer Faces technology. Adding UI Components to a Page Using the HTML Component Tags discusses the tags in more detail.

Adding the view and form Tags

All JavaServer Faces pages are represented by a tree of components, called a view. The view tag represents the root of the view. All JavaServer Faces component tags must be inside of a view tag, which is defined in the core tag library.

The form tag represents an input form component, which allows the user to input some data and submit it to the server, usually by clicking a button. All UI component tags that represent editable components (such as text fields and menus) must be nested inside the form tag. In the case of the greeting.jsp page, some of the tags contained in the form are outputText, inputText, commandButton, and message. You can specify an ID for the form tag. This ID maps to the associated form UI component on the server.

With the view and form tags added, our page looks like this (minus the HTML and HEAD tags):

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
    </h:form>
</f:view>

Adding a Label Component

The outputText tag represents a label. The greeting.jsp page has two outputText tags. One of the tags displays the number 0. The other tag displays the number 10:

    <h:outputText lang="en_US"
         value="#{UserNumberBean.minimum}"/>
    <h:outputText value="#{UserNumberBean.maximum}"/>

The value attributes of the tags get the values from the minimum and maximum properties of UserNumberBean using value expressions, which are used to reference data stored in other objects, such as beans. See Backing Beans for more information on value expressions.

With the addition of the outputText tags (along with some static text), the greeting page looks like the following:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
        <h2>Hi. My name is Duke. I’m thinking of a number from
         <h:outputText lang="en_US"
             value="#{UserNumberBean.minimum}"/> to
         <h:outputText value="#{UserNumberBean.maximum}"/>.
        Can you guess it?</h2>
    </h:form>
</f:view>

Adding an Image

To display images on a page, you use the graphicImage tag. The url attribute of the tag specifies the path to the image file. Let’s add Duke to the page using a graphicImage tag:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
        <h2>Hi. My name is Duke. I’m thinking of a number from
         <h:outputText lang="en_US"
             value="#{UserNumberBean.minimum}"/> to
         <h:outputText value="#{UserNumberBean.maximum}"/>.
        Can you guess it?</h2>
        <h:graphicImage id="waveImg" url="/wave.med.gif" />
    </h:form>
</f:view>

Adding a Text Field

The inputText tag represents a text field component. In the guessNumber example, this text field takes an integer input value. The instance of this tag included in greeting.jsp has three attributes: id, label, and value.

<h:inputText id="userNo" label="User Number"
        value="#{UserNumberBean.userNumber}">
        ...
</h:inputText>

The id attribute corresponds to the ID of the component object represented by this tag. In this case, an id attribute is required because the message tag (which is used to display validation error messages) needs it to refer to the userNo component.

The label attribute specifies the name to be used by error messages to refer to the component. In this example, label is set to User Number. As an example, if a user were to enter 23, the error message that would be displayed is:


User Number: Validation Error: Value is greater than allowable maximum of 10.

The value attribute binds the userNo component value to the bean property UserNumberBean.userNumber, which holds the data entered into the text field.

After adding the inputText tag, the greeting page looks like the following:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
        <h2>Hi. My name is Duke. I’m thinking of a number from
         <h:outputText lang="en_US"
             value="#{UserNumberBean.minimum}"/> to
         <h:outputText value="#{UserNumberBean.maximum}"/>.
        Can you guess it?</h2>
        <h:graphicImage id="waveImg" url="/wave.med.gif" />
        <h:inputText id="userNo" label="User Number"
            value="#{UserNumberBean.userNumber}">
            ...
        </h:inputText>
    </h:form>
</f:view>

See Backing Beans for more information on creating beans, binding to bean properties, referencing bean methods, and configuring beans.

See Using Text Components for more information on the inputText tag.

Registering a Validator on a Text Field

By nesting the validateLongRange tag within a text field’s component’s tag, the page author registers a LongRangeValidator onto the text field. This validator checks whether the component’s local data is within a certain range, defined by the validateLongRange tag’s minimum and maximum attributes.

In the case of the greeting page, you need to validate the number the user enters into the text field. So, you add a validateLongRange tag inside the inputText tag. The maximum and minimum attributes of the validateLongRange tag get their values from the minimum and maximum properties of UserNumberBean using the value expressions #{UserNumberBean.minimum} and #{UserNumberBean.maximum}. See Backing Beans for details on value expressions.

After adding the validateLongRange tag, the page looks like this:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
        <h2>Hi. My name is Duke. I’m thinking of a number from
         <h:outputText lang="en_US"
             value="#{UserNumberBean.minimum}"/> to
         <h:outputText value="#{UserNumberBean.maximum}"/>.
        Can you guess it?</h2>
        <h:graphicImage id="waveImg" url="/wave.med.gif" />
        <h:inputText id="userNo" label="User Number"
            value="#{UserNumberBean.userNumber}">
                <f:validateLongRange
                     minimum="#{UserNumberBean.minimum}"
                     maximum="#{UserNumberBean.maximum}" />
        </h:inputText>
    </h:form>
</f:view>

For more information on the standard validators included with JavaServer Faces technology, see Using the Standard Validators.

Adding a Custom Message

JavaServer Faces technology provides standard error messages that display on the page when conversion or validation fails. In some cases, you might need to override the standard message. For example, if a user were to enter a letter into the text field on greeting.jsp, he or she would see the following error message:


User Number: ’m’ must be a number between -2147483648 and 2147483647 Example: 9346

This is wrong because the field really only accepts values from 0 through 10.

To override this message, you add a converterMessage attribute on the inputText tag. This attribute references the custom error message:

<h:inputText id="userNo" label="User Number"
         value="#{UserNumberBean.userNumber}"
         converterMessage="#{ErrMsg.userNoConvert}">
...
</h:inputText>

The expression that converterMessage uses references the userNoConvert key of the ErrMsg resource bundle. The application architect needs to define the message in the resource bundle and configure the resource bundle. See Configuring Error Messages for more information on this.

See Referencing Error Messages for more information on referencing error messages.

Adding a Button

The commandButton tag represents the button used to submit the data entered in the text field. The action attribute specifies an outcome that helps the navigation mechanism decide which page to open next. Defining Page Navigation discusses this further.

With the addition of the commandButton tag, the greeting page looks like the following:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
        <h2>Hi. My name is Duke. I’m thinking of a number from
         <h:outputText lang="en_US"
             value="#{UserNumberBean.minimum}"/> to
         <h:outputText value="#{UserNumberBean.maximum}"/>.
        Can you guess it?</h2>
        <h:graphicImage id="waveImg" url="/wave.med.gif" />
        <h:inputText id="userNo" label="User Number"
            value="#{UserNumberBean.userNumber}">
                <f:validateLongRange
                     minimum="#{UserNumberBean.minimum}"
                     maximum="#{UserNumberBean.maximum}" />
        </h:inputText>
        <h:commandButton id="submit"
             action="success" value="Submit" />
    </h:form>
</f:view>

See Using Command Components for Performing Actions and Navigation for more information on the commandButton tag.

Displaying Error Messages

A message tag is used to display error messages on a page when data conversion or validation fails after the user submits the form. The message tag in greeting.jsp displays an error message if the data entered in the field does not comply with the rules specified by the LongRangeValidator implementation, whose tag is registered on the text field component.

The error message displays wherever you place the message tag on the page. The message tag’s style attribute allows you to specify the formatting style for the message text. Its for attribute refers to the component whose value failed validation, in this case the userNo component represented by the inputText tag in the greeting.jsp page.

Put the message tag near the end of the page:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
    <h:form id="helloForm1">
        <h2>Hi. My name is Duke. I’m thinking of a number from
         <h:outputText lang="en_US"
             value="#{UserNumberBean.minimum}"/> to
         <h:outputText value="#{UserNumberBean.maximum}"/>.
        Can you guess it?</h2>
        <h:graphicImage id="waveImg" url="/wave.med.gif" />
        <h:inputText id="userNo" label="User Number"
            value="#{UserNumberBean.userNumber}"
            converterMessage="#{ErrMsg.userNoConvert}">
            <f:validateLongRange
                     minimum="#{UserNumberBean.minimum}"
                     maximum="#{UserNumberBean.maximum}" />
        </h:inputText>
        <h:commandButton id="submit"
             action="success" value="Submit" />
        <h:message showSummary="true" showDetail="false"
                style="color: red;
                 font-family: ’New Century Schoolbook’, serif;
                 font-style: oblique;
                 text-decoration: overline"
                 id="errors1"
                 for="userNo"/>
    </h:form>
</f:view>

Now you have completed the greeting page. Assuming you have also done the response.jsp page, you can move on to defining the page navigation rules.

Defining Page Navigation

Defining page navigation involves determining which page to go to after the user clicks a button or a hyperlink. Navigation for the application is defined in the application configuration resource file using a powerful rule-based system. Here is one of the navigation rules defined for the guessNumber example:

<navigation-rule>
    <from-view-id>/greeting.jsp</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/response.jsp</to-view-id>
    </navigation-case>
</navigation-rule>
<navigation-rule>
    <from-view-id>/response.jsp</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/greeting.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

This navigation rule states that when the button on the greeting page is clicked the application will navigate to response.jsp if the navigation system is given a logical outcome of success.

In the case of the Guess Number example, the logical outcome is defined by the action attribute of the UICommand component that submits the form:

<h:commandButton id="submit" action="success"
     value="Submit" />

To learn more about how navigation works, see Navigation Model.

Configuring Error Messages

In case the standard error messages don’t meet your needs, you can create new ones in resource bundles and configure the resource bundles in your application configuration resource file. The guessNumber example has one custom converter message, as described in Adding a Custom Message.

This message is stored in the resource bundle, ApplicationMessages.properties:

userNoConvert=The value you entered is not a number.

The resource bundle is configured in the application configuration file:

<application>
    <resource-bundle>
        <base-name>guessNumber.ApplicationMessages</base-name>
        <var>ErrMsg</var>
    </resource-bundle>
</application>

The base-name element indicates the fully-qualified name of the resource bundle. The var element indicates the name by which page authors refer to the resource bundle with the expression language. Here is the inputText tag again:

<h:inputText id="userNo" label="User Number"
    value="#{UserNumberBean.userNumber}"
        converterMessage="#{ErrMsg.userNoConvert}">
        ...
</h:inputText>

The expression on the converterMessage attribute references the userNoConvert key of the ErrMsg resource bundle.

See Registering Custom Error Messages for more information on configuring custom error messages.

Developing the Beans

Developing beans is one responsibility of the application developer. A typical JavaServer Faces application couples a backing bean with each page in the application. The backing bean defines properties and methods that are associated with the UI components used on the page.

The page author binds a component’s value to a bean property using the component tag’s value attribute to refer to the property. Recall that the userNo component on the greeting.jsp page references the userNumber property of UserNumberBean:

<h:inputText id="userNo" label="User Number"
            value="#{UserNumberBean.userNumber}">
...
</h:inputText>

Here is the userNumber backing bean property that maps to the data for the userNo component:

Integer userNumber = null;
...
public void setUserNumber(Integer user_number) {
    userNumber = user_number;
 }
public Integer getUserNumber() {
    return userNumber;
}
public String getResponse() {
    if(userNumber != null &&
         userNumber.compareTo(randomInt) == 0) {
            return "Yay! You got it!";
    } else {
        return "Sorry, "+userNumber+" is incorrect.";
    }
}

See Backing Beans for more information on creating backing beans.

Adding Managed Bean Declarations

After developing the backing beans to be used in the application, you need to configure them in the application configuration resource file so that the JavaServer Faces implementation can automatically create new instances of the beans whenever they are needed.

The task of adding managed bean declarations to the application configuration resource file is the application architect’s responsibility. Here is a managed bean declaration for UserNumberBean:

<managed-bean>
    <managed-bean-name>UserNumberBean</managed-bean-name>
    <managed-bean-class>
        guessNumber.UserNumberBean
    </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
        <property-name>minimum</property-name>
        <property-class>long</property-class>
        <value>0</value>
    </managed-property>
    <managed-property>
        <property-name>maximum</property-name>
        <property-class>long</property-class>
        <value>10</value>
    </managed-property>
</managed-bean>

This declaration configures UserNumberBean so that its minimum property is initialized to 0, its maximum property is initialized to 10, and it is added to session scope when it is created.

A page author can use the unified EL to access one of the bean’s properties, like this:

<h:outputText value="#{UserNumberBean.minimum}"/>

For more information on configuring beans, see Configuring a Bean.

User Interface Component Model

JavaServer Faces UI components are configurable, reusable elements that compose the user interfaces of JavaServer Faces applications. A component can be simple, such as a button, or compound, such as a table, which can be composed of multiple components.

JavaServer Faces technology provides a rich, flexible component architecture that includes the following:

This section briefly describes each of these pieces of the component architecture.

User Interface Component Classes

JavaServer Faces technology provides a set of UI component classes and associated behavioral interfaces that specify all the UI component functionality, such as holding component state, maintaining a reference to objects, and driving event handling and rendering for a set of standard components.

The component classes are completely extensible, allowing component writers to create their own custom components. See Chapter 13, Creating Custom UI Components for an example of a custom image map component.

All JavaServer Faces UI component classes extend UIComponentBase, which defines the default state and behavior of a UI component. The following set of UI component classes is included with JavaServer Faces technology:

In addition to extending UIComponentBase, the component classes also implement one or more behavioral interfaces, each of which defines certain behavior for a set of components whose classes implement the interface.

These behavioral interfaces are as follows:

UICommand implements ActionSource2 and StateHolder. UIOutput and component classes that extend UIOutput implement StateHolder and ValueHolder. UIInput and component classes that extend UIInput implement EditableValueHolder, StateHolder, and ValueHolder. UIComponentBase implements StateHolder. See the JavaServer Faces Technology 1.2 API Specification for more information on these interfaces.

Only component writers will need to use the component classes and behavioral interfaces directly. Page authors and application developers will use a standard UI component by including a tag that represents it on a JSP page. Most of the components can be rendered in different ways on a page. For example, a UICommand component can be rendered as a button or a hyperlink.

The next section explains how the rendering model works and how page authors choose how to render the components by selecting the appropriate tags.

Component Rendering Model

The JavaServer Faces component architecture is designed such that the functionality of the components is defined by the component classes, whereas the component rendering can be defined by a separate renderer. This design has several benefits, including:

A render kit defines how component classes map to component tags that are appropriate for a particular client. The JavaServer Faces implementation includes a standard HTML render kit for rendering to an HTML client.

The render kit defines a set of Renderer classes for each component that it supports. Each Renderer class defines a different way to render the particular component to the output defined by the render kit. For example, a UISelectOne component has three different renderers. One of them renders the component as a set of radio buttons. Another renders the component as a combo box. The third one renders the component as a list box.

Each JSP custom tag defined in the standard HTML render kit is composed of the component functionality (defined in the UIComponent class) and the rendering attributes (defined by the Renderer class). For example, the two tags in Table 10–1 represent a UICommand component rendered in two different ways.

Table 10–1 UICommand Tags

Tag 

Rendered As 

commandButton

Login button.

commandLink

Hyperlink.

The command part of the tags shown in Table 10–1 corresponds to the UICommand class, specifying the functionality, which is to fire an action. The button and hyperlink parts of the tags each correspond to a separate Renderer class, which defines how the component appears on the page.

The JavaServer Faces implementation provides a custom tag library for rendering components in HTML. It supports all the component tags listed in Table 10–2. To learn how to use the tags in an example, see Adding UI Components to a Page Using the HTML Component Tags.

Table 10–2 The UI Component Tags

Tag 

Functions 

Rendered As 

Appearance 

column

Represents a column of data in a UIData component.

A column of data in an HTML table 

A column in a table

commandButton

Submits a form to the application. 

An HTML <input type=type> element, where the type value can be submit, reset, or image

A button

commandLink

Links to another page or location on a page. 

An HTML <a href> element

A hyperlink

dataTable

Represents a data wrapper. 

An HTML <table> element

A table that can be updated dynamically

form

Represents an input form. The inner tags of the form receive the data that will be submitted with the form. 

An HTML <form> element

No appearance 

graphicImage

Displays an image. 

An HTML <img> element

An image 

inputHidden

Allows a page author to include a hidden variable in a page. 

An HTML <input type=hidden> element

No appearance

inputSecret

Allows a user to input a string without the actual string appearing in the field. 

An HTML <input type=password> element

A text field, which displays a row of characters instead of the actual string entered

inputText

Allows a user to input a string. 

An HTML <input type=text> element

A text field

inputTextarea

Allows a user to enter a multiline string. 

An HTML <textarea> element

A multi-row text field

message

Displays a localized message. 

An HTML <span> tag if styles are used

A text string 

messages

Displays localized messages. 

A set of HTML <span> tags if styles are used

A text string 

outputFormat

Displays a localized message. 

Plain text 

Plain text 

outputLabel

Displays a nested component as a label for a specified input field. 

An HTML <label> element

Plain text

outputLink

Links to another page or location on a page without generating an action event. 

An HTML <a> element

A hyperlink 

outputText

Displays a line of text. 

Plain text 

Plain text

panelGrid

Displays a table. 

An HTML <table> element with <tr> and <td> elements

A table

panelGroup

Groups a set of components under one parent. 

 

A row in a table 

selectBooleanCheckbox

Allows a user to change the value of a Boolean choice. 

An HTML <input type=checkbox> element.

A check box

selectItem

Represents one item in a list of items in a UISelectOne component.

An HTML <option> element

No appearance 

selectItems

Represents a list of items in a UISelectOne component.

A list of HTML <option> elements

No appearance 

selectManyCheckbox

Displays a set of check boxes from which the user can select multiple values. 

A set of HTML <input> elements of type checkbox

A set of check boxes

selectManyListbox

Allows a user to select multiple items from a set of items, all displayed at once. 

An HTML <select> element

A list box

selectManyMenu

Allows a user to select multiple items from a set of items. 

An HTML <select> element

A scrollable combo box

selectOneListbox

Allows a user to select one item from a set of items, all displayed at once. 

An HTML <select> element

A list box

selectOneMenu

Allows a user to select one item from a set of items. 

An HTML <select> element

A scrollable combo box

selectOneRadio

Allows a user to select one item from a set of items. 

An HTML <input type=radio> element

A set of radio buttons

Conversion Model

A JavaServer Faces application can optionally associate a component with server-side object data. This object is a JavaBeans component, such as a backing bean. An application gets and sets the object data for a component by calling the appropriate object properties for that component.

When a component is bound to an object, the application has two views of the component’s data:

The JavaServer Faces implementation automatically converts component data between these two views when the bean property associated with the component is of one of the types supported by the component’s data. For example, if a UISelectBoolean component is associated with a bean property of type java.lang.Boolean, the JavaServer Faces implementation will automatically convert the component’s data from String to Boolean. In addition, some component data must be bound to properties of a particular type. For example, a UISelectBoolean component must be bound to a property of type boolean or java.lang.Boolean.

Sometimes you might want to convert a component’s data to a type other than a standard type, or you might want to convert the format of the data. To facilitate this, JavaServer Faces technology allows you to register a Converter implementation on UIOutput components and components whose classes subclass UIOutput. If you register the Converter implementation on a component, the Converter implementation converts the component’s data between the two views.

You can either use the standard converters supplied with the JavaServer Faces implementation or create your own custom converter.

To create and use a custom converter in your application, three things must happen:

Event and Listener Model

The JavaServer Faces event and listener model is similar to the JavaBeans event model in that it has strongly typed event classes and listener interfaces that an application can use to handle events generated by UI components.

An Event object identifies the component that generated the event and stores information about the event. To be notified of an event, an application must provide an implementation of the Listener class and must register it on the component that generates the event. When the user activates a component, such as by clicking a button, an event is fired. This causes the JavaServer Faces implementation to invoke the listener method that processes the event.

JavaServer Faces technology supports three kinds of events: value-change events, action events, and data-model events.

An action event occurs when the user activates a component that implements ActionSource. These components include buttons and hyperlinks.

A value-change event occurs when the user changes the value of a component represented by UIInput or one of its subclasses. An example is selecting a check box, an action that results in the component’s value changing to true. The component types that can generate these types of events are the UIInput, UISelectOne, UISelectMany, and UISelectBoolean components. Value-change events are fired only if no validation errors were detected.

Depending on the value of the immediate property (see The immediate Attribute) of the component emitting the event, action events can be processed during the invoke application phase or the apply request values phase, and value-change events can be processed during the process validations phase or the apply request values phase.

A data-model event occurs when a new row of a UIData component is selected. The discussion of data-model events is an advanced topic. It is not covered in this tutorial but may be discussed in future versions of this tutorial.

There are two ways to cause your application to react to action events or value-change events emitted by a standard component:

See Implementing an Event Listener for information on how to implement an event listener. See Registering Listeners on Components for information on how to register the listener on a component.

See Writing a Method to Handle an Action Event and Writing a Method to Handle a Value-Change Event for information on how to implement backing bean methods that handle these events.

See Referencing a Backing Bean Method for information on how to refer to the backing bean method from the component tag.

When emitting events from custom components, you must implement the appropriate Event class and manually queue the event on the component in addition to implementing an event listener class or a backing bean method that handles the event. Handling Events for Custom Components explains how to do this.

Validation Model

JavaServer Faces technology supports a mechanism for validating the local data of editable components (such as text fields). This validation occurs before the corresponding model data is updated to match the local value.

Like the conversion model, the validation model defines a set of standard classes for performing common data validation checks. The JavaServer Faces core tag library also defines a set of tags that correspond to the standard Validator implementations. See Table 11–7 for a list of all the standard validation classes and corresponding tags.

Most of the tags have a set of attributes for configuring the validator’s properties, such as the minimum and maximum allowable values for the component’s data. The page author registers the validator on a component by nesting the validator’s tag within the component’s tag.

The validation model also allows you to create your own custom validator and corresponding tag to perform custom validation. The validation model provides two ways to implement custom validation:

If you are implementing a Validator interface, you must also:

If you are implementing a backing bean method to perform validation, you also must reference the validator from the component tag’s validator attribute. See Referencing a Method That Performs Validation for more information.

Navigation Model

The JavaServer Faces navigation model makes it easy to define page navigation and to handle any additional processing needed to choose the sequence in which pages are loaded.

As defined by JavaServer Faces technology, navigation is a set of rules for choosing the next page to be displayed after a button or hyperlink is clicked. These rules are defined by the application architect in the application configuration resource file (see Application Configuration Resource File) using a small set of XML elements.

To handle navigation in the simplest application, you simply

The Guess Number example uses this kind of simple navigation. Here is an example navigation rule from the guessNumber application described in Defining Page Navigation:

<navigation-rule>
    <from-view-id>/greeting.jsp</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/response.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

This rule states that when the button component on greeting.jsp is activated, the application will navigate from the greeting.jsp page to the tut-install/javaeetutorial5/examples/web/guessNumber/web/response.jsp page if the outcome referenced by the button component’s tag is success. Here is the commandButton tag from greeting.jsp that specifies a logical outcome of success:

<h:commandButton id="submit" action="success"
         value="Submit" />

As the example demonstrates, each navigation-rule element defines how to get from one page (specified in the from-view-id element) to the other pages of the application. The navigation-rule elements can contain any number of navigation-case elements, each of which defines the page to open next (defined by to-view-id) based on a logical outcome (defined by from-outcome).

In more complicated applications, the logical outcome can also come from the return value of an action method in a backing bean. This method performs some processing to determine the outcome. For example, the method can check whether the password the user entered on the page matches the one on file. If it does, the method might return success; otherwise, it might return failure. An outcome of failure might result in the logon page being reloaded. An outcome of success might cause the page displaying the user’s credit card activity to open. If you want the outcome to be returned by a method on a bean, you must refer to the method using a method expression, using the action attribute, as shown by this example:

<h:commandButton id="submit"
     action="#{userNumberBean.getOrderStatus}" value="Submit" />

When the user clicks the button represented by this tag, the corresponding component generates an action event. This event is handled by the default ActionListener instance, which calls the action method referenced by the component that triggered the event. The action method returns a logical outcome to the action listener.

    The listener passes the logical outcome and a reference to the action method that produced the outcome to the default NavigationHandler. The NavigationHandler selects the page to display next by matching the outcome or the action method reference against the navigation rules in the application configuration resource file by the following process:

  1. The NavigationHandler selects the navigation rule that matches the page currently displayed.

  2. It matches the outcome or the action method reference it received from the default ActionListener with those defined by the navigation cases.

  3. It tries to match both the method reference and the outcome against the same navigation case.

  4. If the previous step fails, the navigation handler attempts to match the outcome.

  5. Finally, the navigation handler attempts to match the action method reference if the previous two attempts failed.

When the NavigationHandler achieves a match, the render response phase begins. During this phase, the page selected by the NavigationHandler will be rendered.

For more information on how to define navigation rules, see Configuring Navigation Rules.

For more information on how to implement action methods to handle navigation, see Writing a Method to Handle an Action Event.

For more information on how to reference outcomes or action methods from component tags, see Referencing a Method That Performs Navigation.

Backing Beans

A typical JavaServer Faces application includes one or more backing beans, each of which is a JavaServer Faces managed bean that is associated with the UI components used in a particular page. Managed beans are JavaBeans components (see JavaBeans Components) that you can configure using the managed bean facility, which is described in Configuring Beans. This section introduces the basic concepts on creating, configuring, and using backing beans in an application.

Creating a Backing Bean Class

In addition to defining a no-arg constructor, as all JavaBeans components must do, a backing bean class also defines a set of UI component properties and possibly a set of methods that perform functions for a component.

Each of the component properties can be bound to one of the following:

The most common functions that backing bean methods perform include the following:

As with all JavaBeans components, a property consists of a private data field and a set of accessor methods, as shown by this code from the Guess Number example:

Integer userNumber = null;
...
public void setUserNumber(Integer user_number) {
    userNumber = user_number;
 }
public Integer getUserNumber() {
    return userNumber;
}
public String getResponse() {
    ...
}

Because backing beans follow JavaBeans component conventions, you can reference beans you’ve already written from your JavaServer Faces pages.

When a bean property is bound to a component’s value, it can be any of the basic primitive and numeric types or any Java object type for which the application has access to an appropriate converter. For example, a property can be of type Date if the application has access to a converter that can convert the Date type to a String and back again. See Writing Bean Properties for information on which types are accepted by which component tags.

When a bean property is bound to a component instance, the property’s type must be the same as the component object. For example, if a UISelectBoolean is bound to the property, the property must accept and return a UISelectBoolean object.

Likewise, if the property is bound to a converter, validator, or listener instance then the property must be of the appropriate converter, validator, or listener type.

For more information on writing beans and their properties, see Writing Bean Properties.

Configuring a Bean

JavaServer Faces technology supports a sophisticated managed bean creation facility, which allows application architects to do the following:

An application architect configures the beans in the application configuration resource file. To learn how to configure a managed bean, see Configuring Beans. The managed bean configuration used by the Guess Number example is the following:

<managed-bean>
    <managed-bean-name>UserNumberBean</managed-bean-name>
    <managed-bean-class>
        guessNumber.UserNumberBean
    </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
        <property-name>minimum</property-name>
        <property-class>long</property-class>
        <value>0</value>
    </managed-property>
    <managed-property>
        <property-name>maximum</property-name>
        <property-class>long</property-class>
        <value>10</value>
    </managed-property>
</managed-bean>

The JavaServer Faces implementation processes this element on application startup time. When UserNumberBean is first referenced from the page, the JavaServer Faces implementation initializes it and sets the values of the properties, maximum and minimum. The bean is then stored in session scope if no instance exists. As such, the bean is available for all pages in the application.

A page author can then access the bean properties from the component tags on the page using the unified EL, as shown here:

<h:outputText value="#{UserNumberBean.minimum}"/>

The part of the expression before the . matches the name defined by the managed-bean-name element. The part of the expression after the . matches the name defined by the property-name element corresponding to the same managed-bean declaration.

Notice that the application configuration resource file does not configure the userNumber property. Any property that does not have a corresponding managed-property element will be initialized to whatever the constructor of the bean class has the instance variable set to. The next section explains more about using the unified EL to reference backing beans.

For more information on configuring beans using the managed bean creation Facility, see Configuring Beans.

Using the Unified EL to Reference Backing Beans

To bind UI component values and objects to backing bean properties or to reference backing bean methods from UI component tags, page authors use the unified expression language (EL) syntax defined by JSP 2.1. As explained in Unified Expression Language, some of the features this language offers are:

These features are all especially important for supporting the sophisticated UI component model offered by JavaServer Faces technology.

Deferred evaluation of expressions is important because the JavaServer Faces life cycle is split into separate phases so that component event handling, data conversion and validation, and data propagation to external objects are all performed in an orderly fashion. The implementation must be able to delay the evaluation of expressions until the proper phase of the life cycle has been reached. Therefore, its tag attributes always use deferred evaluation syntax, which is distinguished by the #{} delimiters. The Life Cycle of a JavaServer Faces Page describes the life cycle in detail.

In order to store data in external objects, almost all JavaServer Faces tag attributes use lvalue value expressions, which are expressions that allow both getting and setting data on external objects.

Finally, some component tag attributes accept method expressions that reference methods that handle component events, or validate or convert component data.

To illustrate a JavaServer Faces tag using the unified EL, let’s suppose that the userNo tag of the guessNumber application referenced a method rather than using LongRangeValidator to perform the validation of user input :

<h:inputText id="userNo"
     value="#{UserNumberBean.userNumber}"
     validator="#{UserNumberBean.validate}" />

This tag binds the userNo component’s value to the UserNumberBean.userNumber backing bean property using an lvalue expression. It uses a method expression to refer to the UserNumberBean.validate method, which performs validation of the component’s local value. The local value is whatever the user enters into the field corresponding to this tag. This method is invoked when the expression is evaluated, which is during the process validation phase of the life cycle.

Nearly all JavaServer Faces tag attributes accept value expressions. In addition to referencing bean properties, value expressions can also reference lists, maps, arrays, implicit objects, and resource bundles.

Another use of value expressions is binding a component instance to a backing bean property. A page author does this by referencing the property from the binding attribute:

<inputText binding="#{UserNumberBean.userNoComponent}" />

Those component tags that use method expressions are UIInput component tags and UICommand component tags. See sections Using Text Components and Using Command Components for Performing Actions and Navigation for more information on how these component tags use method expressions.

In addition to using expressions with the standard component tags, you can also configure your custom component properties to accept expressions by creating ValueExpression or MethodExpression instances for them. See Creating Custom Component Classes and Enabling Component Properties to Accept Expressions for more information on enabling your component’s attributes to support expressions.

To learn more about using expressions to bind to backing bean properties, see Binding Component Values and Instances to External Data Sources.

For information on referencing backing bean methods from component tags, see Referencing a Backing Bean Method.

The Life Cycle of a JavaServer Faces Page

The life cycle of a JavaServer Faces page is somewhat similar to that of a JSP page: The client makes an HTTP request for the page, and the server responds with the page translated to HTML. However, the JavaServer Faces life cycle differs from the JSP life cycle in that it is split up into multiple phases in order to support the sophisticated UI component model. This model requires that component data be converted and validated, component events be handled, and component data be propagated to beans in an orderly fashion.

A JavaServer Faces page is also different from a JSP page in that it is represented by a tree of UI components, called a view. During the life cycle, the JavaServer Faces implementation must build the view while considering state saved from a previous submission of the page. When the client submits a page, the JavaServer Faces implementation performs several tasks, such as validating the data input of components in the view and converting input data to types specified on the server side.

The JavaServer Faces implementation performs all these tasks as a series of steps in the JavaServer Faces request-response life cycle. Figure 10–3 illustrates these steps.

Figure 10–3 JavaServer Faces Standard Request-Response Life Cycle

Flow diagram of Faces request and Faces response, including
event and validation processing, error handling, model updating, application
invocation.

The life cycle handles both kinds of requests: initial requests and postbacks. When a user makes an initial request for a page, he or she is requesting the page for the first time. When a user executes a postback, he or she submits the form contained on a page that was previously loaded into the browser as a result of executing an initial request. When the life cycle handles an initial request, it only executes the restore view and render response phases because there is no user input or actions to process. Conversely, when the life cycle handles a postback, it executes all of the phases.

Usually, the first request for a JavaServer Faces pages comes in as a result of clicking a hyperlink on an HTML page that links to the JavaServer Faces page. To render a response that is another JavaServer Faces page, the application creates a new view and stores it in the FacesContext instance, which represents all of the contextual information associated with processing an incoming request and creating a response. The application then acquires object references needed by the view and calls FacesContext.renderResponse, which forces immediate rendering of the view by skipping to the Render Response Phase of the life cycle, as is shown by the arrows labelled Render Response in the diagram.

Sometimes, an application might need to redirect to a different web application resource, such as a web service, or generate a response that does not contain JavaServer Faces components. In these situations, the developer must skip the rendering phase (Render Response Phase) by calling FacesContext.responseComplete. This situation is also shown in the diagram, this time with the arrows labelled Response Complete.

The most common situation is that a JavaServer Faces component submits a request for another JavaServer Faces page. In this case, the JavaServer Faces implementation handles the request and automatically goes through the phases in the life cycle to perform any necessary conversions, validations, and model updates, and to generate the response.

This rest of this section explains each of the life cycle phases using the guessNumber example.

The details of the life cycle explained in this section are primarily intended for developers who need to know information such as when validations, conversions, and events are usually handled and what they can do to change how and when they are handled. Page authors don’t necessarily need to know the details of the life cycle.

Restore View Phase

When a request for a JavaServer Faces page is made, such as when a link or a button is clicked, the JavaServer Faces implementation begins the restore view phase.

During this phase, the JavaServer Faces implementation builds the view of the page, wires event handlers and validators to components in the view, and saves the view in the FacesContext instance, which contains all the information needed to process a single request. All the application’s component tags, event handlers, converters, and validators have access to the FacesContext instance.

If the request for the page is an initial request, the JavaServer Faces implementation creates an empty view during this phase and the life cycle advances to the render response phase, during which the empty view is populated with the components referenced by the tags in the page.

If the request for the page is a postback, a view corresponding to this page already exists. During this phase, the JavaServer Faces implementation restores the view by using the state information saved on the client or the server.

The view for the greeting.jsp page of the guessNumber example would have the UIView component at the root of the tree, with helloForm as its child and the rest of the JavaServer Faces UI components as children of helloForm.

Apply Request Values Phase

After the component tree is restored, each component in the tree extracts its new value from the request parameters by using its decode method. The value is then stored locally on the component. If the conversion of the value fails, an error message associated with the component is generated and queued on FacesContext. This message will be displayed during the render response phase, along with any validation errors resulting from the process validations phase.

In the case of the userNo component on the greeting.jsp page, the value is whatever the user entered in the field. Because the object property bound to the component has an Integer type, the JavaServer Faces implementation converts the value from a String to an Integer.

If any decode methods or event listeners called renderResponse on the current FacesContext instance, the JavaServer Faces implementation skips to the render response phase.

If events have been queued during this phase, the JavaServer Faces implementation broadcasts the events to interested listeners.

If some components on the page have their immediate attributes (see The immediate Attribute) set to true, then the validation, conversion, and events associated with these components will be processed during this phase.

At this point, if the application needs to redirect to a different web application resource or generate a response that does not contain any JavaServer Faces components, it can call FacesContext.responseComplete.

At the end of this phase, the components are set to their new values, and messages and events have been queued.

Process Validations Phase

During this phase, the JavaServer Faces implementation processes all validators registered on the components in the tree. It examines the component attributes that specify the rules for the validation and compares these rules to the local value stored for the component.

If the local value is invalid, the JavaServer Faces implementation adds an error message to the FacesContext instance, and the life cycle advances directly to the render response phase so that the page is rendered again with the error messages displayed. If there were conversion errors from the apply request values phase, the messages for these errors are also displayed.

If any validate methods or event listeners called renderResponse on the current FacesContext, the JavaServer Faces implementation skips to the render response phase.

At this point, if the application needs to redirect to a different web application resource or generate a response that does not contain any JavaServer Faces components, it can call FacesContext.responseComplete.

If events have been queued during this phase, the JavaServer Faces implementation broadcasts them to interested listeners.

In the case of the greeting.jsp page, the JavaServer Faces implementation processes the standard validator registered on the userNo inputText tag. It verifies that the data the user entered in the text field is an integer in the range 0 to 10. If the data is invalid or if conversion errors occurred during the apply request values phase, processing jumps to the render response phase, during which the greeting.jsp page is rendered again, with the validation and conversion error messages displayed in the component associated with the message tag.

Update Model Values Phase

After the JavaServer Faces implementation determines that the data is valid, it can walk the component tree and set the corresponding server-side object properties to the components’ local values. The JavaServer Faces implementation will update only the bean properties pointed at by an input component’s value attribute. If the local data cannot be converted to the types specified by the bean properties, the life cycle advances directly to the render response phase so that the page is re-rendered with errors displayed. This is similar to what happens with validation errors.

If any updateModels methods or any listeners called renderResponse on the current FacesContext instance, the JavaServer Faces implementation skips to the render response phase.

At this point, if the application needs to redirect to a different web application resource or generate a response that does not contain any JavaServer Faces components, it can call FacesContext.responseComplete.

If events have been queued during this phase, the JavaServer Faces implementation broadcasts them to interested listeners.

At this stage, the userNo property of the UserNumberBean is set to the local value of the userNumber component.

Invoke Application Phase

During this phase, the JavaServer Faces implementation handles any application-level events, such as submitting a form or linking to another page.

At this point, if the application needs to redirect to a different web application resource or generate a response that does not contain any JavaServer Faces components, it can call FacesContext.responseComplete.

If the view being processed was reconstructed from state information from a previous request and if a component has fired an event, these events are broadcast to interested listeners.

The greeting.jsp page from the guessNumber example has one application-level event associated with the UICommand component. When processing this event, a default ActionListener implementation retrieves the outcome, success, from the component’s action attribute. The listener passes the outcome to the default NavigationHandler. The NavigationHandler matches the outcome to the proper navigation rule defined in the application’s application configuration resource file to determine which page needs to be displayed next. See Configuring Navigation Rules for more information on managing page navigation. The JavaServer Faces implementation then sets the response view to that of the new page. Finally, the JavaServer Faces implementation transfers control to the render response phase.

Render Response Phase

During this phase, the JavaServer Faces implementation delegates authority for rendering the page to the JSP container if the application is using JSP pages. If this is an initial request, the components represented on the page will be added to the component tree as the JSP container executes the page. If this is not an initial request, the components are already added to the tree so they needn’t be added again. In either case, the components will render themselves as the JSP container traverses the tags in the page.

If the request is a postback and errors were encountered during the apply request values phase, process validations phase, or update model values phase, the original page is rendered during this phase. If the pages contain message or messages tags, any queued error messages are displayed on the page.

After the content of the view is rendered, the state of the response is saved so that subsequent requests can access it and it is available to the restore view phase.

In the case of the guessNumber example, if a request for the greeting.jsp page is an initial request, an empty view representing this page is built and saved in FacesContext during the restore view phase. During this phase, the empty view is populated with the components referenced in the page and then rendered during this phase. If a request for the page is a postback (such as when the user enters some invalid data and clicks Submit), the tree is rebuilt during the restore view phase and continues through the request processing life cycle phases.

Further Information about JavaServer Faces Technology

For more information on JavaServer Faces technology, see:

Chapter 11 Using JavaServer Faces Technology in JSP Pages

The page author’s responsibility is to design the pages of a JavaServer Faces application. This includes laying out the components on the page and wiring them to backing beans, validators, converters, and other server-side objects associated with the page. This chapter uses the Duke’s Bookstore application and the Coffee Break application (see Chapter 36, The Coffee Break Application) to describe how page authors use the JavaServer Faces tags to perform the following tasks:

This chapter also describes how to include custom objects created by application developers and component writers on a JSP page.

The Example JavaServer Faces Application

The JavaServer Faces technology chapters of this tutorial primarily use a rewritten version of the Duke’s Bookstore example to illustrate the basic concepts of JavaServer Faces technology. This version of the Duke’s Bookstore example includes several JavaServer Faces technology features:

This version of Duke’s Bookstore includes the same pages listed in Table 5–1. It also includes the tut-install/javaeetutorial5/examples/web/bookstore6/web/chooselocale.jsp page, which displays the custom image map that allows you to select the locale of the application. This page is displayed first and advances directly to the bookstore.jsp page after the locale is selected.

The packages of the Duke’s Bookstore application are:

Chapter 12, Developing with JavaServer Faces Technology describes how to program backing beans, custom converters and validators, and event listeners. Chapter 13, Creating Custom UI Components describes how to program event handlers, custom components, renderers, and tag handlers.

The source code for the application is located in the tut-install/javaeetutorial5/examples/web/bookstore6/ directory.

    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 5.5, select File->Open Project.

  3. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/web/
  4. Select the bookstore6 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 bookstore6 project, and select Undeploy and Deploy.

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

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

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

  2. Type ant. This target will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore6/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore6/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/bookstore6/.

To learn how to configure the example, refer to the web.xml file, which includes the following elements:

To run the example, open the URL http://localhost:8080/bookstore6 in a browser.

Setting Up a Page

A typical JavaServer Faces page includes the following elements:

This section tells you how to add these elements to your pages and briefly describes the subview tag for including JavaServer Faces pages inside other pages.

To use the JavaServer Faces UI components in your JSP page, you need to give the page access to the two standard tag libraries: the JavaServer Faces HTML render kit tag library and the JavaServer Faces core tag library. The JavaServer Faces standard HTML render kit tag library defines tags that represent common HTML user interface components. The JavaServer Faces core tag library defines tags that perform core actions and are independent of a particular render kit.

Using these tag libraries is similar to using any other custom tag library. This chapter assumes that you are familiar with the basics of using custom tags in JSP pages (see Using Custom Tags).

As is the case with any tag library, each JavaServer Faces tag library must have a TLD that describes it. The html_basic TLD describes the JavaServer Faces standard HTML render kit tag library. The jsf_core TLD describes the JavaServer Faces core tag library.

Refer to the TLD documentation at http://java.sun.com/javaee/javaserverfaces/1.2/docs/tlddocs/index.html for a complete list of the JavaServer Faces tags and their attributes.

To use any of the JavaServer Faces tags, you need to include these taglib directives at the top of each page containing the tags defined by these tag libraries:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

The uri attribute value uniquely identifies the TLD. The prefix attribute value is used to distinguish tags belonging to the tag library. You can use other prefixes rather than the h or f prefixes. However, you must use the prefix you have chosen when including the tag in the page. For example, the form tag must be referenced in the page using the h prefix because the preceding tag library directive uses the h prefix to distinguish the tags defined in html_basic.tld:

<h:form ...>

A page containing JavaServer Faces tags is represented by a tree of components. At the root of the tree is the UIViewRoot component. The view tag represents this component on the page. Therefore, all component tags on the page must be enclosed in the view tag, which is defined in the jsf_core TLD:

<f:view>
    ... other JavaServer Faces tags, possibly mixed with other
     content ...
</f:view>

You can enclose other content, including HTML and other JSP tags, within the view tag, but all JavaServer Faces tags must be enclosed within the view tag.

The view tag has four optional attributes:

An advanced developer might implement the methods referenced by beforePhase and afterPhase to perform such functions as initialize or release resources on a per-page basis. This feature is outside of the scope of this tutorial.

The form tag is nested inside of the view tag. As its name suggests, the form tag represents a form, which is submitted when a button or hyperlink on the page is clicked. For the data of other components on the page to be submitted with the form, the tags representing the components must be nested inside the form tag. See Adding a Form Component for more details on using the form tag.

If you want to include a page containing JavaServer Faces tags within another JSP page that includes JavaServer Faces tags, you must enclose the entire nested page in a subview tag. You can add the subview tag on the parent page and nest a jsp:include inside it to include the page:

<f:subview id="myNestedPage">
    <jsp:include page="theNestedPage.jsp" />
</f:subview>

You can also include the subview tag inside the nested page, but it must enclose all the JavaServer Faces tags on the nested page.

The subview tag has two optional attributes: binding and rendered. The binding attribute binds to a component that implements NamingContainer. One potential use case of binding a subview component to a bean is if you want to dynamically add components to the subview in the backing bean.

The rendered attribute can be set to true or false, indicating whether or not the components nested in the subview tag should be rendered.

In summary, a typical JSP page that uses JavaServer Faces tags will look somewhat like this:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<f:view>
    <h:form>
        other JavaServer Faces tags and core tags,
         including one or more button or hyperlink components for
         submitting the form
    </h:form>
</f:view>

The sections Using the Core Tags and Adding UI Components to a Page Using the HTML Component Tags describe how to use the core tags from the JavaServer Faces core tag library and the component tags from the JavaServer Faces standard HTML render kit tag library.

Using the Core Tags

The tags included in the JavaServer Faces core tag library are used to perform core actions that are independent of a particular render kit. These tags are listed in Table 11–1.

Table 11–1 The jsf_core Tags

Tag Categories 

Tags 

Functions 

Event-handling tags 

actionListener

Registers an action listener on a parent component 

phaseListener

Registers a PhaseListener instance on a UIViewRoot component

setPropertyActionListener

Registers a special action listener whose sole purpose is to push a value into a backing bean when a form is submitted 

valueChangeListener

Registers a value-change listener on a parent component 

Attribute configuration tag

attribute

Adds configurable attributes to a parent component 

Data conversion tags

converter

Registers an arbitrary converter on the parent component 

convertDateTime

Registers a DateTime converter instance on the parent component

convertNumber

Registers a Number converter instance on the parent component

Facet tag

facet

Signifies a nested component that has a special relationship to its enclosing tag 

Localization tag 

loadBundle

Specifies a ResourceBundle that is exposed as a Map

Parameter substitution tag

param

Substitutes parameters into a MessageFormat instance and adds query string name-value pairs to a URL

Tags for representing items in a list 

selectItem

Represents one item in a list of items in a UISelectOne or UISelectMany component

selectItems

Represents a set of items in a UISelectOne or UISelectMany component

Container tag

subview

Contains all JavaServer Faces tags in a page that is included in another JSP page containing JavaServer Faces tags 

Validator tags

validateDoubleRange

Registers a DoubleRangeValidator on a component

validateLength

Registers a LengthValidator on a component

validateLongRange

Registers a LongRangeValidator on a component

validator

Registers a custom validator on a component

Output tag 

verbatim

Generates a UIOutput component that gets its content from the body of this tag

Container for form tags 

view

Encloses all JavaServer Faces tags on the page 

These tags are used in conjunction with component tags and are therefore explained in other sections of this tutorial. Table 11–2 lists the sections that explain how to use specific jsf_core tags.

Table 11–2 Where the jsf_core Tags Are Explained

Tags 

Where Explained 

Event-handling tags 

Registering Listeners on Components

Data conversion tags

Using the Standard Converters

facet

Using Data-Bound Table Components and Laying Out Components with the UIPanel Component

loadBundle

Rendering Components for Selecting Multiple Values

param

Displaying a Formatted Message with the outputFormat Tag

selectItem and selectItems

The UISelectItem, UISelectItems, and UISelectItemGroup Components

subview

Setting Up a Page

verbatim

Rendering a Hyperlink with the outputLink Tag

view

Setting Up a Page

Validator tags

Using the Standard Validators and Creating a Custom Validator

Adding UI Components to a Page Using the HTML Component Tags

The tags defined by the JavaServer Faces standard HTML render kit tag library represent HTML form components and other basic HTML elements. These components display data or accept data from the user. This data is collected as part of a form and is submitted to the server, usually when the user clicks a button. This section explains how to use each of the component tags shown in Table 10–2.

The next section explains the more important tag attributes that are common to most component tags. Please refer to the TLD documentation at http://java.sun.com/javaee/javaserverfaces/1.2/docs/tlddocs/index.html for a complete list of tags and their attributes.

For each of the components discussed in the following sections, Writing Bean Properties explains how to write a bean property bound to a particular UI component or its value.

UI Component Tag Attributes

In general, most of the component tags support these attributes:

All of the UI component tag attributes (except id) can accept expressions, as defined by the unified EL described in Unified Expression Language.

The id Attribute

The id attribute is not required for a component tag except in the case when another component or a server-side class must refer to the component. If you don’t include an id attribute, the JavaServer Faces implementation automatically generates a component ID. Unlike most other JavaServer Faces tag attributes, the id attribute only takes expressions using the immediate evaluation syntax, which uses the ${} delimiters.

The immediate Attribute

UIInput components and command components (those that implement ActionSource, such as buttons and hyperlinks) can set the immediate attribute to true to force events, validations, and conversions to be processed during the apply request values phase of the life cycle. Page authors need to carefully consider how the combination of an input component’s immediate value and a command component’s immediate value determines what happens when the command component is activated.

Assume that you have a page with a button and a field for entering the quantity of a book in a shopping cart. If both the button’s and the field’s immediate attributes are set to true, the new value of the field will be available for any processing associated with the event that is generated when the button is clicked. The event associated with the button and the event, validation, and conversion associated with the field are all handled during the apply request values phase.

If the button’s immediate attribute is set to true but the field’s immediate attribute is set to false, the event associated with the button is processed without updating the field’s local value to the model layer. This is because any events, conversion, or validation associated with the field occurs during its usual phases of the life cycle, which come after the apply request values phase.

The bookshowcart.jsp page of the Duke’s Bookstore application has examples of components using the immediate attribute to control which component’s data is updated when certain buttons are clicked. The quantity field for each book has its immediate attribute set to false. (The quantity fields are generated by the UIData component. See Using Data-Bound Table Components, for more information.) The immediate attribute of the Continue Shopping hyperlink is set to true. The immediate attribute of the Update Quantities hyperlink is set to false.

If you click the Continue Shopping hyperlink, none of the changes entered into the quantity input fields will be processed. If you click the Update Quantities hyperlink, the values in the quantity fields will be updated in the shopping cart.

The rendered Attribute

A component tag uses a Boolean JavaServer Faces expression language (EL) expression, along with the rendered attribute, to determine whether or not the component will be rendered. For example, the check commandLink component on the bookcatalog.jsp page is not rendered if the cart contains no items:

<h:commandLink id="check"
    ...
    rendered="#{cart.numberOfItems > 0}">
    <h:outputText
        value="#{bundle.CartCheck}"/>
</h:commandLink>

Unlike nearly every other JavaServer Faces tag attribute, the rendered attribute is restricted to using rvalue expressions. As explained in Unified Expression Language, rvalue expressions can only read data; they cannot write the data back to the data source. Therefore, expressions used with rendered attributes can use the arithmetic operators and literals that rvalue expressions can use but lvalue expressions cannot use. For example, the expression in the preceding example uses the > operator.

The style and styleClass Attributes

The style and styleClass attributes allow you to specify Cascading Style Sheets (CSS) styles for the rendered output of your component tags. Displaying Error Messages with the message and messages Tags describes an example of using the style attribute to specify styles directly in the attribute. A component tag can instead refer to a CSS stylesheet class. The dataTable tag on the bookcatalog.jsp page of the Duke’s Bookstore application references the style class list-background:

<h:dataTable id="books"
    ...
    styleClass="list-background"
    value="#{bookDBAO.books}"
    var="book">

The stylesheet that defines this class is stylesheet.css, which is included in the application. For more information on defining styles, please the see Cascading Style Sheets Specification at http://www.w3.org/Style/CSS/.

The value and binding Attributes

A tag representing a component defined by UIOutput or a subclass of UIOutput uses value and binding attributes to bind its component’s value or instance respectively to an external data source. Binding Component Values and Instances to External Data Sources explains how to use these attributes.

Adding a Form Component

A UIForm component class represents an input form, which includes child components that contain data that is either presented to the user or submitted with the form.

Figure 11–1 shows a typical login form, in which a user enters a user name and password, and submits the form by clicking the Login button.

Figure 11–1 A Typical Form

Screen capture of form with User Name and Password text
fields and a Login button.

The form tag represents the UIForm component on the page and encloses all the components that display or collect data from the user, as shown here:

<h:form>
... other JavaServer Faces tags and other content...
</h:form>

The form tag can also include HTML markup to lay out the components on the page. The form tag itself does not perform any layout; its purpose is to collect data and to declare attributes that can be used by other components in the form. A page can include multiple form tags, but only the values from the form that the user submits will be included in the postback.

Using Text Components

Text components allow users to view and edit text in web applications. The basic kinds of text components are:

Figure 11–2 shows examples of these text components.

Figure 11–2 Example Text Components

Screen capture of form. "User Name" labels a text field.
"Password" labels a password field. "Comments" labels a text area.

An editable text component in a JavaServer Faces application is represented by a UIInput component. One example is a text field. A read-only text component in a JavaServer Faces application is represented by a UIOutput component. One example is a label.

The UIInput and UIOutput components can each be rendered in four ways to display more specialized text components. Table 11–3 lists all the renderers of UIInput and UIOutput and the tags that represent the component and renderer combination. Recall from Component Rendering Model that the name of a tag is composed of the name of the component and the name of the renderer. For example, the inputText tag refers to a UIInput component that is rendered with the Text renderer.

Table 11–3 UIInput and UIOutput Tags

Component 

Renderer 

Tag 

Function 

UIInput

Hidden

inputHidden

Allows a page author to include a hidden variable in a page 

Secret

inputSecret

The standard password field: Accepts one line of text with no spaces and displays it as a set of asterisks as it is typed 

Text

inputText

The standard text field: Accepts a text string of one line 

TextArea

inputTextarea

The standard text area: Accepts multiple lines of text 

UIOutput

Label

outputLabel

The standard read-only label: Displays a component as a label for a specified input field 

Link

outputLink

Displays an <a href> tag that links to another page without generating an action event

OutputMessage

outputFormat

Displays a localized message 

Text

outputText

Displays a text string of one line 

The UIInput component tags support the following tag attributes in addition to those described at the beginning of Adding UI Components to a Page Using the HTML Component Tags. This list does not include all the attributes supported by the UIInput component tags, just those that page authors will use most often. Please refer to the html_basic.tld file for the complete list.

The UIOutput component tags support the converter tag attribute in addition to those listed in Adding UI Components to a Page Using the HTML Component Tags. The rest of this section explains how to use selected tags listed in Table 11–3. The other tags are written in a similar way.

Rendering a Text Field with the inputText Tag

The inputText tag is used to display a text field. It represents the combination of a Text renderer and a UIInput component. A similar tag, the outputText tag, displays a read-only, single-line string. It represents the combination of a Text renderer and a UIOutput component. This section shows you how to use the inputText tag. The outputText tag is written in a similar way.

Here is an example of an inputText tag from the bookcashier.jsp page:

<h:inputText id="name" label="Customer Name" size="50"
    value="#{cashier.name}"
    required="true"
     requiredMessage="#{customMessages.CustomerName}">
     <f:valueChangeListener
         type="com.sun.bookstore6.listeners.NameChanged" />
 </h:inputText>

The label attribute specifies a user-friendly name that will be used in the substitution parameters of error messages displayed for this component.

The value attribute refers to the name property of CashierBean. This property holds the data for the name component. After the user submits the form, the value of the name property in CashierBean will be set to the text entered in the field corresponding to this tag.

The required attribute causes the page to reload with errors displayed if the user does not enter a value in the name text field. The JavaServer Faces implementation checks whether the value of the component is null or is an empty String.

If your component must have a non-null value or a String value at least one character in length, you should add a required attribute to your component tag and set it to true. If your tag does have a required attribute that is set to true and the value is null or a zero-length string, no other validators registered on the tag are called. If your tag does not have a required attribute set to true, other validators registered on the tag are called, but those validators must handle the possibility of a null or zero-length string.

The requiredMessage attribute references an error message from a resource bundle, which is declared in the application configuration file. Refer to Registering Custom Error Messages for details on how to declare and reference the resource bundle.

Rendering a Label with the outputLabel Tag

The outputLabel tag is used to attach a label to a specified input field for accessibility purposes. The bookcashier.jsp page uses an outputLabel tag to render the label of a check box:

<h:selectBooleanCheckbox
     id="fanClub"
    rendered="false"
    binding="#{cashier.specialOffer}" />
<h:outputLabel for="fanClub"
    rendered="false"
    binding="#{cashier.specialOfferText}"  >
    <h:outputText id="fanClubLabel"
        value="#{bundle.DukeFanClub}" />
</h:outputLabel>
...

The for attribute of the outputLabel tag maps to the id of the input field to which the label is attached. The outputText tag nested inside the outputLabel tag represents the actual label component. The value attribute on the outputText tag indicates the text that is displayed next to the input field.

Instead of using an outputText tag for the text displayed as a label, you can simply use the outputLabel tag’s value attribute. The following code snippet shows what the previous code snippet would look like if it used the value attribute of the outputLabel tag to specify the text of the label.

<h:selectBooleanCheckbox
     id="fanClub"
    rendered="false"
    binding="#{cashier.specialOffer}" />
    <h:outputLabel for="fanClub"
        rendered="false"
        binding="#{cashier.specialOfferText}"
         value="#{bundle.DukeFanClub}" />
    </h:outputLabel>
...

Rendering a Hyperlink with the outputLink Tag

The outputLink tag is used to render a hyperlink that, when clicked, loads another page but does not generate an action event. You should use this tag instead of the commandLink tag if you always want the URL (specified by the outputLink tag’s value attribute) to open and do not have to perform any processing when the user clicks on the link. The Duke’s Bookstore application does not utilize this tag, but here is an example of it:

<h:outputLink value="javadocs">
    Documentation for this demo
</h:outputLink>

The text in the body of the outputLink tag identifies the text the user clicks to get to the next page.

Displaying a Formatted Message with the outputFormat Tag

The outputFormat tag allows a page author to display concatenated messages as a MessageFormat pattern, as described in the API documentation for java.text.MessageFormat (see http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html). Here is an example of an outputFormat tag from the bookshowcart.jsp page of the Duke’s Bookstore application:

<h:outputFormat value="#{bundle.CartItemCount}">
    <f:param value="#{cart.numberOfItems}"/>
</h:outputFormat>

The value attribute specifies the MessageFormat pattern. The param tag specifies the substitution parameters for the message.

In the example outputFormat tag, the value for the parameter maps to the number of items in the shopping cart. When the message is displayed on the page, the number of items in the cart replaces the {0} in the message corresponding to the CartItemCount key in the bundle resource bundle:

Your shopping cart contains " + "{0,choice,0#no items|1#one item|1< {0} items

This message represents three possibilities:

The value of the parameter replaces the {0} from the message in the sentence in the third bullet. This is an example of a value-expression-enabled tag attribute accepting a complex EL expression.

An outputFormat tag can include more than one param tag for those messages that have more than one parameter that must be concatenated into the message. If you have more than one parameter for one message, make sure that you put the param tags in the proper order so that the data is inserted in the correct place in the message.

A page author can also hard code the data to be substituted in the message by using a literal value with the value attribute on the param tag.

Rendering a Password Field with the inputSecret Tag

The inputSecret tag renders an <input type="password"> HTML tag. When the user types a string into this field, a row of asterisks is displayed instead of the text the user types. The Duke’s Bookstore application does not include this tag, but here is an example of one:

<h:inputSecret redisplay="false"
    value="#{LoginBean.password}" />

In this example, the redisplay attribute is set to false. This will prevent the password from being displayed in a query string or in the source file of the resulting HTML page.

Using Command Components for Performing Actions and Navigation

The button and hyperlink components are used to perform and action, such as submitting a form, and for navigating to another page.

Command components in JavaServer Faces applications are represented by the UICommand component, which performs an action when it is activated. The UICommand component supports two renderers: Button and Link as UICommand component renderers.

The commandButton tag represents the combination of a UICommand component and a Button renderer and is rendered as a button. The commandLink tag represents the combination of a UICommand component and a Link renderer and is rendered as a hyperlink.

In addition to the tag attributes listed in Adding UI Components to a Page Using the HTML Component Tags, the commandButton and commandLink tags can use these attributes:

See Referencing a Method That Performs Navigation for more information on using the action attribute.

See Referencing a Method That Handles an Action Event for details on using the actionListener attribute.

Rendering a Button with the commandButton Tag

The bookcashier.jsp page of the Duke’s Bookstore application includes a commandButton tag. When a user clicks the button, the data from the current page is processed, and the next page is opened. Here is the commandButton tag from bookcashier.jsp:

<h:commandButton value="#{bundle.Submit}"
     action="#{cashier.submit}"/>

Clicking the button will cause the submit method of CashierBean to be invoked because the action attribute references the submit method of the CashierBean backing bean. The submit method performs some processing and returns a logical outcome. This is passed to the default NavigationHandler, which matches the outcome against a set of navigation rules defined in the application configuration resource file.

The value attribute of the preceding example commandButton tag references the localized message for the button’s label. The bundle part of the expression refers to the ResourceBundle that contains a set of localized messages. The Submit part of the expression is the key that corresponds to the message that is displayed on the button. For more information on referencing localized messages, see Rendering Components for Selecting Multiple Values. See Referencing a Method That Performs Navigation for information on how to use the action attribute.

Rendering a Hyperlink with the commandLink Tag

The commandLink tag represents an HTML hyperlink and is rendered as an HTML <a> element. The commandLink tag is used to submit an action event to the application. See Implementing Action Listeners for more information on action events.

A commandLink tag must include a nested outputText tag, which represents the text the user clicks to generate the event. The following tag is from the chooselocale.jsp page from the Duke’s Bookstore application.

<h:commandLink id="NAmerica" action="bookstore"
     actionListener="#{localeBean.chooseLocaleFromLink}">
     <h:outputText value="#{bundle.English}" />
</h:commandLink>

This tag will render the following HTML:

<a id="_id3:NAmerica" href="#"
     onclick="document.forms[’_id3’][’_id3:NAmerica’].
    value=’_id3:NAmerica’;
     document.forms[’_id3’].submit();
     return false;">English</a>

Note –

The commandLink tag will render JavaScript. If you use this tag, make sure your browser is JavaScript-enabled.


Using Data-Bound Table Components

Data-bound table components display relational data in a tabular format. Figure 11–3 shows an example of this kind of table.

Figure 11–3 Table on the bookshowcart.jsp Page

Screen capture of cart, showing quantities, titles, prices,
and Remove Item buttons.

In a JavaServer Faces application, the UIData component supports binding to a collection of data objects. It does the work of iterating over each record in the data source. The standard Table renderer displays the data as an HTML table. The UIColumn component represents a column of data within the table. Here is a portion of the dataTable tag used by the bookshowcart.jsp page of the Duke’s Bookstore example:

<h:dataTable id="items"
     captionClass="list-caption"
    columnClasses="list-column-center, list-column-left,
         list-column-right, list-column-center"
    footerClass="list-footer"
    headerClass="list-header"
    rowClasses="list-row-even, list-row-odd"
    styleClass="list-background"
    summary="#{bundle.ShoppingCart}"
    value="#{cart.items}"
    var="item">
    <h:column headerClass="list-header-left">
        <f:facet name="header">
            <h:outputText value="#{bundle.ItemQuantity}" />
        </f:facet>
        <h:inputText id="quantity" size="4"
            value="#{item.quantity}" >
            ...
        </h:inputText>
        ...
    </h:column>
    <h:column>
        <f:facet name="header">
            <h:outputText value="#{bundle.ItemTitle}"/>
        </f:facet>
        <h:commandLink action="#{showcart.details}">
            <h:outputText value="#{item.item.title}"/>
        </h:commandLink>
    </h:column>
    ...
    <f:facet name="footer"
        <h:panelGroup>
            <h:outputText value="#{bundle.Subtotal}"/>
            <h:outputText value="#{cart.total}" />
                <f:convertNumber type="currency" />
            </h:outputText>
        </h:panelGroup>
    </f:facet>
    <f:facet name="caption"
        <h:outputText value="#{bundle.Caption}"/>
</h:dataTable>

Figure 11–3 shows a data grid that this dataTable tag can display.

The example dataTable tag displays the books in the shopping cart as well as the quantity of each book in the shopping cart, the prices, and a set of buttons, which the user can click to remove books from the shopping cart.

The column tags represent columns of data in a UIData component. While the UIData component is iterating over the rows of data, it processes the UIColumn component associated with each column tag for each row in the table.

The UIData component shown in the preceding code example iterates through the list of books (cart.items) in the shopping cart and displays their titles, authors, and prices. Each time UIData iterates through the list of books, it renders one cell in each column.

The dataTable and column tags use facets to represent parts of the table that are not repeated or updated. These include headers, footers, and captions.

In the preceding example, column tags include facet tags for representing column headers or footers. The column tag allows you to control the styles of these headers and footers by supporting the headerClass and footerClass attributes. These attributes accept space-separated lists of CSS style classes, which will be applied to the header and footer cells of the corresponding column in the rendered table.

Facets can have only one child, and so a panelGroup tag is needed if you want to group more than one component within a facet. Because the facet tag representing the footer includes more than one tag, the panelGroup is needed to group those tags. Finally, this dataTable tag includes a facet tag with its name attribute set to caption, causing a table caption to be rendered below the table.

This table is a classic use case for a UIData component because the number of books might not be known to the application developer or the page author at the time the application is developed. The UIData component can dynamically adjust the number of rows of the table to accommodate the underlying data.

The value attribute of a dataTable tag references the data to be included in the table. This data can take the form of

All data sources for UIData components have a DataModel wrapper. Unless you explicitly construct a DataModel wrapper, the JavaServer Faces implementation will create one around data of any of the other acceptable types. See Writing Bean Properties for more information on how to write properties for use with a UIData component.

The var attribute specifies a name that is used by the components within the dataTable tag as an alias to the data referenced in the value attribute of dataTable.

In the dataTable tag from the bookshowcart.jsp page, the value attribute points to a list of books. The var attribute points to a single book in that list. As the UIData component iterates through the list, each reference to item points to the current book in the list.

The UIData component also has the ability to display only a subset of the underlying data. This is not shown in the preceding example. To display a subset of the data, you use the optional first and rows attributes.

The first attribute specifies the first row to be displayed. The rows attribute specifies the number of rows, starting with the first row, to be displayed. For example, if you wanted to display records 2 through 10 of the underlying data, you would set first to 2 and rows to 9. When you display a subset of the data in your pages, you might want to consider including a link or button that causes subsequent rows to display when clicked. By default, both first and rows are set to zero, and this causes all the rows of the underlying data to display.

The dataTable tag also has a set of optional attributes for adding styles to the table:

Each of these attributes can specify more than one style. If columnClasses or rowClasses specifies more than one style, the styles are applied to the columns or rows in the order that the styles are listed in the attribute. For example, if columnClasses specifies styles list-column-center and list-column-right and if there are two columns in the table, the first column will have style list-column-center, and the second column will have style list-column-right.

If the style attribute specifies more styles than there are columns or rows, the remaining styles will be assigned to columns or rows starting from the first column or row. Similarly, if the style attribute specifies fewer styles than there are columns or rows, the remaining columns or rows will be assigned styles starting from the first style.

Adding Graphics and Images with the graphicImage Tag

In a JavaServer Faces application, the UIGraphic component represents an image. The graphicImage tag is used to render a UIGraphic component on a page. The Duke’s Bookstore application uses a graphicImage tag to display the map image on the chooselocale.jsp page:

<h:graphicImage id="mapImage" url="/template/world.jpg"
     alt="#{bundle.chooseLocale}" usemap="#worldMap" />

The url attribute specifies the path to the image. It also corresponds to the local value of the UIGraphic component so that the URL can be retrieved, possibly from a backing bean. The URL of the example tag begins with a /, which adds the relative context path of the web application to the beginning of the path to the image.

The title attribute specifies the alternative text displayed when the user mouses over the image. In this example, the title attribute refers to a localized message. See Performing Localization for details on how to localize your JavaServer Faces application.

The usemap attribute refers to the image map defined by the custom component, MapComponent, which is on the same page. See Chapter 13, Creating Custom UI Components for more information on the image map.

Laying Out Components with the UIPanel Component

In a JavaServer Faces application, you use the UIPanel component as a layout container for a set of component components. When you use the renderers from the HTML render kit, UIPanel is rendered as an HTML table. This component differs from UIData in that UIData can dynamically add or delete rows to accommodate the underlying data source, whereas UIPanel must have the number of rows predetermined. Table 11–4 lists all the renderers and tags corresponding to the UIPanel component.

Table 11–4 UIPanel Renderers and Tags

Renderer 

Tag 

Renderer Attributes 

Function 

Grid

panelGrid

columnClasses, columns, footerClass, headerClass, panelClass, rowClasses

Displays a table 

Group

panelGroup

layout

Groups a set of components under one parent 

The panelGrid tag is used to represent an entire table. The panelGroup tag is used to represent rows in a table. Other UI component tags are used to represent individual cells in the rows.

The panelGrid tag has a set of attributes that specify CSS stylesheet classes: columnClasses, footerClass, headerClass, panelClass, and rowClasses. These stylesheet attributes are optional. The panelGrid tag also has a columns attribute. The columns attribute is required if you want your table to have more than one column because the columns attribute tells the renderer how to group the data in the table.

If the headerClass attribute value is specified, the panelGrid must have a header as its first child. Similarly, if a footerClass attribute value is specified, the panelGrid must have a footer as its last child.

The Duke’s Bookstore application includes three panelGrid tags on the bookcashier.jsp page. Here is a portion of one of them:

<h:panelGrid columns="3" headerClass="list-header"
    rowClasses="list-row-even, list-row-odd"
    styleClass="list-background"
    title="#{bundle.Checkout}">
    <f:facet name="header">
        <h:outputText value="#{bundle.Checkout}"/>
    </f:facet>
    <h:outputText value="#{bundle.Name}" />
    <h:inputText id="name" size="50"
         value="#{cashier.name}"
        required="true">
         <f:valueChangeListener
             type="listeners.NameChanged" />
    </h:inputText>
    <h:message styleClass="validationMessage" for="name"/>
    <h:outputText value="#{bundle.CCNumber}"/>
    <h:inputText id="ccno" size="19"
        converter="CreditCardConverter" required="true">
         <bookstore:formatValidator
             formatPatterns="9999999999999999|
                9999 9999 9999 9999|9999-9999-9999-9999"/>
    </h:inputText>
    <h:message styleClass="validationMessage"  for="ccno"/>
    ...
</h:panelGrid>

This panelGrid tag is rendered to a table that contains components for the customer of the bookstore to input personal information. This panelGrid tag uses stylesheet classes to format the table. The CSS classes are defined in the stylesheet.css file in the tut-install/javaeetutorial5/examples/web/bookstore6/web/ directory. The list-header definition is

.list-header {
     background-color: #ffffff;
    color: #000000;
    text-align: center;
}

Because the panelGrid tag specifies a headerClass, the panelGrid must contain a header. The example panelGrid tag uses a facet tag for the header. Facets can have only one child, and so a panelGroup tag is needed if you want to group more than one component within a facet. Because the example panelGrid tag has only one cell of data, a panelGroup tag is not needed.

The panelGroup tag has one attribute, called layout, in addition to those listed in UI Component Tag Attributes. If the layout attribute has the value block then an HTML div element is rendered to enclose the row; otherwise, an HTML span element is rendered to enclose the row. If you are specifying styles for the panelGroup tag, you should set the layout attribute to block in order for the styles to be applied to the components within the panelGroup tag. This is because styles such as those that set width and height are not applied to inline elements, which is how content enclosed by the span element is defined.

A panelGroup tag can also be used to encapsulate a nested tree of components so that the tree of components appears as a single component to the parent component.

The data represented by the nested component tags is grouped into rows according to the value of the columns attribute of the panelGrid tag. The columns attribute in the example is set to 3, and therefore the table will have three columns. In which column each component is displayed is determined by the order that the component is listed on the page modulo 3. So if a component is the fifth one in the list of components, that component will be in the 5 modulo 3 column, or column 2.

Rendering Components for Selecting One Value

Another common UI component is one that allows a user to select one value, whether it be the only value available or one of a set of choices. The most common examples of this kind of component are:

Figure 11–4 shows examples of these components.

Figure 11–4 Example Select One Components

Screen capture of radio buttons, check box, drop-down
menu, and list box.

Displaying a Check Box Using the selectBooleanCheckbox Tag

The UISelectBoolean class defines components that have a boolean value. The selectBooleanCheckbox tag is the only tag that JavaServer Faces technology provides for representing boolean state. The Duke’s Bookstore application includes a selectBooleanCheckbox tag on the bookcashier.jsp page:

<h:selectBooleanCheckbox
     id="fanClub"
    rendered="false"
    binding="#{cashier.specialOffer}" />
<h:outputLabel
     for="fanClub"
    rendered="false"
    binding="#{cashier.specialOfferText}">
     <h:outputText
         id="fanClubLabel"
        value="#{bundle.DukeFanClub}" />
</h:outputLabel>

This example tag displays a check box to allow users to indicate whether they want to join the Duke Fan Club. The label for the check box is rendered by the outputLabel tag. The actual text is represented by the nested outputText tag. Binding a Component Instance to a Bean Property discusses this example in more detail.

Displaying a Menu Using the selectOneMenu Tag

A UISelectOne component allows the user to select one value from a set of values. This component can be rendered as a list box, a set of radio buttons, or a menu. This section explains the selectOneMenu tag. The selectOneRadio and selectOneListbox tags are written in a similar way. The selectOneListbox tag is similar to the selectOneMenu tag except that selectOneListbox defines a size attribute that determines how many of the items are displayed at once.

The selectOneMenu tag represents a component that contains a list of items, from which a user can choose one item. The menu is also commonly known as a drop-down list or a combo box. The following code snippet shows the selectOneMenu tag from the bookcashier.jsp page of the Duke’s Bookstore application. This tag allows the user to select a shipping method:

<h:selectOneMenu   id="shippingOption"
    required="true"
    value="#{cashier.shippingOption}">
    <f:selectItem
        itemValue="2"
        itemLabel="#{bundle.QuickShip}"/>
    <f:selectItem
        itemValue="5"
        itemLabel="#{bundle.NormalShip}"/>
    <f:selectItem
        itemValue="7"
        itemLabel="#{bundle.SaverShip}"/>
 </h:selectOneMenu>

The value attribute of the selectOneMenu tag maps to the property that holds the currently selected item’s value. You are not required to provide a value for the currently selected item. If you don’t provide a value, the first item in the list is selected by default.

Like the selectOneRadio tag, the selectOneMenu tag must contain either a selectItems tag or a set of selectItem tags for representing the items in the list. The UISelectItem, UISelectItems, and UISelectItemGroup Components explains these tags.

Rendering Components for Selecting Multiple Values

In some cases, you need to allow your users to select multiple values rather than just one value from a list of choices. You can do this using one of the following kinds of components:

Figure 11–5 shows examples of these components.

Figure 11–5 Example Select Many Components

Screen capture of check box set, drop-down menu, and
list box.

The UISelectMany class defines a component that allows the user to select zero or more values from a set of values. This component can be rendered as a set of check boxes, a list box, or a menu. This section explains the selectManyCheckbox tag. The selectManyListbox tag and selectManyMenu tag are written in a similar way.

A list box differs from a menu in that it displays a subset of items in a box, whereas a menu displays only one item at a time when the user is not selecting the menu. The size attribute of the selectManyListbox tag determines the number of items displayed at one time. The list box includes a scroll bar for scrolling through any remaining items in the list.

The selectManyCheckbox tag renders a set of check boxes, with each check box representing one value that can be selected. Duke’s Bookstore uses a selectManyCheckbox tag on the bookcashier.jsp page to allow the user to subscribe to one or more newsletters:

<h:selectManyCheckbox
    id="newsletters"
    layout="pageDirection"
    value="#{cashier.newsletters}">
    <f:selectItems
        value="#{newsletters}"/>
</h:selectManyCheckbox>

The value attribute of the selectManyCheckbox tag identifies the CashierBean backing bean property, newsletters, for the current set of newsletters. This property holds the values of the currently selected items from the set of check boxes. You are not required to provide a value for the currently selected items. If you don’t provide a value, the first item in the list is selected by default.

The layout attribute indicates how the set of check boxes are arranged on the page. Because layout is set to pageDirection, the check boxes are arranged vertically. The default is lineDirection, which aligns the check boxes horizontally.

The selectManyCheckbox tag must also contain a tag or set of tags representing the set of check boxes. To represent a set of items, you use the selectItems tag. To represent each item individually, you use a selectItem tag for each item. The following subsection explains these tags in more detail.

The UISelectItem, UISelectItems, and UISelectItemGroup Components

UISelectItem and UISelectItems represent components that can be nested inside a UISelectOne or a UISelectMany component. UISelectItem is associated with a SelectItem instance, which contains the value, label, and description of a single item in the UISelectOne or UISelectMany component.

The UISelectItems instance represents either of the following:

Figure 11–6 shows an example of a list box constructed with a SelectItems component representing two SelectItemGroup instances, each of which represents two categories of beans. Each category is an array of SelectItem instances.

Figure 11–6 An Example List Box Created Using SelectItemGroup Instances

Screen capture of list box with two groups of items.

The selectItem tag represents a UISelectItem component. The selectItems tag represents a UISelectItems component. You can use either a set of selectItem tags or a single selectItems tag within your selectOne or selectMany tag.

The advantages of using the selectItems tag are as follows:

The advantages of using selectItem are as follows:

For more information on writing component properties for the UISelectItems components, see Writing Bean Properties. The rest of this section shows you how to use the selectItems and selectItem tags.

Using the selectItems Tag

Here is the selectManyCheckbox tag from the section Rendering Components for Selecting Multiple Values:

<h:selectManyCheckbox
    id="newsletters"
    layout="pageDirection"
    value="#{cashier.newsletters}">
    <f:selectItems
        value="#{newsletters}"/>
</h:selectManyCheckbox>

The value attribute of the selectItems tag is bound to the newsletters managed bean, which is configured in the application configuration resource file. The newsletters managed bean is configured as a list:

<managed-bean>
    <managed-bean-name>newsletters</managed-bean-name>
    <managed-bean-class>
        java.util.ArrayList</managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
    <list-entries>
        <value-class>javax.faces.model.SelectItem</value-class>
        <value>#{newsletter0}</value>
        <value>#{newsletter1}</value>
        <value>#{newsletter2}</value>
        <value>#{newsletter3}</value>
    </list-entries>
</managed-bean>
<managed-bean>
<managed-bean-name>newsletter0</managed-bean-name>
<managed-bean-class>
    javax.faces.model.SelectItem</managed-bean-class>
<managed-bean-scope>none</managed-bean-scope>
<managed-property>
    <property-name>label</property-name>
    <value>Duke’s Quarterly</value>
</managed-property>
<managed-property>
    <property-name>value</property-name>
    <value>200</value>
</managed-property>
</managed-bean>
...

As shown in the managed-bean element, the UISelectItems component is a collection of SelectItem instances. See Initializing Array and List Properties for more information on configuring collections as beans.

You can also create the list corresponding to a UISelectMany or UISelectOne component programmatically in the backing bean. See Writing Bean Properties for information on how to write a backing bean property corresponding to a UISelectMany or UISelectOne component.

The arguments to the SelectItem constructor are:

UISelectItems Properties describes in more detail how to write a backing bean property for a UISelectItems component.

Using the selectItem Tag

The selectItem tag represents a single item in a list of items. Here is the example from Displaying a Menu Using the selectOneMenu Tag:

<h:selectOneMenu
       id="shippingOption" required="true"
     value="#{cashier.shippingOption}">
    <f:selectItem
        itemValue="2"
        itemLabel="#{bundle.QuickShip}"/>
    <f:selectItem
        itemValue="5"
        itemLabel="#{bundle.NormalShip}"/>
    <f:selectItem
        itemValue="7"
        itemLabel="#{bundle.SaverShip}"/>
 </h:selectOneMenu>

The itemValue attribute represents the default value of the SelectItem instance. The itemLabel attribute represents the String that appears in the drop-down menu component on the page.

The itemValue and itemLabel attributes are value-binding-enabled, meaning that they can use value-binding expressions to refer to values in external objects. They can also define literal values, as shown in the example selectOneMenu tag.

Displaying Error Messages with the message and messages Tags

The message and messages tags are used to display error messages when conversion or validation fails. The message tag displays error messages related to a specific input component, whereas the messages tag displays the error messages for the entire page.

Here is an example message tag from the guessNumber application, discussed in Steps in the Development Process:

<h:inputText id="userNo" value="#{UserNumberBean.userNumber}">
    <f:validateLongRange minimum="0" maximum="10" />
 <h:commandButton id="submit"
         action="success" value="Submit" /><p>
<h:message
     style="color: red;
     font-family: ’New Century Schoolbook’, serif;
     font-style: oblique;
     text-decoration: overline" id="errors1" for="userNo"/>

The for attribute refers to the ID of the component that generated the error message. The error message is displayed at the same location that the message tag appears in the page. In this case, the error message will appear after the Submit button.

The style attribute allows you to specify the style of the text of the message. In the example in this section, the text will be red, New Century Schoolbook, serif font family, and oblique style, and a line will appear over the text. The message and messages tags support many other attributes for defining styles. Please refer to the TLD documentation for more information on these attributes.

Another attribute the messages tag supports is the layout attribute. Its default value is list, which indicates that the messages are displayed in a bulleted list using the HTML ul and li elements. If you set the attribute to table, the messages will be rendered in a table using the HTML table element.

The preceding example shows a standard validator is registered on input component. The message tag displays the error message associated with this validator when the validator cannot validate the input component’s value. In general, when you register a converter or validator on a component, you are queueing the error messages associated with the converter or validator on the component. The message and messages tags display the appropriate error messages that are queued on the component when the validators or converters registered on that component fail to convert or validate the component’s value.

All the standard error messages that come with the standard converters and validators are listed in section 2.5.4 of the JavaServer Faces specification. An application architect can override these standard messages and supply error messages for custom converters and validators by registering custom error messages with the application by means of the message-bundle element of the application configuration file. Referencing Error Messages explains more about error messages.

Using Localized Data

JavaServer Faces applications make use of three different kinds of data that can be localized:

This section discusses how to access the first two kinds of data from the page. Performing Localization explains how to produce localized error messages as well as how to localize dynamic data. If you are not familiar with the basics of localizing web applications, see Chapter 15, Internationalizing and Localizing Web Applications.

All data in the Duke’s Bookstore application have been localized for Spanish, French, German, and American English. The image map on the first page allows you to select your preferred locale. See Chapter 13, Creating Custom UI Components for information on how the image map custom component was created.

All the localized data is stored in resource bundles, which are represented as either ResourceBundle classes or text files, usually with the extension .properties. For more information about resource bundles, see http://java.sun.com/docs/books/tutorial/i18n/index.html.

After the application developer has produced a resource bundle, the application architect puts it in the same directory as the application classes. The static text data for the Duke’s Bookstore application is stored in a ResourceBundle class called BookstoreMessages. The error messages are stored in another resource bundle called ApplicationMessages. After the resource bundles have been created and before their data can be accessed, they must be made available to the application, as explained in the following section.

Loading a Resource Bundle

To reference error messages or static data from the page, you first need to make available the resource bundle containing the data.

To make available resource bundles that contain static data, you need to do one of two things:

Here is an example loadBundle tag from bookstore.jsp:

<f:loadBundle var="bundle"
    basename="messages.BookstoreMessages" />

The basename attribute value specifies the fully-qualified class name of the ResourceBundle class, which in this case is located in the messages package of the bookstore application.

The var attribute is an alias to the ResourceBundle class. This alias can be used by other tags in the page in order to access the localized messages.

In the case of resource bundles that contain error messages, you need to register the resource bundle with the application in the configuration file using the message-bundle element, as explained in Registering Custom Error Messages. One exception is if you are referencing the error messages from the input component attributes described in Referencing Error Messages. In that case, you load the resource bundles containing these messages in the same way you load resource bundles containing static text.

Referencing Localized Static Data

To reference static localized data from a resource bundle, you use a value expression from an attribute of the component tag that will display the localized data. You can reference the message from any component tag attribute that is enabled to accept value expressions.

The value expression has the notation var.message, in which var matches the var attribute of the loadBundle tag or the var element in the configuration file, and message matches the key of the message contained in the resource bundle, referred to by the var attribute. Here is an example from bookstore.jsp:

<h:outputText value="#{bundle.Talk}"/>

Notice that bundle matches the var attribute from the loadBundle tag and that Talk matches the key in the ResourceBundle.

Another example is the graphicImage tag from chooselocale.jsp:

<h:graphicImage id="mapImage" url="/template/world.jpg"
     alt="#{bundle.ChooseLocale}"
    usemap="#worldMap" />

The alt attribute is enabled to accept value expressions. In this case, the alt attribute refers to localized text that will be included in the alternative text of the image rendered by this tag.

See Creating Custom Component Classes and Enabling Component Properties to Accept Expressions for information on how to enable value binding on your custom component’s attributes.

Referencing Error Messages

A JavaServer Faces page uses the message or messages tags to access error messages, as explained in Displaying Error Messages with the message and messages Tags.

The error messages that these tags access include:

When a converter or validator is registered on an input component, the appropriate error message is automatically queued on the component.

A page author can override the error messages queued on a component by using the following attributes of the component’s tag:

All three attributes are enabled to take literal values and value expressions. If an attribute uses a value expression, this expression references the error message in a resource bundle. This resource bundle must be made available to the application in one of the following ways:

Conversely, the message-bundle element must be used to make available to the application those resource bundles containing custom error messages that are queued on the component as a result of a custom converter or validator being registered on the component.

The bookcashier.jsp page includes an example of the requiredMessage attribute using a value expression to reference an error message:

<h:inputText id="ccno" size="19"
    required="true"
    requiredMessage="#{customMessages.ReqMessage}" >
    ...
</h:inputText>
<h:message styleClass="error-message"  for="ccno"/>

The value expression that requiredMessage is using in this example references the error message with the ReqMessage key in the resource bundle, customMessages.

This message replaces the corresponding message queued on the component and will display wherever the message or messages tag is placed on the page.

See Registering Custom Error Messages and Registering Custom Localized Static Text for information on how to use the message-bundle and resource-bundle element to register resource bundles that contain error messages.

Using the Standard Converters

The JavaServer Faces implementation provides a set of Converter implementations that you can use to convert component data. For more information on the conceptual details of the conversion model, see Conversion Model.

The standard Converter implementations, located in the javax.faces.convert package, are as follows:

Each of these converters has a standard error message associated with them. If you have registered one of these converters onto a component on your page, and the converter is not able to convert the component’s value, the converter’s error message will display on the page. For example, the error message that displays if BigIntegerConverter fails to convert a value is:


{0} must be a number consisting of one or more digits

In this case the {0} substitution parameter will be replaced with the name of the input component on which the converter is registered. See section 2.4.5 of the JavaServer Faces specification, version 1.2, for a complete list of error messages.

Two of the standard converters (DateTimeConverter and NumberConverter) have their own tags, which allow you to configure the format of the component data using the tag attributes. Using DateTimeConverter discusses using DateTimeConverter. Using NumberConverter discusses using NumberConverter. The following section explains how to convert a component’s value including how to register the other standard converters with a component.

Converting a Component’s Value

To use a particular converter to convert a component’s value, you need to register the converter onto the component. You can register any of the standard converters on a component in one of four ways:

As an example of the second approach, if you want a component’s data to be converted to an Integer, you can simply bind the component’s value to a property similar to this:

Integer age = 0;
public Integer getAge(){ return age;}
public void setAge(Integer age) {this.age = age;}

If the component is not bound to a bean property, you can employ the third technique by using the converter attribute on the component tag:

<h:inputText
    converter="javax.faces.convert.IntegerConverter" />

This example shows the converter attribute referring to the fully-qualified class name of the converter. The converter attribute can also take the ID of the component. If the converter is a custom converter, the ID is defined in the application configuration resource file (see Application Configuration Resource File).

The data corresponding to this example inputText tag will be converted to a java.lang.Integer. Notice that the Integer type is already a supported type of the NumberConverter. If you don’t need to specify any formatting instructions using the convertNumber tag attributes, and if one of the other converters will suffice, you can simply reference that converter using the component tag’s converter attribute.

Finally, you can nest a converter tag within the component tag and use either the converter tag’s converterId attribute or its binding attribute to reference the converter.

The converterId attribute must reference the converter’s ID. Again, if the converter is a custom converter, the value of converterID must match the ID in the application configuration resource file; otherwise it must match the ID as defined in the converter class. Here is an example:

<h:inputText value="#{LoginBean.Age}" />
    <f:converter converterId="Integer" />
</h:inputText>

Instead of using the converterId attribute, the converter tag can use the binding attribute. The binding attribute must resolve to a bean property that accepts and returns an appropriate Converter instance. See Binding Converters, Listeners, and Validators to Backing Bean Properties for more information.

Using DateTimeConverter

You can convert a component’s data to a java.util.Date by nesting the convertDateTime tag inside the component tag. The convertDateTime tag has several attributes that allow you to specify the format and type of the data. Table 11–5 lists the attributes.

Here is a simple example of a convertDateTime tag from the bookreceipt.jsp page:

<h:outputText id= "shipDate" value="#{cashier.shipDate}">
    <f:convertDateTime dateStyle="full" />
</h:outputText>

When binding the DateTime converter to a component, ensure that the backing bean property to which the component is bound is of type java.util.Date. In the case of the preceding example, cashier.shipDate must be of type java.util.Date.

Here is an example of a date and time that the preceding tag can display:


Saturday, Feb 22, 2003

You can also display the same date and time using this tag:

<h:outputText value="#{cashier.shipDate}">
    <f:convertDateTime
         pattern="EEEEEEEE, MMM dd, yyyy" />
</h:outputText>

If you want to display the example date in Spanish, you can use the locale attribute:

<h:inputText value="#{cashier.shipDate}">
    <f:convertDateTime dateStyle="full"
         locale="Locale.SPAIN"
        timeStyle="long" type="both" />
</h:inputText>

This tag would display


sabado 23 de septiembre de 2006

Please refer to the Customizing Formats lesson of the Java Tutorial at http://java.sun.com/docs/books/tutorial/i18n/format/simpleDateFormat.html for more information on how to format the output using the pattern attribute of the convertDateTime tag.

Table 11–5 convertDateTime Tag Attributes

Attribute 

Type 

Description 

binding

DateTimeConverter

Used to bind a converter to a backing bean property 

dateStyle

String

Defines the format, as specified by java.text.DateFormat, of a date or the date part of a date string. Applied only if type is date (or both) and pattern is not defined. Valid values: default, short, medium, long, and full. If no value is specified, default is used.

locale

String or Locale

Locale whose predefined styles for dates and times are used during formatting or parsing. If not specified, the Locale returned by FacesContext.getLocale will be used.

pattern

String

Custom formatting pattern that determines how the date/time string should be formatted and parsed. If this attribute is specified, dateStyle, timeStyle, and type attributes are ignored.

timeStyle

String

Defines the format, as specified by java.text.DateFormat, of a time or the time part of a date string. Applied only if type is time and pattern is not defined. Valid values: default, short, medium, long, and full. If no value is specified, default is used.

timeZone

String or TimeZone

Time zone in which to interpret any time information in the date string.

type

String

Specifies whether the string value will contain a date, a time, or both. Valid values are date, time, or both. If no value is specified, date is used.

Using NumberConverter

You can convert a component’s data to a java.lang.Number by nesting the convertNumber tag inside the component tag. The convertNumber tag has several attributes that allow you to specify the format and type of the data. Table 11–6 lists the attributes.

The bookcashier.jsp page of Duke’s Bookstore uses a convertNumber tag to display the total prices of the books in the shopping cart:

<h:outputText value="#{cart.total}" >
    <f:convertNumber type="currency"/>
</h:outputText>

When binding the Number converter to a component, ensure that the backing bean property to which the component is bound is of primitive type or has a type of java.lang.Number. In the case of the preceding example, cart.total is of type java.lang.Number.

Here is an example of a number this tag can display


$934

This number can also be displayed using this tag:

<h:outputText id="cartTotal"
     value="#{cart.Total}" >
    <f:convertNumber pattern="
$####"
 />
</h:outputText>

Please refer to the Customizing Formats lesson of the Java Tutorial at http://java.sun.com/docs/books/tutorial/i18n/format/decimalFormat.html for more information on how to format the output using the pattern attribute of the convertNumber tag.

Table 11–6 convertNumber Attributes

Attribute 

Type 

Description 

binding

NumberConverter

Used to bind a converter to a backing bean property 

currencyCode

String

ISO 4217 currency code, used only when formatting currencies. 

currencySymbol

String

Currency symbol, applied only when formatting currencies. 

groupingUsed

boolean

Specifies whether formatted output contains grouping separators. 

integerOnly

boolean

Specifies whether only the integer part of the value will be parsed. 

locale

String or Locale

Locale whose number styles are used to format or parse data.

maxFractionDigits

int

Maximum number of digits formatted in the fractional part of the output. 

maxIntegerDigits

int

Maximum number of digits formatted in the integer part of the output. 

minFractionDigits

int

Minimum number of digits formatted in the fractional part of the output. 

minIntegerDigits

int

Minimum number of digits formatted in the integer part of the output. 

pattern

String

Custom formatting pattern that determines how the number string is formatted and parsed. 

type

String

Specifies whether the string value is parsed and formatted as a number, currency, or percentage. If not specified, number is used.

Registering Listeners on Components

An application developer can implement listeners as classes or as backing bean methods. If a listener is a backing bean method, the page author references the method from either the component’s valueChangeListener attribute or its actionListener attribute. If the listener is a class, the page author can reference the listener from either a valueChangeListener tag or an actionListener tag and nest the tag inside the component tag in order to register the listener on the component.

Referencing a Method That Handles an Action Event and Referencing a Method That Handles a Value-change Event describe how a page author uses the valueChangeListener and actionListener attributes to reference backing bean methods that handle events.

The Duke’s Bookstore application includes a ValueChangeListener implementation class but does not use an ActionListener implementation class. This section explains how to register the NameChanged value-change listener and a hypothetical LocaleChange action listener implementation on components. Implementing Value-Change Listeners explains how to implement NameChanged. Implementing Action Listeners explains how to implement the hypothetical LocaleChange listener.

Registering a Value-Change Listener on a Component

A page author can register a ValueChangeListener implementation on a component that implements EditableValueHolder by nesting a valueChangeListener tag within the component’s tag on the page. The valueChangeListener tag supports two attributes:

A page author must use one of these attributes to reference the value-change listener. The type attribute accepts a literal or a value expression. The binding attribute only accepts a value expression, which must point to a backing bean property that accepts and returns a ValueChangeListener implementation.

Following is the tag corresponding to the name component from the bookcashier.jsp page. It uses the type attribute to reference a value-change listener:

<h:inputText  id="name" size="50" value="#{cashier.name}"
     required="true">    
     <f:valueChangeListener type="listeners.NameChanged" />
</h:inputText>

The type attribute specifies the custom NameChanged listener as the ValueChangeListener implementation to register on the name component.

After this component tag is processed and local values have been validated, its corresponding component instance will queue the ValueChangeEvent associated with the specified ValueChangeListener to the component.

The binding attribute is used to bind a ValueChangeListener implementation to a backing bean property. It works in a similar way to the binding attribute supported by the standard converter tags. Binding Component Values and Instances to External Data Sources explains more about binding listeners to backing bean properties.

Registering an Action Listener on a Component

A page author can register an ActionListener implementation on a UICommand component by nesting an actionListener tag within the component’s tag on the page. Similarly to the valueChangeListener tag, the actionListener tag supports both the type and binding attributes. A page author must use one of these attributes to reference the action listener.

Duke’s Bookstore does not use any ActionListener implementations. Here is one of the commandLink tags on the chooselocale.jsp page, changed to reference an ActionListener implementation rather than a backing bean method:

<h:commandLink id="NAmerica" action="bookstore">
     <f:actionListener type="listeners.LocaleChange" />
</h:commandLink>

The type attribute of the actionListener tag specifies the fully qualified class name of the ActionListener implementation. Similarly to the valueChangeListener tag, the actionListener tag also supports the binding attribute. Binding Converters, Listeners, and Validators to Backing Bean Properties explains more about how to bind listeners to backing bean properties.

When this tag’s component is activated, the component’s decode method (or its associated Renderer) automatically queues the ActionEvent implementation associated with the specified ActionListener implementation onto the component.

In addition to the actionListener tag that allows you register a custom listener onto a component, the core tag library includes the setPropertyActionListener tag. You use this tag to register a special action listener onto the ActionSource instance associated with a component. When the component is activated, the listener will store the object referenced by the tag’s value attribute into the object referenced by the tag’s target attribute.

The bookcatalog.jsp page uses setPropertyActionListener with two components: the commandLink component used to link to the bookdetails.jsp page and the commandButton component used to add a book to the cart:

<c:forEach items="#{bookDBAO.books}" var="book"
     varStatus="stat">
    <c:set var="book" scope="request" value="${book}"/>
        ...
    <h:commandLink action="#{catalog.details}"
        value="#{book.title}">
        <f:setPropertyActionListener
             target="#{requestScope.book}" value="#{book}"/>
    </h:commandLink>
    ...
    <h:commandButton id="add"
        action="#{catalog.add}" value="#{bundle.CartAdd}">
        <f:setPropertyActionListener
             target="#{requestScope.book}" value="#{book}"/>
    </h:commandButton>
    <c:remove var="book" scope="request"/>
</c:forEach>

As shown in the preceding code, the commandLink and commandButton components are within a forEach tag, which iterates over the list of books. The var attribute refers to a single book in the list of books.

The object referenced by the var attribute of a forEach tag is in page scope. However, in this case, you need to put this object into request scope so that when the user activates the commandLink component to go to bookdetails.jsp or activates the commandButton component to go to bookcatalog.jsp, the book data is available to those pages. Therefore, the setPropertyActionListener tag is used to set the current book object into request scope when the commandLink or commandButton component is activated.

In the preceding example, the setPropertyActionListener tag’s value attribute references the book object. The setPropertyActionListener tag’s target attribute references the value expression requestScope.book, which is where the book object referenced by the value attribute is stored when the commandLink or the commandButton component is activated.

Using the Standard Validators

JavaServer Faces technology provides a set of standard classes and associated tags that page authors and application developers can use to validate a component’s data. Table 11–7 lists all the standard validator classes and the tags that allow you to use the validators from the page.

Table 11–7 The Validator Classes

Validator Class 

Tag 

Function 

DoubleRangeValidator

validateDoubleRange

Checks whether the local value of a component is within a certain range. The value must be floating-point or convertible to floating-point. 

LengthValidator

validateLength

Checks whether the length of a component’s local value is within a certain range. The value must be a java.lang.String.

LongRangeValidator

validateLongRange

Checks whether the local value of a component is within a certain range. The value must be any numeric type or String that can be converted to a long.

All these validator classes implement the Validator interface. Component writers and application developers can also implement this interface to define their own set of constraints for a component’s value.

Similarly to the standard converters, each of these validators has one or more standard error messages associated with it. If you have registered one of these validators onto a component on your page, and the validator is not able to validate the component’s value, the validator’s error message will display on the page. For example, the error message that displays when the component’s value exceeds the maximum value allowed by LongRangeValidator is the following:


{1}: Validation Error: Value is greater than allowable maximum of "{0}"

In this case the {1} substitution parameter is replaced by the component’s label or ID, and the {0} substitution parameter is replaced with the maximum value allowed by the validator.

See section 2.5.4 of the JavaServer Faces specification for the complete list of error messages. See Displaying Error Messages with the message and messages Tags for information on how to display validation error messages on the page when validation fails.

Validating a Component’s Value

In order to validate a component’s value using a particular validator, you need to register the validator on the component. You have three ways to do this:

See Referencing a Method That Performs ValidationReferencing a Method That Performs Validation for more information on using the validator attribute.

The validatorId attribute works similarly to the converterId attribute of the converter tag, as described in Converting a Component’s Value. See Binding Converters, Listeners, and Validators to Backing Bean Properties for more information on using the binding attribute of the validator tag.

Keep in mind that validation can be performed only on components that implement EditableValueHolder because these components accept values that can be validated.

Using the LongRangeValidator

The Duke’s Bookstore application uses a validateLongRange tag on the quantity input field of the bookshowcart.jsp page:

<h:inputText id="quantity" size="4"
     value=
"#{item.quantity}
" >
    <f:validateLongRange minimum="1"/>
</h:inputText>
<h:message for="quantity"/>

This tag requires that the user enter a number that is at least 1. The size attribute specifies that the number can have no more than four digits. The validateLongRange tag also has a maximum attribute, with which you can set a maximum value of the input.

The attributes of all the standard validator tags accept value expressions. This means that the attributes can reference backing bean properties rather than specify literal values. For example, the validateLongRange tag in the preceding example can reference a backing bean property called minimum to get the minimum value acceptable to the validator implementation:

<f:validateLongRange minimum="#{ShowCartBean.minimum}" />

Binding Component Values and Instances to External Data Sources

As explained in Backing Beans, a component tag can wire its component’s data to a back-end data object by doing one of the following:

A component tag’s value attribute uses a value expression to bind the component’s value to an external data source, such as a bean property. A component tag’s binding attribute uses a value expression to bind a component instance to a bean property.

When a component instance is bound to a backing bean property, the property holds the component’s local value. Conversely, when a component’s value is bound to a backing bean property, the property holds the value stored in the backing bean. This value is updated with the local value during the update model values phase of the life cycle. There are advantages to both of these techniques.

Binding a component instance to a bean property has these advantages:

Binding a component’s value to a bean property has these advantages:

In most situations, you will bind a component’s value rather than its instance to a bean property. You’ll need to use a component binding only when you need to change one of the component’s attributes dynamically. For example, if an application renders a component only under certain conditions, it can set the component’s rendered property accordingly by accessing the property to which the component is bound.

When referencing the property using the component tag’s value attribute, you need to use the proper syntax. For example, suppose a backing bean called MyBean has this int property:

int currentOption = null;
int getCurrentOption(){...}
void setCurrentOption(int option){...}

The value attribute that references this property must have this value-binding expression:

#{MyBean.currentOption}

In addition to binding a component’s value to a bean property, the value attribute can specify a literal value or can map the component’s data to any primitive (such as int), structure (such as an array), or collection (such as a list), independent of a JavaBeans component. Table 11–8 lists some example value-binding expressions that you can use with the value attribute.

Table 11–8 Example Value-binding Expressions

Value 

Expression 

A Boolean 

cart.numberOfItems > 0

A property initialized from a context init parameter

initParam.quantity

A bean property 

CashierBean.name

Value in an array 

books[3]

Value in a collection 

books["fiction"]

Property of an object in an array of objects 

books[3].price

The next two sections explain in more detail how to use the value attribute to bind a component’s value to a bean property or other external data sources and how to use the binding attribute to bind a component instance to a bean property.

Binding a Component Value to a Property

To bind a component’s value to a bean property, you specify the name of the bean and the property using the value attribute. As explained in Backing Beans, the value expression of the component tag’s value attribute must match the corresponding managed bean declaration in the application configuration resource file.

This means that the name of the bean in the value expression must match the managed-bean-name element of the managed bean declaration up to the first period (.) in the expression. Similarly, the part of the value expression after the period must match the name specified in the corresponding property-name element in the application configuration resource file.

For example, consider this managed bean configuration, which configures the ImageArea bean corresponding to the North America part of the image map on the chooselocale.jsp page of the Duke’s Bookstore application:

<managed-bean>
    <managed-bean-name> NA </managed-bean-name>
    <managed-bean-class> model.ImageArea </managed-bean-class>
    <managed-bean-scope> application </managed-bean-scope>
    <managed-property>
        <property-name>shape</property-name>
        <value>poly</value>
    </managed-property>
    <managed-property>
        <property-name>alt</property-name>
        <value>NAmerica</value>
    </managed-property>
    ...
</managed-bean>

This example configures a bean called NA, which has several properties, one of which is called shape.

Although the area tags on the chooselocale.jsp page do not bind to an ImageArea property (they bind to the bean itself), to do this, you refer to the property using a value expression from the value attribute of the component’s tag:

<h:outputText value="#{NA.shape}" />

Much of the time you will not include definitions for a managed bean’s properties when configuring it. You need to define a property and its value only when you want the property to be initialized with a value when the bean is initialized.

If a component tag’s value attribute must refer to a property that is not initialized in the managed-bean configuration, the part of the value-binding expression after the period must match the property name as it is defined in the backing bean.

See Application Configuration Resource File for information on how to configure beans in the application configuration resource file.

Writing Bean Properties explains in more detail how to write the backing bean properties for each of the component types.

Binding a Component Value to an Implicit Object

One external data source that a value attribute can refer to is an implicit object.

The bookreceipt.jsp page of the Duke’s Bookstore application includes a reference to an implicit object from a parameter substitution tag:

<h:outputFormat title="thanks" value="#{bundle.ThankYouParam}">
    <f:param value="#{sessionScope.name}"/>
</h:outputFormat>

This tag gets the name of the customer from the session scope and inserts it into the parameterized message at the key ThankYouParam from the resource bundle. For example, if the name of the customer is Gwen Canigetit, this tag will render:


Thank you, Gwen Canigetit, for purchasing your books from us.

The name tag on the bookcashier.jsp page has the NameChanged listener implementation registered on it. This listener saves the customer’s name in the session scope when the bookcashier.jsp page is submitted. See Implementing Value-Change Listeners for more information on how this listener works. See Registering a Value-Change Listener on a Component to learn how the listener is registered on the tag.

Retrieving values from other implicit objects is done in a similar way to the example shown in this section. Table 11–9 lists the implicit objects that a value attribute can refer to. All of the implicit objects except for the scope objects are read-only and therefore should not be used as a value for a UIInput component.

Table 11–9 Implicit Objects

Implicit Object 

What It Is 

applicationScope

A Map of the application scope attribute values, keyed by attribute name

cookie

A Map of the cookie values for the current request, keyed by cookie name

facesContext

The FacesContext instance for the current request

header

A Map of HTTP header values for the current request, keyed by header name

headerValues

A Map of String arrays containing all the header values for HTTP headers in the current request, keyed by header name

initParam

A Map of the context initialization parameters for this web application

param

A Map of the request parameters for this request, keyed by parameter name

paramValues

A Map of String arrays containing all the parameter values for request parameters in the current request, keyed by parameter name

requestScope

A Map of the request attributes for this request, keyed by attribute name

sessionScope

A Map of the session attributes for this request, keyed by attribute name

view

The root UIComponent in the current component tree stored in the FacesRequest for this request

Binding a Component Instance to a Bean Property

A component instance can be bound to a bean property using a value expression with the binding attribute of the component’s tag. You usually bind a component instance rather than its value to a bean property if the bean must dynamically change the component’s attributes.

Here are two tags from the bookcashier.jsp page that bind components to bean properties:

<h:selectBooleanCheckbox
     id="fanClub"
    rendered="false"
    binding="#{cashier.specialOffer}" />
<h:outputLabel for="fanClub"
    rendered="false"        
    binding="#{cashier.specialOfferText}"  >
    <h:outputText id="fanClubLabel"
        value="#{bundle.DukeFanClub}"
    />
</h:outputLabel>

The selectBooleanCheckbox tag renders a check box and binds the fanClub UISelectBoolean component to the specialOffer property of CashierBean. The outputLabel tag binds the component representing the check box’s label to the specialOfferText property of CashierBean. If the application’s locale is English, the outputLabel tag renders:


I’d like to join the Duke Fan Club, free with my purchase of over $100

The rendered attributes of both tags are set to false, which prevents the check box and its label from being rendered. If the customer orders more than $100 (or 100 euros) worth of books and clicks the Submit button, the submit method of CashierBean sets both components’ rendered properties to true, causing the check box and its label to be rendered.

These tags use component bindings rather than value bindings because the backing bean must dynamically set the values of the components’ rendered properties.

If the tags were to use value bindings instead of component bindings, the backing bean would not have direct access to the components, and would therefore require additional code to access the components from the FacesContext instance to change the components’ rendered properties.

Writing Properties Bound to Component Instances explains how to write the bean properties bound to the example components and also discusses how the submit method sets the rendered properties of the components.

Binding Converters, Listeners, and Validators to Backing Bean Properties

As described previously in this chapter, a page author can bind converter, listener, and validator implementations to backing bean properties using the binding attributes of the tags used to register the implementations on components.

This technique has similar advantages to binding component instances to backing bean properties, as described in Binding Component Values and Instances to External Data Sources. In particular, binding a converter, listener, or validator implementation to a backing bean property yields the following benefits:

Whether you are binding a converter, listener, or validator to a backing bean property, the process is the same for any of the implementations:

For example, say that you want to bind the standard DateTime converter to a backing bean property because the application developer wants the backing bean to set the formatting pattern of the user’s input rather than let the page author do it. First, the page author registers the converter onto the component by nesting the convertDateTime tag within the component tag. Then, the page author references the property with the binding attribute of the convertDateTime tag:

<h:inputText value="#{LoginBean.birthDate}">
    <f:convertDateTime binding="#{LoginBean.convertDate}" />
</h:inputText>

The convertDate property would look something like this:

private DateTimeConverter convertDate;
public DateTimeConverter getConvertDate() {
    ...
    return convertDate;
{
public void setConvertDate(DateTimeConverter convertDate) {
    convertDate.setPattern("EEEEEEEE, MMM dd, yyyy");
    this.convertDate = convertDate;
}

See Writing Properties Bound to Converters, Listeners, or Validators for more information on writing backing bean properties for converter, listener, and validator implementations.

Referencing a Backing Bean Method

A component tag has a set of attributes for referencing backing bean methods that can perform certain functions for the component associated with the tag. These attributes are summarized in Table 11–10.

Table 11–10 Component Tag Attributes That Reference Backing Bean Methods

Attribute 

Function 

action

Refers to a backing bean method that performs navigation processing for the component and returns a logical outcome String

actionListener

Refers to a backing bean method that handles action events 

validator

Refers to a backing bean method that performs validation on the component’s value 

valueChangeListener

Refers to a backing bean method that handles value-change events 

Only components that implement ActionSource can use the action and actionListener attributes. Only components that implement EditableValueHolder can use the validator or valueChangeListener attributes.

The component tag refers to a backing bean method using a method expression as a value of one of the attributes. The method referenced by an attribute must follow a particular signature, which is defined by the tag attribute’s definition in the TLD. For example, the definition of the validator attribute of the inputText tag in html_basic.tld is the following:

void validate(javax.faces.context.FacesContext,
     javax.faces.component.UIComponent, java.lang.Object)

The following four sections give examples of how to use the four different attributes.

Referencing a Method That Performs Navigation

If your page includes a component (such as a button or hyperlink) that causes the application to navigate to another page when the component is activated, the tag corresponding to this component must include an action attribute. This attribute does one of the following

The bookcashier.jsp page of the Duke’s Bookstore application has a commandButton tag that refers to a backing bean method that calculates the shipping date. If the customer has ordered more than $100 (or 100 euros) worth of books, this method also sets the rendered properties of some of the components to true and returns null; otherwise it returns receipt, which causes the bookreceipt.jsp page to display. Here is the commandButton tag from the bookcashier.jsp page:

<h:commandButton
    value="#{bundle.Submit}"
    action="#{cashier.submit}" />

The action attribute uses a method expression to refer to the submit method of CashierBean. This method will process the event fired by the component corresponding to this tag.

Writing a Method to Handle Navigation describes how to implement the submit method of CashierBean.

The application architect must configure a navigation rule that determines which page to access given the current page and the logical outcome, which is either returned from the backing bean method or specified in the tag. See Configuring Navigation Rules for information on how to define navigation rules in the application configuration resource file.

Referencing a Method That Handles an Action Event

If a component on your page generates an action event, and if that event is handled by a backing bean method, you refer to the method by using the component’s actionListener attribute.

The chooselocale.jsp page of the Duke’s Bookstore application includes some components that generate action events. One of them is the NAmerica component:

<h:commandLink id="NAmerica" action="bookstore"
     actionListener="#{localeBean.chooseLocaleFromLink}">

The actionListener attribute of this component tag references the chooseLocaleFromLink method using a method expression. The chooseLocaleFromLink method handles the event of a user clicking on the hyperlink rendered by this component.

Writing a Method to Handle an Action Event describes how to implement a method that handles an action event.

Referencing a Method That Performs Validation

If the input of one of the components on your page is validated by a backing bean method, you refer to the method from the component’s tag using the validator attribute.

The Coffee Break application includes a method that performs validation of the email input component on the checkoutForm.jsp page. Here is the tag corresponding to this component:

<h:inputText id="email" value="#{checkoutFormBean.email}"
    size="25" maxlength="125"
    validator="#{checkoutFormBean.validateEmail}"/>

This tag references the validate method described in Writing a Method to Perform Validation using a method expression.

Referencing a Method That Handles a Value-change Event

If you want a component on your page to generate a value-change event and you want that event to be handled by a backing bean method, you refer to the method using the component’s valueChangeListener attribute.

The name component on the bookcashier.jsp page of the Duke’s Bookstore application references a ValueChangeListener implementation that handles the event of a user entering a name in the name input field:

<h:inputText
     id="name"
     size="50"
     value="#{cashier.name}"
     required="true">
    <f:valueChangeListener type="listeners.NameChanged" />
</h:inputText>

For illustration, Writing a Method to Handle a Value-Change Event describes how to implement this listener with a backing bean method instead of a listener implementation class. To refer to this backing bean method, the tag uses the valueChangeListener attribute:

<h:inputText
     id="name"
     size="50"
     value="#{cashier.name}"
     required="true"
    valueChangeListener="#{cashier.processValueChange}" />
</h:inputText>

The valueChangeListener attribute of this component tag references the processValueChange method of CashierBean using a method expression. The processValueChange method handles the event of a user entering his name in the input field rendered by this component.

Writing a Method to Handle a Value-Change Event describes how to implement a method that handles a ValueChangeEvent.

Using Custom Objects

As a page author, you might need to use custom converters, validators, or components packaged with the application on your JSP pages.

A custom converter is applied to a component in one of the following ways:

A custom validator is applied to a component in one of the following ways:

To use a custom component, you add the custom tag associated with the component to the page.

As explained in Setting Up a Page, you must ensure that the TLD that defines any custom tags is packaged in the application if you intend to use the tags in your pages. 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 file.

You also need to include a taglib declaration in the page so that the page has access to the tags. All custom objects for the Duke’s Bookstore application are defined in bookstore.tld. Here is the taglib declaration that you would include on your page so that you can use the tags from this TLD:

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

When including the custom tag in the page, you can consult the TLD to determine which attributes the tag supports and how they are used.

The next three sections describe how to use the custom converter, validator, and UI components included in the Duke’s Bookstore application.

Using a Custom Converter

As described in the previous section, to apply the data conversion performed by a custom converter to a particular component’s value, you must either reference the custom converter from the component tag’s converter attribute or from a converter tag nested inside the component tag.

If you are using the component tag’s converter attribute, this attribute must reference the Converter implementation’s identifier or the fully-qualified class name of the converter. The application architect provides this identifier when registering the Converter implementation with the application, as explained in Registering a Custom Converter. Creating a Custom Converter explains how a custom converter is implemented.

The identifier for the credit card converter is CreditCardConverter. The CreditCardConverter instance is registered on the ccno component, as shown in this tag from the bookcashier.jsp page:

<h:inputText id="ccno"
    size="19"
    converter="CreditCardConverter"
    required="true">
    ...
</h:inputText>

By setting the converter attribute of a component’s tag to the converter’s identifier or its class name, you cause that component’s local value to be automatically converted according to the rules specified in the Converter implementation.

Instead of referencing the converter from the component tag’s converter attribute, you can reference the converter from a converter tag nested inside the component’s tag. To reference the custom converter using the converter tag, you do one of the following:

Using a Custom Validator

To register a custom validator on a component, you must do one of the following:

Here is the custom formatValidator tag from the ccno field on the bookcashier.jsp page of the Duke’s Bookstore application:

<h:inputText id="ccno" size="19"
    ...
    required="true">
    <bookstore:formatValidator
         formatPatterns="9999999999999999|9999 9999 9999 9999|
        9999-9999-9999-9999" />
</h:inputText>
<h:message styleClass="validationMessage"  for="ccno"/>

This tag validates the input of the ccno field against the patterns defined by the page author in the formatPatterns attribute.

You can use the same custom validator for any similar component by simply nesting the custom validator tag within the component tag.

Creating a Custom Validator describes how to create the custom validator and its custom tag.

If the application developer who created the custom validator prefers to configure the attributes in the Validator implementation rather than allow the page author to configure the attributes from the page, the developer will not create a custom tag for use with the validator.

    In this case, the page author must nest the validator tag inside the tag of the component whose data needs to be validated. Then the page author needs to do one of the following:

  1. Set the validator tag’s validatorId attribute to the ID of the validator that is defined in the application configuration resource file. Registering a Custom Validator explains how to configure the validator in the application configuration resource file.

  2. Bind the custom Validator implementation to a backing bean property using the validator tag’s binding attribute, as described in Binding Converters, Listeners, and Validators to Backing Bean Properties.

The following tag registers a hypothetical validator on a component using a validator tag and references the ID of the validator:

<h:inputText id="name" value="#{CustomerBean.name}"
            size="10" ... >
    <f:validator validatorId="customValidator" />
    ...
</h:inputText>

Using a Custom Component

In order to use a custom component in a page, you need to declare the tag library that defines the custom tag that renders the custom component, as explained in Using Custom Objects, and you add the component’s tag to the page.

The Duke’s Bookstore application includes a custom image map component on the chooselocale.jsp page. This component allows you to select the locale for the application by clicking on a region of the image map:

...
<h:graphicImage id="mapImage" url="/template/world.jpg"
    alt="#{bundle.chooseLocale}"
    usemap="#worldMap" />
    <bookstore:map id="worldMap" current="NAmericas"
         immediate="true"
        action="bookstore"
        actionListener="#{localeBean.chooseLocaleFromMap}">
        <bookstore:area id="NAmerica" value="#{NA}"
             onmouseover="/template/world_namer.jpg"
             onmouseout="/template/world.jpg"
            targetImage="mapImage" />
        ...
        <bookstore:area id="France" value="#{fraA}"
            onmouseover="/template/world_france.jpg"
             onmouseout="/template/world.jpg"
            targetImage="mapImage" />
</bookstore:map>

The standard graphicImage tag associates an image (world.jpg) with an image map that is referenced in the usemap attribute value.

The custom map tag that represents the custom component, MapComponent, specifies the image map, and contains a set of area tags. Each custom area tag represents a custom AreaComponent and specifies a region of the image map.

On the page, the onmouseover and onmouseout attributes specify the image that is displayed when the user performs the actions described by the attributes. The page author defines what these images are. The custom renderer also renders an onclick attribute.

In the rendered HTML page, the onmouseover, onmouseout, and onclick attributes define which JavaScript code is executed when these events occur. When the user moves the mouse over a region, the onmouseover function associated with the region displays the map with that region highlighted. When the user moves the mouse out of a region, the onmouseout function redisplays the original image. When the user clicks a region, the onclick function sets the value of a hidden input tag to the ID of the selected area and submits the page.

When the custom renderer renders these attributes in HTML, it also renders the JavaScript code. The custom renderer also renders the entire onclick attribute rather than let the page author set it.

The custom renderer that renders the map tag also renders a hidden input component that holds the current area. The server-side objects retrieve the value of the hidden input field and set the locale in the FacesContext instance according to which region was selected.

Chapter 13, Creating Custom UI Components describes the custom tags in more detail and also explains how to create the custom image map components, renderers, and tags.

Chapter 12 Developing with JavaServer Faces Technology

Chapter 11, Using JavaServer Faces Technology in JSP Pages shows how the page author can bind components to server-side objects by using the component tags and core tags on the JSP page. The application developer’s responsibility is to program the server-side objects of a JavaServer Faces application. These objects include backing beans, converters, event handlers, and validators.

This chapter uses the Duke’s Bookstore application (see The Example JavaServer Faces Application) to explain all of the application developer’s responsibilities, including

Writing Bean Properties

As explained in Backing Beans, a backing bean property can be bound to one of the following items:

These properties follow JavaBeans component conventions (see JavaBeans Components).

The UI component’s tag binds the component’s value to a property using its value attribute and binds the component’s instance to a property using its binding attribute, as explained in Binding Component Values and Instances to External Data Sources. Likewise, all the converter, listener, and validator tags use their binding attributes to bind their associated implementations to backing bean properties, as explained in Binding Converters, Listeners, and Validators to Backing Bean Properties.

To bind a component’s value to a backing bean property, the type of the property must match the type of the component’s value to which it is bound. For example, if a backing bean property is bound to a UISelectBoolean component’s value, the property should accept and return a boolean value or a Boolean wrapper Object instance.

To bind a component instance, the property must match the component type. For example, if a backing bean property is bound to a UISelectBoolean instance, the property should accept and return UISelectBoolean.

Similarly, in order to bind a converter, listener, or validator implementation to a property, the property must accept and return the same type of converter, listener, or validator object. For example, if you are using the convertDateTime tag to bind a DateTime converter to a property, that property must accept and return a DateTime instance.

The rest of this section explains how to write properties that can be bound to component values, to component instances for the component objects described in Adding UI Components to a Page Using the HTML Component Tags, and to converter, listener, and validator implementations.

Writing Properties Bound to Component Values

To write a backing bean property bound to a component’s value, you must know the types that the component’s value can be so that you can make the property match the type of the component’s value.

Table 12–1 lists all the component classes described in Adding UI Components to a Page Using the HTML Component Tags and the acceptable types of their values.

When page authors bind components to properties using the value attributes of the component tags, they need to ensure that the corresponding properties match the types of the components’ values.

Table 12–1 Acceptable Types of Component Values

Component 

Acceptable Types of Component Values 

UIInput, UIOutput, UISelectItem, UISelectOne

Any of the basic primitive and numeric types or any Java programming language object type for which an appropriate Converter implementation is available.

UIData

array of beans, List of beans, single bean, java.sql.ResultSet, javax.servlet.jsp.jstl.sql.Result, javax.sql.RowSet.

UISelectBoolean

boolean or Boolean.

UISelectItems

java.lang.String, Collection, Array, Map.

UISelectMany

array or List. Elements of the array or List can be any of the standard types.

UIInput and UIOutput Properties

The following tag binds the name component to the name property of CashierBean.

<h:inputText id="name" size="50"
    value="#{cashier.name}"
    required="true">
     <f:valueChangeListener
         type="com.sun.bookstore6.listeners.NameChanged" />
 </h:inputText>

Here is the bean property bound to the name component:

protected String name = null;
 public void setName(String name) {
    this.name = name;
}
public String getName() {
    return this.name;
}

As Using the Standard Converters describes, to convert the value of a UIInput or UIOutput component, you can either apply a converter or create the bean property bound to the component with the desired type. Here is the example tag explained in Using DateTimeConverter that displays the date books will be shipped:

<h:outputText value="#{cashier.shipDate}">
    <f:convertDateTime dateStyle="full" />
</h:outputText>

The application developer must ensure that the property bound to the component represented by this tag has a type of java.util.Date. Here is the shipDate property in CashierBean:

protected Date shipDate;
public Date getShipDate() {
    return this.shipDate;
}
public void setShipDate(Date shipDate) {
    this.shipDate = shipDate;
}

See Binding Component Values and Instances to External Data Sources for more information on applying a Converter implementation.

UIData Properties

UIData components must be bound to one of the types listed in Table 12–1. The UIData component from the bookshowcart.jsp page of the Duke’s Bookstore example is discussed in the section Using Data-Bound Table Components. Here is part of the start tag of dataTable from that section:

<h:dataTable  id="items"
    ...
    value="#{cart.items}"
    var="item" >

The value expression points to the items property of the ShoppingCart bean. The ShoppingCart bean maintains a map of ShoppingCartItem beans.

The getItems method from ShoppingCart populates a List with ShoppingCartItem instances that are saved in the items map from when the customer adds books to the cart:

public synchronized List getItems() {
    List results = new ArrayList();
    results.addAll(this.items.values());
    return results;
}

All the components contained in the UIData component are bound to the properties of the ShoppingCart bean that is bound to the entire UIData component. For example, here is the outputText tag that displays the book title in the table:

<h:commandLink action="#{showcart.details}">
    <h:outputText value="#{item.item.title}"/>
</h:commandLink>

The book title is actually a hyperlink to the bookdetails.jsp page. The outputText tag uses the value expression #{item.item.title} to bind its UIOutput component to the title property of the Book bean. The first item in the expression is the ShoppingCartItem instance that the dataTable tag is referencing while rendering the current row. The second item in the expression refers to the item property of ShoppingCartItem, which returns a Book bean. The title part of the expression refers to the title property of Book. The value of the UIOutput component corresponding to this tag is bound to the title property of the Book bean:

private String title = null;
public String getTitle() {
    return this.title;
}
public void setTitle(String title) {
    this.title=title;
}

UISelectBoolean Properties

Properties that hold the UISelectBoolean component’s data must be of boolean or Boolean type. The example selectBooleanCheckbox tag from the section Rendering Components for Selecting One Value binds a component to a property. Here is an example that binds a component value to a property:

<h:selectBooleanCheckbox title="#{bundle.receiveEmails}"
     value="#{custFormBean.receiveEmails}" >
</h:selectBooleanCheckbox>
<h:outputText value="#{bundle.receiveEmails}">

Here is an example property that can be bound to the component represented by the example tag:

    protected boolean receiveEmails = false;
        ...
    public void setReceiveEmails(boolean receiveEmails) {
        this.receiveEmails = receiveEmails;
    }
    public boolean getReceiveEmails() {
        return receiveEmails;
    }

UISelectMany Properties

Because a UISelectMany component allows a user to select one or more items from a list of items, this component must map to a bean property of type List or array. This bean property represents the set of currently selected items from the list of available items.

Here is the example selectManyCheckbox tag from Rendering Components for Selecting Multiple Values:

<h:selectManyCheckbox
    id="newsletters"
    layout="pageDirection"
    value="#{cashier.newsletters}">
    <f:selectItems value="#{newsletters}"/>
</h:selectManyCheckbox>

Here is a bean property that maps to the value of this selectManyCheckbox example:

protected String newsletters[] = new String[0];

public void setNewsletters(String newsletters[]) {
    this.newsletters = newsletters;
}
public String[] getNewsletters() {
    return this.newsletters;
}

As explained in the section Rendering Components for Selecting Multiple Values, the UISelectItem and UISelectItems components are used to represent all the values in a UISelectMany component. See UISelectItem Properties and UISelectItems Properties for information on how to write the bean properties for the UISelectItem and UISelectItems components.

UISelectOne Properties

UISelectOne properties accept the same types as UIInput and UIOutput properties. This is because a UISelectOne component represents the single selected item from a set of items. This item can be any of the primitive types and anything else for which you can apply a converter.

Here is the example selectOneMenu tag from Displaying a Menu Using the selectOneMenu Tag:

<h:selectOneMenu   id="shippingOption"
    required="true"
    value="#{cashier.shippingOption}">
    <f:selectItem
        itemValue="2"
        itemLabel="#{bundle.QuickShip}"/>
    <f:selectItem
        itemValue="5"
        itemLabel="#{bundle.NormalShip}"/>
    <f:selectItem
        itemValue="7"
        itemLabel="#{bundle.SaverShip}"/>
 </h:selectOneMenu>

Here is the property corresponding to this tag:

protected String shippingOption = "2";

public void setShippingOption(String shippingOption) {
    this.shippingOption = shippingOption;
}
public String getShippingOption() {
    return this.shippingOption;
}

Note that shippingOption represents the currently selected item from the list of items in the UISelectOne component.

As explained in the section Displaying a Menu Using the selectOneMenu Tag, the UISelectItem and UISelectItems components are used to represent all the values in a UISelectOne component. See UISelectItem Properties and UISelectItems Properties for information on how to write the backing bean properties for the UISelectItem and UISelectItems components.

UISelectItem Properties

A UISelectItem component represents one value in a set of values in a UISelectMany or UISelectOne component. The backing bean property that a UISelectItem component is bound to must be of type SelectItem. A SelectItem object is composed of an Object representing the value, along with two Strings representing the label and description of the SelectItem object.

The Duke’s Bookstore application does not use any UISelectItem components whose values are bound to backing beans. The example selectOneMenu tag from Displaying a Menu Using the selectOneMenu Tag contains selectItem tags that set the values of the list of items in the page. Here is an example bean property that can set the values for this list in the bean:

SelectItem itemOne = null;

SelectItem getItemOne(){
    return itemOne;

}

void setItemOne(SelectItem item) {
    itemOne = item;
}

UISelectItems Properties

UISelectItems components are children of UISelectMany and UISelectOne components. Each UISelectItems component is composed of either a set of SelectItem instances or a set of SelectItemGroup instances. As described in Using the selectItems Tag, a SelectItemGroup is composed of a set of SelectItem instances. This section describes how to write the properties for selectItems tags containing SelectItem instances and for selectItems tags containing SelectItemGroup instances.

Properties for SelectItems Composed of SelectItem Instances

Using the selectItems Tag describes how the newsletters list of the Duke’s Bookstore application is populated using the application configuration resource file. You can also populate the SelectItems with SelectItem instances programmatically in the backing bean. This section explains how to do this.

In your backing bean, you create a list that is bound to the SelectItem component. Then you define a set of SelectItem objects, set their values, and populate the list with the SelectItem objects. Here is an example code snippet that shows how to create a SelectItems property:

import javax.faces.component.SelectItem;
...
protected ArrayList options = null;
protected SelectItem newsletter0 =
     new SelectItem("200", "Duke’s Quarterly", "");
...
//in constructor, populate the list
options.add(newsletter0);
options.add(newsletter1);
options.add(newsletter2);
...
public SelectItem getNewsletter0(){
    return newsletter0;
}

void setNewsletter0(SelectItem firstNL) {
    newsletter0 = firstNL;
}
// Other SelectItem properties

public Collection[] getOptions(){
    return options;
}
public void setOptions(Collection[] options){
    this.options = new ArrayList(options);
}

The code first initializes options as a list. Each newsletter property is defined with values. Then, each newsletter SelectItem is added to the list. Finally, the code includes the obligatory setOptions and getOptions accessor methods.

Properties for SelectItems Composed of SelectItemGroup Instances

The preceding section explains how to write the bean property for a SelectItems component composed of SelectItem instances. This section explains how to change the example property from the preceding section so that the SelectItems is composed of SelectItemGroup instances.

Let’s separate the newsletters into two groups: One group includes Duke’s newsletters, and the other group includes the Innovator’s Almanac and Random Ramblings newsletters.

In your backing bean, you need a list that contains two SelectItemGroup instances. Each SelectItemGroup instance contains two SelectItem instances, each representing a newsletter:

import javax.faces.model.SelectItemGroup;
...
private ArrayList optionsGroup = null;

optionsGroup = new ArrayList(2);

private static final SelectItem options1[] = {
    new SelectItem("200", "Duke’s Quarterly", "");
    new SelectItem("202",
         "Duke’s Diet and Exercise Journal", "");
};
private static final SelectItem options2[] = {
    new SelectItem("201", "Innovator’s Almanac", "");
    new SelectItem("203", "Random Ramblings", "");
};

SelectItemGroup group1 =
     new SelectItemGroup("Duke’s", null, true, options1);
SelectItemGroup group2 =
    new SelectItemGroup("General Interest", null, true,
         options2);

optionsGroup.add(group1);
optionsGroup.add(group2);
...
public Collection getOptionsGroup() {
    return optionsGroup;
}
 public void setOptionsGroup(Collection newGroupOptions) {
    optionsGroup = new ArrayList(newGroupOptions);
}

The code first initializes optionsGroup as a list. The optionsGroup list contains two SelectItemGroup objects. Each object is initialized with the label of the group appearing in the list or menu; a value; a Boolean indicating whether or not the label is disabled; and an array containing two SelectItem instances. Then each SelectItemGroup is added to the list. Finally, the code includes the setOptionsGroup and getOptionsGroup accessor methods so that the tag can access the values. The selectItems tag references the optionsGroup property to get the SelectItemGroup objects for populating the list or menu on the page.

Writing Properties Bound to Component Instances

A property bound to a component instance returns and accepts a component instance rather than a component value. Here are the tags described in Binding a Component Instance to a Bean Property that bind components to backing bean properties:

<h:selectBooleanCheckbox
     id="fanClub"
    rendered="false"
    binding="#{cashier.specialOffer}" />
<h:outputLabel for="fanClub"
    rendered="false"
    binding="#{cashier.specialOfferText}"  >
    <h:outputText id="fanClubLabel"
        value="#{bundle.DukeFanClub}" />
</h:outputLabel>

As Binding a Component Instance to a Bean Property explains, the selectBooleanCheckbox tag renders a check box and binds the fanClub UISelectBoolean component to the specialOffer property of CashierBean. The outputLabel tag binds the fanClubLabel component (which represents the check box’s label) to the specialOfferText property of CashierBean. If the user orders more than $100 (or 100 euros) worth of books and clicks the Submit button, the submit method of CashierBean sets both components’ rendered properties to true, causing the check box and label to display when the page is re-rendered.

Because the components corresponding to the example tags are bound to the backing bean properties, these properties must match the components’ types. This means that the specialOfferText property must be of UIOutput type, and the specialOffer property must be of UISelectBoolean type:

UIOutput specialOfferText = null;

public UIOutput getSpecialOfferText() {
    return this.specialOfferText;
}
public void setSpecialOfferText(UIOutput specialOfferText) {
    this.specialOfferText = specialOfferText;
}

UISelectBoolean specialOffer = null;

public UISelectBoolean getSpecialOffer() {
    return this.specialOffer;
}
public void setSpecialOffer(UISelectBoolean specialOffer) {
    this.specialOffer = specialOffer;
}

See Backing Beans for more general information on component binding.

See Referencing a Method That Performs Navigation for information on how to reference a backing bean method that performs navigation when a button is clicked.

See Writing a Method to Handle Navigation for more information on writing backing bean methods that handle navigation.

Writing Properties Bound to Converters, Listeners, or Validators

All of the standard converter, listener, and validator tags that are included with JavaServer Faces technology support binding attributes that allow page authors to bind converter, listener, or validator implementations to backing bean properties.

The following example from Binding Converters, Listeners, and Validators to Backing Bean Properties shows a standard convertDateTime tag using a value expression with its binding attribute to bind the DateTimeConverter instance to the convertDate property of LoginBean:

<h:inputText value="#{LoginBean.birthDate}">
    <f:convertDateTime binding="#{LoginBean.convertDate}" />
</h:inputText>

The convertDate property must therefore accept and return a DateTimeConverter object, as shown here:

private DateTimeConverter convertDate;
public DateTimeConverter getConvertDate() {
    ...
    return convertDate;
{
public void setConvertDate(DateTimeConverter convertDate) {
    convertDate.setPattern("EEEEEEEE, MMM dd, yyyy");
    this.convertDate = convertDate;
}

Because the converter is bound to a backing bean property, the backing bean property is able to modify the attributes of the converter or add new functionality to it. In the case of the preceding example, the property sets the date pattern that the converter will use to parse the user’s input into a Date object.

The backing bean properties that are bound to validator or listener implementations are written in the same way and have the same general purpose.

Performing Localization

As mentioned in Rendering Components for Selecting Multiple Values, data and messages in the Duke’s Bookstore application have been localized for French, German, Spanish, and American English.

This section explains how to produce the localized error messages as well as how to localize dynamic data and messages.

Rendering Components for Selecting Multiple Values describes how page authors access localized data from the page.

If you are not familiar with the basics of localizing web applications, see Chapter 15, Internationalizing and Localizing Web Applications.

Creating a Resource Bundle

A ResourceBundle contains a set of localized messages. To learn how to create a ResourceBundle, see http://java.sun.com/docs/books/tutorial/i18n/index.html.

After you create the ResourceBundle, put it in the same directory as your classes. Much of the data for the Duke’s Bookstore application is stored in a ResourceBundle called BookstoreMessages, located in tut-install/javaeetutorial5/examples/web/bookstore/src/com/sun/bookstore/messages/.

Localizing Dynamic Data

The Duke’s Bookstore application has some data that is set dynamically in backing beans. Because of this, the beans must load the localized data themselves; the data can’t be loaded from the page.

The message method in tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/backing/AbstractBean.java is a general-purpose method that looks up localized data used in the backing beans:

protected void message(String clientId, String key) {
    // Look up the requested message text
    String text = null;
    try {
        ResourceBundle bundle =
            ResourceBundle.getBundle("messages.BookstoreMessages",
                context().getViewRoot().getLocale());
        text = bundle.getString(key);
    } catch (Exception e) {
        text = "???" + key + "???";
    }
    // Construct and add a FacesMessage containing it
    context().addMessage(clientId, new FacesMessage(text));
}

This method gets the current locale from the UIViewRoot instance of the current request and loads the localized data for the messages using the getBundle method, passing in the path to the ResourceBundle and the current locale.

The other backing beans call this method by using the key to the message that they are trying to retrieve from the resource bundle. Here is a call to the message method from tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/backing/ShowCartBean.java:

message(null, "Quantities Updated");

Localizing Messages

The JavaServer Faces API provides two ways to create messages from a resource bundle:

Registering Custom Error Messages includes an example of registering a ResourceBundle in the application configuration resource file.

Creating a Message with a Message Factory

    To use a message factory to create a message, follow these steps:

  1. Register the ResourceBundle instance with the application. This is explained in Registering Custom Error Messages.

  2. Create a message factory implementation. You can simply copy the MessageFactory class included with the Duke’s Bookstore application to your application.

  3. Access a message from your application by calling the getMessage(FacesContext, String, Object) method of the MessageFactory class. The MessageFactory class uses the FacesContext to access the Application instance on which the messages are registered. The String argument is the key that corresponds to the message in the ResourceBundle. The Object instance typically contains the substitution parameters that are embedded in the message. For example, the custom validator described in Implementing the Validator Interface will substitute the format pattern for the {0} in this error message:


    Input must match one of the following patterns {0}

Implementing the Validator Interface gives an example of accessing messages.

Using FacesMessage to Create a Message

Instead of registering messages in the application configuration resource file, you can access the ResourceBundle directly from the code. The validateEmail method from the Coffee Break example does this:

...
String message = "";
...
message = CoffeeBreakBean.loadErrorMessage(context,
    CoffeeBreakBean.CB_RESOURCE_BUNDLE_NAME,
         "EMailError");
context.addMessage(toValidate.getClientId(context),
    new FacesMessage(message));
...

These lines also call the loadErrorMessage to get the message from the ResourceBundle. Here is the loadErrorMessage method from CoffeeBreakBean:

public static String loadErrorMessage(FacesContext context,
     String basename, String key) {
    if ( bundle == null ) {
         try {
            bundle = ResourceBundle.getBundle(basename,
                 context.getViewRoot().getLocale());
        } catch (Exception e) {
            return null;
        }
    }
    return bundle.getString(key);
}

Creating a Custom Converter

As explained in Conversion Model, if the standard converters included with JavaServer Faces technology don’t perform the data conversion that you need, you can easily create a custom converter to perform this specialized conversion.

All custom converters must implement the Converter interface. This implementation, at a minimum, must define how to convert data both ways between the two views of the data described in Conversion Model.

This section explains how to implement the Converter interface to perform a custom data conversion. To make this implementation available to the application, the application architect registers it with the application, as explained in Registering a Custom Converter. To use the implementation, the page author must register it on a component, as explained in Registering a Custom Converter.

The Duke’s Bookstore application uses a custom Converter implementation, called tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/converters/CreditCardConverter.java, to convert the data entered in the Credit Card Number field on the bookcashier.jsp page. It strips blanks and hyphens from the text string and formats it so that a blank space separates every four characters.

To define how the data is converted from the presentation view to the model view, the Converter implementation must implement the getAsObject(FacesContext, UIComponent, String) method from the Converter interface. Here is the implementation of this method from CreditCardConverter:

public Object getAsObject(FacesContext context,
     UIComponent component, String newValue)
         throws ConverterException {

    String convertedValue = null;
    if ( newValue == null ) {
        return newValue;
    }
    // Since this is only a String to String conversion,
     // this conversion does not throw ConverterException.
    
    convertedValue = newValue.trim();
    if ( (convertedValue.contains("-")) ||
         (convertedValue.contains(" "))) {
        char[] input = convertedValue.toCharArray();
        StringBuffer buffer = new StringBuffer(input.length);
        for ( int i = 0; i < input.length; ++i ) {
            if ( input[i] == ’-’ || input[i] == ’ ’  ) {
                continue;
            } else {
                buffer.append(input[i]);
            }
        }
        convertedValue = buffer.toString();
    }
        return convertedValue;
}

During the apply request values phase, when the components’ decode methods are processed, the JavaServer Faces implementation looks up the component’s local value in the request and calls the getAsObject method. When calling this method, the JavaServer Faces implementation passes in the current FacesContext instance, the component whose data needs conversion, and the local value as a String. The method then writes the local value to a character array, trims the hyphens and blanks, adds the rest of the characters to a String, and returns the String.

To define how the data is converted from the model view to the presentation view, the Converter implementation must implement the getAsString(FacesContext, UIComponent, Object) method from the Converter interface. Here is the implementation of this method from CreditCardConverter:

public String getAsString(FacesContext context,
     UIComponent component, Object value)
     throws ConverterException {
    
    String inputVal = null;
    if ( value == null ) {
        return null;
    }
    // value must be of the type that can be cast to a String.
    try {
        inputVal = (String)value;
    } catch (ClassCastException ce) {
        FacesMessage errMsg = MessageFactory.getMessage(
        CONVERSION_ERROR_MESSAGE_ID,
         (new Object[] { value, inputVal }));
        throw new ConverterException(errMsg.getSummary());
    }
    // insert spaces after every four characters for better
     // readability if it doesn’t already exist.
     char[] input = inputVal.toCharArray();
     StringBuffer buffer = new StringBuffer(input.length + 3);
    for ( int i = 0; i < input.length; ++i ) {
        if ( (i % 4) == 0 && i != 0) {
            if (input[i] != ’ ’ || input[i] != ’-’){
                 buffer.append(" ");
                 // if there are any "-"’s convert them to blanks.
             } else if (input[i] == ’-’) {
                buffer.append(" ");
             }
         }
         buffer.append(input[i]);
    }
     String convertedValue = buffer.toString();
    return convertedValue;
}

During the render response phase, in which the components’ encode methods are called, the JavaServer Faces implementation calls the getAsString method in order to generate the appropriate output. When the JavaServer Faces implementation calls this method, it passes in the current FacesContext, the UIComponent whose value needs to be converted, and the bean value to be converted. Because this converter does a String-to-String conversion, this method can cast the bean value to a String.

If the value cannot be converted to a String, the method throws an exception, passing the error message from the ResourceBundle, which is registered with the application. Registering Custom Error Messages explains how to register the error messages with the application. Performing Localization explains more about working with localized messages.

If the value can be converted to a String, the method reads the String to a character array and loops through the array, adding a space after every four characters.

Implementing an Event Listener

As explained in Event and Listener Model, JavaServer Faces technology supports action events and value-change events.

Action events occur when the user activates a component that implements ActionSource. These events are represented by the class javax.faces.event.ActionEvent.

Value-change events occur when the user changes the value of a component that implements EditableValueHolder. These events are represented by the class javax.faces.event.ValueChangeEvent.

One way to handle these events is to implement the appropriate listener classes. Listener classes that handle the action events in an application must implement the interface javax.faces.event.ActionListener. Similarly, listeners that handle the value-change events must implement the interface javax.faces.event.ValueChangeListener.

This section explains how to implement the two listener classes.

If you need to handle events generated by custom components, you must implement an event handler and manually queue the event on the component as well as implement an event listener. See Handling Events for Custom Components for more information.


Note –

You need not create an ActionListener implementation to handle an event that results solely in navigating to a page and does not perform any other application-specific processing. See Writing a Method to Handle Navigation for information on how to manage page navigation.


Implementing Value-Change Listeners

A ValueChangeListener implementation must include a processValueChange(ValueChangeEvent) method. This method processes the specified value-change event and is invoked by the JavaServer Faces implementation when the value-change event occurs. The ValueChangeEvent instance stores the old and the new values of the component that fired the event.

The NameChanged listener implementation is registered on the name UIInput component on the bookcashier.jsp page. This listener stores into session scope the name the user entered in the text field corresponding to the name component. When the bookreceipt.jsp page is loaded, it displays the first name inside the message:


"Thank you, {0} for purchasing your books from us."

Here is part of the NameChanged listener implementation:

...
public class NameChanged extends Object implements
     ValueChangeListener {

     public void processValueChange(ValueChangeEvent event)
        throws AbortProcessingException {
    
        if (null != event.getNewValue()) {
            FacesContext.getCurrentInstance().
                getExternalContext().getSessionMap().
                    put("name", event.getNewValue());
        }
    }
}

When the user enters the name in the text field, a value-change event is generated, and the processValueChange(ValueChangeEvent) method of the NameChanged listener implementation is invoked. This method first gets the ID of the component that fired the event from the ValueChangeEvent object. Next, it puts the value, along with an attribute name, into the session map of the FacesContext instance.

Registering a Value-Change Listener on a Component explains how to register this listener onto a component.

Implementing Action Listeners

An ActionListener implementation must include a processAction(ActionEvent) method. The processAction(ActionEvent) method processes the specified action event. The JavaServer Faces implementation invokes the processAction(ActionEvent) method when the ActionEvent occurs.

The Duke’s Bookstore application does not use any ActionListener implementations. Instead, it uses method expressions from actionListener attributes to refer to backing bean methods that handle events. This section explains how to turn one of these methods into an ActionListener implementation.

The chooselocale.jsp page allows the user to select a locale for the application by clicking on one of a set of hyperlinks. When the user clicks one of the hyperlinks, an action event is generated, and the chooseLocaleFromLink(ActionEvent) method of LocaleBean is invoked. Instead of implementing a bean method to handle this event, you can create a listener implementation to handle it. To do this, you do the following:

The listener implementation would look something like this:

...
public class LocaleChangeListener extends Object implements
     ActionListener {

    private HashMap<String, Locale> locales = null;
    
     public LocaleChangeListener() {
        locales = new HashMap<String, Locale>(4);
        locales.put("NAmerica", new Locale("en", "US"));
        locales.put("SAmerica", new Locale("es", "MX"));
        locales.put("Germany", new Locale("de", "DE"));
        locales.put("France", new Locale("fr", "FR"));
    }

    public void processAction(ActionEvent event)
        throws AbortProcessingException {
        
        String current = event.getComponent().getId();
        FacesContext context = FacesContext.getCurrentInstance();
        context.getViewRoot().setLocale((Locale)
         locales.get(current));
     }
}

Registering an Action Listener on a Component explains how to register this listener onto a component.

Creating a Custom Validator

If the standard validators don’t perform the validation checking you need, you can easily create a custom validator to validate user input. As explained in Validation Model, there are two ways to implement validation code:

Writing a Method to Perform Validation explains how to implement a backing bean method to perform validation. The rest of this section explains how to implement the Validator interface.

If you choose to implement the Validator interface and you want to allow the page author to configure the validator’s attributes from the page, you also must create a custom tag for registering the validator on a component.

If you prefer to configure the attributes in the Validator implementation, you can forgo creating a custom tag and instead let the page author register the validator on a component using the validator tag, as described in Using a Custom Validator.

You can also create a backing bean property that accepts and returns the Validator implementation you create as described in Writing Properties Bound to Converters, Listeners, or Validators. The page author can use the validator tag’s binding attribute to bind the Validator implementation to the backing bean property.

Usually, you will want to display an error message when data fails validation. You need to store these error messages in resource bundle, as described in Creating a Resource Bundle.

After creating the resource bundle, you have two ways to make the messages available to the application. You can queue the error messages onto the FacesContext programmatically. Or, you can have the application architect register the error messages using the application configuration resource file, as explained in Registering Custom Error Messages.

The Duke’s Bookstore application uses a general-purpose custom validator (called tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/validators/FormatValidator.java) that validates input data against a format pattern that is specified in the custom validator tag. This validator is used with the Credit Card Number field on the bookcashier.jsp page. Here is the custom validator tag:

<bookstore:formatValidator
     formatPatterns="9999999999999999|9999 9999 9999 9999|
        9999-9999-9999-9999"/>

According to this validator, the data entered in the field must be one of the following:

The rest of this section describes how this validator is implemented and how to create a custom tag so that the page author can register the validator on a component.

Implementing the Validator Interface

A Validator implementation must contain a constructor, a set of accessor methods for any attributes on the tag, and a validate method, which overrides the validate method of the Validator interface.

The FormatValidator class also defines accessor methods for setting the formatPatterns attribute, which specifies the acceptable format patterns for input into the fields. In addition, the class overrides the validate method of the Validator interface. This method validates the input and also accesses the custom error messages to be displayed when the String is invalid.

The validate method performs the actual validation of the data. It takes the FacesContext instance, the component whose data needs to be validated, and the value that needs to be validated. A validator can validate only data of a component that implements EditableValueHolder.

Here is the validate method from FormatValidator:

public void validate(FacesContext context, UIComponent component, Object toValidate) {

    boolean valid = false;
    String value = null;
    if ((context == null) || (component == null)) {
        throw new NullPointerException();
    }
    if (!(component instanceof UIInput)) {
        return;
    }
    if ( null == formatPatternsList || null == toValidate) {
        return;
    }
    value = toValidate.toString();
    //validate the value against the list of valid patterns.
    Iterator patternIt = formatPatternsList.iterator();
    while (patternIt.hasNext()) {
        valid = isFormatValid(
            ((String)patternIt.next()), value);
        if (valid) {
            break;
        }
    }
    if ( !valid ) {
        FacesMessage errMsg =
            MessageFactory.getMessage(context,
                FORMAT_INVALID_MESSAGE_ID,
                     (new Object[] {formatPatterns}));
            throw new ValidatorException(errMsg);
    }
}

This method gets the local value of the component and converts it to a String. It then iterates over the formatPatternsList list, which is the list of acceptable patterns as specified in the formatPatterns attribute of the custom validator tag.

While iterating over the list, this method checks the pattern of the component’s local value against the patterns in the list. If the pattern of the local value does not match any pattern in the list, this method generates an error message. It then passes the message to the constructor of ValidatorException. Eventually the message is queued onto the FacesContext instance so that the message is displayed on the page during the render response phase.

The error messages are retrieved from the Application instance by MessageFactory. An application that creates its own custom messages must provide a class, such as MessageFactory, that retrieves the messages from the Application instance. When creating your own application, you can simply copy the MessageFactory class from the Duke’s Bookstore application to your application.

The getMessage(FacesContext, String, Object) method of MessageFactory takes a FacesContext, a static String that represents the key into the Properties file, and the format pattern as an Object. The key corresponds to the static message ID in the FormatValidator class:

public static final String FORMAT_INVALID_MESSAGE_ID =
     "FormatInvalid";
}

When the error message is displayed, the format pattern will be substituted for the {0} in the error message, which, in English, is


Input must match one of the following patterns {0}

JavaServer Faces applications can save the state of validators and components on either the client or the server. Specifying Where State Is Saved explains how to configure your application to save state on either the client or the server.

If your JavaServer Faces application saves state on the client (which is the default), you need to make the Validator implementation implement StateHolder as well as Validator. In addition to implementing StateHolder, the Validator implementation needs to implement the saveState(FacesContext) and restoreState(FacesContext, Object) methods of StateHolder. With these methods, the Validator implementation tells the JavaServer Faces implementation which attributes of the Validator implementation to save and restore across multiple requests.

To save a set of values, you must implement the saveState(FacesContext) method. This method is called during the render response phase, during which the state of the response is saved for processing on subsequent requests. When implementing the saveState(FacesContext) method, you need to create an array of objects and add the values of the attributes you want to save to the array. Here is the saveState(FacesContext) method from FormatValidator:

public Object saveState(FacesContext context) {
    Object values[] = new Object[2];
    values[0] = formatPatterns;
    values[1] = formatPatternsList;
    return (values);
}

To restore the state saved with the saveState(FacesContext) method in preparation for the next postback, the Validator implementation implements restoreState(FacesContext, Object). The restoreState(FacesContext, Object) method takes the FacesContext instance and an Object instance, which represents the array that is holding the state for the Validator implementation. This method sets the Validator implementation’s properties to the values saved in the Object array. Here is the restoreState(FacesContext, Object) method from FormatValidator:

public void restoreState(FacesContext context, Object state) {
     Object values[] = (Object[]) state;
    formatPatterns = (String) values[0];
    formatPatternsList = (ArrayList) values[1];
}

As part of implementing StateHolder, the custom Validator implementation must also override the isTransient and setTransient(boolean) methods of StateHolder. By default, transientValue is false, which means that the Validator implementation will have its state information saved and restored. Here are the isTransient and setTransient(boolean) methods of FormatValidator:

private boolean transientValue = false;

public boolean isTransient() {
    return (this.transientValue);
}

public void setTransient(boolean transientValue) {
    this.transientValue = transientValue;
}

Saving and Restoring State describes how a custom component must implement the saveState(FacesContext) and restoreState(FacesContext, Object) methods.

Creating a Custom Tag

If you implemented a Validator interface rather than implementing a backing bean method that performs the validation, you need to do one of the following:

To create a custom tag, you need to do two things:

Using a Custom Validator explains how to use the custom validator tag on the page.

Writing the Tag Handler

The tag handler associated with a custom validator tag must extend the ValidatorELTag class. This class is the base class for all custom tag handlers that create Validator instances and register them on UI components. The FormatValidatorTag class registers the FormatValidator instance onto the component.

The FormatValidatorTag tag handler class does the following:

The formatPatterns attribute of the formatValidator tag supports literals and value expressions. Therefore, the accessor method for this attribute in the FormatValidatorTag class must accept and return an instance of ValueExpression:

protected ValueExpression formatPatterns = null;

public void setFormatPatterns(ValueExpression fmtPatterns){
    formatPatterns = fmtPatterns;
}

Finally, the createValidator method creates an instance of FormatValidator, extracts the value from the formatPatterns attribute’s value expression and sets the formatPatterns property of FormatValidator to this value:

the formatPatterns property of FormatValidator to this value:

protected Validator createValidator() throws JspException {
    FacesContext facesContext =
         FacesContext.getCurrentInstance();
    FormatValidator result = null;
    if(validatorID != null){
        result = (FormatValidator) facesContext.getApplication()
            .createValidator(validatorID);
    }
    String patterns = null;
    if (formatPatterns != null) {
        if (!formatPatterns.isLiteralText()) {
            patterns = (String)
             formatPatterns.getValue(facesContext.getELContext());
        } else {
            patterns = formatPatterns.getExpressionString();
        }

Writing the Tag Library Descriptor

To define a tag, you declare it in a tag library descriptor (TLD), which is an XML document that describes a tag library. A TLD contains information about a library and each tag contained in it. See Tag Library Descriptors for more information about TLDs.

The custom validator tag is defined in bookstore.tld, located in the tut-install/javaeetutorial5/examples/web/bookstore6/web/WEB-INF/ directory. It contains a tag definition for formatValidator:

<tag>
    <name>formatValidator</name>
    ...
    <tag-class>
        com.sun.bookstore6.taglib.FormatValidatorTag</tag-class>
    <attribute>
        <name>formatPatterns</name>
        <required>true</required>
        <deferred-value>
            <type>String</type>
        </deferred-value>
    </attribute>
</tag>

The name element defines the name of the tag as it must be used in the page. The tag-class element defines the tag handler class. The attribute elements define each of the tag’s attributes. The formatPatterns attribute is the only attribute that the tag supports. The deferred-value element indicates that the formatPatterns attribute accepts deferred value expressions. The type element says that the expression resolves to a property of type String.

Writing Backing Bean Methods

Methods of a backing bean perform application-specific functions for components on the page. These functions include performing validation on the component’s value, handling action events, handling value-change events, and performing processing associated with navigation.

By using a backing bean to perform these functions, you eliminate the need to implement the Validator interface to handle the validation or the Listener interface to handle events. Also, by using a backing bean instead of a Validator implementation to perform validation, you eliminate the need to create a custom tag for the Validator implementation. Creating a Custom ValidatorCreating a Custom Validator describes implementing a custom validator. Implementing an Event Listener describes implementing a listener class.

In general, it’s good practice to include these methods in the same backing bean that defines the properties for the components referencing these methods. The reason is that the methods might need to access the component’s data to determine how to handle the event or to perform the validation associated with the component.

This section describes the requirements for writing the backing bean methods.

Writing a Method to Handle Navigation

A backing bean method that handles navigation processing, called an action method, must be a public method that takes no parameters and returns an Object, which is the logical outcome that the navigation system uses to determine what page to display next. This method is referenced using the component tag’s action attribute.

The following action method in CashierBean is invoked when a user clicks the Submit button on the bookcashier.jsp page. If the user has ordered more than $100 (or 100 euros) worth of books, this method sets the rendered properties of the fanClub and specialOffer components to true. This causes them to be displayed on the page the next time the page is rendered.

After setting the components’ rendered properties to true, this method returns the logical outcome null. This causes the JavaServer Faces implementation to re-render the bookcashier.jsp page without creating a new view of the page. If this method were to return purchase (which is the logical outcome to use to advance to bookcashier.jsp, as defined by the application configuration resource file), the bookcashier.jsp page would re-render without retaining the customer’s input. In this case, you want to re-render the page without clearing the data.

If the user does not purchase more than $100 (or 100 euros) worth of books or the thankYou component has already been rendered, the method returns receipt.

The default NavigationHandler provided by the JavaServer Faces implementation matches the logical outcome, as well as the starting page (bookcashier.jsp) against the navigation rules in the application configuration resource file to determine which page to access next. In this case, the JavaServer Faces implementation loads the bookreceipt.jsp page after this method returns.

public String submit() {
    ...
    if(cart().getTotal() > 100.00 &&
         !specialOffer.isRendered())
    {
        specialOfferText.setRendered(true);
        specialOffer.setRendered(true);
        return null;
    } else if (specialOffer.isRendered() &&
         !thankYou.isRendered()){
        thankYou.setRendered(true);
        return null;
    } else {
        clear();
        return ("receipt");
    }
}

Typically, an action method will return a String outcome, as shown in the previous example. Alternatively, you can define an Enum class that encapsulates all possible outcome strings and then make an action method return an enum constant, which represents a particular String outcome defined by the Enum class. In this case, the value returned by a call to the Enum class’s toString method must match that specified by the from-outcome element in the appropriate navigation rule configuration defined in the application configuration file.

The Duke’s Bank example uses an Enum class to encapsulate all logical outcomes:

public enum Navigation  {
    main, accountHist, accountList, atm, atmAck, transferFunds,
     transferAck, error
}

When an action method returns an outcome, it uses the dot notation to reference the outcome from the Enum class:

public Object submit(){
    ...
    return Navigation.accountHist;
}

Referencing a Method That Performs Navigation explains how a component tag references this method. Binding a Component Instance to a Bean Property discusses how the page author can bind these components to bean properties. Writing Properties Bound to Component Instances discusses how to write the bean properties to which the components are bound. Configuring Navigation Rules provides more information on configuring navigation rules.

Writing a Method to Handle an Action Event

A backing bean method that handles an action event must be a public method that accepts an action event and returns void. This method is referenced using the component tag’s actionListener attribute. Only components that implement ActionSource can refer to this method.

The following backing bean method from LocaleBean of the Duke’s Bookstore application processes the event of a user clicking one of the hyperlinks on the chooselocale.jsp page:

public void chooseLocaleFromLink(ActionEvent event) {
    String current = event.getComponent().getId();
    FacesContext context = FacesContext.getCurrentInstance();
    context.getViewRoot().setLocale((Locale)
        locales.get(current));
}

This method gets the component that generated the event from the event object. Then it gets the component’s ID. The ID indicates a region of the world. The method matches the ID against a HashMap object that contains the locales available for the application. Finally, it sets the locale using the selected value from the HashMap object.

Referencing a Method That Handles an Action Event explains how a component tag references this method.

Writing a Method to Perform Validation

Rather than implement the Validator interface to perform validation for a component, you can include a method in a backing bean to take care of validating input for the component.

A backing bean method that performs validation must accept a FacesContext, the component whose data must be validated, and the data to be validated, just as the validate method of the Validator interface does. A component refers to the backing bean method by using its validator attribute. Only values of UIInput components or values of components that extend UIInput can be validated.

Here is the backing bean method of CheckoutFormBean from the Coffee Break example:

public void validateEmail(FacesContext context,
     UIComponent toValidate, Object value) {
    
    String message = "";
    String email = (String) value;
    if (email.contains(’@’)) {
        ((UIInput)toValidate).setValid(false);
        message = CoffeeBreakBean.loadErrorMessage(context,
             CoffeeBreakBean.CB_RESOURCE_BUNDLE_NAME,
            "EMailError");
        context.addMessage(toValidate.getClientId(context),
            new FacesMessage(message));
    }
}

The validateEmail method first gets the local value of the component. It then checks whether the @ character is contained in the value. If it isn’t, the method sets the component’s valid property to false. The method then loads the error message and queues it onto the FacesContext instance, associating the message with the component ID.

See Referencing a Method That Performs Validation for information on how a component tag references this method.

Writing a Method to Handle a Value-Change Event

A backing bean that handles a value-change event must be a public method that accepts a value-change event and returns void. This method is referenced using the component’s valueChangeListener attribute.

The Duke’s Bookstore application does not have any backing bean methods that handle value-change events. It does have a ValueChangeListener implementation, as explained in the Implementing Value-Change Listeners section.

For illustration, this section explains how to write a backing bean method that can replace the ValueChangeListener implementation.

As explained in Registering a Value-Change Listener on a Component, the name component of the bookcashier.jsp page has a ValueChangeListener instance registered on it. This ValueChangeListener instance handles the event of entering a value in the field corresponding to the component. When the user enters a value, a value-change event is generated, and the processValueChange(ValueChangeEvent) method of the ValueChangeListener class is invoked.

Instead of implementing ValueChangeListener, you can write a backing bean method to handle this event. To do this, you move the processValueChange(ValueChangeEvent) method from the ValueChangeListener class, called NameChanged, to your backing bean.

Here is the backing bean method that processes the event of entering a value in the name field on the bookcashier.jsp page:

public void processValueChange(ValueChangeEvent event)
    throws AbortProcessingException {
    if (null != event.getNewValue()) {
        FacesContext.getCurrentInstance().
            getExternalContext().getSessionMap().
                put("name", event.getNewValue());
    }
}    

The page author can make this method handle the ValueChangeEvent object emitted by a UIInput component by referencing this method from the component tag’s valueChangeListener attribute. See Referencing a Method That Handles a Value-change Event for more information.

Chapter 13 Creating Custom UI Components

JavaServer Faces technology offers a basic set of standard, reusable UI components that enable page authors and application developers to quickly and easily construct UIs for web applications. But often an application requires a component that has additional functionality or requires a completely new component. JavaServer Faces technology allows a component writer to extend the standard components to enhance their functionality or create custom components.

In addition to extending the functionality of standard components, a component writer might want to give a page author the ability to change the appearance of the component on the page. Or the component writer might want to render a component to a different client. Enabled by the flexible JavaServer Faces architecture, a component writer can separate the definition of the component behavior from its appearance by delegating the rendering of the component to a separate renderer. In this way, a component writer can define the behavior of a custom component once but create multiple renderers, each of which defines a different way to render the component to a particular kind of client device.

As well as providing a means to easily create custom components and renderers, the JavaServer Faces design also makes it easy to reference them from the page through JSP custom tag library technology.

This chapter uses the image map custom component from the Duke’s Bookstore application (see The Example JavaServer Faces Application) to explain how a component writer can create simple custom components, custom renderers, and associated custom tags, and take care of all the other details associated with using the components and renderers in an application.

If you are creating components intended for use with an IDE such as Sun Java Studio Creator, you might need to take some extra steps beyond what this chapter details to get your components to work with the IDE. For information on how to make your custom components work with Sun Java Studio Creator, see the article Writing Custom Components for Java Studio Creator Part 1: Developing a Component Library, located at http://developers.sun.com/prodtech/javatools/jscreator/reference/techart/2/writing_custom_components.html.

Determining Whether You Need a Custom Component or Renderer

The JavaServer Faces implementation supports a rich set of components and associated renderers, which are enough for most simple applications. This section helps you decide whether you need a custom component or custom renderer or instead can use a standard component and renderer.

When to Use a Custom Component

A component class defines the state and behavior of a UI component. This behavior includes converting the value of a component to the appropriate markup, queuing events on components, performing validation, and other functionality.

You need to create a custom component in these situations:

You do not need to create a custom component in these cases:

When to Use a Custom Renderer

If you are creating a custom component, you need to ensure, among other things, that your component class performs these operations:

The JavaServer Faces specification supports two programming models for handling encoding and decoding:

By delegating the operations to the renderer, you have the option of associating your custom component with different renderers so that you can represent the component in different ways on the page. If you don’t plan to render a particular component in different ways, it’s simpler to let the component class handle the rendering.

If you aren’t sure whether you will need the flexibility offered by separate renderers but you want to use the simpler direct-implementation approach, you can actually use both models. Your component class can include some default rendering code, but it can delegate rendering to a renderer if there is one.

Component, Renderer, and Tag Combinations

When you create a custom component, you will usually create a custom renderer to go with it. You will also need a custom tag to associate the component with the renderer and to reference the component from the page.

In rare situations, however, you might use a custom renderer with a standard component rather than a custom component. Or you might use a custom tag without a renderer or a component. This section gives examples of these situations and summarizes what’s required for a custom component, renderer, and tag.

You would use a custom renderer without a custom component if you wanted to add some client-side validation on a standard component. You would implement the validation code with a client-side scripting language, such as JavaScript, and then render the JavaScript with the custom renderer. In this situation, you need a custom tag to go with the renderer so that its tag handler can register the renderer on the standard component.

Custom components as well as custom renderers need custom tags associated with them. However, you can have a custom tag without a custom renderer or custom component. For example, suppose that you need to create a custom validator that requires extra attributes on the validator tag. In this case, the custom tag corresponds to a custom validator and not to a custom component or custom renderer. In any case, you still need to associate the custom tag with a server-side object.

Table 13–1 summarizes what you must or can associate with a custom component, custom renderer, or custom tag.

Table 13–1 Requirements for Custom Components, Custom Renderers, and Custom Tags

Custom Item 

Must Have 

Can Have 

Custom component 

Custom tag 

Custom renderer or standard renderer 

Custom renderer 

Custom tag 

Custom component or standard component 

Custom JavaServer Faces tag 

Some server-side object, like a component, a custom renderer, or custom validator 

Custom component or standard component associated with a custom renderer 

Understanding the Image Map Example

Duke’s Bookstore includes a custom image map component on the chooselocale.jsp page. This image map displays a map of the world. When the user clicks one of a particular set of regions in the map, the application sets the locale on the UIViewRoot component of the current FacesContext to the language spoken in the selected region. The hotspots of the map are the United States, Spanish-speaking Central and South America, France, and Germany.

Why Use JavaServer Faces Technology to Implement an Image Map?

JavaServer Faces technology is an ideal framework to use for implementing this kind of image map because it can perform the work that must be done on the server without requiring you to create a server-side image map.

In general, client-side image maps are preferred over server-side image maps for several reasons. One reason is that the client-side image map allows the browser to provide immediate feedback when a user positions the mouse over a hotspot. Another reason is that client-side image maps perform better because they don’t require round-trips to the server. However, in some situations, your image map might need to access the server to retrieve data or to change the appearance of non-form controls, tasks that a client-side image map cannot do.

Because the image map custom component uses JavaServer Faces technology, it has the best of both styles of image maps: It can handle the parts of the application that need to be performed on the server, while allowing the other parts of the application to be performed on the client side.

Understanding the Rendered HTML

Here is an abbreviated version of the form part of the HTML page that the application needs to render:

<form id="_id38" method="post"
     action="/bookstore6/chooselocale.faces" ... >
    ...
    <img id="_id38:mapImage"
         src="/bookstore6/template/world.jpg"
         alt="Choose Your Preferred Locale from the Map"
         usemap="#worldMap" />
         <map name="worldMap">
            <area alt="NAmerica"                        
                 coords="53,109,1,110,2,167,,..."
                shape="poly"
                 onmouseout=
                    "document.forms[0][’_id_id38:mapImage’].src=
                        ’/bookstore6/template/world.jpg’"
                onmouseover=
                    "document.forms[0][’_id_id38:mapImage’].src=
                        ’/bookstore6/template/world_namer.jpg’"
                onclick=
                    "document.forms[0][’worldMap_current’].
                        value=
                            ’NAmerica’;document.forms[0].submit()"
            />
            <input type="hidden" name="worldMap_current">
        </map>
        ...
</form>

The img tag associates an image (world.jpg) with the image map referenced in the usemap attribute value.

The map tag specifies the image map and contains a set of area tags.

Each area tag specifies a region of the image map. The onmouseover, onmouseout, and onclick attributes define which JavaScript code is executed when these events occur. When the user moves the mouse over a region, the onmouseover function associated with the region displays the map with that region highlighted. When the user moves the mouse out of a region, the onmouseout function redisplays the original image. If the user clicks on a region, the onclick function sets the value of the input tag to the ID of the selected area and submits the page.

The input tag represents a hidden control that stores the value of the currently selected area between client-server exchanges so that the server-side component classes can retrieve the value.

The server-side objects retrieve the value of worldMap_current and set the locale in the FacesContext instance according to the region that was selected.

Understanding the JSP Page

Here is an abbreviated form of the JSP page that the image map component will use to generate the HTML page shown in the preceding section:

<f:view>
    <f:loadBundle basename="messages.BookstoreMessages"
         var="bundle"/>
    <h:form>
        ...
        <h:graphicImage id="mapImage" url="/template/world.jpg"
             alt="#{bundle.ChooseLocale}"
            usemap="#worldMap" />
         <bookstore:map id="worldMap" current="NAmericas"
             immediate="true" action="bookstore"
            actionListener="#{localeBean.chooseLocaleFromMap}">
            <bookstore:area id="NAmerica" value="#{NA}"
                 onmouseover="/template/world_namer.jpg"
                 onmouseout="/template/world.jpg"
                 targetImage="mapImage" />
            <bookstore:area id="SAmerica" value="#{SA}"
                onmouseover="/template/world_samer.jpg"
                onmouseout="/template/world.jpg"
                 targetImage="mapImage" />
            <bookstore:area id="Germany" value="#{gerA}"
                onmouseover="/template/world_germany.jpg"
                 onmouseout="/template/world.jpg"
                 targetImage="mapImage" />
            <bookstore:area id="France" value="#{fraA}"
                 onmouseover="/template/world_france.jpg"
                onmouseout="/template/world.jpg"
                 targetImage="mapImage" />
            </bookstore:map>
        ...
    </h:form>
</f:view>

The alt attribute of graphicImage maps to the localized string "Choose Your Locale from the Map".

The actionListener attribute of the map tag points at a method in LocaleBean that accepts an action event. This method changes the locale according to the area selected from the image map. The way this event is handled is explained more in Handling Events for Custom Components.

The action attribute specifies a logical outcome String, which is matched against the navigation rules in the application configuration resource file. For more information on navigation, see the section Configuring Navigation Rules.

The immediate attribute of the map tag is set to true, which indicates that the default ActionListener implementation should execute during the apply request values phase of the request-processing life cycle, instead of waiting for the invoke application phase. Because the request resulting from clicking the map does not require any validation, data conversion, or server-side object updates, it makes sense to skip directly to the invoke application phase.

The current attribute of the map tag is set to the default area, which is NAmerica.

Notice that the area tags do not contain any of the JavaScript, coordinate, or shape data that is displayed on the HTML page. The JavaScript is generated by the AreaRenderer class. The onmouseover and onmouseout attribute values indicate the image to be loaded when these events occur. How the JavaScript is generated is explained more in Performing Encoding.

The coordinate, shape, and alternate text data are obtained through the value attribute, whose value refers to an attribute in application scope. The value of this attribute is a bean, which stores the coords, shape, and alt data. How these beans are stored in the application scope is explained more in the next section.

Configuring Model Data

In a JavaServer Faces application, data such as the coordinates of a hotspot of an image map is retrieved from the value attribute through a bean. However, the shape and coordinates of a hotspot should be defined together because the coordinates are interpreted differently depending on what shape the hotspot is. Because a component’s value can be bound only to one property, the value attribute cannot refer to both the shape and the coordinates.

To solve this problem, the application encapsulates all of this information in a set of ImageArea objects. These objects are initialized into application scope by the managed bean creation facility (see Backing Beans). Here is part of the managed bean declaration for the ImageArea bean corresponding to the South America hotspot:

<managed-bean>
    ...
    <managed-bean-name>SA</managed-bean-name>
    <managed-bean-class>
        components.model.ImageArea
    </managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
    <managed-property>
        <property-name>shape</property-name>
        <value>poly</value>
    </managed-property>
    <managed-property>
        <property-name>alt</property-name>
        <value>SAmerica</value>
    </managed-property>
    <managed-property>
        <property-name>coords</property-name>
        <value>89,217,95,100...</value>    
    </managed-property>
</managed-bean>

For more information on initializing managed beans with the managed bean creation facility, see the section Application Configuration Resource File.

The value attributes of the area tags refer to the beans in the application scope, as shown in this area tag from chooselocale.jsp:

<bookstore:area id="NAmerica"
         value="#{NA}"
         onmouseover="/template/world_namer.jpg"
         onmouseout="/template/world.jpg" />

To reference the ImageArea model object bean values from the component class, you implement a getValue method in the component class. This method calls super.getValue. The superclass of tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/components/AreaComponent.java, UIOutput, has a getValue method that does the work of finding the ImageArea object associated with AreaComponent. The AreaRenderer class, which needs to render the alt, shape, and coords values from the ImageArea object, calls the getValue method of AreaComponent to retrieve the ImageArea object.

ImageArea iarea = (ImageArea) area.getValue();

ImageArea is only a simple bean, so you can access the shape, coordinates, and alternative text values by calling the appropriate accessor methods of ImageArea. Creating the Renderer Class explains how to do this in the AreaRenderer class.

Summary of the Application Classes

Table 13–2 summarizes all the classes needed to implement the image map component.

Table 13–2 Image Map Classes

Class 

Function 

AreaSelectedEvent

The ActionEvent indicating that an AreaComponent from the MapComponent has been selected.

AreaTag

The tag handler that implements the area custom tag.

MapTag

The tag handler that implements the map custom tag.

AreaComponent

The class that defines AreaComponent, which corresponds to the area custom tag.

MapComponent

The class that defines MapComponent, which corresponds to the map custom tag.

AreaRenderer

This Renderer performs the delegated rendering for AreaComponent.

ImageArea

The bean that stores the shape and coordinates of the hotspots. 

LocaleBean

The backing bean for the chooselocale.jsp page.

The Duke's Bookstore source directory, called bookstore-dir, is tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/. The event and listener classes are located in bookstore-dir/listeners/. The tag handlers are located in bookstore-dir/taglib/. The component classes are located in bookstore-dir/components/. The renderer classes are located in bookstore-dir/renderers/. ImageArea is located in bookstore-dir/model/. LocaleBean is located in bookstore-dir/backing/.

Steps for Creating a Custom Component

    You can apply the following steps while developing your own custom component.

  1. Create a custom component class that does the following:

    1. Overrides the getFamily method to return the component family, which is used to look up renderers that can render the component.

    2. Includes the rendering code or delegates it to a renderer (explained in step 2).

    3. Enables component attributes to accept expressions.

    4. Queues an event on the component if the component generates events.

    5. Saves and restores the component state.

  2. Delegate rendering to a renderer if your component does not handle the rendering. To do this:

    1. Create a custom renderer class by extending javax.faces.render.Renderer.

    2. Register the renderer to a render kit.

    3. Identify the renderer type in the component tag handler.

  3. Register the component.

  4. Create an event handler if your component generates events.

  5. Write a tag handler class that extends javax.faces.webapp.UIComponentELTag. In this class, you need a getRendererType method, which returns the type of your custom renderer if you are using one (explained in step 2); a getComponentType method, which returns the type of the custom component; and a setProperties method, with which you set all the new attributes of your component.

  6. Create a tag library descriptor (TLD) that defines the custom tag.

The application architect does the work of registering the custom component and the renderer. See Registering a Custom Converter and Registering a Custom Renderer with a Render Kit for more information. Using a Custom Component discusses how to use the custom component in a JavaServer Faces page.

Creating Custom Component Classes

As explained in When to Use a Custom Component, a component class defines the state and behavior of a UI component. The state information includes the component’s type, identifier, and local value. The behavior defined by the component class includes the following:

The UIComponentBase class defines the default behavior of a component class. All the classes representing the standard components extend from UIComponentBase. These classes add their own behavior definitions, as your custom component class will do.

Your custom component class must either extend UIComponentBase directly or extend a class representing one of the standard components. These classes are located in the javax.faces.component package and their names begin with UI.

If your custom component serves the same purpose as a standard component, you should extend that standard component rather than directly extend UIComponentBase. For example, suppose you want to create an editable menu component. It makes sense to have this component extend UISelectOne rather than UIComponentBase because you can reuse the behavior already defined in UISelectOne. The only new functionality you need to define is to make the menu editable.

Whether you decide to have your component extend UIComponentBase or a standard component, you might also want your component to implement one or more of these behavioral interfaces:

If your component extends UIComponentBase, it automatically implements only StateHolder. Because all components directly or indirectly extend UIComponentBase, they all implement StateHolder.

If your component extends one of the other standard components, it might also implement other behavioral interfaces in addition to StateHolder. If your component extends UICommand, it automatically implements ActionSource2. If your component extends UIOutput or one of the component classes that extend UIOutput, it automatically implements ValueHolder. If your component extends UIInput, it automatically implements EditableValueHolder and ValueHolder. See the JavaServer Faces API Javadoc to find out what the other component classes implement.

You can also make your component explicitly implement a behavioral interface that it doesn’t already by virtue of extending a particular standard component. For example, if you have a component that extends UIInput and you want it to fire action events, you must make it explicitly implement ActionSource2 because a UIInput component doesn’t automatically implement this interface.

The image map example has two component classes: AreaComponent and MapComponent. The MapComponent class extends UICommand and therefore implements ActionSource2, which means it can fire action events when a user clicks on the map. The AreaComponent class extends the standard component UIOutput.

The MapComponent class represents the component corresponding to the map tag:

<bookstore:map id="worldMap" current="NAmericas"
     immediate="true"
     action="bookstore"
    actionListener="#{localeBean.chooseLocaleFromMap}">

The AreaComponent class represents the component corresponding to the area tag:

<bookstore:area id="NAmerica" value="#{NA}"
    onmouseover="/template/world_namer.jpg"
     onmouseout="/template/world.jpg"
     targetImage="mapImage" />

MapComponent has one or more AreaComponent instances as children. Its behavior consists of the following

The rendering of the map and input tags is performed by tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/renderers/MapRenderer.java, but MapComponent delegates this rendering to MapRenderer.

AreaComponent is bound to a bean that stores the shape and coordinates of the region of the image map. You’ll see how all this data is accessed through the value expression in Creating the Renderer Class. The behavior of AreaComponent consists of the following

Although these tasks are actually performed by AreaRenderer, AreaComponent must delegate the tasks to AreaRenderer. See Delegating Rendering to a Renderer for more information.

The rest of this section describes the tasks that MapComponent performs as well as the encoding and decoding that it delegates to MapRenderer. Handling Events for Custom Components details how MapComponent handles events.

Specifying the Component Family

If your custom component class delegates rendering, it needs to override the getFamily method of UIComponent to return the identifier of a component family, which is used to refer to a component or set of components that can be rendered by a renderer or set of renderers. The component family is used along with the renderer type to look up renderers that can render the component.

Because MapComponent delegates its rendering, it overrides the getFamily method:

public String getFamily() {
    return ("Map");
}

The component family identifier, Map, must match that defined by the component-family elements included in the component and renderer configurations in the application configuration resource file. Registering a Custom Renderer with a Render Kit explains how to define the component family in the renderer configuration. Registering a Custom Component explains how to define the component family in the component configuration.

Performing Encoding

During the render response phase, the JavaServer Faces implementation processes the encoding methods of all components and their associated renderers in the view. The encoding methods convert the current local value of the component into the corresponding markup that represents it in the response.

The UIComponentBase class defines a set of methods for rendering markup: encodeBegin, encodeChildren, and encodeEnd. If the component has child components, you might need to use more than one of these methods to render the component; otherwise, all rendering should be done in encodeEnd.

Because MapComponent is a parent component of AreaComponent, the area tags must be rendered after the beginning map tag and before the ending map tag. To accomplish this, the MapRenderer class renders the beginning map tag in encodeBegin and the rest of the map tag in encodeEnd.

The JavaServer Faces implementation automatically invokes the encodeEnd method of AreaComponent’s renderer after it invokes MapRenderer’s encodeBegin method and before it invokes MapRenderer’s encodeEnd method. If a component needs to perform the rendering for its children, it does this in the encodeChildren method.

Here are the encodeBegin and encodeEnd methods of MapRenderer:

public void encodeBegin(FacesContext context,
     UIComponent component) throws IOException {
    if ((context == null)|| (component == null)){
        throw new NullPointerException();
    }
    MapComponent map = (MapComponent) component;
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("map", map);
    writer.writeAttribute("name", map.getId(),"id");
}
public void encodeEnd(FacesContext context) throws IOException {
    if ((context == null) || (component == null)){
        throw new NullPointerException();
    }
    MapComponent map = (MapComponent) component;
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("input", map);
    writer.writeAttribute("type", "hidden", null);
    writer.writeAttribute("name",
         getName(context,map), "clientId");(
    writer.endElement("input");
    writer.endElement("map");
}

Notice that encodeBegin renders only the beginning map tag. The encodeEnd method renders the input tag and the ending map tag.

The encoding methods accept a UIComponent argument and a FacesContext argument. The FacesContext instance contains all the information associated with the current request. The UIComponent argument is the component that needs to be rendered.

The rest of the method renders the markup to the ResponseWriter instance, which writes out the markup to the current response. This basically involves passing the HTML tag names and attribute names to the ResponseWriter instance as strings, retrieving the values of the component attributes, and passing these values to the ResponseWriter instance.

The startElement method takes a String (the name of the tag) and the component to which the tag corresponds (in this case, map). (Passing this information to the ResponseWriter instance helps design-time tools know which portions of the generated markup are related to which components.)

After calling startElement, you can call writeAttribute to render the tag’s attributes. The writeAttribute method takes the name of the attribute, its value, and the name of a property or attribute of the containing component corresponding to the attribute. The last parameter can be null, and it won’t be rendered.

The name attribute value of the map tag is retrieved using the getId method of UIComponent, which returns the component’s unique identifier. The name attribute value of the input tag is retrieved using the getName(FacesContext, UIComponent) method of MapRenderer.

If you want your component to perform its own rendering but delegate to a renderer if there is one, include the following lines in the encoding method to check whether there is a renderer associated with this component.

if (getRendererType() != null) {
    super.encodeEnd(context);
    return;
}

If there is a renderer available, this method invokes the superclass’s encodeEnd method, which does the work of finding the renderer. The MapComponent class delegates all rendering to MapRenderer, so it does not need to check for available renderers.

In some custom component classes that extend standard components, you might need to implement other methods in addition to encodeEnd. For example, if you need to retrieve the component’s value from the request parameters, you must also implement the decode method.

Performing Decoding

During the apply request values phase, the JavaServer Faces implementation processes the decode methods of all components in the tree. The decode method extracts a component’s local value from incoming request parameters and uses a Converter class to convert the value to a type that is acceptable to the component class.

A custom component class or its renderer must implement the decode method only if it must retrieve the local value or if it needs to queue events. The MapRenderer instance retrieves the local value of the hidden input field and sets the current attribute to this value by using its decode method. The setCurrent method of MapComponent queues the event by calling queueEvent, passing in the AreaSelectedEvent instance generated by MapComponent.

Here is the decode method of MapRenderer:

public void decode(FacesContext context, UIComponent component) {
    if ((context == null) || (component == null)) {
        throw new NullPointerException();
    }
    MapComponent map = (MapComponent) component;
    String key = getName(context, map);
    String value = (String)context.getExternalContext().
        getRequestParameterMap().get(key);
    if (value != null)
         map.setCurrent(value);
    }
}

The decode method first gets the name of the hidden input field by calling getName(FacesContext, UIComponent). It then uses that name as the key to the request parameter map to retrieve the current value of the input field. This value represents the currently selected area. Finally, it sets the value of the MapComponent class’s current attribute to the value of the input field.

Enabling Component Properties to Accept Expressions

Nearly all the attributes of the standard JavaServer Faces tags can accept expressions, whether they are value expressions or method expressions. It is recommended that you also enable your component attributes to accept expressions because this is what page authors expect, and it gives page authors much more flexibility when authoring their pages.

Creating the Component Tag Handler describes how MapTag, the tag handler for the map tag, sets the component’s values when processing the tag. It does this by providing the following:

To retrieve the expression objects that setProperties stored, the component class must implement a method for each property that accesses the appropriate expression object, extracts the value from it and returns the value.

Because MapComponent extends UICommand, the UICommand class already does the work of getting the ValueExpression and MethodExpression instances associated with each of the attributes that it supports.

However, if you have a custom component class that extends UIComponentBase, you will need to implement the methods that get the ValueExpression and MethodExpression instances associated with those attributes that are enabled to accept expressions. For example, if MapComponent extended UIComponentBase instead of UICommand, it would need to include a method that gets the ValueExpression instance for the immediate attribute:

public boolean isImmediate() {
    if (this.immediateSet) {
        return (this.immediate);
    }
    ValueExpression ve = getValueExpression("immediate");
    if (ve != null) {
        Boolean value = (Boolean) ve.getValue(
            getFacesContext().getELContext());
        return (value.booleanValue());
    } else {
        return (this.immediate);
    }
}

The properties corresponding to the component attributes that accept method expressions must accept and return a MethodExpression object. For example, if MapComponent extended UIComponentBase instead of UICommand, it would need to provide an action property that returns and accepts a MethodExpression object:

public MethodExpression getAction() {
    return (this.action);
}
public void setAction(MethodExpression action) {
    this.action = action;
}

Saving and Restoring State

Because component classes implement StateHolder, they must implement the saveState(FacesContext) and restoreState(FacesContext, Object) methods to help the JavaServer Faces implementation save and restore the state of components across multiple requests.

To save a set of values, you must implement the saveState(FacesContext) method. This method is called during the render response phase, during which the state of the response is saved for processing on subsequent requests. Here is the method from MapComponent:

public Object saveState(FacesContext context) {
    Object values[] = new Object[2];
    values[0] = super.saveState(context);
    values[1] = current;
    return (values);
}

This method initializes an array, which will hold the saved state. It next saves all of the state associated with MapComponent.

A component that implements StateHolder must also provide an implementation for restoreState(FacesContext, Object), which restores the state of the component to that saved with the saveState(FacesContext) method. The restoreState(FacesContext, Object) method is called during the restore view phase, during which the JavaServer Faces implementation checks whether there is any state that was saved during the last render response phase and needs to be restored in preparation for the next postback. Here is the restoreState(FacesContext, Object) method from MapComponent:

public void restoreState(FacesContext context, Object state) {
    Object values[] = (Object[]) state;
     super.restoreState(context, values[0]);
    current = (String) values[1];
}

This method takes a FacesContext and an Object instance, representing the array that is holding the state for the component. This method sets the component’s properties to the values saved in the Object array.

When you implement these methods in your component class, be sure to specify in the deployment descriptor where you want the state to be saved: either client or server. If state is saved on the client, the state of the entire view is rendered to a hidden field on the page.

To specify where state is saved for a particular web application, you need to set the javax.faces.STATE_SAVING_METHOD context parameter to either client or server in your application’s deployment descriptor. See Saving and Restoring State for more information on specifying where state is saved in the deployment descriptor.

Delegating Rendering to a Renderer

Both MapComponent and AreaComponent delegate all of their rendering to a separate renderer. The section Performing Encoding explains how MapRenderer performs the encoding for MapComponent. This section explains in detail the process of delegating rendering to a renderer using AreaRenderer, which performs the rendering for AreaComponent.

To delegate rendering, you perform these tasks:

Creating the Renderer Class

When delegating rendering to a renderer, you can delegate all encoding and decoding to the renderer, or you can choose to do part of it in the component class. The AreaComponent class delegates encoding to the AreaRenderer class.

To perform the rendering for AreaComponent, AreaRenderer must implement an encodeEnd method. The encodeEnd method of AreaRenderer retrieves the shape, coordinates, and alternative text values stored in the ImageArea bean that is bound to AreaComponent. Suppose that the area tag currently being rendered has a value attribute value of "fraA". The following line from encodeEnd gets the value of the attribute "fraA" from the FacesContext instance.

ImageArea ia = (ImageArea)area.getValue();

The attribute value is the ImageArea bean instance, which contains the shape, coords, and alt values associated with the fraA AreaComponent instance. Configuring Model Data describes how the application stores these values.

After retrieving the ImageArea object, it renders the values for shape, coords, and alt by simply calling the associated accessor methods and passing the returned values to the ResponseWriter instance, as shown by these lines of code, which write out the shape and coordinates:

writer.startElement("area", area);
writer.writeAttribute("alt", iarea.getAlt(), "alt");
writer.writeAttribute("coords", iarea.getCoords(), "coords");
writer.writeAttribute("shape", iarea.getShape(), "shape");

The encodeEnd method also renders the JavaScript for the onmouseout, onmouseover, and onclick attributes. The page author need only provide the path to the images that are to be loaded during an onmouseover or onmouseout action:

<bookstore:area id="France" value="#{fraA}"
     onmouseover="/template/world_france.jpg"
     onmouseout="/template/world.jpg" targetImage="mapImage" />

The AreaRenderer class takes care of generating the JavaScript for these actions, as shown in the following code from encodeEnd. The JavaScript that AreaRenderer generates for the onclick action sets the value of the hidden field to the value of the current area’s component ID and submits the page.

sb = new StringBuffer("document.forms[0][’").
    append(targetImageId).append("’].src=’");
sb.append(getURI(context,
     (String) area.getAttributes().get("onmouseout")));
sb.append("’");
writer.writeAttribute("onmouseout", sb.toString(),
     "onmouseout");
sb = new StringBuffer("document.forms[0][’").
    append(targetImageId).append("’].src=’");
sb.append(getURI(context,
     (String) area.getAttributes().get("onmouseover")));
sb.append("’");
writer.writeAttribute("onmouseover", sb.toString(),
     "onmouseover");
sb = new StringBuffer("document.forms[0][’");
sb.append(getName(context, area));
sb.append("’].value=’");
sb.append(iarea.getAlt());
sb.append("’; document.forms[0].submit()");
writer.writeAttribute("onclick", sb.toString(), "value");
writer.endElement("area");

By submitting the page, this code causes the JavaServer Faces life cycle to return back to the restore view phase. This phase saves any state information, including the value of the hidden field, so that a new request component tree is constructed. This value is retrieved by the decode method of the MapComponent class. This decode method is called by the JavaServer Faces implementation during the apply request values phase, which follows the restore view phase.

In addition to the encodeEnd method, AreaRenderer contains an empty constructor. This is used to create an instance of AreaRenderer so that it can be added to the render kit.

Identifying the Renderer Type

During the render response phase, the JavaServer Faces implementation calls the getRendererType method of the component’s tag handler to determine which renderer to invoke, if there is one.

The getRendererType method of AreaTag must return the type associated with AreaRenderer. You identify this type when you register AreaRenderer with the render kit, as described in Registering a Custom Renderer with a Render Kit. Here is the getRendererType method from the AreaTag class:

public String getRendererType() { return ("DemoArea");}

Creating the Component Tag Handler explains more about the getRendererType method.

Handling Events for Custom Components

As explained in Implementing an Event Listener, events are automatically queued on standard components that fire events. A custom component, on the other hand, must manually queue events from its decode method if it fires events.

Performing Decoding explains how to queue an event on MapComponent using its decode method. This section explains how to write the class representing the event of clicking on the map and how to write the method that processes this event.

As explained in Understanding the JSP Page, the actionListener attribute of the map tag points to the chooseLocaleFromMap method of the bean LocaleBean. This method processes the event of clicking the image map. Here is the chooseLocaleFromMap method of LocaleBean:

public void chooseLocaleFromMap(ActionEvent actionEvent) {
    AreaSelectedEvent event = (AreaSelectedEvent) actionEvent;
    String current = event.getMapComponent().getCurrent();
    FacesContext context = FacesContext.getCurrentInstance();
    context.getViewRoot().setLocale((Locale)
        locales.get(current));
}

When the JavaServer Faces implementation calls this method, it passes in an ActionEvent object that represents the event generated by clicking on the image map. Next, it casts it to an AreaSelectedEvent object (see tut-install/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/listeners/AreaSelectedEvent.java). Then this method gets the MapComponent associated with the event. It then gets the value of the MapComponent object’s current attribute, which indicates the currently selected area. The method then uses the value of the current property to get the Locale object from a HashMap object, which is constructed elsewhere in the LocaleBean class. Finally the method sets the locale of the FacesContext instance to the Locale obtained from the HashMap object.

In addition to the method that processes the event, you need the event class itself. This class is very simple to write: You have it extend ActionEvent and provide a constructor that takes the component on which the event is queued and a method that returns the component. Here is the AreaSelectedEvent class used with the image map:

public class AreaSelectedEvent extends ActionEvent {
    ...
    public AreaSelectedEvent(MapComponent map) {
        super(map);
    }
    public MapComponent getMapComponent() {
        return ((MapComponent) getComponent());
    }
}

As explained in the section Creating Custom Component Classes, in order for MapComponent to fire events in the first place, it must implement ActionSource. Because MapComponent extends UICommand, it also implements ActionSource.

Creating the Component Tag Handler

Now that you’ve created your component and renderer classes, you’re ready to define how a tag handler processes the tag representing the component and renderer combination. If you’ve created your own JSP custom tags before, creating a component tag handler should be easy for you.

In JavaServer Faces applications, the tag handler class associated with a component drives the render response phase of the JavaServer Faces life cycle. For more information on the JavaServer Faces life cycle, see The Life Cycle of a JavaServer Faces Page.

The first thing that the tag handler does is to retrieve the type of the component associated with the tag. Next, it sets the component’s attributes to the values given in the page. It then returns the type of the renderer (if there is one) to the JavaServer Faces implementation so that the component’s encoding can be performed when the tag is processed. Finally, it releases resources used during the processing of the tag.

The image map custom component includes two tag handlers: AreaTag and MapTag. To see how the operations on a JavaServer Faces tag handler are implemented, let’s take a look at MapTag.

The MapTag class extends UIComponentELTag, which supports jsp.tagext.Tag functionality as well as JavaServer Faces-specific functionality. UIComponentELTag is the base class for all JavaServer Faces tags that correspond to a component. Tags that need to process their tag bodies should instead subclass UIComponentBodyELTag.

Retrieving the Component Type

As explained earlier, the first thing MapTag does is to retrieve the type of the component. It does this by using the getComponentType operation:

    public String getComponentType() {
        return ("DemoMap");
    }

The value returned from getComponentType must match the value configured for the component with the component-type element of the application’s application configuration resource file. Registering a Custom Component explains how to configure a component.

Setting Component Property Values

After retrieving the type of the component, the tag handler sets the component’s property values to those supplied as tag attributes values in the page. This section assumes that your component properties are enabled to accept expressions, as explained in Enabling Component Properties to Accept Expressions.

Getting the Attribute Values

Before setting the values in the component class, the MapTag handler first gets the attribute values from the page by means of JavaBeans component properties that correspond to the attributes. The following code shows the property used to access the value of the immediate attribute.

private javax.el.ValueExpression immediate = null;

public void setImmediate(javax.el.ValueExpression immediate)
 {
    this.immediate = immediate;
}

As this code shows, the setImmediate method takes a ValueExpression object. This means that the immediate attribute of the map tag accepts value expressions.

Similarly, the setActionListener and setAction methods take MethodExpression objects, which means that these attributes accept method expressions. The following code shows the properties used to access the values of the actionListener and the action attributes

private javax.el.MethodExpression actionListener = null;

public void setActionListener(
    javax.el.MethodExpression actionListener) {
    
    this.actionListener = actionListener;
}
private javax.el.MethodExpression action = null;

public void setAction(javax.el.MethodExpression action) {
        this.action = action;
}

Setting the Component Property Values

To pass the value of the tag attributes to MapComponent, the tag handler implements the setProperties method. The way setProperties passes the attribute values to the component class depends on whether the values are value expressions or method expressions.

Setting Value Expressions on Component Properties

When the attribute value is a value expression, setProperties first checks if it is not a literal expression. If the expression is not a literal, setProperties stores the expression into a collection, from which the component class can retrieve it and resolve it at the appropriate time. If the expression is a literal, setProperties performs any required type conversion and then does one of the following:

The following piece of the MapTag handler’s setProperties method sets the renderer-dependent property, styleClass, and the renderer-independent property, immediate:

if (styleClass != null) {
    if (!styleClass.isLiteralText()) {
        map.setValueExpression("styleClass", styleClass);
    } else {
        map.getAttributes().put("styleClass",
             styleClass.getExpressionString());
    }
}
...
if (immediate != null) {
    if (!immediate.isLiteralText()) {
        map.setValueExpression("immediate", immediate);
    } else {
        map.setImmediate(new
             Boolean(immediate.getExpressionString()).
                booleanValue());
    }
}

Setting Method Expressions on Component Properties

The process of setting the properties that accept method expressions is done differently depending on the purpose of the method. The actionListener attribute uses a method expression to reference a method that handles action events. The action attribute uses a method expression to either specify a logical outcome or to reference a method that returns a logical outcome, which is used for navigation purposes.

To handle the method expression referenced by actionListener, the setProperties method must wrap the expression in a special action listener object called MethodExpressionActionListener. This listener executes the method referenced by the expression when it receives the action event. The setProperties method then adds this MethodExpressionActionListener object to the list of listeners to be notified when the event of a user clicking on the map occurs. The following piece of setProperties does all of this:

if (actionListener != null) {
    map.addActionListener(
        new MethodExpressionActionListener(actionListener));
}

If your component fires value change events, your tag handler’s setProperties method does a similar thing, except it wraps the expression in a MethodExpressionValueChangeListener object and adds the listener using the addValueChangeListener method.

In the case of the method expression referenced by the action attribute, the setProperties method uses the setActionExpression method of ActionSource2 to set the corresponding property on MapComponent:

if (action != null) {
    map.setActionExpression(action);
}

Providing the Renderer Type

After setting the component properties, the tag handler provides a renderer type (if there is a renderer associated with the component) to the JavaServer Faces implementation. It does this using the getRendererType method:

public String getRendererType() {return "DemoMap";}

The renderer type that is returned is the name under which the renderer is registered with the application. See Delegating Rendering to a Renderer for more information.

If your component does not have a renderer associated with it, getRendererType should return null. In this case, the renderer-type element in the application configuration file should also be set to null.

Releasing Resources

It’s recommended practice that all tag handlers implement a release method, which releases resources allocated during the execution of the tag handler. The release method of MapTag as follows:

public void release() {
    super.release();
    current = null;
    styleClass = null;
    actionListener = null;
    immediate = null;
    action = null;
}

This method first calls the UIComponentTag.release method to release resources associated with UIComponentTag. Next, the method sets all attribute values to null.

Defining the Custom Component Tag in a Tag Library Descriptor

To define a tag, you declare it in a TLD. The web container uses the TLD to validate the tag. The set of tags that are part of the HTML render kit are defined in the html_basic TLD.

The custom tags area and map are defined in bookstore.tld. The bookstore.tld file defines tags for all the custom components and the custom validator tag described in Creating a Custom Tag.

All tag definitions must be nested inside the taglib element in the TLD. Each tag is defined by a tag element. Here is part of the tag definition of the map tag:

<tag>
    <name>map</name>
    <tag-class>taglib.MapTag</tag-class>
    <attribute>
        <name>binding</name>
        <required>false</required>
        <deferred-value>
            <type>
                javax.faces.component.UIComponent
            </type>
        </deferred-value>
    </attribute>
    <attribute>
        <name>current</name>
        <required>false</required>
        <deferred-value>
            <type>
                java.lang.String
            </type>
        </deferred-value>
    </attribute>
    ...
    <attribute>
        <name>actionListener</name>
        <required>false</required>
        <deferred-method>
            <method-signature>
                void actionListener(javax.faces.event.ActionEvent)
            </method-signature>
        </deferred-method>
        <type>String</type>
    </attribute>
    ...
</tag>

At a minimum, each tag must have a name (the name of the tag) and a tag-class attribute, which specifies the fully-qualified class name of the tag handler.

Each attribute element defines one of the tag attributes. As described in Defining a Tag Attribute Type, the attribute element must define what kind of value the attribute accepts, which for JavaServer Faces tags is either a deferred value expression or a method expression.

To specify that an attribute accepts a deferred value expression, you define the type that the corresponding component property accepts using a type element nested inside of a deferred-value element, as shown for the binding and current attribute definitions in the preceding code snippet.

To specify that an attribute accepts a method expression, you define the signature of the method that expression references using a method-signature element nested inside a deferred-method element, as shown by the actionListener attribute definition in the preceding code snippet. The actual name of the method is ignored by the runtime.

For more information on defining tags in a TLD, consult the Tag Library Descriptors section of this tutorial.

Chapter 14 Configuring JavaServer Faces Applications

The responsibilities of the application architect include the following:

This chapter explains how to perform all the responsibilities of the application architect.

Application Configuration Resource File

JavaServer Faces technology provides a portable configuration format (as an XML document) for configuring resources. An application architect creates one or more files, called application configuration resource files, that use this format to register and configure objects and to define navigation rules. An application configuration resource file is usually called faces-config.xml.

The application configuration resource file must be valid against the schema located at http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd.

In addition, each file must include the following, in this order:

You can have more than one application configuration resource file. The JavaServer Faces implementation finds the file or files by looking for the following:

To access resources registered with the application, an application developer uses an instance of the Application class, which is automatically created for each application. The Application instance acts as a centralized factory for resources that are defined in the XML file.

When an application starts up, the JavaServer Faces implementation creates a single instance of the Application class and configures it with the information you configure in the application configuration resource file.

Configuring Beans

To instantiate backing beans and other managed beans used in a JavaServer Faces application and store them in scope, you use the managed bean creation facility. This facility is configured in the application configuration resource file using managed-bean XML elements to define each bean. This file is processed at application startup time. When a page references a bean, the JavaServer Faces implementation initializes it according to its configuration in the application configuration resource file.

With the managed bean creation facility, you can:

This section shows you how to initialize beans using the managed bean creation facility. See Writing Bean Properties and Writing Backing Bean Methods for information on programming backing beans. Binding Component Values and Instances to External Data Sources explains how to reference a managed bean from the component tags.

Using the managed-bean Element

You create a bean using a managed-bean element, which represents an instance of a bean class that must exist in the application. At runtime, the JavaServer Faces implementation processes the managed-bean element. If a page references the bean, the JavaServer Faces implementation instantiates the bean as specified by the element configuration if no instance exists.

Here is an example managed bean configuration from the Duke’s Bookstore application:

<managed-bean>
    <managed-bean-name> NA </managed-bean-name>
        <managed-bean-class>
             com.sun.bookstore6.model.ImageArea
         </managed-bean-class>
        <managed-bean-scope> application </managed-bean-scope>
        <managed-property>
            <property-name>shape</property-name>
            <value>poly</value>
        </managed-property>
        ...
    </managed-bean-name>
</managed-bean>

    Using NetBeans IDE, you can add a managed bean declaration by doing the following:

  1. After opening your project in NetBeans IDE, expand the project node in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes of the project node.

  3. Double-click faces-config.xml.

  4. After faces-config.xml opens in the editor pane, right-click in the editor pane.

  5. Select JavaServer Faces -> Add Managed Bean.

  6. In the Add Managed Bean dialog:

    1. Enter the display name of the bean in the Bean Name field.

    2. Click Browse to locate the bean’s class.

  7. In the Browse Class dialog:

    1. Start typing the name of the class you are looking for in the Class Name field. While you are typing, the dialog will show the matching classes.

    2. Select the class from the Matching Classes box.

    3. Click OK.

  8. In the Add Managed Bean dialog:

    1. Select the bean’s scope from the Scope menu.

    2. Click Add.

  9. In the Projects tab, right-click the bookstore1 project, and select Undeploy and Deploy.

The preceding steps will add the managed-bean element and three elements inside of it: a managed-bean-name element, a managed-bean-class element and a managed-bean-scope element. You will need to edit the XML of the configuration file directly to further configure this managed bean.

The managed-bean-name element defines the key under which the bean will be stored in a scope. For a component’s value to map to this bean, the component tag’s value attribute must match the managed-bean-name up to the first period. For example, this value expression maps to the shape property of the ImageArea instance, NA:

value="#{NA.shape}"

The part before the period (.) matches the managed-bean-name of ImageArea. Adding UI Components to a Page Using the HTML Component Tags has more examples of using the value attribute to bind components to bean properties.

The managed-bean-class element defines the fully qualified name of the JavaBeans component class used to instantiate the bean. It is the application developer’s responsibility to ensure that the class complies with the configuration of the bean in the application configuration resource file. This includes making sure that the types of the properties in the bean match those configured for the bean in the configuration file.

The managed-bean-scope element defines the scope in which the bean will be stored. The four acceptable scopes are none, request, session, or application. If you define the bean with a none scope, the bean is instantiated anew each time it is referenced, and so it does not get saved in any scope. One reason to use a scope of none is that a managed bean references another managed bean. The second bean should be in none scope if it is supposed to be created only when it is referenced. See Initializing Managed Bean Properties for an example of initializing a managed bean property.

If you are configuring a backing bean that is referenced by a component tag’s binding attribute, you should define the bean with a request scope. If you placed the bean in session or application scope instead, the bean would need to take precautions to ensure thread safety because UIComponent instances depend on running inside of a single thread.

The managed-bean element can contain zero or more managed-property elements, each corresponding to a property defined in the bean class. These elements are used to initialize the values of the bean properties. If you don’t want a particular property initialized with a value when the bean is instantiated, do not include a managed-property definition for it in your application configuration resource file.

If a managed-bean element does not contain other managed-bean elements, it can contain one map-entries element or list-entries element. The map-entries element configures a set of beans that are instances of Map. The list-entries element configures a set of beans that are instances of List.

To map to a property defined by a managed-property element, you must ensure that the part of a component tag’s value expression after the period matches the managed-property element’s property-name element. In the earlier example, the shape property is initialized with the value poly. The next section explains in more detail how to use the managed-property element.

Initializing Properties Using the managed-property Element

A managed-property element must contain a property-name element, which must match the name of the corresponding property in the bean. A managed-property element must also contain one of a set of elements (listed in Table 14–1) that defines the value of the property. This value must be of the same type as that defined for the property in the corresponding bean. Which element you use to define the value depends on the type of the property defined in the bean. Table 14–1 lists all the elements used to initialize a value.

Table 14–1 Subelements of managed-property Elements That Define Property Values

Element 

Value That It Defines 

list-entries

Defines the values in a list 

map-entries

Defines the values of a map 

null-value

Explicitly sets the property to null

value

Defines a single value, such as a String or int, or a JavaServer Faces EL expression

Using the managed-bean Element includes an example of initializing String properties using the value subelement. You also use the value subelement to initialize primitive and other reference types. The rest of this section describes how to use the value subelement and other subelements to initialize properties of Java Enum types, java.util.Map, array, and Collection, as well as initialization parameters.

Referencing a Java Enum Type

As of version 1.2 of JavaServer Faces technology, a managed bean property can also be a Java Enum type (see http://java.sun.com/javase/6/docs/api/java/lang/Enum.html). In this case, the value element of the managed-property element must be a String that matches one of the String constants of the Enum. In other words, the String must be one of the valid values that can be returned if you were to call valueOf(Class, String) on enum, where Class is the Enum class and String is the contents of the value subelement. For example, suppose the managed bean property is the following:

public enum Suit { Hearts, Spades, Diamonds, Clubs}
 ...
public Suit getSuit() { ... return Suit.Hearts; }

Assuming that you want to configure this property in the application configuration file, the corresponding managed-property element would look like this:

<managed-property>
    <property-name>Suit</property-name>
    <value>Hearts</value>
</managed-property>

When the system encounters this property, it iterates over each of the members of the enum and calls toString() on each member until it finds one that is exactly equal to the value from the value element.

Referencing an Initialization Parameter

Another powerful feature of the managed bean creation facility is the ability to reference implicit objects from a managed bean property.

Suppose that you have a page that accepts data from a customer, including the customer’s address. Suppose also that most of your customers live in a particular area code. You can make the area code component render this area code by saving it in an implicit object and referencing it when the page is rendered.

You can save the area code as an initial default value in the context initParam implicit object by adding a context parameter to your web application and setting its value in the deployment descriptor. For example, to set a context parameter called defaultAreaCode to 650, add a context-param element to the deployment descriptor, give the parameter the name defaultAreaCode and the value 650.

Next, you write a managed-bean declaration that configures a property that references the parameter:

<managed-bean>
    <managed-bean-name>customer</managed-bean-name>
        <managed-bean-class>CustomerBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>areaCode</property-name>
                <value>#{initParam.defaultAreaCode}</value>
            </managed-property>
            ...
</managed-bean>

To access the area code at the time the page is rendered, refer to the property from the area component tag’s value attribute:

<h:inputText id=area value="#{customer.areaCode}"

Retrieving values from other implicit objects is done in a similar way. See Implicit Objects for a list of implicit objects.

Initializing Map Properties

The map-entries element is used to initialize the values of a bean property with a type of java.util.Map if the map-entries element is used within a managed-property element. A map-entries element contains an optional key-class element, an optional value-class element, and zero or more map-entry elements.

Each of the map-entry elements must contain a key element and either a null-value or value element. Here is an example that uses the map-entries element:

<managed-bean>
    ...
    <managed-property>
        <property-name>prices</property-name>
        <map-entries>
            <map-entry>
                <key>My Early Years: Growing Up on *7</key>
                <value>30.75</value>
            </map-entry>
            <map-entry>
                <key>Web Servers for Fun and Profit</key>
                <value>40.75</value>
            </map-entry>
        </map-entries>
    </managed-property>
</managed-bean>

The map that is created from this map-entries tag contains two entries. By default, all the keys and values are converted to java.lang.String. If you want to specify a different type for the keys in the map, embed the key-class element just inside the map-entries element:

<map-entries>
    <key-class>java.math.BigDecimal</key-class>
    ...
</map-entries>

This declaration will convert all the keys into java.math.BigDecimal. Of course, you must make sure that the keys can be converted to the type that you specify. The key from the example in this section cannot be converted to a java.math.BigDecimal because it is a String.

If you also want to specify a different type for all the values in the map, include the value-class element after the key-class element:

<map-entries>
    <key-class>int</key-class>
    <value-class>java.math.BigDecimal</value-class>
    ...
</map-entries>

Note that this tag sets only the type of all the value subelements.

The first map-entry in the preceding example includes a value subelement. The value subelement defines a single value, which will be converted to the type specified in the bean.

The second map-entry defines a value element, which references a property on another bean. Referencing another bean from within a bean property is useful for building a system from fine-grained objects. For example, a request-scoped form-handling object might have a pointer to an application-scoped database mapping object. Together the two can perform a form-handling task. Note that including a reference to another bean will initialize the bean if it does not already exist.

Instead of using a map-entries element, it is also possible to assign the entire map using a value element that specifies a map-typed expression.

Initializing Array and List Properties

The list-entries element is used to initialize the values of an array or List property. Each individual value of the array or List is initialized using a value or null-value element. Here is an example:

<managed-bean>
    ...
    <managed-property>
        <property-name>books</property-name>
        <list-entries>
            <value-class>java.lang.String</value-class>
            <value>Web Servers for Fun and Profit</value>
            <value>#{myBooks.bookId[3]}</value>
            <null-value/>
        </list-entries>
    </managed-property>
</managed-bean>

This example initializes an array or a List. The type of the corresponding property in the bean determines which data structure is created. The list-entries element defines the list of values in the array or List. The value element specifies a single value in the array or List and can reference a property in another bean. The null-value element will cause the setBooks method to be called with an argument of null. A null property cannot be specified for a property whose data type is a Java primitive, such as int or boolean.

Initializing Managed Bean Properties

Sometimes you might want to create a bean that also references other managed beans so that you can construct a graph or a tree of beans. For example, suppose that you want to create a bean representing a customer’s information, including the mailing address and street address, each of which is also a bean. The following managed-bean declarations create a CustomerBean instance that has two AddressBean properties: one representing the mailing address, and the other representing the street address. This declaration results in a tree of beans with CustomerBean as its root and the two AddressBean objects as children.

<managed-bean>
    <managed-bean-name>customer</managed-bean-name>
    <managed-bean-class>
        com.mycompany.mybeans.CustomerBean
    </managed-bean-class>
    <managed-bean-scope> request </managed-bean-scope>
    <managed-property>
        <property-name>mailingAddress</property-name>
        <value>#{addressBean}</value>
    </managed-property>
    <managed-property>
        <property-name>streetAddress</property-name>
        <value>#{addressBean}</value>
    </managed-property>
    <managed-property>
        <property-name>customerType</property-name>
        <value>New</value>
    </managed-property>
</managed-bean>
<managed-bean>
    <managed-bean-name>addressBean</managed-bean-name>
    <managed-bean-class>
        com.mycompany.mybeans.AddressBean
    </managed-bean-class>
    <managed-bean-scope> none </managed-bean-scope>
    <managed-property>
        <property-name>street</property-name>
        <null-value/>
    <managed-property>
    ...
</managed-bean>

The first CustomerBean declaration (with the managed-bean-name of customer) creates a CustomerBean in request scope. This bean has two properties: mailingAddress and streetAddress. These properties use the value element to reference a bean named addressBean.

The second managed bean declaration defines an AddressBean but does not create it because its managed-bean-scope element defines a scope of none. Recall that a scope of none means that the bean is created only when something else references it. Because both the mailingAddress and the streetAddress properties reference addressBean using the value element, two instances of AddressBean are created when CustomerBean is created.

When you create an object that points to other objects, do not try to point to an object with a shorter life span because it might be impossible to recover that scope’s resources when it goes away. A session-scoped object, for example, cannot point to a request-scoped object. And objects with none scope have no effective life span managed by the framework, so they can point only to other none scoped objects. Table 14–2 outlines all of the allowed connections.

Table 14–2 Allowable Connections between Scoped Objects

An Object of This Scope 

May Point to an Object of This Scope 

none

none

application

none, application

session

none, application, session

request

none, application, session, request

Be sure not allow cyclical references between objects. For example, neither of the AddressBean objects in the preceding example should point back to the CustomerBean object because CustomerBean already points to the AddressBean objects.

Initializing Maps and Lists

In addition to configuring Map and List properties, you can also configure a Map and a List directly so that you can reference them from a tag rather than referencing a property that wraps a Map or a List.

The Duke’s Bookstore application configures a List to initialize the list of free newsletters, from which users can choose a set of newsletters to subscribe to on the bookcashier.jsp page:

<managed-bean>
    ...
<managed-bean-name>newsletters</managed-bean-name>
    <managed-bean-class>
        java.util.ArrayList
    </managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
    <list-entries>
        <value-class>javax.faces.model.SelectItem</value-class>
        <value>#{newsletter0}</value>
        <value>#{newsletter1}</value>
        <value>#{newsletter2}</value>
        <value>#{newsletter3}</value>
    </list-entries>
</managed-bean>
<managed-bean>
    <managed-bean-name>newsletter0</managed-bean-name>
    <managed-bean-class>
        javax.faces.model.SelectItem
    </managed-bean-class>
    <managed-bean-scope>none</managed-bean-scope>
    <managed-property>
        <property-name>label</property-name>
        <value>Duke’s Quarterly</value>
    </managed-property>
    <managed-property>
        <property-name>value</property-name>
        <value>200</value>
    </managed-property>
</managed-bean>
...

This configuration initializes a List called newsletters. This list is composed of SelectItem instances, which are also managed beans. See Using the selectItem Tag for more information on SelectItem. Note that, unlike the example in Initializing Map Properties, the newsletters list is not a property on a managed bean. (It is not wrapped with a managed-property element.) Instead, the list is the managed bean.

Registering Custom Error Messages

If you create custom error messages (which are displayed by the message and messages tags) for your custom converters or validators, you must make them available at application startup time. You do this in one of two ways: by queuing the message onto the FacesContext instance programmatically (as described in Performing Localization) or by registering the messages with your application using the application configuration resource file.

Here is the part of the file that registers the messages for the Duke’s Bookstore application:

<application>
    <message-bundle>
        com.sun.bookstore6.resources.ApplicationMessages
    </message-bundle>
    <locale-config>
        <default-locale>en</default-locale>
        <supported-locale>es</supported-locale>
        <supported-locale>de</supported-locale>
        <supported-locale>fr</supported-locale>
    </locale-config>
</application>

This set of elements will cause your Application instance to be populated with the messages contained in the specified resource bundle.

The message-bundle element represents a set of localized messages. It must contain the fully qualified path to the resource bundle containing the localized messages (in this case, resources.ApplicationMessages).

The locale-config element lists the default locale and the other supported locales. The locale-config element enables the system to find the correct locale based on the browser’s language settings. Duke’s Bookstore manually sets the locale and so it overrides these settings. Therefore, it’s not necessary to use locale-config to specify the default or supported locales in Duke’s Bookstore.

The supported-locale and default-locale tags accept the lowercase, two-character codes as defined by ISO 639 (see http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt). Make sure that your resource bundle actually contains the messages for the locales that you specify with these tags.

To access the localized message, the application developer merely references the key of the message from the resource bundle. See Performing Localization for more information.

Registering Custom Localized Static Text

Any custom localized static text you create that is not loaded into the page using the loadBundle tag must be registered with the application using the resource-bundle element in the application configuration resource file for your pages to have access to the text. Likewise, any custom error messages that are referenced by the converterMessage, requiredMessage, or validatorMessage attributes of an input component tag must also be made available to the application by way of the loadBundle tag or the resource-bundle element of the application configuration file.

Here is the part of the file that registers some custom error messages for the Duke’s Bookstore application:

<application>
    ...
    <resource-bundle>
        <base-name>
            com.sun.bookstore6.resources.CustomMessages
        </base-name>
        <var>customMessages</var>
    </resource-bundle>    
    ...
</application>

Similarly to the loadBundle tag, the value of the base-name subelement specifies the fully-qualified class name of the ResourceBundle class, which in this case is located in the resources package of the application.

Also similarly to the var attribute of the loadBundle tag, the var subelement of the resource-bundle element is an alias to the ResourceBundle class. This alias is used by tags in the page to identify the resource bundle.

The locale-config element shown in the previous section also applies to the messages and static text identified by the resource-bundle element. As with resource bundles identified by the message-bundle element, make sure that the resource bundle identified by the resource-bundle element actually contains the messages for the locales that you specify with these locale-config elements.

To access the localized message, the page author uses a value expression to reference the key of the message from the resource bundle. See Performing Localization for more information.

Registering a Custom Validator

If the application developer provides an implementation of the Validator interface to perform validation, you must register this custom validator in the application configuration resource file by using the validator XML element:

<validator>
    ...
    <validator-id>FormatValidator</validator-id>
    <validator-class>
        com.sun.bookstore6.validators.FormatValidator
    </validator-class>
    <attribute>
        ...
        <attribute-name>formatPatterns</attribute-name>
        <attribute-class>java.lang.String</attribute-class>
    </attribute>
</validator>

The validator-id and validator-class elements are required subelements. The validator-id element represents the identifier under which the Validator class should be registered. This ID is used by the tag class corresponding to the custom validator tag.

The validator-class element represents the fully qualified class name of the Validator class.

The attribute element identifies an attribute associated with the Validator implementation. It has required attribute-name and attribute-class subelements. The attribute-name element refers to the name of the attribute as it appears in the validator tag. The attribute-class element identifies the Java type of the value associated with the attribute.

Creating a Custom Validator explains how to implement the Validator interface.

Using a Custom Validator explains how to reference the validator from the page.

Registering a Custom Converter

As is the case with a custom validator, if the application developer creates a custom converter, you must register it with the application. Here is the converter configuration for CreditCardConverter from the Duke’s Bookstore application:

<converter>
    <description>
        Converter for credit card
         numbers that normalizes
         the input to a standard format
    </description>
    <converter-id>CreditCardConverter</converter-id>
    <converter-class>
        com.sun.bookstore6.converters.CreditCardConverter
    </converter-class>
</converter>

The converter element represents a Converter implementation and contains required converter-id and converter-class elements.

The converter-id element identifies an ID that is used by the converter attribute of a UI component tag to apply the converter to the component’s data. Using a Custom Converter includes an example of referencing the custom converter from a component tag.

The converter-class element identifies the Converter implementation.

Creating a Custom Converter explains how to create a custom converter.

Configuring Navigation Rules

As explained in Navigation Model, navigation is a set of rules for choosing the next page to be displayed after a button or hyperlink component is clicked. Navigation rules are defined in the application configuration resource file.

Each navigation rule specifies how to navigate from one page to a set of other pages. The JavaServer Faces implementation chooses the proper navigation rule according to which page is currently displayed.

After the proper navigation rule is selected, the choice of which page to access next from the current page depends on two factors:

The outcome can be anything the developer chooses, but Table 14–3 lists some outcomes commonly used in web applications.

Table 14–3 Common Outcome Strings

Outcome 

What It Means 

success

Everything worked. Go on to the next page. 

failure

Something is wrong. Go on to an error page. 

logon

The user needs to log on first. Go on to the logon page. 

no results

The search did not find anything. Go to the search page again. 

Usually, the action method performs some processing on the form data of the current page. For example, the method might check whether the user name and password entered in the form match the user name and password on file. If they match, the method returns the outcome success. Otherwise, it returns the outcome failure. As this example demonstrates, both the method used to process the action and the outcome returned are necessary to determine the proper page to access.

Here is a navigation rule that could be used with the example just described:

<navigation-rule>
    <from-view-id>/logon.jsp</from-view-id>
    <navigation-case>
        <from-action>#{LogonForm.logon}</from-action>
        <from-outcome>success</from-outcome>
        <to-view-id>/storefront.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-action>#{LogonForm.logon}</from-action>
        <from-outcome>failure</from-outcome>
        <to-view-id>/logon.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

This navigation rule defines the possible ways to navigate from logon.jsp. Each navigation-case element defines one possible navigation path from logon.jsp. The first navigation-case says that if LogonForm.logon returns an outcome of success, then storefront.jsp will be accessed. The second navigation-case says that logon.jsp will be re-rendered if LogonForm.logon returns failure.

The configuration of an application’s page flow consists of a set of navigation rules. Each rule is defined by the navigation-rule element in the faces-config.xml file.

The navigation rules of the Duke’s Bookstore application are very simple. Here are two complex navigation rules that could be used with the Duke’s Bookstore application:

<navigation-rule>
    <from-view-id>/catalog.jsp</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/bookcashier.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-outcome>out of stock</from-outcome>
        <from-action>
            #{catalog.buy}
        </from-action>
        <to-view-id>/outofstock.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-outcome>error</from-outcome>
        <to-view-id>/error.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

The first navigation rule in this example says that the application will navigate from catalog.jsp to

The second navigation rule says that the application will navigate from any page to error.jsp if the application encountered an error.

Each navigation-rule element corresponds to one component tree identifier defined by the optional from-view-id element. This means that each rule defines all the possible ways to navigate from one particular page in the application. If there is no from-view-id element, the navigation rules defined in the navigation-rule element apply to all the pages in the application. The from-view-id element also allows wildcard matching patterns. For example, this from-view-id element says that the navigation rule applies to all the pages in the books directory:

<from-view-id>/books/*</from-view-id>

As shown in the example navigation rule, a navigation-rule element can contain zero or more navigation-case elements. The navigation-case element defines a set of matching criteria. When these criteria are satisfied, the application will navigate to the page defined by the to-view-id element contained in the same navigation-case element.

The navigation criteria are defined by optional from-outcome and from-action elements. The from-outcome element defines a logical outcome, such as success. The from-action element uses a method expression to refer to an action method that returns a String, which is the logical outcome. The method performs some logic to determine the outcome and returns the outcome.

The navigation-case elements are checked against the outcome and the method expression in this order:

When any of these cases is matched, the component tree defined by the to-view-id element will be selected for rendering.

    Using NetBeans IDE, you can configure a navigation rule by doing the following:

  1. After opening your project in NetBeans IDE, expand the project node in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes of the project node.

  3. Double-click faces-config.xml.

  4. After faces-config.xml opens in the editor pane, right-click in the editor pane.

  5. Select JavaServer Faces->Add Navigation Rule.

  6. In the Add Navigation Rule dialog:

    1. Enter or browse for the page that represents the starting view for this navigation rule.

    2. Click Add.

  7. Right-click again in the editor pane.

  8. Select JavaServer Faces -> Add Navigation Case.

  9. In the Add Navigation Case dialog:

    1. From the From View menu, select the page that represents the starting view for the navigation rule (from step 6a).

    2. (optional) In the From Action field, enter the action method invoked when the component that triggered navigation is activated.

    3. (optional) In the From Outcome field, enter the logical outcome string that the activated component references from its action attribute.

    4. From the To View menu, select or browse for the page that will be opened if this navigation case is selected by the navigation system.

    5. Click Add.

      Referencing a Method That Performs Navigation explains how to use a component tag’s action attribute to point to an action method. Writing a Method to Handle Navigation explains how to write an action method.

Registering a Custom Renderer with a Render Kit

When the application developer creates a custom renderer, as described in Delegating Rendering to a Renderer, you must register it using the appropriate render kit. Because the image map application implements an HTML image map, AreaRenderer (as well as MapRenderer) should be registered using the HTML render kit.

You register the renderer using the render-kit element of the application configuration resource file. Here is the configuration of AreaRenderer from the Duke’s Bookstore application:

<render-kit>
    <renderer>
        <component-family>Area</component-family>
        <renderer-type>DemoArea</renderer-type>
        <renderer-class>
            com.sun.bookstore6.renderers.AreaRenderer
        </renderer-class>
        <attribute>
            <attribute-name>onmouseout</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
        </attribute>
        <attribute>
            <attribute-name>onmouseover</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
        </attribute>
        <attribute>
            <attribute-name>styleClass</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
        </attribute>
    </renderer>
    ...

The render-kit element represents a RenderKit implementation. If no render-kit-id is specified, the default HTML render kit is assumed. The renderer element represents a Renderer implementation. By nesting the renderer element inside the render-kit element, you are registering the renderer with the RenderKit implementation associated with the render-kit element.

The renderer-class is the fully qualified class name of the Renderer.

The component-family and renderer-type elements are used by a component to find renderers that can render it. The component-family identifier must match that returned by the component class’s getFamily method. The component family represents a component or set of components that a particular renderer can render. The renderer-type must match that returned by the getRendererType method of the tag handler class.

By using the component family and renderer type to look up renderers for components, the JavaServer Faces implementation allows a component to be rendered by multiple renderers and allows a renderer to render multiple components.

Each of the attribute tags specifies a render-dependent attribute and its type. The attribute element doesn’t affect the runtime execution of your application. Instead, it provides information to tools about the attributes the Renderer supports.

The object that is responsible for rendering a component (be it the component itself or a renderer to which the component delegates the rendering) can use facets to aid in the rendering process. These facets allow the custom component developer to control some aspects of rendering the component. Consider this custom component tag example:

<d:dataScroller>
    <f:facet name="header">
        <h:panelGroup>
            <h:outputText value="Account Id"/>
            <h:outputText value="Customer Name"/>
            <h:outputText value="Total Sales"/>
        </h:panelGroup>
    </f:facet>
    <f:facet name="next">
        <h:panelGroup>
            <h:outputText value="Next"/>
            <h:graphicImage url="/images/arrow-right.gif" />
        </h:panelGroup>
    </f:facet>
        ...
</d:dataScroller>

The dataScroller component tag includes a component that will render the header and a component that will render the Next button. If the renderer associated with this component renders the facets you can include the following facet elements in the renderer element:

<facet>
    <description>This facet renders as the
         header of the table. It should be a panelGroup
         with the same number of columns as the data
    </description>
    <display-name>header</display-name>
    <facet-name>header</facet-name>
</facet>
 <facet>
    <description>This facet renders as the content
         of the "next" button in the scroller. It should be a
         panelGroup that includes an outputText tag that
         has the text "Next" and a right arrow icon.
    </description>
     <display-name>Next</display-name>
    <facet-name>next</facet-name>
</facet>

If a component that supports facets provides its own rendering and you want to include facet elements in the application configuration resource file, you need to put them in the component’s configuration rather than the renderer’s configuration.

Registering a Custom Component

In addition to registering custom renderers (as explained in the preceding section), you also must register the custom components that are usually associated with the custom renderers.

Here is the component element from the application configuration resource file that registers AreaComponent:

<component>
    <component-type>DemoArea</component-type>
    <component-class>
        com.sun.bookstore6.components.AreaComponent
    </component-class>
    <property>
        <property-name>alt</property-name>
        <property-class>java.lang.String</property-class>
    </property>
    <property>
        <property-name>coords</property-name>
        <property-class>java.lang.String</property-class>
    </property>
    <property>
        <property-name>shape</property-name>
        <property-class>java.lang.String</property-class>
    </property>
</component>

The component-type element indicates the name under which the component should be registered. Other objects referring to this component use this name. For example, the component-type element in the configuration for AreaComponent defines a value of DemoArea, which matches the value returned by the AreaTag class’s getComponentType method.

The component-class element indicates the fully qualified class name of the component. The property elements specify the component properties and their types.

If the custom component can include facets, you can configure the facets in the component configuration using facet elements, which are allowed after the component-class elements. See Registering a Custom Renderer with a Render Kit for further details on configuring facets.

Basic Requirements of a JavaServer Faces Application

In addition to configuring your application, you must satisfy other requirements of JavaServer Faces applications, including properly packaging all the necessary files and providing a deployment descriptor. This section describes how to perform these administrative tasks.

JavaServer Faces applications must be compliant with the Servlet specification, version 2.3 (or later) and the JavaServer Pages specification, version 1.2 (or later). All applications compliant with these specifications are packaged in a WAR file, which must conform to specific requirements in order to execute across different containers. At a minimum, a WAR file for a JavaServer Faces application must contain the following:

The WAR file typically has this directory structure:

index.html
JSP pages
WEB-INF/
   web.xml
   faces-config.xml
   tag library descriptors (optional)
   classes/
      class files
         Properties files
   lib/
      JAR files

The web.xml file (or deployment descriptor), the set of JAR files, and the set of application files must be contained in the WEB-INF directory of the WAR file.

Configuring an Application with a Deployment Descriptor

Web applications are configured using elements contained in the web application deployment descriptor. The deployment descriptor for a JavaServer Faces application must specify certain configurations, which include the following:

The deployment descriptor can also specify other, optional configurations, including:

This section gives more details on these configurations. Where appropriate, it also describes how you can make these configurations using NetBeans IDE.

Identifying the Servlet for Life Cycle Processing

One requirement of a JavaServer Faces application is that all requests to the application that reference previously saved JavaServer Faces components must go through FacesServlet. A FacesServlet instance manages the request processing life cycle for web applications and initializes the resources required by JavaServer Faces technology.

Before a JavaServer Faces application can launch the first JSP page, the web container must invoke the FacesServlet instance in order for the application life cycle process to start. The application life cycle is described in the section The Life Cycle of a JavaServer Faces Page.

To make sure that the FacesServlet instance is invoked, you provide a mapping to it. The mapping to FacesServlet can be a prefix mapping, such as /guess/*, or an extension mapping, such as *.faces. The mapping is used to identify a JSP page as having JavaServer Faces content. Because of this, the URL to the first JSP page of the application must include the mapping.

In the case of prefix mapping, there are two ways to accomplish this:

The second method allows users to start the application from the first JSP page, rather than start it from an HTML page. However, the second method requires users to identify the first JSP page. When you use the first method, users need only enter

http://localhost:8080/guessNumber

In the case of extension mapping, if a request comes to the server for a JSP page with a .faces extension, the container will send the request to the FacesServlet instance, which will expect a corresponding JSP page of the same name to exist containing the content. For example, if the request URL is http://localhost/bookstore6/bookstore.faces, FacesServlet will map it to the bookstore.jsp page.

    If you are using NetBeans IDE, the time to map the FacesServlet instance is when you create your JavaServer Faces project with NetBeans IDE:

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

  2. In the New Project dialog, select Web from the Categories tree.

  3. Select Web Application from the Projects panel.

  4. Click Next.

  5. Fill out the information in the Name and Location screen of the wizard.

  6. Click Next.

  7. Select the JavaServer Faces check box in the Framewoks screen.

  8. Enter the mapping, such as *.faces, to the FacesServlet instance in the Servlet URL Mapping field.

  9. Click Finish.

    After your project is open in NetBeans IDE, you can change the mapping to the FacesServlet instance by doing the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click Servlets at the top of the editor pane. The FacesServlet configuration appears in the editor pane.

    If you prefer to edit the web.xml file directly, perform the following steps to configure a mapping to the FacesServlet instance:

  1. Include a servlet element in the deployment descriptor.

  2. Inside the servlet element, include a display-name element and set it to FacesServlet.

  3. Also inside the servlet element, add a servlet-name element and set it to FacesServlet.

  4. Add a third element, called servlet-class, inside the servlet element and set it to javax.faces.webapp.FacesServlet. This is the fully-qualified class name of the FacesServlet class.

  5. After the servlet element, add a servlet-mapping element.

  6. Inside the servlet-mapping element, add a servlet-name element and set it to FacesServlet. This must match the name identified by the servlet-name element described in step 3.

  7. Also inside the servlet-mapping element, add a url-pattern element and set it to whatever mapping you prefer. This will be the path to FacesServlet. Users of the application will include this path in the URL when they access the application. For the guessNumber application, the path is /guess/*.

Specifying a Path to an Application Configuration Resource File

As explained in Application Configuration Resource File, an application can have multiple application configuration resource files. If these files are not located in the directories that the implementation searches by default or the files are not named faces-config.xml, you need to specify paths to these files.

    To specify these paths using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter javax.faces.CONFIG_FILES in the Param Name field.

    2. Enter the path to your configuration file in the Param Value field.

    3. Click OK.

  8. Repeat steps 1 through 7 for each configuration file.

    To specify paths to the files by editing the deployment descriptor directly follow these steps:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-value element inside the context-param element and call it javax.faces.CONFIG_FILES.

  3. Add a param-value element inside the context-param element and give it the path to your configuration file. For example, the path to the guessNumber application’s application configuration resource file is /WEB-INF/faces-config.xml.

  4. Repeat steps 2 and 3 for each application configuration resource file that your application contains.

Specifying Where State Is Saved

When implementing the state-holder methods (described in Saving and Restoring State), you specify in your deployment descriptor where you want the state to be saved, either client or server. You do this by setting a context parameter in your deployment descriptor.

    To specify where state is saved using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter javax.faces.STATE_SAVING_METHOD in the Param Name field.

    2. Enter client or server in the Param Value field.

    3. Click OK.

    To specify where state is saved by editing the deployment descriptor directly follow these steps:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-name element inside the context-param element and give it the name javax.faces.STATE_SAVING_METHOD.

  3. Add a param-value element to the context-param element and give it the value client or server, depending on whether you want state saved in the client or the server.

If state is saved on the client, the state of the entire view is rendered to a hidden field on the page. The JavaServer Faces implementation saves the state on the client by default. Duke’s Bookstore saves its state in the client.

Encrypting Client State

When you are choosing to save state on the client, you are essentially saying that you want state to be sent over the wire and saved on the client in a hidden field. Clearly, this opens the door to potential tampering with the state information. To prevent this from happening, you can specify that the state must be encrypted before it is transmitted to the client.

    To specify that state must be encrypted using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click References at the top of the editor pane.

  5. Expand the Environment Entries node.

  6. Click Add.

  7. In the Add Environment Entry dialog:

    1. Enter com.sun.faces.ClientStateSavingPassword in the Entry Name field.

    2. Select java.lang.String from the Entry Type menu.

    3. Click OK.

    To specify that state must be encrypted by editing the deployment descriptor directly, do the following:

  1. Add an env-entry element to your deployment descriptor.

  2. Add an env-entry-name element to the env-entry element and give it the name com.sun.faces.ClientStateSavingPassword.

  3. Add an env-entry-value element to the env-entry element, and give it your password. The password that you provide is used to generate keys and ciphers for encryption.

  4. Add an env-entry-type element and give it the type of your password, which must be java.lang.String.

If your deployment descriptor does not contain this environment entry then no encryption of client-side state will occur.

Restricting Access to JavaServer Faces Components

In addition to identifying the FacesServlet instance and providing a mapping to it, you should also ensure that all applications use FacesServlet to process JavaServer Faces components. You do this by setting a security constraint.

    To set a security constraint using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click Security at the top of the editor pane.

  5. Click Add Security Constraint.

  6. Enter a name for the constraint in the Display Name field.

  7. Click Add to add a web resource collection.

  8. In the Add Web Resource dialog:

    1. Enter a name for the web resource collection in the Resource Name field.

    2. In the URL pattern field, enter the path to a JSP page to which you want to restrict access, such as /response.jsp. Use commas to separate multiple patterns.

    3. Click OK.

    To set a security constraint by editing the deployment descriptor directly, add a security-constraint element, and inside the security-constraint element, add the following:

  1. Add a display-name element to identify the name of the constraint.

  2. Add a web-resource-collection element.

  3. Inside the web-resource-collection element, add a web-resource-name element that identifies the purpose of the collection.

  4. Add a url-pattern element inside the web-resource-collection element and enter the path to a JSP page to which you want to restrict access, such as /response.jsp.

  5. Continue to add URL patterns for all the JSP pages to which you want to restrict access.

Turning On Validation of XML Files

Your application contains one or more application configuration resource files written in XML. You can force the JavaServer Faces implementation to validate the XML of these files by setting the validateXML flag to true.

    To set the flag using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter com.sun.faces.validateXml in the Param Name field.

    2. Enter true in the Param Value field.

    3. Click OK.

    To set the flag in the deployment descriptor directly, do the following:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-name element inside the context-param element and give it the name com.sun.faces.validateXml.

  3. Add a param-value element to the context-param element and give it the value true. The default value is false.

Verifying Custom Objects

If your application includes custom objects, such as custom components, converters, validators, and renderers, you can verify when the application starts that they can be created. To do this, you set the verifyObjects flag to true.

    To set the flag using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter com.sun.faces.verifyObjects in the Param Name field.

    2. Enter true in the Param Value field.

    3. Click OK.

    To set the flag in the deployment descriptor directly, do the following:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-name element inside the context-param element and give it the name com.sun.faces.verifyObjects.

  3. Add a param-value element to the context-param element and give it the value true. The default value is false.

Normally, this flag should be set to false during development because it takes extra time to check the objects.

Including the Required JAR Files

JavaServer Faces applications require several JAR files to run properly. These JAR files are as follows:

The jsf-api.jar and the jsf-impl.jar files are located in as-install/lib. The jstl.jar file is bundled in appserv-jstl.jar. The other JAR files are bundled in the appserv-rt.jar, also located in as-install/lib/.

When packaging and deploying your JavaServer Faces application, you do not need to explicitly package any of the JAR files.

Including the Classes, Pages, and Other Resources

When packaging web applications using the included build scripts, you’ll notice that the scripts package resources as described here:

When packaging your own applications, you can use NetBeans IDE or you can use the build scripts included with the tutorial examples, as explained throughout the preceding chapters. You can modify the build scripts to fit your situation. However, it is recommended that you continue to package your WAR files as described in this section because this technique complies with commonly-accepted practice for packaging web applications.

Chapter 15 Internationalizing and Localizing Web Applications

The process of preparing an application to support more than one language and data format is called internationalization. Localization is the process of adapting an internationalized application to support a specific region or locale. Examples of locale-dependent information include messages and user interface labels, character sets and encoding, and date and currency formats. Although all client user interfaces should be internationalized and localized, it is particularly important for web applications because of the global nature of the web.

Java Platform Localization Classes

In the Java 2 platform, java.util.Locale represents a specific geographical, political, or cultural region. The string representation of a locale consists of the international standard two-character abbreviation for language and country and an optional variant, all separated by underscore (_) characters. Examples of locale strings include fr (French), de_CH (Swiss German), and en_US_POSIX (English on a POSIX-compliant platform).

Locale-sensitive data is stored in a java.util.ResourceBundle. A resource bundle contains key-value pairs, where the keys uniquely identify a locale-specific object in the bundle. A resource bundle can be backed by a text file (properties resource bundle) or a class (list resource bundle) containing the pairs. You construct resource bundle instance by appending a locale string representation to a base name.

For more details on internationalization and localization in the Java 2 platform, see http://java.sun.com/docs/books/tutorial/i18n/index.html.

In the web technology chapters, the Duke’s Bookstore applications contain resource bundles with the base name messages.BookstoreMessages for the locales en_US, fr_FR, de_DE, and es_MX.

Providing Localized Messages and Labels

Messages and labels should be tailored according to the conventions of a user’s language and region. There are two approaches to providing localized messages and labels in a web application:

The Duke’s Bookstore applications follow the second approach. Here are a few lines from the default resource bundle messages.BookstoreMessages.java:

{"TitleCashier", "Cashier"},
{"TitleBookDescription", "Book Description"},
{"Visitor", "You are visitor number "},
{"What", "What We’re Reading"},
{"Talk", " talks about how Web components can transform the way you develop 
applications for the Web. This is a must read for any self respecting Web developer!"},
{"Start", "Start Shopping"},

Establishing the Locale

To get the correct strings for a given user, a web application either retrieves the locale (set by a browser language preference) from the request using the getLocale method, or allows the user to explicitly select the locale.

The JSTL versions of Duke’s Bookstore automatically retrieve the locale from the request and store it in a localization context (see Internationalization Tag Library). It is also possible for a component to explicitly set the locale by using the fmt:setLocale tag.

The JavaServer Faces version of Duke’s Bookstore allows the user to explicitly select the locale. The user selection triggers a method that stores the locale in the FacesContext object. The locale is then used in resource bundle selection and is available for localizing dynamic data and messages (see Localizing Dynamic Data):

<h:commandLink id="NAmerica" action="storeFront"
    actionListener="#{localeBean.chooseLocaleFromLink}">
    <h:outputText value="#{bundle.english}" />
</h:commandLink>
public void chooseLocaleFromLink(ActionEvent event) {
    String current = event.getComponent().getId();
    FacesContext context = FacesContext.getCurrentInstance();
    context.getViewRoot().setLocale((Locale)
        locales.get(current));
}

Setting the Resource Bundle

After the locale is set, the controller of a web application typically retrieves the resource bundle for that locale and saves it as a session attribute (see Associating Objects with a Session) for use by other components:

messages = ResourceBundle.getBundle("com.sun.bookstore.messages.BookstoreMessages", 
    locale);
session.setAttribute("messages", messages);

The resource bundle base name for the JSTL versions of Duke’s Bookstore is set at deployment time through a context parameter. When a session is initiated, the resource bundle for the user’s locale is stored in the localization context. It is also possible to override the resource bundle at runtime for a given scope using the fmt:setBundle tag and for a tag body using the fmt:bundle tag.

The JavaServer Faces version of Duke’s Bookstore uses two methods for setting the resource bundle. One method is letting the JSP pages set the resource bundle using the f:loadBundle tag. This tag loads the correct resource bundle according to the locale stored in FacesContext.

<f:loadBundle basename="messages.BookstoreMessages"
    var="bundle"/>

For information on this tag, see Loading a Resource Bundle.

Another way a JavaServer Faces application sets the resource bundle is by configuring it in the application configuration file. There are two XML elements that you can use to set the resource bundle: message-bundle and resource-bundle.

If the error messages are queued onto a component as a result of a converter or validator being registered on the component, then these messages are automatically displayed on the page using the message or messages tag. These messages must be registered with the application using the message-bundle tag:

<message-bundle>
    resources.ApplicationMessages
</message-bundle>

For more information on using this element, see Registering Custom Error Messages.

Resource bundles containing messages that are explicitly referenced from a JavaServer Faces tag attribute using a value expression must be registered using the resource-bundle element of the configuration file:

<resource-bundle>
    <base-name>com.sun.bookstore6.resources.CustomMessages</base-name>
    <var>customMessages</var>
</resource-bundle>

For more information on using this element, see Registering Custom Localized Static Text

Retrieving Localized Messages

A web component written in the Java programming language retrieves the resource bundle from the session:

ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

Then it looks up the string associated with the key Talk as follows:

messages.getString("Talk");

The JSP versions of the Duke’s Bookstore application uses the fmt:message tag to provide localized strings for messages, HTML link text, button labels, and error messages:

<fmt:message key="Talk"/>

For information on the JSTL messaging tags, see Messaging Tags.

The JavaServer Faces version of Duke’s Bookstore retrieves messages using either the message or messages tag, or by referencing the message from a tag attribute using a value expression.

You can only use a message or messages tag to display messages that are queued onto a component as a result of a converter or validator being registered on the component. The following example shows a message tag that displays the error message queued on the userNo input component if the validator registered on the component fails to validate the value the user enters into the component.

<h:inputText id="userNo" value="#{UserNumberBean.userNumber}">
    <f:validateLongRange minimum="0" maximum="10" />
     ...
<h:message
     style="color: red;
     text-decoration: overline" id="errors1" for="userNo"/>

For more information on using the message or messages tags, see Displaying Error Messages with the message and messages Tags.

Messages that are not queued on a component and are therefore not loaded automatically are referenced using a value expression. You can reference a localized message from almost any JavaServer Faces tag attribute.

The value expression that references a message has the same notation whether you loaded the resource bundle with the loadBundle tag or registered it with the resource-bundle element in the configuration file.

The value expression notation is var.message, in which var matches the var attribute of the loadBundle tag or the var element defined in the resource-bundle element of the configuration file, and message matches the key of the message contained in the resource bundle, referred to by the var attribute.

Here is an example from bookstore.jsp:

<h:outputText value="#{bundle.Talk}"/>

Notice that bundle matches the var attribute from the loadBundle tag and that Talk matches the key in the resource bundle.

For information on using localized messages in JavaServer Faces, see Rendering Components for Selecting Multiple Values.

Date and Number Formatting

Java programs use the DateFormat.getDateInstance(int, locale) to parse and format dates in a locale-sensitive manner. Java programs use the NumberFormat.getXXXInstance(locale) method, where XXX can be Currency, Number, or Percent, to parse and format numerical values in a locale-sensitive manner. The servlet version of Duke’s Bookstore uses the currency version of this method to format book prices.

JSTL applications use the fmt:formatDate and fmt:parseDate tags to handle localized dates and use the fmt:formatNumber and fmt:parseNumber tags to handle localized numbers, including currency values. For information on the JSTL formatting tags, see Formatting Tags. The JSTL version of Duke’s bookstore uses the fmt:formatNumber tag to format book prices and the fmt:formatDate tag to format the ship date for an order:

<fmt:formatDate value="${shipDate}" type="date"
    dateStyle="full"/>.

The JavaServer Faces version of Duke’s Bookstore uses date/time and number converters to format dates and numbers in a locale-sensitive manner. For example, the same shipping date is converted in the JavaServer Faces version as follows:

<h:outputText value="#{cashier.shipDate}">
    <f:convertDateTime dateStyle="full"/>
</h:outputText>

For information on JavaServer Faces converters, see Using the Standard Converters.

Character Sets and Encodings

The following sections describe character sets and character encodings.

Character Sets

A character set is a set of textual and graphic symbols, each of which is mapped to a set of nonnegative integers.

The first character set used in computing was US-ASCII. It is limited in that it can represent only American English. US-ASCII contains uppercase and lowercase Latin alphabets, numerals, punctuation, a set of control codes, and a few miscellaneous symbols.

Unicode defines a standardized, universal character set that can be extended to accommodate additions. When the Java program source file encoding doesn’t support Unicode, you can represent Unicode characters as escape sequences by using the notation \uXXXX, where XXXX is the character’s 16-bit representation in hexadecimal. For example, the Spanish version of the Duke’s Bookstore message file uses Unicode for non-ASCII characters:

{"TitleCashier", "Cajero"},
{"TitleBookDescription", "Descripci" + "\u00f3" + "n del
 Libro"},
{"Visitor", "El visitante" + "\u00fa" + "mero "},
{"What", "Qu" + "\u00e9" + " libros leemos"},
{"Talk", " describe cómo los componentes de software de web
 pueden transformar la manera en que desarrollamos las
 aplicaciones para la web. Este libro es obligatorio para
 cualquier programador de respeto!"},
{"Start", "Empezar a Comprar"},

Character Encoding

A character encoding maps a character set to units of a specific width and defines byte serialization and ordering rules. Many character sets have more than one encoding. For example, Java programs can represent Japanese character sets using the EUC-JP or Shift-JIS encodings, among others. Each encoding has rules for representing and serializing a character set.

The ISO 8859 series defines 13 character encodings that can represent texts in dozens of languages. Each ISO 8859 character encoding can have up to 256 characters. ISO-8859-1 (Latin-1) comprises the ASCII character set, characters with diacritics (accents, diaereses, cedillas, circumflexes, and so on), and additional symbols.

UTF-8 (Unicode Transformation Format, 8-bit form) is a variable-width character encoding that encodes 16-bit Unicode characters as one to four bytes. A byte in UTF-8 is equivalent to 7-bit ASCII if its high-order bit is zero; otherwise, the character comprises a variable number of bytes.

UTF-8 is compatible with the majority of existing web content and provides access to the Unicode character set. Current versions of browsers and email clients support UTF-8. In addition, many new web standards specify UTF-8 as their character encoding. For example, UTF-8 is one of the two required encodings for XML documents (the other is UTF-16).

See Appendix Figure 37–6 for more information on character encodings in the Java 2 platform.

Web components usually use PrintWriter to produce responses; PrintWriter automatically encodes using ISO-8859-1. Servlets can also output binary data using OutputStream classes, which perform no encoding. An application that uses a character set that cannot use the default encoding must explicitly set a different encoding.

For web components, three encodings must be considered:

Request Encoding

The request encoding is the character encoding in which parameters in an incoming request are interpreted. Currently, many browsers do not send a request encoding qualifier with the Content-Type header. In such cases, a web container will use the default encoding, ISO-8859-1, to parse request data.

If the client hasn’t set character encoding and the request data is encoded with a different encoding from the default, the data won’t be interpreted correctly. To remedy this situation, you can use the ServletRequest.setCharacterEncoding(String enc) method to override the character encoding supplied by the container. To control the request encoding from JSP pages, you can use the JSTL fmt:requestEncoding tag. You must call the method or tag before parsing any request parameters or reading any input from the request. Calling the method or tag once data has been read will not affect the encoding.

Page Encoding

For JSP pages, the page encoding is the character encoding in which the file is encoded.

For JSP pages in standard syntax, the page encoding is determined from the following sources:

If none of these is provided, ISO-8859-1 is used as the default page encoding.

For JSP pages in XML syntax (JSP documents), the page encoding is determined as described in section 4.3.3 and appendix F.1 of the XML specification.

The pageEncoding and contentType attributes determine the page character encoding of only the file that physically contains the page directive. A web container raises a translation-time error if an unsupported page encoding is specified.

Response Encoding

The response encoding is the character encoding of the textual response generated by a web component. The response encoding must be set appropriately so that the characters are rendered correctly for a given locale. A web container sets an initial response encoding for a JSP page from the following sources:

If none of these is provided, ISO-8859-1 is used as the default response encoding.

The setCharacterEncoding, setContentType, and setLocale methods can be called repeatedly to change the character encoding. Calls made after the servlet response’s getWriter method has been called or after the response is committed have no effect on the character encoding. Data is sent to the response stream on buffer flushes (for buffered pages) or on encountering the first content on unbuffered pages.

Calls to setContentType set the character encoding only if the given content type string provides a value for the charset attribute. Calls to setLocale set the character encoding only if neither setCharacterEncoding nor setContentType has set the character encoding before. To control the response encoding from JSP pages, you can use the JSTL fmt.setLocale tag.

    To obtain the character encoding for a locale, the setLocale method checks the locale encoding mapping for the web application. For example, to map Japanese to the Japanese-specific encoding Shift_JIS, follow these steps:

  1. Select the WAR.

  2. Click the Advanced Settings button.

  3. In the Locale Character Encoding table, Click the Add button.

  4. Enter ja in the Extension column.

  5. Enter Shift_JIS in the Character Encoding column.

If a mapping is not set for the web application, setLocale uses a Application Server mapping.

The first application in Chapter 5, JavaServer Pages Technology allows a user to choose an English string representation of a locale from all the locales available to the Java 2 platform and then outputs a date localized for that locale. To ensure that the characters in the date can be rendered correctly for a wide variety of character sets, the JSP page that generates the date sets the response encoding to UTF-8 by using the following directive:

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

Further Information about Internationalizing Web Applications

For a detailed discussion on internationalizing web applications, see the Java BluePrints for the Enterprise at http://java.sun.com/blueprints/enterprise.