Part II explores the technologies in the web tier. This part contains the following chapters:
A web application is a dynamic extension of a web or application server. Web applications are of the following types:
Presentation-oriented: A presentation-oriented web application generates interactive web pages containing various types of markup language (HTML, XHTML, XML, and so on) and dynamic content in response to requests. Development of presentation-oriented web applications is covered in Chapter 4, JavaServer Faces Technology through Chapter 9, Developing with JavaServer Faces Technology.
Service-oriented: A service-oriented web application implements the endpoint of a web service. Presentation-oriented applications are often clients of service-oriented web applications. Development of service-oriented web applications is covered in Chapter 12, Building Web Services with JAX-WS and Chapter 13, Building RESTful Web Services with JAX-RS in Part III, Web Services.
The following topics are addressed here:
In the Java EE platform, web components provide the dynamic extension capabilities for a web server. Web components can be Java servlets, web pages implemented with JavaServer Faces technology, web service endpoints, or JSP pages. Figure 3–1 illustrates the interaction between a web client and a web application that uses a servlet. 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 can pass the request to another web component. A web component eventually generates a HTTPServletResponse object. The web server converts this object to an HTTP response and returns it to the client.
Servlets are Java programming language classes that dynamically process requests and construct responses. Java technologies, such as JavaServer Faces and Facelets, are used for building interactive web applications. (Frameworks can also be used for this purpose.) Although servlets and Java Server Faces and Facelets pages can be used to accomplish similar things, each has its own strengths. Servlets are best suited for service-oriented applications (web service endpoints can be implemented as servlets) and the control functions of a presentation-oriented application, such as dispatching requests and handling nontextual data. Java Server Faces and Facelets pages are more appropriate for generating text-based markup, such as XHTML, and are generally used for presentation–oriented applications.
Web components are supported by the services of a runtime platform called a web container. A web container provides such services as request dispatching, security, concurrency, and lifecycle management. A web container also gives web components access to such APIs 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 can be specified using Java EE annotations or can be maintained in a text file in XML format called a web application deployment descriptor (DD). A web application 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 lifecycle and explains how to package and deploy very simple web applications on the GlassFish Server. The chapter moves on to configuring web applications and discusses how to specify the most commonly used configuration parameters.
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:
Develop the web component code.
Develop the web application deployment descriptor, if necessary.
Compile the web application components and helper classes referenced by the components.
Optionally, package the application into a deployable unit.
Deploy the application into a web container.
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–2) and then displays a greeting after the name is submitted (Figure 3–3).
The Hello application contains two web components that generate the greeting and the response. This chapter discusses the following simple applications:
hello1, a JavaServer Faces technology-based application that uses two XHTML pages and a backing bean
hello2, a servlet-based web application in which the components are implemented by two servlet classes
The applications are used to illustrate tasks involved in packaging, deploying, configuring, and running an application that contains web components. The source code for the examples is in the tut-install/examples/web/hello1/ and tut-install/examples/web/hello2/ directories.
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:
Server-side utility classes, such as shopping carts
Client-side classes, such as applets and utility classes
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 XHTML 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 can contain the following files and directories:
classes: A directory that contains server-side classes: servlets, enterprise bean class files, utility classes, and JavaBeans components
tags: A directory that contains tag files, which are implementations of tag libraries
lib: A directory that contains JAR files that contain enterprise beans, and JAR archives of libraries called by server-side classes
Deployment descriptors, such as web.xml (the web application deployment descriptor) and ejb-jar.xml (an EJB deployment descriptor)
A web module needs a web.xml file if it uses JavaServer Faces technology, if it must specify certain kinds of security information, or if you want to override information specified by web component annotations.
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 GlassFish Server, the file must contain a runtime deployment descriptor. The runtime DD is an XML file that contains such information as the context root of the web application and the mapping of the portable names of an application’s resources to the GlassFish Server’s resources. The GlassFish Server web application runtime DD is named sun-web.xml and is located in the WEB-INF directory. The structure of a web module that can be deployed on the GlassFish Server is shown in Figure 3–4.
For example, the sun-web.xml file for the hello1 application specifies the following context root:
<context-root>/hello1</context-root>
The hello1 application is a web module that uses JavaServer Faces technology to display a greeting and response. You can use a text editor to view the application files, or you can use NetBeans IDE.
In NetBeans IDE, select File->Open Project.
In the Open Project dialog, navigate to:
tut-install/examples/web/ |
Select the hello1 folder.
Select the Open as Main Project check box.
Expand the Web Pages node and double-click the index.xhtml file to view it in the right-hand pane.
The index.html file is the default landing page for a Facelets application. For this application, the page uses simple tag markup to display a form with a graphic image, a header, a text field, and two command buttons:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Facelets Hello Greeting</title> </h:head> <h:body> <h:form> <h:graphicImage url="duke.waving.gif"/> <h2>Hello, my name is Duke. What's yours?</h2> <h:inputText id="username" value="#{hello.name}" required="true" requiredMessage="A name is required." maxlength="25"> </h:inputText> <p></p> <h:commandButton id="submit" value="Submit" action="response"> </h:commandButton> <h:commandButton id="reset" value="Reset" type="reset"> </h:commandButton> </h:form> </h:body> </html>
The most complex element on the page is the inputText text field. The maxlength attribute specifies the maximum length of the field. The required attribute specifies that the field must be filled out; the requiredMessage attribute provides the error message to be displayed if the field is left empty. Finally, the value attribute contains an expression that will be provided by the Hello backing bean.
The Submit commandButton element specifies the action as response, meaning that when the button is clicked, the response.xhtml page is displayed.
Double-click the response.xhtml file to view it.
The response page appears. Even simpler than the greeting page, the response page contains a graphic image, a header that displays the expression provided by the backing bean, and a single button whose action element transfers you back to the index.xhtml page:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Facelets Hello Response</title> </h:head> <h:body> <h:form> <h:graphicImage url="duke.waving.gif"/> <h2>Hello, #{hello.name}!</h2> <p></p> <h:commandButton id="back" value="Back" action="index" /> </h:form> </h:body> </html>
Expand the Source Packages node, then the hello1 node.
Double-click the Hello.java file to view it.
The Hello class, called a backing bean class, provides getter and setter methods for the name property used in the Facelets page expressions. By default, the expression language refers to the class name, with the first letter in lowercase (hello.name).
package hello1; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class Hello { private String name; public Hello() { } public String getName() { return name; } public void setName(String user_name) { this.name = user_name; } }
Under the Web Pages node, expand the WEB-INF node and double-click the web.xml file to view it.
The web.xml file contains several elements that are required for a Facelets application. All these are created automatically when you use NetBeans IDE to create an application:
A context parameter specifying the project stage:
<context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param>
A context parameter provides configuration information needed by a web application. An application can define its own context parameters. In addition, JavaServer Faces technology and Java Servlet technology define context parameters that an application can use.
A servlet element and its servlet-mapping element specifying the FacesServlet:
<servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping>
A welcome-file-list element specifying the location of the landing page; note that the location is faces/index.xhtml, not just index.xhtml:
<welcome-file-list> <welcome-file>faces/index.xhtml</welcome-file> </welcome-file-list>
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 hello1 sample application.
A context root identifies a web application in a Java EE server. A context root must start with a forward slash (/) and end with a string.
In a packaged web module for deployment on the GlassFish Server, the context root is stored in sun-web.xml.
To view or edit the context root, follow these steps.
Expand the Web Pages and WEB-INF nodes of the hello1 project.
Double-click sun-web.xml.
In the General tab, observe that the Context Root field is set to /hello1.
If you needed to edit this value, you could do so here. When you create a new application, you type the context root here.
(Optional) Click the XML tab.
Observe that the context root value /hello1 is enclosed by the context-root element. You could also edit the value here.
Select File->Open Project.
In the Open Project dialog, navigate to:
tut-install/examples/web/ |
Select the hello1 folder.
Select the Open as Main Project check box.
Click Open Project.
In the Projects tab, right-click the hello1 project and select Build.
In a terminal window, go to:
tut-install/examples/web/hello1/ |
Type the following command:
ant |
This command spawns any necessary compilations, copies files to the directory tut-install/examples/web/hello1/build/, creates the WAR file, and copies it to the directory tut-install/examples/web/hello1/dist/.
You can deploy a WAR file to the GlassFish Server by
Using NetBeans IDE
Using the Ant utility
Using the asadmin command
Using the Administration Console
Copying the WAR file into the domain-dir/autodeploy/ directory
Throughout the tutorial, you will use NetBeans IDE or Ant for packaging and deploying.
In a terminal window, go to:
tut-install/examples/web/hello1/ |
Type the following command:
ant deploy |
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.
Open a web browser.
Type the following URL:
http://localhost:8080/hello1/ |
Type your name and click Submit.
The response page displays the name you submitted. Click the Back button to try again.
The GlassFish Server provides two ways to view the deployed web modules: the Administration Console and the asadmin command.
Open the URL http://localhost:4848/ in a browser.
Select the Applications node.
The deployed web modules appear in the Deployed Applications table.
A typical iterative development cycle involves deploying a web module and then making changes to the application components. To update a deployed web module, follow these steps.
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 pages 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/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.
In the GlassFish Server, dynamic reloading is enabled by default.
If for some reason you do not want the default dynamic reloading behavior, follow these steps in the Administration Console.
Open the URL http://localhost:4848/ in a browser.
Select the GlassFish Server node.
Select the Advanced tab.
To disable dynamic reloading, deselect the Reload Enabled check box.
To change the interval at which applications and modules are checked for code changes and dynamically reloaded, type a number of seconds in the Reload Poll Interval field.
The default value is 2 seconds.
Click the Save button.
You can undeploy web modules and other types of enterprise applications by using either NetBeans IDE or the Ant tool.
Ensure that the GlassFish Server is running.
In the Services window, expand the Servers node, GlassFish Server instance, and the Applications node.
Right-click the hello1 module and choose Undeploy.
To delete the class files and other build artifacts, right-click the project and choose Clean.
In a terminal window, go to:
tut-install/examples/web/hello1/ |
Type the following command:
ant undeploy |
To delete the class files and other build artifacts, type the following command:
ant clean |
Web applications are configured by means of annotations or by 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. Examples demonstrate procedures for configuring the Hello, World application.
When it receives a request, the web container must determine which web component should handle the request. The web container 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, optionally, a URL pattern:
http://host:port/context-root[/url-pattern] |
You set the URL pattern for a servlet by using the @WebServlet annotation in the servlet source file. For example, the GreetingServlet.java file in the hello2 application contains the following annotation, specifying the URL pattern as /greeting:
@WebServlet("/greeting") public class GreetingServlet extends HttpServlet { ...
This annotation indicates that the URL pattern /greeting follows the context root. Therefore, when the servlet is deployed locally, it is accessed with the following URL:
http://localhost:8080/hello2/greeting |
To access the servlet by using only the context root, specify "/" as the URL pattern.
The hello2 application behaves almost identically to the hello1 application, but it is implemented using Java Servlet technology instead of JavaServer Faces technology. You can use a text editor to view the application files, or you can use NetBeans IDE.
In NetBeans IDE, select File->Open Project.
In the Open Project dialog, navigate to:
tut-install/examples/web/ |
Select the hello2 folder.
Select the Open as Main Project check box.
Expand the Source Packages node, then the servlets node.
Double-click the GreetingServlet.java file to view it.
This servlet overrides the doGet method, implementing the GET method of HTTP. The servlet displays a simple HTML greeting form whose Submit button, like that of hello1, specifies a response page for its action. The following excerpt begins with the @WebServlet annotation that specifies the URL pattern, relative to the context root:
@WebServlet("/greeting") public class GreetingServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setBufferSize(8192); PrintWriter out = response.getWriter(); // then write the data of the response out.println("<html>" + "<head><title>Servlet Hello</title></head>"); // then write the data of the response out.println("<body bgcolor=\"#ffffff\">" + "<img src=\"duke.waving.gif\" alt=\"Duke waving\">" + "<h2>Hello, 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>"); String username = request.getParameter("username"); if (username != null && username.length() > 0) { RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/response"); if (dispatcher != null) { dispatcher.include(request, response); } } out.println("</body></html>"); out.close(); } ...
Double-click the ResponseServlet.java file to view it.
This servlet also overrides the doGet method, displaying only the response. The following excerpt begins with the @WebServlet annotation, which specifies the URL pattern, relative to the context root:
@WebServlet("/response") public class ResponseServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); // then write the data of the response String username = request.getParameter("username"); if (username != null && username.length() > 0) { out.println("<h2>Hello, " + username + "!</h2>"); } } ...
Under the Web Pages node, expand the WEB-INF node and double-click the sun-web.xml file to view it.
In the General tab, observe that the Context Root field is set to /hello2.
For this simple servlet application, a web.xml file is not required.
You can use either NetBeans IDE or Ant to build, package, deploy, and run the hello2 example.
Select File->Open Project.
In the Open Project dialog, navigate to:
tut-install/examples/web/ |
Select the hello2 folder.
Select the Open as Main Project check box.
Click Open Project.
In the Projects tab, right-click the hello2 project and select Build.
Right-click the project and select Deploy.
In a web browser, open the URL http://localhost:8080/hello2/greeting.
The URL specifies the context root, followed by the URL pattern.
The application looks much like the hello1 application shown in Figure 3–2. The major difference is that after you click the Submit button, the response appears below the greeting, not on a separate page.
In a terminal window, go to:
tut-install/examples/web/hello2/ |
Type the following command:
ant |
This target builds the WAR file and copies it to the tut-install/examples/web/hello2/dist/ directory.
Type ant deploy.
Ignore the URL shown in the deploy target output.
In a web browser, open the URL http://localhost:8080/hello2/greeting.
The URL specifies the context root, followed by the URL pattern.
The application looks much like the hello1 application shown in Figure 3–2. The major difference is that after you click the Submit button, the response appears below the greeting, not on a separate page.
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 that 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 XHTML 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 that matches in the WAR.
If no welcome file is specified, the GlassFish Server will use a file named index.html as the default welcome file. If there is no welcome file and no file named index.html, the GlassFish Server returns a directory listing.
By convention, you specify the welcome file for a JavaServer Faces application as faces/file-name.xhtml.
The web components in a web module share an object that represents their application context. You can pass initialization parameters to the context or to a web component.
Open the project if you haven’t already.
Expand the project’s node in the Projects pane.
Expand the Web Pages node and then the WEB-INF node.
Double-click web.xml.
Click General at the top of the editor pane.
Expand the Context Parameters node.
Click Add.
An Add Context Parameter dialog opens.
In the Parameter Name field, type the name that specifies the context object.
In the Parameter Value field, type the parameter to pass to the context object.
Click OK.
You can use the @WebServlet annotation to specify web component initialization parameters by using the initParams attribute and the @WebInitParam annotation. For example:
@WebServlet(urlPatterns="/MyPattern", initParams= {@WebInitParam(name="ccc", value="333")}) |
Alternatively, you can add an initialization parameter to the web.xml file. To do this using NetBeans IDE, follow these steps.
Open the project if you haven’t already.
Expand the project’s node in the Projects pane.
Expand the Web Pages node and then the WEB-INF node.
Double-click web.xml.
Click Servlets at the top of the editor pane.
Click the Add button under the Initialization Parameters table.
An Add Initialization Parameter dialog opens.
In the Parameter Name field, type the name of the parameter.
In the Parameter Value Field, type the parameter’s value.
Click OK.
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 and any type of error screen.
You can have multiple error-page elements in your deployment descriptor. Each element 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.
Open the project if you haven’t already.
Expand the project’s node in the Projects pane.
Expand the Web Pages node and then the WEB-INF node.
Double-click web.xml.
Click Pages at the top of the editor pane.
Expand the Error Pages node.
Click Add.
The Add Error Page dialog opens.
Click Browse to locate the page that you want to act as the error page.
In the Error Code field, type the HTTP status code that will cause the error page to be opened.
In the Exception Type field, type the exception that will cause the error page to load.
Click OK.
If your web component uses such objects 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 on using it in web applications. First, you can inject resources only into container-managed objects, since 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 such objects as simple JavaBeans components. However, JavaServer Faces managed beans are managed by the container; therefore, they can accept resource injections.
Components that can accept resource injections are listed in Table 3–1.
This section explains how to use a couple of the annotations supported by a servlet container to inject resources. Chapter 21, Running the Persistence Examples, explains how web applications use annotations supported by the Java Persistence API. Chapter 25, Getting Started Securing Web Applications, explains 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 |
The @Resource annotation is used to declare a reference to a resource, such as a data source, an enterprise bean, or an environment entry.
The @Resource annotation is specified on a class, a method, or a 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’s 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 21, Running the Persistence Examples describes these annotations and the use of the Java Persistence API in web applications.
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;
For more information on web applications, see
JavaServer Faces 2.0 specification:
JavaServer Faces technology web site:
http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html
Java Servlet 3.0 specification:
Java Servlet web site:
http://www.oracle.com/technetwork/java/index-jsp-135475.html
JavaServer Faces technology is a server-side component framework for building Java technology-based web applications.
JavaServer Faces technology consists of the following:
An API for representing components and managing their state; handling events, server-side validation, and data conversion; defining page navigation; supporting internationalization and accessibility; and providing extensibility for all these features
Tag libraries for adding components to web pages and for connecting components to server-side objects
JavaServer Faces technology provides a well-defined programming model and various tag libraries. These features significantly ease the burden of building and maintaining web applications with server-side user interfaces (UIs). With minimal effort, you can complete the following tasks.
Create a web page.
Drop components onto a web page by adding component tags.
Bind components on a page to server-side data.
Wire component-generated events to server-side application code.
Save and restore application state beyond the life of server requests.
Reuse and extend components through customization.
This chapter provides an overview of JavaServer Faces technology. After explaining what a JavaServer Faces application is and reviewing some of the primary benefits of using JavaServer Faces technology, this chapter describes the process of creating a simple JavaServer Faces application. This chapter also introduces the JavaServer Faces lifecycle by describing the example JavaServer Faces application progressing through the lifecycle stages.
The following topics are addressed here:
The functionality provided by a JavaServer Faces application is similar to that of any other Java web application. A typical JavaServer Faces application includes the following parts:
A set of web pages in which components are laid out
A set of tags to add components to the web page
A set of backing beans, which are JavaBeans components that define properties and functions for components on a page
A web deployment descriptor (web.xml file)
Optionally, one or more application configuration resource files, such as a faces-config.xml file, which can be used to define page navigation rules and configure beans and other custom objects, such as custom components
Optionally, a set of custom objects, which can include custom components, validators, converters, or listeners, created by the application developer
A set of custom tags for representing custom objects on the page
Figure 4–1 shows the interaction between client and server in a typical JavaServer Faces application. In response to a client request, a web page is rendered by the web container that implements JavaServer Faces technology.
The web page, myfacelet.xhtml, is built using JavaServer Faces component tags. Component tags are used to add components to the view (represented by myUI in the diagram), which is the server-side representation of the page. In addition to components, the web page can also reference objects, such as the following:
Any event listeners, validators, and converters that are registered on the components
The JavaBeans components that capture the data and process the application-specific functionality of the components
On request from the client, the view is rendered as a response. Rendering is the process whereby, based on the server-side view, the web container generates output, such as HTML or XHTML, that can be read by the client, such as a browser.
One of the greatest advantages of JavaServer Faces technology is that it offers a clean separation between behavior and presentation for web applications. A JavaServer Faces application can map HTTP requests to component-specific event handling and manage components as stateful objects on the server. 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 a single piece of the development process and provides a simple programming model to link the pieces. For example, page authors with no programming expertise can use JavaServer Faces technology tags in a web page to link to server-side objects without writing any scripts.
Another important goal of JavaServer Faces technology is to leverage familiar component and web-tier concepts without limiting you to a particular scripting technology or markup language. JavaServer Faces technology APIs are layered directly on top of the Servlet API, as shown in Figure 4–2.
This layering of APIs enables several important application use cases, such as using different presentation technologies, creating your own custom components directly from the component classes, and generating output for various client devices.
Facelets technology, available as part of JavaServer Faces 2.0, is now the preferred presentation technology for building JavaServer Faces technology-based web applications. For more information on Facelets technology features, see Chapter 5, Introduction to Facelets.
Facelets technology offers several advantages.
Code can be reused and extended for components through the templating and composite component features.
When you use the JavaServer Faces Annotations feature, you can automatically register the backing bean as a resource available for JavaServer Faces applications. In addition, implicit navigation rules allow developers to quickly configure page navigation. These features reduce the manual configuration process for applications.
Most important, JavaServer Faces technology provides a rich architecture for managing component state, processing component data, validating user input, and handling events.
JavaServer Faces technology provides an easy and user-friendly process for creating web applications. Developing a simple JavaServer Faces application typically requires the following tasks:
Developing backing beans
Adding managed bean declarations
Creating web pages using component tags
Mapping the FacesServlet instance
This section describes those tasks through the process of creating a simple JavaServer Faces Facelets application.
The example is a Hello application that includes a backing bean and a web page. When accessed by a client, the web page prints out a Hello World message. The example application is located in the directory tut-install/examples/web/hello. The tasks involved in developing this application can be examined by looking at the application components in detail.
As mentioned earlier in this chapter, a backing bean, a type of managed bean, is a JavaBeans component that is managed by JavaServer Faces technology. Components in a page are associated with backing beans that provide application logic. The example backing bean, Hello.java, contains the following code:
package hello; import javax.faces.bean.ManagedBean; @ManagedBean public class Hello { final String world = "Hello World!"; public String getworld() { return world; } }
The example backing bean sets the value of the variable world with the string "Hello World!". The @ManagedBean annotation registers the backing bean as a resource with the JavaServer Faces implementation. For more information on managed beans and annotations, see Chapter 9, Developing with JavaServer Faces Technology.
In a typical Facelets application, web pages are created in XHTML. The example web page, beanhello.xhtml, is a simple XHTML page. It has the following content:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Facelets Hello World</title> </h:head> <h:body> #{hello.world} </h:body> </html>
A Facelets XHTML web page can also contain several other elements, which are covered later in this tutorial.
The web page connects to the backing bean through the Expression Language (EL) value expression #{hello.world}, which retrieves the value of the world property from the backing bean Hello. Note the use of hello to reference the backing bean Hello. If no name is specified in the @ManagedBean annotation, the backing bean is always accessed with the first letter of the class name in lowercase.
For more information on using EL expressions, see Chapter 6, Expression Language. For more information about Facelets technology, see Chapter 5, Introduction to Facelets. For more information about the JavaServer Faces programming model and building web pages using JavaServer Faces technology, see Chapter 7, Using JavaServer Faces Technology in Web Pages.
The final task requires mapping the FacesServlet, which is done through the web deployment descriptor (web.xml). A typical mapping of FacesServlet is as follows:
<servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping>
The preceding file segment represents part of a typical JavaServer Faces web deployment descriptor. The web deployment descriptor can also contain other content relevant to a JavaServer Faces application configuration, but that information is not covered here.
Mapping the FacesServlet is automatically done for you if you are using an IDE such as NetBeans IDE.
Every web application has a lifecycle. Common tasks, such as handling incoming requests, decoding parameters, modifying and saving state, and rendering web pages to the browser, are all performed during a web application lifecycle. Some web application frameworks hide the details of the lifecycle from you, whereas others require you to manage them manually.
By default, JavaServer Faces automatically handles most of the lifecycle actions for you. However, it also exposes the various stages of the request lifecycle, so that you can modify or perform different actions if your application requirements warrant it.
It is not necessary for the beginning user to understand the lifecycle of a JavaServer Faces application, but the information can be useful for creating more complex applications.
The lifecycle of a JavaServer Faces application starts and ends with the following activity: The client makes a request for the web page, and the server responds with the page. The lifecycle consists of two main phases: execute and render.
During the execute phase, several actions can take place:
The application view is built or restored.
The request parameter values are applied.
Conversions and validations are performed for component values.
Backing beans are updated with component values.
Application logic is invoked.
For a first (initial) request, only the view is built. For subsequent (postback) requests, some or all of the other actions can take place.
In the render phase, the requested view is rendered as a response to the client. Rendering is typically the process of generating output, such as HTML or XHTML, that can be read by the client, usually a browser.
The following short description of the example JavaServer Faces application passing through its lifecycle summarizes the activity that takes place behind the scenes.
The hello example application goes through the following stages when it is deployed on the GlassFish Server.
When the hello application is built and deployed on the GlassFish Server, the application is in an uninitiated state.
When a client makes an initial request for the beanhello.xhtml web page, the hello Facelets application is compiled.
The compiled Facelets application is executed, and a new component tree is constructed for the hello application and is placed in a FacesContext.
The component tree is populated with the component and the backing bean property associated with it, represented by the EL expression hello.world.
A new view is built, based on the component tree.
The view is rendered to the requesting client as a response.
The component tree is destroyed automatically.
On subsequent (postback) requests, the component tree is rebuilt, and the saved state is applied.
For more detailed information on the JavaServer Faces lifecycle, see the JavaServer Faces Specification, Version 2.0.
In NetBeans IDE, select File->Open Project.
In the Open Project dialog box, navigate to:
tut-install/examples/web |
Select the hello folder.
Select the Open as Main Project check box.
Click Open Project.
In the Projects tab, right-click the hello project and select Run.
This step compiles, assembles, and deploys the application and then brings up a web browser window displaying the following URL:
http://localhost:8080/hello |
The output looks like this:
Hello World! |
For more information on JavaServer Faces technology, see
JavaServer Faces 2.0 specification:
JavaServer Faces technology web site:
http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html
JavaServer Faces 2.0 technology download web site:
http://www.oracle.com/technetwork/java/javaee/download-139288.html
Mojarra (JavaServer Faces 2.0) Release Notes:
https://javaserverfaces.dev.java.net/nonav/rlnotes/2.0.0/index.html
The term Facelets refers to the view declaration language for JavaServer Faces technology. JavaServer Pages (JSP) technology, previously used as the presentation technology for JavaServer Faces, does not support all the new features available in JavaServer Faces 2.0. JSP technology is considered to be a deprecated presentation technology for JavaServer Faces 2.0. Facelets is a part of the JavaServer Faces specification and also the preferred presentation technology for building JavaServer Faces technology-based applications.
The following topics are addressed here:
Facelets is a powerful but lightweight page declaration language that is used to build JavaServer Faces views using HTML style templates and to build component trees. Facelets features include the following:
Use of XHTML for creating web pages
Support for Facelets tag libraries in addition to JavaServer Faces and JSTL tag libraries
Support for the Expression Language (EL)
Templating for components and pages
Advantages of Facelets for large-scale development projects include the following:
Support for code reuse through templating and composite components
Functional extensibility of components and other server-side objects through customization
Faster compilation time
Compile-time EL validation
High-performance rendering
In short, the use of Facelets reduces the time and effort that needs to be spent on development and deployment.
Facelets views are usually created as XHTML pages. JavaServer Faces implementations support XHTML pages created in conformance with the XHTML Transitional Document Type Definition (DTD), as listed at http://www.w3.org/TR/xhtml1/#a_dtd_XHTML-1.0-Transitional. By convention, web pages built with XHTML have an .xhtml extension.
JavaServer Faces technology supports various tag libraries to add components to a web page. To support the JavaServer Faces tag library mechanism, Facelets uses XML namespace declarations. Table 5–1 lists the tag libraries supported by Facelets.
Table 5–1 Tag Libraries Supported by Facelets
Tag Library |
URI |
Prefix |
Example |
Contents |
---|---|---|---|---|
JavaServer Faces Facelets Tag Library |
http://java.sun.com/jsf/facelets |
ui: |
ui:component ui:insert |
Tags for templating |
JavaServer Faces HTML Tag Library |
http://java.sun.com/jsf/html |
h: |
h:head h:body h:outputText h:inputText |
JavaServer Faces component tags for all UIComponents |
JavaServer Faces Core Tag Library |
http://java.sun.com/jsf/core |
f: |
f:actionListener f:attribute |
Tags for JavaServer Faces custom actions that are independent of any particular RenderKit |
JSTL Core Tag Library |
http://java.sun.com/jsp/jstl/core |
c: |
c:forEach c:catch |
JSTL 1.1 Core Tags |
JSTL Functions Tag Library |
http://java.sun.com/jsp/jstl/functions |
fn: |
fn:toUpperCase fn:toLowerCase |
JSTL 1.1 Functions Tags |
In addition, Facelets supports tags for composite components for which you can declare custom prefixes. For more information on composite components, see Composite Components.
Based on the JavaServer Faces support for Expression Language (EL) syntax defined by JSP 2.1, Facelets uses EL expressions to reference properties and methods of backing beans. EL expressions can be used to bind component objects or values to methods or properties of managed beans. For more information on using EL expressions, see Using the EL to Reference Backing Beans.
This section describes the general steps involved in developing a JavaServer Faces application. The following tasks are usually required:
Developing the backing beans
Creating the pages using the component tags
Defining page navigation
Mapping the FacesServlet instance
Adding managed bean declarations
The example used in this tutorial is the guessnumber application. The application presents you with a page that asks you to guess a number between 0 and 10, validates your input against a random number, and responds with another page that informs you whether you guessed the number correctly or incorrectly.
In a typical JavaServer Faces application, each page of the application connects to a backing bean, a type of managed bean. The backing bean defines the methods and properties that are associated with the components.
The following managed bean class, UserNumberBean.java, generates a random number from 0 to 10:
package guessNumber; import java.util.Random; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @ManagedBean @SessionScoped public class UserNumberBean { Integer randomInt = null; Integer userNumber = null; String response = null; private long maximum=10; private long minimum=0; public UserNumberBean() { Random randomGR = new Random(); randomInt = new Integer(randomGR.nextInt(10)); System.out.println("Duke's number: " + randomInt); } 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."; } } public long getMaximum() { return (this.maximum); } public void setMaximum(long maximum) { this.maximum = maximum; } public long getMinimum() { return (this.minimum); } public void setMinimum(long minimum) { this.minimum = minimum; } }
Note the use of the @ManagedBean annotation, which registers the backing bean as a resource with JavaServer Faces implementation. The @SessionScoped annotation registers the bean scope as session.
Creating a page or view is the responsibility of a page author. This task involves adding components on the pages, wiring the components to backing bean values and properties, and registering converters, validators, or listeners onto the components.
For the example application, XHTML web pages serve as the front end. The first page of the example application is a page called greeting.xhtml. A closer look at various sections of this web page provides more information.
The first section of the web page declares the content type for the page, which is XHTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The next section declares the XML namespace for the tag libraries that are used in the web page:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
The next section uses various tags to insert components into the web page:
h:head> <title>Guess Number Facelets Application</title> </h:head> <h:body> <h:form> <h:graphicImage value="#{resource['images:wave.med.gif']}"/> <h2> Hi, my name is Duke. I am thinking of a number from #{userNumberBean.minimum} to #{userNumberBean.maximum}. Can you guess it? <p></p> <h:inputText id="userNo" value="#{userNumberBean.userNumber}"> <f:validateLongRange minimum="#{userNumberBean.minimum}" maximum="#{userNumberBean.maximum}"/> </h:inputText> <h:commandButton id="submit" value="Submit" action="response.xhtml"/> <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"/> </h2> </h:form> </h:body>
Note the use of the following tags:
Facelets HTML tags (those beginning with h:) to add components
The Facelets core tag f:validateLongRange to validate the user input
An inputText component accepts user input and sets the value of the backing bean property userNumber through the EL expression #{userNumberBean.userNumber}. The input value is validated for value range by the JavaServer Faces standard validator f:validateLongRange.
The image file, wave.med.gif, is added to the page as a resource. For more details about the resources facility, see Resources.
A commandButton component with the ID submit starts validation of the input data when a user clicks the button. Using implicit navigation, the component redirects the client to another page, response.xhtml, which shows the response to your input.
You can now create the second page, response.xhtml, with the following content:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Guess Number Facelets Application</title> </h:head> <h:body> <h:form> <h:graphicImage value="#{resource['images:wave.med.gif']}"/> <h2> <h:outputText id="result" value="#{userNumberBean.response}"/> </h2> <h:commandButton id="back" value="Back" action="greeting.xhtml"/> </h:form> </h:body> </html>
Configuring a JavaServer Faces application involves mapping the Faces Servlet in the web deployment descriptor file, such as a web.xml file, and possibly adding managed bean declarations, navigation rules, and resource bundle declarations to the application configuration resource file, faces-config.xml.
If you are using NetBeans IDE, a web deployment descriptor file is automatically created for you. In such an IDE-created web.xml file, change the default greeting page, which is index.xhtml, to greeting.xhtml. Here is an example web.xml file, showing this change in bold.
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file>faces/greeting.xhtml</welcome-file> </welcome-file-list> </web-app>
Note the use of the context parameter PROJECT_STAGE. This parameter identifies the status of a JavaServer Faces application in the software lifecycle.
The stage of an application can affect the behavior of the application. For example, if the project stage is defined as Development, debugging information is automatically generated for the user. If not defined by the user, the default project stage is Production.
You can use either NetBeans IDE or Ant to build, package, deploy, and run the guessnumber example. The source code for this example is available in the tut-install/examples/web/guessnumber directory.
In NetBeans IDE, select File->Open Project.
In the Open Project dialog, navigate to:
tut-install/examples/web/ |
Select the guessnumber folder.
Select the Open as Main Project check box.
Click Open Project.
In the Projects tab, right-click the guessnumber project and select Deploy.
This option builds and deploys the example application to your GlassFish Server instance.
In a terminal window, go to:
tut-install/examples/web/guessnumber/ |
Type the following command:
ant |
This command calls the default target, which builds and packages the application into a WAR file, guessnumber.war, that is located in the dist directory.
Make sure that the GlassFish Server is started.
To deploy the application, type the following command:
ant deploy |
Open a web browser.
Type the following URL in your web browser:
http://localhost:8080/guessnumber |
The web page shown in Figure 5–1 appears.
In the text field, type a number from 0 to 10 and click Submit.
Another page appears, reporting whether your guess is correct or incorrect.
If you guessed incorrectly, click the Back button to return to the main page.
You can continue to guess until you get the correct answer.
JavaServer Faces technology provides the tools to implement user interfaces that are easy to extend and reuse. Templating is a useful Facelets feature that allows you to create a page that will act as the base, or template, for the other pages in an application. By using templates, you can reuse code and avoid recreating similarly constructed pages. Templating also helps in maintaining a standard look and feel in an application with a large number of pages.
Table 5–2 lists Facelets tags that are used for templating and their respective functionality.
Table 5–2 Facelets Templating Tags
Tag |
Function |
---|---|
ui:component |
Defines a component that is created and added to the component tree. |
ui:composition |
Defines a page composition that optionally uses a template. Content outside of this tag is ignored. |
ui:debug |
Defines a debug component that is created and added to the component tree. |
ui:decorate |
Similar to the composition tag but does not disregard content outside this tag. |
ui:define |
Defines content that is inserted into a page by a template. |
ui:fragment |
Similar to the component tag but does not disregard content outside this tag. |
ui:include |
Encapsulate and reuse content for multiple pages. |
ui:insert |
Inserts content into a template. |
ui:param |
Used to pass parameters to an included file. |
ui:repeat |
Used as an alternative for loop tags, such as c:forEach or h:dataTable. |
ui:remove |
Removes content from a page. |
For more information on Facelets templating tags, see the documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/.
The Facelets tag library includes the main templating tag ui:insert. A template page that is created with this tag allows you to define a default structure for a page. A template page is used as a template for other pages, usually referred to as client pages.
Here is an example of a template saved as template.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link href="./resources/css/default.css" rel="stylesheet" type="text/css" /> <link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" /> <title>Facelets Template</title> </h:head> <h:body> <div id="top" class="top"> <ui:insert name="top">Top Section</ui:insert> </div> <div> <div id="left"> <ui:insert name="left">Left Section</ui:insert> </div> <div id="content" class="left_content"> <ui:insert name="content">Main Content</ui:insert> </div> </div> </h:body> </html>
The example page defines an XHTML page that is divided into three sections: a top section, a left section, and a main section. The sections have style sheets associated with them. The same structure can be reused for the other pages of the application.
The client page invokes the template by using the ui:composition tag. In the following example, a client page named templateclient.xhtml invokes the template page named template.xhtml from the preceding example. A client page allows content to be inserted with the help of the ui:define tag.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <h:body> <ui:composition template="./template.xhtml"> <ui:define name="top"> Welcome to Template Client Page </ui:define> <ui:define name="left"> <h:outputLabel value="You are in the Left Section"/> </ui:define> <ui:define name="content"> <h:graphicImage value="#{resource['images:wave.med.gif']}"/> <h:outputText value="You are in the Main Content Section"/> </ui:define> </ui:composition> </h:body> </html>
You can use NetBeans IDE to create Facelets template and client pages. For more information on creating these pages, see http://netbeans.org/kb/docs/web/jsf20-intro.html.
JavaServer Faces technology offers the concept of composite components with Facelets. A composite component is a special type of template that acts as a component.
Any component is essentially a piece of reusable code that behaves in a particular way. For example, an inputText component accepts user input. A component can also have validators, converters, and listeners attached to it to perform certain defined actions.
A composite component consists of a collection of markup tags and other existing components. This reusable, user-created component has a customized, defined functionality and can have validators, converters, and listeners attached to it like any other component.
With Facelets, any XHTML page that contains markup tags and other components can be converted into a composite component. Using the resources facility, the composite component can be stored in a library that is available to the application from the defined resources location.
Table 5–3 lists the most commonly used composite tags and their functions.
Table 5–3 Composite Component Tags
Tag |
Function |
---|---|
composite:interface |
Declares the usage contract for a composite component. The composite component can be used as a single component whose feature set is the union of the features declared in the usage contract. |
composite:implementation |
Defines the implementation of the composite component. If a composite:interface element appears, there must be a corresponding composite:implementation. |
composite:attribute |
Declares an attribute that may be given to an instance of the composite component in which this tag is declared. |
composite:insertChildren |
Any child components or template text within the composite component tag in the using page will be reparented into the composite component at the point indicated by this tag’s placement within the composite:implementation section. |
composite:valueHolder |
Declares that the composite component whose contract is declared by the composite:interface in which this element is nested exposes an implementation of ValueHolder suitable for use as the target of attached objects in the using page. |
composite:editableValueHolder |
Declares that the composite component whose contract is declared by the composite:interface in which this element is nested exposes an implementation of EditableValueHolder suitable for use as the target of attached objects in the using page. |
composite:actionSource |
Declares that the composite component whose contract is declared by the composite:interface in which this element is nested exposes an implementation of ActionSource2 suitable for use as the target of attached objects in the using page. |
For more information and a complete list of Facelets composite tags, see the documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/.
The following example shows a composite component that accepts an email address as input:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:composite="http://java.sun.com/jsf/composite" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>This content will not be displayed</title> </h:head> <h:body> <composite:interface> <composite:attribute name="value" required="false"/> </composite:interface> <composite:implementation> <h:outputLabel value="Email id: "></h:outputLabel> <h:inputText value="#{cc.attrs.value}"></h:inputText> </composite:implementation> </h:body> </html>
Note the use of cc.attrs.value when defining the value of the inputText component. The word cc in JavaServer Faces is a reserved word for composite components. The #{cc.attrs.attribute-name} expression is used to access the attributes defined for the composite component’s interface, which in this case happens to be value.
The preceding example content is stored as a file named email.xhtml in a folder named resources/emcomp, under the application web root directory. This directory is considered a library by JavaServer Faces, and a component can be accessed from such a library. For more information on resources, see Resources.
The web page that uses this composite component is generally called a using page. The using page includes a reference to the composite component, in the xml namespace declarations:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:em="http://java.sun.com/jsf/composite/emcomp/"> <h:head> <title>Using a sample composite component</title> </h:head> <body> <h:form> <em:email value="Enter your email id" /> </h:form> </body> </html>
The local composite component library is defined in the xml namespace with the declaration xmlns:em="http://java.sun.com/jsf/composite/emcomp/". The component itself is accessed through the use of em:email tag. The preceding example content can be stored as a web page named emuserpage.xhtml under the web root directory. When compiled and deployed on a server, it can be accessed with the following URL:
http://localhost:8080/application-name/faces/emuserpage.xhtml
Web resources are any software artifacts that the web application requires for proper rendering, including images, script files, and any user-created component libraries. Resources must be collected in a standard location, which can be one of the following.
A resource packaged in the web application root must be in a subdirectory of a resources directory at the web application root: resources/resource-identifier.
A resource packaged in the web application’s classpath must be in a subdirectory of the META-INF/resources directory within a web application: META-INF/resources/resource-identifier.
The JavaServer Faces runtime will look for the resources in the preceding listed locations, in that order.
Resource identifiers are unique strings that conform to the following format:
[locale-prefix/][library-name/][library-version/]resource-name[/resource-version]
Elements of the resource identifier in brackets ([]) are optional, indicating that only a resource-name, which is usually a file name, is a required element.
Resources can be considered as a library location. Any artifact, such as a composite component or a template that is stored in the resources directory, becomes accessible to the other application components, which can use it to create a resource instance.
This chapter introduces the Expression Language (also referred to as the EL), which provides an important mechanism for enabling the presentation layer (web pages) to communicate with the application logic (backing beans). The EL is used by both JavaServer Faces technology and JavaServer Pages (JSP) technology. The EL represents a union of the expression languages offered by JavaServer Faces technology and JSP technology.
The following topics are addressed here:
The EL allows page authors to use simple expressions to dynamically access data from JavaBeans components. For example, the test attribute of the following conditional tag is supplied with an EL expression that compares 0 with the number of items in the session-scoped bean named cart.
<c:if test="${sessionScope.cart.numberOfItems > 0}"> ... </c:if>
JavaServer Faces technology uses the EL for the following functions:
Deferred and immediate evaluation of expressions
The ability to set as well as get data
The ability to invoke methods
See Using the EL to Reference Backing Beans for more information on how to use the EL in JavaServer Faces applications.
To summarize, the EL provides a way to use simple expressions to perform the following tasks:
Dynamically read application data stored in JavaBeans components, various data structures, and implicit objects
Dynamically write data, such as user input into forms, to JavaBeans components
Invoke arbitrary static and public methods
Dynamically perform arithmetic operations
The EL is also used to specify the following kinds of expressions that a custom tag attribute will accept:
Immediate evaluation expressions or deferred evaluation expressions. An immediate evaluation expression is evaluated at once by the underlying technology, such as JavaServer Faces. A deferred evaluation expression can be evaluated later by the underlying technology using the EL.
Value expression or method expression. A value expression references data, whereas a method expression invokes a method.
Rvalue expression or lvalue expression. An rvalue expression can only read a value, whereas an lvalue expression can both read and write that value to an external object.
Finally, the EL provides a pluggable API for resolving expressions so custom resolvers that can handle expressions not already supported by the EL can be implemented.
The EL supports both immediate and deferred evaluation of expressions. Immediate evaluation means that the expression is evaluated and the result returned as soon as the page is first rendered. Deferred evaluation means that the technology using the expression language can use its own machinery to evaluate the expression sometime later during the page’s lifecycle, whenever it is appropriate to do so.
Those expressions that are evaluated immediately use the ${} syntax. Expressions whose evaluation is deferred use the #{} syntax.
Because of its multiphase lifecycle, JavaServer Faces technology uses mostly deferred evaluation expressions. During the lifecycle, component events are handled, data is validated, and other tasks are performed in a particular order. Therefore, a JavaServer Faces implementation must defer evaluation of expressions until the appropriate point in the lifecycle.
Other technologies using the EL might have different reasons for using deferred expressions.
All expressions using the ${} syntax are evaluated immediately. These expressions can be used only within template text or as the value of a 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 JavaServer Faces implementation 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 preceding example expression cannot set the total price, but instead can only get the total price from the cart bean.
Deferred evaluation expressions take the form #{expr} and can be evaluated at other phases of a page lifecycle 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 lifecycle, 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 lifecycle. During this phase, the expression merely accesses the value of name from the customer bean, as is done in immediate evaluation.
For a postback request, the JavaServer Faces implementation evaluates the expression at different phases of the lifecycle, 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
Method expressions
Value expressions (both immediate and deferred) and method expressions are explained in the next section.
The 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 can be further categorized into rvalue and lvalue expressions. Rvalue expressions 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 the following two value expressions:
${customer.name}
#{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, adds the value to the response, and gets rendered on the page. The same can happen with the second expression. However, the tag handler can defer the evaluation of this expression to a later time in the page lifecycle, if the technology using this tag allows.
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 request, this expression can be used to set the value of the name property with user input. In this case, the expression acts as an lvalue expression.
Both rvalue and lvalue expressions can refer to the following objects and their properties or attributes:
JavaBeans components
Collections
Java SE enumerated types
Implicit objects
To refer to these objects, you write an expression using a variable that is the name of the object. The following expression references a backing bean (a JavaBeans component) called customer:
${customer}
The web container evaluates the 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, a null value is returned.
You can use a custom EL resolver to alter the way variables are resolved. 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.
To reference an enum constant with an expression, 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, 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 Suit.hearts before it is compared to the instance:
${mySuit == "hearts"}
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.
To reference the name property of the customer bean, use either the expression ${customer.name} or the expression ${customer["name"]}. The part inside the 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 constant can also be referenced in this way. However, as with JavaBeans component properties, the properties of an Enum class must follow JavaBeans component conventions. This means that a property must at least have an accessor method called getProperty, where Property is the name of the property that can be referenced by an expression.
For example, consider 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 Enum class Planet:
${myPlanet.mass}
If you are accessing an item in an array or list, you must use either a literal value that can be converted to int or the [] notation with an int and without quotes. The following examples could resolve to the same item in a list or array, assuming that socks can be converted to int:
${customer.orders[1]}
${customer.orders.socks}
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:
${"literal"}
${customer.age + 20}
${true}
${57}
The EL defines the following literals:
Boolean: true and false
Integer: as in Java
Floating-point: as in Java
String: with single and double quotes; " is escaped as \", ' is escaped as \', and \ is escaped as \\
Null: null
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 whether mySuit is spade:
${mySuit == "spade"}
When it resolves this expression, the EL resolving mechanism 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"}
Value expressions using the ${} delimiters can be used in
Static text
Any standard or custom tag attribute that can accept an expression
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.
Lvalue expressions can be used only in tag attributes that can accept lvalue expressions.
A tag attribute value using either an rvalue or lvalue expression can be set in the following ways:
With a single expression construct:
<some:tag value="${expr}"/>
<another:tag value="#{expr}"/>
These expressions are evaluated, and the result is converted to the attribute’s expected type.
With one or more expressions separated or surrounded by text:
<some:tag value="some${expr}${expr}text${expr}"/>
<another:tag value="some#{expr}#{expr}text#{expr}"/>
These kinds of expression, called composite expressions, are evaluated from left to right. Each expression embedded in the composite expression is converted to a String and then concatenated with any intervening text. The resulting String is then converted to the attribute’s expected type.
With text only:
<some:tag value="sometext"/>
This expression is called a literal expression. In this case, the attribute’s String value is converted to the attribute’s expected type. Literal value expressions have special syntax rules. See Literal Expressions for more information. When a tag attribute has an enum type, the expression that the attribute uses must be a literal expression. For example, the tag attribute can use the expression "hearts" to mean Suit.hearts. The literal is converted to Suit, and the attribute gets the value Suit.hearts.
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.2 Expression Language specification (available from http://jcp.org/aboutJava/communityprocess/final/jsr245/) for the complete type conversion rules.
Another feature of the EL is its support of deferred method expressions. A method expression is used to invoke an arbitrary public method of a bean, which can return a result.
In JavaServer Faces technology, a component tag represents a 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 for 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 as a text field. The validator attribute of this inputText tag references a method, called validateName, in the bean, called customer.
Because a method can be invoked during different phases of the lifecycle, method expressions must always use the deferred evaluation syntax.
Like lvalue expressions, method expressions can use the . and the [] operators. For example, #{object.method} is equivalent to #{object["method"]}. The literal inside the [] is converted 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:
With a single expression construct, where bean refers to a JavaBeans component and method refers to a method of the JavaBeans component:
<some:tag value="#{bean.method}"/>
The expression is evaluated to a method expression, which is passed to the tag handler. The method represented by the method expression can then be invoked later.
With text only:
<some:tag value="sometext"/>
Method expressions support literals primarily to support action attributes in JavaServer Faces technology. When the method referenced by this method expression is invoked, the method returns the String literal, which is then converted to the expected return type, as defined in the tag’s tag library descriptor.
The EL offers support for parameterized method calls. Method calls can use parameters without having to use static EL functions.
Both the . and [] operators can be used for invoking method calls with parameters, as shown in the following expression syntax:
expr-a[expr-b](parameters)
expr-a.identifier-b(parameters)
In the first expression syntax, expr-a is evaluated to represent a bean object. The expression expr-b is evaluated and cast to a string that represents a method in the bean represented by expr-a. In the second expression syntax, expr-a is evaluated to represent a bean object, and identifier-b is a string that represents a method in the bean object. The parameters in parentheses are the arguments for the method invocation. Parameters can be zero or more values or expressions, separated by commas.
Parameters are supported for both value expressions and method expressions. In the following example, which is a modified tag from the guessnumber application, a random number is provided as an argument rather than from user input to the method call:
<h:inputText value="#{userNumberBean.userNumber('5')}">
The preceding example uses a value expression.
Consider the following example of a JavaServer Faces component tag that uses a method expression:
<h:commandButton action="#{trader.buy}" value="buy"/>
The EL expression trader.buy calls the trader bean’s buy method. You can modify the tag to pass on a parameter. Here is the revised tag where a parameter is passed:
<h:commandButton action="#{trader.buy('SOMESTOCK')}" value="buy"/>
In the preceding example, you are passing the string 'SOMESTOCK' (a stock symbol) as a parameter to the buy method.
For more information on the updated EL, see https://uel.dev.java.net.
As explained in the previous section, all kinds of expressions can be used in tag attributes. Which kind of expression and how it is evaluated, whether immediately or deferred, are determined by the type attribute of the tag’s definition in the Page Description Language (PDL) that defines the tag.
If you plan to create custom tags, for each tag in the PDL, you need to specify what kind of expression to accept. Table 6–1 shows the kinds of tag attributes that accept EL expressions, gives examples of expressions they accept, and provides the type definitions of the attributes that must be added to the PDL. You cannot use #{} syntax for a dynamic attribute, meaning an attribute that accepts dynamically calculated values at runtime. Similarly, you also cannot use the ${} syntax for a deferred attribute.
Table 6–1 Definitions of Tag Attributes That Accept EL Expressions
In addition to the tag attribute types shown in Table 6–1, you can 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.
A literal expression is evaluated to the text of the expression, which is of type String. A literal expression 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:
By creating a composite expression as shown here:
${'${'}exprA}
#{'#{'}exprB}
The resulting values would then be the strings ${exprA} and #{exprB}.
By using the escape characters \$ and \# to escape what would otherwise be treated as an eval-expression:
\${exprA}
\#{exprB}
The resulting values would again be the strings ${exprA} and #{exprB}.
When a literal expression is evaluated, it can be converted to another type. Table 6–2 shows examples of various literal expressions and their expected types and resulting values.
Table 6–2 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 to accept a deferred value expression, when referencing a value, the literal expression is evaluated at a point in the lifecycle that is determined by other factors, such as 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. For example, the commandButton tag of the guessnumber application uses a literal method expression as a logical outcome to tell the JavaServer Faces navigation system which page to display next.
In addition to the . and [] operators discussed in Value and Method Expressions, the EL provides the following operators, which can be used in rvalue expressions only:
Arithmetic: +, - (binary), *, / and div, % and mod, - (unary)
Logical: and, &&, or, ||, not, !
Relational: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le. Comparisons can be made against other values or against Boolean, string, integer, or floating-point literals.
Empty: The empty operator is a prefix operation that can be used to determine whether a value is null or empty.
Conditional: A ? B : C. Evaluate B or C, depending on the result of the evaluation of A.
The precedence of operators highest to lowest, left to right is as follows:
[] .
() (used to change the precedence of operators)
- (unary) not ! empty
* / div % mod
+ - (binary)
< > <= >= lt gt le ge
== != eq ne
&& and
|| or
? :
The following words are reserved for the EL and should not be used as identifiers:
and |
or |
not |
eq |
ne |
lt |
gt |
le |
ge |
true |
false |
null |
instanceof |
empty |
div |
mod |
Table 6–3 contains example EL expressions and the result of evaluating them.
Table 6–3 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. |
Web pages represent the presentation layer for web applications. The process of creating web pages of a JavaServer Faces application includes adding components to the page and wiring them to backing beans, validators, converters, and other server-side objects that are associated with the page.
This chapter explains how to create web pages using various types of component and core tags. In the next chapter, you will learn about adding converters, validators, and listeners to component tags to provide additional functionality to components.
The following topics are addressed here:
A typical JavaServer Faces web page includes the following elements:
A set of namespace declarations that declare the JavaServer Faces tag libraries
Optionally, the new HTML head (h:head) and body (h:body) tags
A form tag (h:form) that represents the user input components
To add the JavaServer Faces components to your web page, you need to provide the page access to the two standard tag libraries: the JavaServer Faces HTML tag library and the JavaServer Faces core tag library. The JavaServer Faces standard HTML tag library defines tags that represent common HTML user interface components. This library is linked to the HTML render kit at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/renderkitdocs/. The JavaServer Faces core tag library defines tags that perform core actions.
For a complete list of JavaServer Faces Facelets tags and their attributes, refer to the documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/.
To use any of the JavaServer Faces tags, you need to include appropriate directives at the top of each page specifying the tag libraries.
For Facelets applications, the XML namespace directives uniquely identify the tag library URI and the tag prefix.
For example, when creating a Facelets XHTML page, include namespace directives as follows:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
The XML namespace URI identifies the tag library location, and the prefix value is used to distinguish the tags belonging to that specific tag library. You can also use other prefixes instead of the standard h or f. However, when including the tag in the page, you must use the prefix that you have chosen for the tag library. For example, in the following web page, the form tag must be referenced using the h prefix because the preceding tag library directive uses the h prefix to distinguish the tags defined in HTML tag library:
<h:form ...>
The sections Adding Components to a Page Using HTML Tags and Using Core Tags describe how to use the component tags from the JavaServer Faces standard HTML tag library and the core tags from the JavaServer Faces core tag library.
The tags defined by the JavaServer Faces standard HTML 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 7–1.
Table 7–1 The Component Tags
The next section explains the important tag attributes that are common to most component tags. For each of the components discussed in the following sections, Writing Bean Properties explains how to write a bean property bound to a particular component or its value.
Most of the component tags support the attributes shown in Table 7–2.
Table 7–2 Common Component Tag Attributes
Attribute |
Description |
---|---|
Identifies a bean property and binds the component instance to it. |
|
Uniquely identifies the component. |
|
If set to true, indicates that any events, validation, and conversion associated with the component should happen when request parameter values are applied, |
|
Specifies a condition under which the component should be rendered. If the condition is not satisfied, the component is not rendered. |
|
Specifies a Cascading Style Sheet (CSS) style for the tag. |
|
Specifies a CSS class that contains definitions of the styles. |
|
Identifies an external data source and binds the component’s value to it. |
All the tag attributes (except id) can accept expressions, as defined by the EL, described in Chapter 6, Expression Language.
The id attribute is not usually required for a component tag but is used 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 takes expressions using only the evaluation syntax described in The immediate Attribute, which uses the ${} delimiters. For more information on expression syntax, see Value Expressions.
Input components and command components (those that implement the ActionSource interface, such as buttons and hyperlinks) can set the immediate attribute to true to force events, validations, and conversions to be processed when request parameter values are applied.
You 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 the immediate attributes of both the button and the field are set to true, the new value entered in 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 as well as the event validation and conversion associated with the field are all handled when request parameter values are applied.
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. The reason is that any events, conversion, or validation associated with the field occurs after request parameter values are applied.
A component tag uses a Boolean EL expression along with the rendered attribute to determine whether the component will be rendered. For example, the commandLink component in the following section of a 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 Value and Method Expressions, these 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 allow you to specify CSS styles for the rendered output of your tags. Displaying Error Messages with the h:message and h: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 class.
The following example shows the use of a dataTable tag that references the style class list-background:
<h:dataTable id="books" ... styleClass="list-background" value="#{bookDBAO.books}" var="book">
The style sheet that defines this class is stylesheet.css, which will be included in the application. For more information on defining styles, see Cascading Style Sheets Specification at http://www.w3.org/Style/CSS/.
A tag representing an output component uses the value and binding attributes to bind its component’s value or instance, respectively, to an external data source.
The HTML head (h:head) and body (h:body) tags add HTML page structure to JavaServer Faces web pages.
The h:head tag represents the head element of an HTML page
The h:body tag represents the body element of an HTML page
The following is an example of an XHTML page using the usual head and body markup tags:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Add a title</title> </head> <body> Add Content </body>
The following is an example of an XHTML page using h:head and h:body tags:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> Add a title </h:head> <h:body> Add Content </h:body>
Both of the preceding example code segments render the same HTML elements. The head and body tags are useful mainly for resource relocation. For more information on resource relocation, see Resource Relocation Using h:output Tags.
An h:form tag represents an input form, which includes child components that can contain data that is either presented to the user or submitted with the form.
Figure 7–1 shows a typical login form in which a user enters a user name and password, then submits the form by clicking the Login button.
The h:form tag represents the form 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 h:form tag can also include HTML markup to lay out the components on the page. Note that the h: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 h:form tags, but only the values from the form submitted by the user will be included in the postback request.
Text components allow users to view and edit text in web applications. The basic types of text components are as follows:
Label, which displays read-only text
Text field, which allows users to enter text, often to be submitted as part of a form
Text area, which is a type of text field that allows users to enter multiple lines of text
Password field, which is a type of text field that displays a set of characters, such as asterisks, instead of the password text that the user enters
Figure 7–2 shows examples of these text components.
Text components can be categorized as either input or output. A JavaServer Faces output component is rendered as read-only text. An example is a label. A JavaServer Faces input component is rendered as editable text. An example is a text field.
The input and output components can each be rendered in various ways to display more specialized text.
Table 7–3 lists the tags that represent the input components.
Table 7–3 Input Tags
Tag |
Function |
---|---|
Allows a page author to include a hidden variable in a page |
|
The standard password field: accepts one line of text with no spaces and displays it as a set of asterisks as it is typed |
|
The standard text field: accepts a one-line text string |
|
The standard text area: accepts multiple lines of text |
The input tags support the tag attributes shown in Table 7–4 in addition to those described in Common Component Tag Attributes. Note that this table does not include all the attributes supported by the input tags but just those that are used most often. For the complete list of attributes, refer to the documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/.
Table 7–4 Input Tag Attributes
Attribute |
Description |
---|---|
Identifies a converter that will be used to convert the component’s local data. See Using the Standard Converters for more information on how to use this attribute. |
|
converterMessage |
Specifies an error message to display when the converter registered on the component fails. |
dir |
Specifies the direction of the text displayed by this component. Acceptable values are LTR, meaning left-to-right, and RTL, meaning right-to-left. |
label |
Specifies a name that can be used to identify this component in error messages. |
lang |
Specifies the code for the language used in the rendered markup, such as en_US. |
required |
Takes a boolean value that indicates whether the user must enter a value in this component. |
requiredMessage |
Specifies an error message to display when the user does not enter a value into the component. |
Identifies a method expression pointing to a backing bean method that performs validation on the component’s data. See Referencing a Method That Performs Validation for an example of using the f:validator tag. |
|
f:validatorMessage |
Specifies an error message to display when the validator registered on the component fails to validate the component’s local value. |
Identifies a method expression that points to a backing bean method that handles the event of entering a value in this component. See Referencing a Method That Handles a Value-Change Event for an example of using valueChangeListener. |
Table 7–5 lists the tags that represent the output components.
Table 7–5 Output Tags
Tag |
Function |
---|---|
Displays a localized message |
|
The standard read-only label: displays a component as a label for a specified input field |
|
Displays an <a href> tag that links to another page without generating an action event |
|
Displays a one-line text string |
The output tags support the converter tag attribute in addition to those listed in Common Component Tag Attributes.
The rest of this section explains how to use some of the tags listed in Table 7–3 and Table 7–5. The other tags are written in a similar way.
The h:inputText tag is used to display a text field. A similar tag, the h:outputText tag, displays a read-only, single-line string. This section shows you how to use the h:inputText tag. The h:outputText tag is written in a similar way.
Here is an example of an h:inputText tag:
<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 a backing bean named 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, displaying errors, 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 tag and set its value to true. If your tag has a required attribute that is set to true and the value is null or a zero-length string, no other validators that are registered on the tag are called. If your tag does not have a required attribute set to true, other validators that are registered on the tag are called, but those validators must handle the possibility of a null or zero-length string. See Validating Null and Empty Strings for more information.
The h: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 typed by the user. Here is an example:
<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.
The h:outputLabel tag is used to attach a label to a specified input field for the purpose of making it accessible. The following page uses an h:outputLabel tag to render the label of a check box:
<h:selectBooleanCheckbox id="fanClub" binding="#{cashier.specialOffer}" /> <h:outputLabel for="fanClub" binding="#{cashier.specialOfferText}" > <h:outputText id="fanClubLabel" value="#{bundle.DukeFanClub}" /> </h:outputLabel> ...
The for attribute of the h:outputLabel tag maps to the id of the input field to which the label is attached. The h:outputText tag nested inside the h:outputLabel tag represents the label component. The value attribute on the h:outputText tag indicates the text that is displayed next to the input field.
Instead of using an h:outputText tag for the text displayed as a label, you can simply use the h: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 h:outputLabel tag to specify the text of the label:
<h:selectBooleanCheckbox id="fanClub" binding="#{cashier.specialOffer}" /> <h:outputLabel for="fanClub" binding="#{cashier.specialOfferText}" value="#{bundle.DukeFanClub}" /> </h:outputLabel> ...
The h: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 h:commandLink tag if you always want the URL specified by the h:outputLink tag’s value attribute to open and do not want any processing to be performed when the user clicks the link. Here is an example:
<h:outputLink value="javadocs"> Documentation for this demo </h:outputLink>
The text in the body of the outputLink tag identifies the text that the user clicks to get to the next page.
The h:outputFormat tag allows display of concatenated messages as a MessageFormat pattern, as described in the API documentation for java.text.MessageFormat. Here is an example of an outputFormat tag:
<h:outputFormat value="Hello, {0}!"> <f:param value="#{hello.name}"/> </h:outputFormat>
The value attribute specifies the MessageFormat pattern. The param tag specifies the substitution parameters for the message. The value of the parameter replaces the {0} in the sentence. If the value of "#{hello.name}" is “Bill”, the message displayed in the page is as follows:
Hello, Bill! |
An h: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. Here is the preceding example modified with an additional parameter:
<h:outputFormat value="Hello, {0}! You are visitor number {1} to the page."> <f:param value="#{hello.name}" /> <f:param value="#{bean.numVisitor}"/> </h:outputFormat>
The value of {1} is replaced by the second parameter. The parameter is an EL expression, bean.numVisitor, where the property numVisitor of the backing bean bean keeps track of visitors to the page. This is an example of a value-expression-enabled tag attribute accepting an EL expression. The message displayed in the page is now as follows:
Hello, Bill! You are visitor number 10 to the page. |
In JavaServer Faces applications, the button and hyperlink component tags are used to perform actions, such as submitting a form, and for navigating to another page. These tags are called command component tags because they perform an action when activated.
The h:commandButton tag is rendered as a button. The h:commandLink tag is rendered as a hyperlink.
In addition to the tag attributes listed in Common Component Tag Attributes, the h:commandButton and h:commandLink tags can use the following attributes:
action, which is either a logical outcome String or a method expression pointing to a bean method that returns a logical outcome String. In either case, the logical outcome String is used to determine what page to access when the command component tag is activated.
actionListener, which is a method expression pointing to a bean method that processes an action event fired by the command component tag.
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.
If you are using a commandButton component tag, the data from the current page is processed when a user clicks the button, and the next page is opened. Here is an example of the h:commandButton tag:
<h:commandButton value="Submit" action="#{cashier.submit}"/>
Clicking the button will cause the submit method of CashierBean to be invoked because the action attribute references this method. The submit method performs some processing and returns a logical outcome.
The value attribute of the example commandButton tag references the button’s label. For information on how to use the action attribute, see Referencing a Method That Performs Navigation.
The h:commandLink tag represents an HTML hyperlink and is rendered as an HTML <a> element. This tag acts like a form’s Submit button and is used to submit an action event to the application.
A h:commandLink tag must include a nested h:outputText tag, which represents the text that the user clicks to generate the event. Here is an example:
<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>
The h:commandLink tag will render JavaScript programming language. If you use this tag, make sure that your browser is enabled for JavaScript technology.
In a JavaServer Faces application, use the h:graphicImage tag to render an image on a page:
<h:graphicImage id="mapImage" url="/template/world.jpg"/>
The url attribute specifies the path to the image. 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.
Alternatively, you can use the facility described in Resources to point to the image location. Here is an example:
<h:graphicImage value="#{resource['images:wave.med.gif']}"/>
In a JavaServer Faces application, you use a panel as a layout container for a set of other components. A panel is rendered as an HTML table. Table 7–6 lists the tags used to create panels.
Table 7–6 Panel Component Tags
Tag |
Attributes |
Function |
---|---|---|
h:panelGrid |
columns,columnClasses, footerClass, headerClass, panelClass, rowClasses |
Displays a table |
h:panelGroup |
layout |
Groups a set of components under one parent |
The h:panelGrid tag is used to represent an entire table. The h:panelGroup tag is used to represent rows in a table. Other tags are used to represent individual cells in the rows.
The columns attribute defines how to group the data in the table and therefore is required if you want your table to have more than one column. The h:panelGrid tag also has a set of optional attributes that specify CSS classes: columnClasses, footerClass, headerClass, panelClass, and rowClasses.
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.
Here is an example:
<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>
The preceding h:panelGrid tag is rendered as a table that contains components in which a customer inputs personal information. This h:panelGrid tag uses style sheet classes to format the table. The following code shows the list-header definition:
.list-header { background-color: #ffffff; color: #000000; text-align: center; }
Because the h: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, so an h:panelGroup tag is needed if you want to group more than one component within a facet. The example h:panelGrid tag has only one cell of data, so an h:panelGroup tag is not needed.
The h:panelGroup tag has an attribute, layout, in addition to those listed in Common Component Tag Attributes. If the layout attribute has the value block, 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 h:panelGroup tag, you should set the layout attribute to block in order for the styles to be applied to the components within the h:panelGroup tag. You should do this 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.
An h: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.
Data, represented by the nested tags, is grouped into rows according to the value of the columns attribute of the h:panelGrid tag. The columns attribute in the example is set to 3, and therefore the table will have three columns. The column in which each component is displayed is determined by the order in which 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.
Another commonly used component is one that allows a user to select one value, whether it is the only value available or one of a set of choices. The most common tags for this kind of component are as follows:
An h:selectBooleanCheckbox tag, displayed as a check box, which represents a Boolean state
An h:selectOneRadio tag, displayed as a set of radio buttons
An h:selectOneMenu tag, displayed as a drop-down menu, with a scrollable list
An h:selectOneListbox tag, displayed as a list box, with an unscrollable list
Figure 7–3 shows examples of these components.
The h:selectBooleanCheckbox tag is the only tag that JavaServer Faces technology provides for representing a Boolean state.
Here is an example that shows how to use the h:selectBooleanCheckbox tag:
<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 text is represented by the nested outputText tag.
A component that allows the user to select one value from a set of values can be rendered as a list box, a set of radio buttons, or a menu. This section describes the h:selectOneMenu tag. The h:selectOneRadio and h:selectOneListbox tags are used in a similar way. The h:selectOneListbox tag is similar to the h:selectOneMenu tag except that h:selectOneListbox defines a size attribute that determines how many of the items are displayed at once.
The h:selectOneMenu tag represents a component that contains a list of items from which a user can choose one item. This menu component is also commonly known as a drop-down list or a combo box. The following code snippet shows how the h:selectOneMenu tag is used to allow 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 h: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 h:selectOneRadio tag, the selectOneMenu tag must contain either an f:selectItems tag or a set of f:selectItem tags for representing the items in the list. Using the f:selectItem and f:selectItems Tags describes these tags.
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 component tags:
An h:selectManyCheckbox tag, displayed as a set of check boxes
Figure 7–4 shows examples of these components.
These tags allow the user to select zero or more values from a set of values. This section explains the h:selectManyCheckbox tag. The h:selectManyListbox and h:selectManyMenu tags are used in a similar way.
Unlike a menu, a list box displays a subset of items in a box; a menu displays only one item at a time when the user is not selecting the menu. The size attribute of the h: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 h:selectManyCheckbox tag renders a set of check boxes, with each check box representing one value that can be selected:
<h:selectManyCheckbox id="newsletters" layout="pageDirection" value="#{cashier.newsletters}"> <f:selectItems value="#{newsletters}"/> </h:selectManyCheckbox>
The value attribute of the h:selectManyCheckbox tag identifies the newsletters property of the Cashier backing bean. 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 is 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 h: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 f:selectItems tag. To represent each item individually, you use a f:selectItem tag. The following subsection explains these tags in more detail.
The f:selectItem and f:selectItems tags represent components that can be nested inside a component that allows you to select one or multiple items. An f:selectItem tag contains the value, label, and description of a single item. An f:selectItems tag contains the values, labels, and descriptions of the entire list of items.
You can use either a set of f:selectItem tags or a single f:selectItems tag within your component tag.
The advantages of using the f:selectItems tag are as follows.
Items can be represented by using different data structures, including Array, Map, and Collection. The value of the f:selectItems tag can represent even a generic collection of POJOs.
Different lists can be concatenated into a single component, and the lists can be grouped within the component.
Values can be generated dynamically at runtime.
The advantages of using f:selectItem are as follows:
Items in the list can be defined from the page.
Less code is needed in the bean for the selectItem properties.
The rest of this section shows you how to use the f:selectItems and f:selectItem tags.
The following example from Displaying Components for Selecting Multiple Values shows how to use the h:selectManyCheckbox tag:
<h:selectManyCheckbox id="newsletters" layout="pageDirection" value="#{cashier.newsletters}"> <f:selectItems value="#{newsletters}"/> </h:selectManyCheckbox>
The value attribute of the f:selectItems tag is bound to the backing bean newsletters.
You can also create the list of items programmatically in the backing bean. See Writing Bean Properties for information on how to write a backing bean property for one of these tags.
The f:selectItem tag represents a single item in a list of items. Here is the example from Displaying a Menu Using the h:selectOneMenu Tag once again:
<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 for the selectItem tag. 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. These attributes can also define literal values, as shown in the example h:selectOneMenu tag.
Data-bound table components display relational data in a tabular format. In a JavaServer Faces application, the h:dataTable component tag supports binding to a collection of data objects and displays the data as an HTML table. The h:column tag represents a column of data within the table, iterating over each record in the data source, which is displayed as a row. Here is an 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"> <h:column headerClass="list-header-left"> <f:facet name="header"> <h:outputText value=Quantity"" /> </f:facet> <h:inputText id="quantity" size="4" value="#{item.quantity}" > ... </h:inputText> ... </h:column> <h:column> <f:facet name="header"> <h:outputText value="Title"/> </f:facet> <h:commandLink> <h:outputText value="#{item.title}"/> </h:commandLink> </h:column> ... <f:facet name="footer" <h:panelGroup> <h:outputText value="Total}"/> <h:outputText value="#{cart.total}" /> <f:convertNumber type="currency" /> </h:outputText> </h:panelGroup> </f:facet> </h:dataTable>
Figure 7–5 shows a data grid that this h:dataTable tag can display.
The example h: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 the user can click to remove books from the shopping cart.
The h:column tags represent columns of data in a data component. While the data component is iterating over the rows of data, it processes the column component associated with each h:column tag for each row in the table.
The h:dataTable tag 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 the h:dataTable tag iterates through the list of books, it renders one cell in each column.
The h:dataTable and h:column tags use facets to represent parts of the table that are not repeated or updated. These parts include headers, footers, and captions.
In the preceding example, h:column tags include f:facet tags for representing column headers or footers. The h: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 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, so an h:panelGroup tag is needed if you want to group more than one component within an f:facet. Because the facet tag representing the footer includes more than one tag, the panelGroup is needed to group those tags. Finally, this h:dataTable tag includes an f: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 data component because the number of books might not be known to the application developer or the page author when that application is developed. The data component can dynamically adjust the number of rows of the table to accommodate the underlying data.
The value attribute of an h:dataTable tag references the data to be included in the table. This data can take the form of any of the following:
A list of beans
An array of beans
A single bean
A javax.faces.model.DataModel object
A java.sql.ResultSet object
A javax.servlet.jsp.jstl.sql.Result object
A javax.sql.RowSet object
All data sources for data 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 data component.
The var attribute specifies a name that is used by the components within the h:dataTable tag as an alias to the data referenced in the value attribute of dataTable.
In the example h:dataTable tag, the value attribute points to a list of books. The var attribute points to a single book in that list. As the h:dataTable tag iterates through the list, each reference to item points to the current book in the list.
The h:dataTable tag also has the ability to display only a subset of the underlying data. This feature 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.
Table 7–7 shows the optional attributes for the h:dataTable tag.
Table 7–7 Optional Attributes for the h:dataTable Tag
Attribute |
Defines Styles for |
---|---|
captionClass |
Table caption |
columnClasses |
All the columns |
footerClass |
Footer |
headerClass |
Header |
rowClasses |
Rows |
styleClass |
The entire table |
Each of the attributes in Table 7–7 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 the table has two columns, 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.
The h:message and h:messages tags are used to display error messages when conversion or validation fails. The h:message tag displays error messages related to a specific input component, whereas the h:messages tag displays the error messages for the entire page.
Here is an example h:message tag from the guessnumber application:
<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 h: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. For more information on these attributes, refer to the documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/.
Another attribute supported by the h:messages tag is the layout attribute. Its default value is list, which indicates that the messages are displayed in a bullet list using the HTML ul and li elements. If you set the attribute value to table, the messages will be rendered in a table using the HTML table element.
The preceding example shows a standard validator that is registered on the input component. The message tag displays the error message that is 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 h:message and h: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.
Standard error messages are provided with standard converters and standard validators. 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.
The ability to create bookmarkable URLs refers to the ability to generate hyperlinks based on a specified navigation outcome and on component parameters.
In HTTP, most browsers by default send GET requests for URL retrieval and POST requests for data processing. The GET requests can have query parameters and can be cached, which is not advised for POST requests, which send data to the external servers. The other JavaServer Faces tags capable of generating hyperlinks use either simple GET requests, as in the case of h:outputlink, or POST requests, as in the case of h:commandLink or h:commandButton tags. GET requests with query parameters provide finer granularity to URL strings. These URLs are created with one or more name=value parameters appended to the simple URL after a ? character and separated by either &; or & strings.
To create a bookmarkable URL, use an h:link or h:button tag. Both of these tags can generate a hyperlink based on the outcome attribute of the component. For example:
<h:link outcome="response" value="Message"> <f:param name="Result" value="#{sampleBean.result}"/> </h:link>
The h:link tag will generate a URL link that points to the response.xhtml file on the same server, appended with the single query parameter created by the f:param tag. When processed, the parameter Result is assigned the value of backing bean’s result method #{sampleBean.result}. The following sample HTML is generated from the preceding set of tags, assuming that the value of the parameter is success:
<a href="http://localhost:8080/guessnumber/response.xhtml?Result=success">Response</a> |
This is a simple GET request. To create more complex GET requests and utilize the complete functionality of the h:link tag, you can use view parameters.
The core tags f:metadata and f:viewparam are used as a source of parameters for configuring the URLs. View parameters are declared as part of f:metadata for a page, as shown in the following example:
<h:body> <f:metadata> <f:viewParam id="name" name="Name" value="#{sampleBean.username}"/> <f:viewParam id="ID" name="uid" value="#{sampleBean.useridentity}"/> </f:metadata> <h:link outcome="response" value="Message" includeViewParams="true"> </h:link> </h:body>
View parameters are declared with the f:viewparam tag and are placed inside the f:metadata tag. If the includeViewParams attribute is set on the component, the view parameters are added to the hyperlink.
The resulting URL will look like this:
http://localhost:8080/guessnumber/response.xhtml?Name=Duke&;uid=2001 |
Because the URL can be the result of various parameter values, the order of the URL creation has been predefined. The order in which the various parameter values are read is as follows:
Component
Navigation-case parameters
View parameters
Resource relocation refers to the ability of a JavaServer Faces application to specify the location where a resource can be rendered. Resource relocation can be defined with the following HTML tags:
h:outputScript
h:outputStylesheet
These tags have name and target attributes, which can be used to define the render location. For a complete list of attributes for these tags, see the documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/.
For the h:outputScript tag, the name and target attributes define where the output of a resource may appear. Here is an example:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head id="head"> <title>Resource Relocation</title> </h:head> <h:body id="body"> <h:form id="form"> <h:outputScript name="hello.js"/> <h:outputStylesheet name="hello.css"/> </h:form> </h:body> </html>
Since the target attribute is not defined in the tag, the style sheet hello.css is rendered in the head, and the hello.js script is rendered in the body of the page as defined by the h:head tag.
Here is the HTML generated by the preceding code:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Resource Relocation</title> <link type="text/css" rel="stylesheet" href="/ctx/faces/javax.faces.resource/hello.css"/> </head> <body> <form id="form" name="form" method="post" action="..." enctype="..."> <script type="text/javascript" src="/ctx/faces/javax.faces.resource/hello.js"> </script> </form> </body> </html>
The original page can be recreated by setting the target attribute for the h:outputScript tag, which allows the incoming GET request to provide the location parameter. Here is an example:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head id="head"> <title>Resource Relocation</title> </h:head> <h:body id="body"> <h:form id="form"> <h:outputScript name="hello.js" target="#{param.location}"/> <h:outputStylesheet name="hello.css"/> </h:form> </h:body> </html>
In this case, if the incoming request does not provide a location parameter, the default locations will still apply: The style sheet is rendered in the head, and the script is rendered inline. However, if the incoming request provides the location parameter as the head, both the style sheet and the script will be rendered in the head element.
The HTML generated by the preceding code is as follows:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Resource Relocation</title> <link type="text/css" rel="stylesheet" href="/ctx/faces/javax.faces.resource/hello.css"/> <script type="text/javascript" src="/ctx/faces/javax.faces.resource/hello.js"> </script> </head> <body> <form id="form" name="form" method="post" action="..." enctype="..."> </form> </body> </html>
Similarly, if the incoming request provides the location parameter as the body, the script will be rendered in the body element.
The preceding section describes simple uses for resource relocation. That feature can add even more functionality for the components and pages. A page author does not have to know the location of a resource or its placement.
By using a @ResourceDependency annotation for the components, component authors can define the resources for the component, such as a style sheet and script. This allows the page authors freedom from defining resource locations.
The tags included in the JavaServer Faces core tag library are used to perform core actions that are not performed by HTML tags. Commonly used core tags, along with the functions they perform, are listed in Table 7–8.
Table 7–8 The Core Tags
These tags, which are used in conjunction with component tags, are explained in other sections of this tutorial. Table 7–9 lists the sections that explain how to use specific core tags.
Table 7–9 Where the Core Tags Are Explained
Tags |
Where Explained |
---|---|
Event handling tags | |
Data conversion tags | |
facet |
Using Data-Bound Table Components and Laying Out Components with the h:panelGrid and h:panelGroup Tags |
loadBundle | |
param | |
selectItem and selectItems | |
Validator tags |
The previous chapter described components and explained how to add them to a web page. This chapter provides information on adding more functionality to the components through converters, listeners, and validators.
Converters are used to convert data that is received from the input components.
Listeners are used to listen to the events happening in the page and perform actions as defined.
Validators are used to validate the data that is received from the input components.
The following topics are addressed here:
The JavaServer Faces implementation provides a set of Converter implementations that you can use to convert component data. The standard Converter implementations, located in the javax.faces.convert package, are as follows:
A standard error message is associated with each of these converters. 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 following error message appears if BigIntegerConverter fails to convert a value:
{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.
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. For more information about using DateTimeConverter, see Using DateTimeConverter. For more information about using NumberConverter, see Using NumberConverter. The following section explains how to convert a component’s value, including how to register other standard converters with a component.
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 in one of the following ways:
Nest one of the standard converter tags inside the component’s tag. These tags are convertDateTime and convertNumber, which are described in Using DateTimeConverter and Using NumberConverter, respectively.
Bind the value of the component to a backing bean property of the same type as the converter.
Refer to the converter from the component tag’s converter attribute.
Nest a converter tag inside of the component tag, and use either the converter tag’s converterId attribute or its binding attribute to refer to the converter.
As an example of the second method, if you want a component’s data to be converted to an Integer, you can simply bind the component’s value to a backing bean property. Here is an example:
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 use the third method by using the converter attribute directly 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.
The data from the inputText tag in the this example will be converted to a java.lang.Integer value. The Integer type is a supported type of NumberConverter. If you don’t need to specify any formatting instructions using the convertNumber tag attributes, and if one of the standard converters will suffice, you can simply reference that converter by 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. 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.
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 8–1 lists the attributes.
Here is a simple example of a convertDateTime tag:
<h:outputText id= "shipDate" value="#{cashier.shipDate}"> <f:convertDateTime dateStyle="full" /> </h:outputText>
When binding the DateTimeConverter to a component, ensure that the backing bean property to which the component is bound is of type java.util.Date. In the preceding example, cashier.shipDate must be of type java.util.Date.
The example tag can display the following output:
Saturday, September 25, 2010 |
You can also display the same date and time by using the following tag where the date format is specified:
<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 the following output:
sabado 25 de septiembre de 2010 |
Refer to the “Customizing Formats” lesson of the Java Tutorial at http://download.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html for more information on how to format the output using the pattern attribute of the convertDateTime tag.
Table 8–1 Attributes for the convertDateTime Tag
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 8–2 lists the attributes.
The following example uses a convertNumber tag to display the total prices of the contents of a shopping cart:
<h:outputText value="#{cart.total}" > <f:convertNumber type="currency"/> </h:outputText>
When binding the NumberConverter to a component, ensure that the backing bean property to which the component is bound is of a primitive type or has a type of java.lang.Number. In the preceding example, cart.total is of type java.lang.Number.
Here is an example of a number that this tag can display:
$934 |
This result can also be displayed by using the following tag, where the currency pattern is specified:
<h:outputText id="cartTotal" value="#{cart.Total}" > <f:convertNumber pattern="$####" /> </h:outputText>
See the “Customizing Formats” lesson of the Java Tutorial at http://download.oracle.com/javase/tutorial/i18n/format/decimalFormat.html for more information on how to format the output by using the pattern attribute of the convertNumber tag.
Table 8–2 Attributes for the convertNumber Tag
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. |
for |
String |
Used with composite components. Refers to one of the objects within the composite component inside which this tag is nested. |
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. |
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 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 explain how a page author uses the valueChangeListener and actionListener attributes to reference backing bean methods that handle events.
This section explains how to register the NameChanged value-change listener and a hypothetical LocaleChange action listener implementation on components.
A ValueChangeListener implementation can be registered on a component that implements EditableValueHolder by nesting a valueChangeListener tag within the component’s tag on the page. The valueChangeListener tag supports the attributes shown in Table 8–3, one of which must be used.
Table 8–3 Attributes for the valueChangeListener Tag
Attribute |
Description |
---|---|
type |
References the fully qualified class name of a ValueChangeListener implementation. Can accept a literal or a value expression. |
binding |
References an object that implements ValueChangeListener. Can accept only a value expression, which must point to a backing bean property that accepts and returns a ValueChangeListener implementation. |
The following example shows a value-change listener registered on a component:
<h:inputText id="name" size="50" value="#{cashier.name}" required="true"> <f:valueChangeListener type="listeners.NameChanged" /> </h:inputText>
In the example, the core tag type attribute specifies the custom NameChanged listener as the ValueChangeListener implementation registered 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. This attribute works in a similar way to the binding attribute supported by the standard converter tags.
A page author can register an ActionListener implementation on a command 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. One of these attributes must be used to reference the action listener.
Here is an example of a commandLink tag that references 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.
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 8–4 lists all the standard validator classes and the tags that allow you to use the validators from the page.
Table 8–4 The Validator Classes
Validator Class |
Tag |
Function |
---|---|---|
BeanValidator |
validateBean |
Registers a bean validator for the component. |
Checks whether the local value of a component is within a certain range. The value must be floating-point or convertible to floating-point. |
||
Checks whether the length of a component’s local value is within a certain range. The value must be a java.lang.String. |
||
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. |
||
RegexValidator |
validateRegEx |
Checks whether the local value of a component is a match against a regular expression from the java.util.regex package. |
RequiredValidator |
validateRequired |
Ensures that the local value is not empty on an EditableValueHolder component. |
Similar 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 unable 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 as follows:
{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.
Instead of using the standard validators, you can use Bean Validation to validate data. See Using Bean Validation for more information.
To validate a component’s value using a particular validator, you need to register that validator on the component. You can do this in one of the following ways:
Nest the validator’s corresponding tag (shown in Table 8–4) inside the component’s tag. Using LongRangeValidator explains how to use the validateLongRange tag. You can use the other standard tags in the same way.
Refer to a method that performs the validation from the component tag’s validator attribute.
Nest a validator tag inside the component tag, and use either the validator tag’s validatorId attribute or its binding attribute to refer to the validator.
See Referencing 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.
Keep in mind that validation can be performed only on components that implement EditableValueHolder, because these components accept values that can be validated.
The following example shows how to use the validateLongRange validator on an input component named quantity:
<h:inputText id="quantity" size="4" value="#{item.quantity}" > <f:validateLongRange minimum="1"/> </h:inputText> <h:message for="quantity"/>
This tag requires the user to 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, which sets a maximum value for the input.
The attributes of all the standard validator tags accept EL 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, as shown here:
<f:validateLongRange minimum="#{ShowCartBean.minimum}" />
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 8–5.
Table 8–5 Component Tag Attributes That Reference Backing Bean Methods
Attribute |
Function |
---|---|
Refers to a backing bean method that performs navigation processing for the component and returns a logical outcome String |
|
Refers to a backing bean method that handles action events |
|
Refers to a backing bean method that performs validation on the component’s value |
|
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 documentation at http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/jsp/. For example, the definition of the validator attribute of the inputText tag is the following:
void validate(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
The following sections give examples of how to use the attributes.
If your page includes a component, such as a button or a 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:
Specifies a logical outcome String that tells the application which page to access next
References a backing bean method that performs some processing and returns a logical outcome String
The following example shows how to reference a navigation method:
<h:commandButton value="#{bundle.Submit}" action="#{cashier.submit}" />
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 following example shows how the method is referenced:
<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 when the user clicks the hyperlink rendered by this component.
If the input of one of the components on your page is validated by a backing bean method, refer to the method from the component’s tag by using the validator attribute.
The following example shows how to reference a method that performs validation on email, an input component:
<h:inputText id="email" value="#{checkoutFormBean.email}" size="25" maxlength="125" validator="#{checkoutFormBean.validateEmail}"/>
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 by using the component’s valueChangeListener attribute.
The following example shows how a component references a ValueChangeListener implementation that handles the event when a user enters 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>
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 by using a method expression. The processValueChange method handles the event of a user entering a name in the input field rendered by this component.
Chapter 7, Using JavaServer Faces Technology in Web Pages and Chapter 8, Using Converters, Listeners, and Validators show how to add components to a page and connect them to server-side objects by using component tags and core tags, as well as how to provide additional functionality to the components through converters, listeners, and validators. Developing a JavaServer Faces application also involves the task of programming the server-side objects: backing beans, converters, event handlers, and validators.
This chapter provides an overview of backing beans and explains how to write methods and properties of backing beans that are used by a JavaServer Faces application. This chapter also introduces the Bean Validation feature.
The following topics are addressed here:
A typical JavaServer Faces application includes one or more backing beans, each of which is a type of JavaServer Faces managed bean that can be associated with the components used in a particular page. This section introduces the basic concepts of creating, configuring, and using backing beans in an application.
A backing bean is created with a constructor with no arguments (like all JavaBeans components) and a set of properties and a set of methods that perform functions for a component. Each of the backing bean properties can be bound to one of the following:
A component value
A component instance
A converter instance
A listener instance
A validator instance
The most common functions that backing bean methods perform include the following:
Validating a component’s data
Handling an event fired by a component
Performing processing to determine the next page to which the application must navigate
As with all JavaBeans components, a property consists of a private data field and a set of accessor methods, as shown by this code:
Integer userNumber = null; ... public void setUserNumber(Integer user_number) { userNumber = user_number; } public Integer getUserNumber() { return userNumber; } public String getResponse() { ... }
When bound to a component’s value, a bean property 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 javax.faces.component.UISelectBoolean component 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, 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.
To bind component values and objects to backing bean properties or to reference backing bean methods from component tags, page authors use the Expression Language syntax. As explained in Overview of the EL, the following are some of the features that EL offers:
Deferred evaluation of expressions
The ability to use a value expression to both read and write data
Method expressions
Deferred evaluation of expressions is important because the JavaServer Faces lifecycle is split into several phases in which 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 lifecycle has been reached. Therefore, the implementation’s tag attributes always use deferred-evaluation syntax, which is distinguished by the #{} delimiter.
To store data in external objects, almost all JavaServer Faces tag attributes use lvalue 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 EL, suppose that a tag of an application referenced a method 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 by using an lvalue expression. The tag 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.
Nearly all JavaServer Faces tag attributes accept value expressions. In addition to referencing bean properties, value expressions can 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}" />
In addition to using expressions with the standard component tags, you can configure your custom component properties to accept expressions by creating javax.el.ValueExpression or javax.el.MethodExpression instances for them.
For information on the EL, see Chapter 6, Expression Language.
For information on referencing backing bean methods from component tags, see Referencing a Backing Bean Method.
As explained in Backing Beans, a backing bean property can be bound to one of the following items:
A component value
A component instance
A converter implementation
A listener implementation
A validator implementation
These properties follow the conventions of JavaBeans components (also called beans). For more information on JavaBeans components, see the JavaBeans Tutorial at http://download.oracle.com/javase/tutorial/javabeans/index.html.
The component’s tag binds the component’s value to a backing bean property by using its value attribute and binds the component’s instance to a backing bean property by using its binding attribute. Likewise, all the converter, listener, and validator tags use their binding attributes to bind their associated implementations 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 to a backing bean property, the property must match the type of component. For example, if a backing bean property is bound to a UISelectBoolean instance, the property should accept and return a UISelectBoolean value.
Similarly, to bind a converter, listener, or validator implementation to a backing bean 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 DateTimeConverter to a property, that property must accept and return a DateTimeConverter 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 Components to a Page Using HTML Tags, and to converter, listener, and validator implementations.
To write a backing bean property that is bound to a component’s value, you must match the property type to the component’s value.
Table 9–1 lists the javax.faces.component classes and the acceptable types of their values.
Table 9–1 Acceptable Types of Component Values
Component Class |
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, though elements of the array or List can be any of the standard types |
When they bind components to properties by using the value attributes of the component tags, page authors need to ensure that the corresponding properties match the types of the components’ values.
In the following example, an h:inputText tag binds the name component to the name property of a backing bean called CashierBean.
<h:inputText id="name" size="50" value="#{cashier.name}"> </h:inputText>
The following code snippet from the backing bean CashierBean shows the bean property type bound by the preceding component tag:
protected String name = null; public void setName(String name) { this.name = name; } public String getName() { return this.name; }
As described in Using the Standard Converters, to convert the value of an input or output component, you can either apply a converter or create the bean property bound to the component with the matching type. Here is the example tag, from Using DateTimeConverter, that displays the date when items will be shipped.
<h:outputText value="#{cashier.shipDate}"> <f:convertDateTime dateStyle="full" /> </h:outputText>
The bean property represented by this tag must have a type of java.util.Date. The following code snippet shows the shipDate property, from the backing bean CashierBean, that is bound by the tag’s value in the preceding example:
protected Date shipDate; public Date getShipDate() { return this.shipDate; } public void setShipDate(Date shipDate) { this.shipDate = shipDate; }
Data components must be bound to one of the backing bean property types listed in Table 9–1. Data components are discussed in 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 a shopping cart bean named cart. The cart bean maintains a map of ShoppingCartItem beans.
The getItems method from the cart bean populates a List with ShoppingCartItem instances that are saved in the items map when the customer adds items to the cart, as shown in the following code segment:
public synchronized List getItems() { List results = new ArrayList(); results.addAll(this.items.values()); return results; }
All the components contained in the data component are bound to the properties of the cart bean that is bound to the entire data component. For example, here is the h:outputText tag that displays the item name in the table:
<h:commandLink action="#{showcart.details}"> <h:outputText value="#{item.item.name}"/> </h:commandLink>
Backing bean properties that hold a UISelectBoolean component’s data must be of boolean or Boolean type. The example selectBooleanCheckbox tag from the section Displaying Components for Selecting One Value binds a component to a property. The following example shows a tag that binds a component value to a boolean 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; }
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.
The following example of the selectManyCheckbox tag comes fromDisplaying Components for Selecting Multiple Values:
<h:selectManyCheckbox id="newsletters" layout="pageDirection" value="#{cashier.newsletters}"> <f:selectItems value="#{newsletters}"/> </h:selectManyCheckbox>
Here is the bean property that maps to the value of the selectManyCheckbox tag from the preceding example:
protected String newsletters[] = new String[0]; public void setNewsletters(String newsletters[]) { this.newsletters = newsletters; } public String[] getNewsletters() { return this.newsletters; }
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 writing the bean properties for the UISelectItem and UISelectItems components.
UISelectOne properties accept the same types as UIInput and UIOutput properties, 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 an example of the selectOneMenu tag from Displaying a Menu Using the h: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 bean 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.
The UISelectItem and UISelectItems components are used to represent all the values in a UISelectOne component. This is explained in the section Displaying a Menu Using the h:selectOneMenu Tag.
For information on how to write the backing bean properties for the UISelectItem and UISelectItems components, see UISelectItem Properties and UISelectItems Properties.
A UISelectItem component represents a single value in a set of values in a UISelectMany or a UISelectOne component. A UISelectItem component must be bound to a backing bean property of type javax.faces.model.SelectItem. A SelectItem object is composed of an Object representing the value, along with two Strings representing the label and description of the UISelectItem object.
The example selectOneMenu tag from Displaying a Menu Using the h:selectOneMenu Tag contains selectItem tags that set the values of the list of items in the page. Here is an example of a 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 components are children of UISelectMany and UISelectOne components. Each UISelectItems component is composed of a set of either javax.faces.model.SelectItem instances or any collection of objects, such as an array, a list, or even POJOs.
This section explains how to write the properties for selectItems tags containing SelectItem instances.
You can populate the UISelectItems with SelectItem instances programmatically in the backing bean.
In your backing bean, create a list that is bound to the SelectItem component.
Define a set of SelectItem objects, set their values, and populate the list with the SelectItem objects.
The following example code snippet from a backing bean shows how to create a SelectItems property:
import javax.faces.model.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.
A property bound to a component instance returns and accepts a component instance rather than a component value. The following components bind a component instance to a backing bean property:
<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 fanClubLabel component, which represents the check box’s label, to the specialOfferText property of CashierBean. If the user orders more than $100 worth of items 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 rerendered.
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 type UIOutput, and the specialOffer property must be of type UISelectBoolean:
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; }
For more general information on component binding, see Backing Beans.
For information on how to reference a backing bean method that performs navigation when a button is clicked, see Referencing a Method That Performs Navigation.
For more information on writing backing bean methods that handle navigation, see Writing a Method to Handle Navigation.
All the standard converter, listener, and validator tags included with JavaServer Faces technology support binding attributes that allow you to bind converter, listener, or validator implementations to backing bean properties.
The following example 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 can 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 uses 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.
Methods of a backing bean can perform several application-specific functions for components on the page. These functions include
Performing processing associated with navigation
Handling action events
Performing validation on the component’s value
Handling value-change events
By using a backing bean to perform these functions, you eliminate the need to implement the Validator interface to handle the validation or one of the listener interfaces 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.
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 for doing so 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.
The following sections explain how to write various types of backing bean methods.
An action method, a backing bean method that handles navigation processing, 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 the page to display next. This method is referenced using the component tag’s action attribute.
The following action method is from a backing bean named CashierBean, which is invoked when a user clicks the Submit button on the page. If the user has ordered more than $100 worth of items, this method sets the rendered properties of the fanClub and specialOffer components to true, causing them to be displayed on the page the next time that 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 rerender the page without creating a new view of the page, retaining the customer’s input. If this method were to return purchase, which is the logical outcome to use to advance to a payment page, the page would rerender without retaining the customer’s input.
If the user does not purchase more than $100 worth of items, or if the thankYou component has already been rendered, the method returns receipt. The JavaServer Faces implementation loads the 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.
The following example uses an Enum class to encapsulate all logical outcomes:
public enum Navigation { main, accountHist, accountList, atm, atmAck, transferFunds, transferAck, error }
When it returns an outcome, an action method uses the dot notation to reference the outcome from the Enum class:
public Object submit(){ ... return Navigation.accountHist; }
The section Referencing a Method That Performs Navigation explains how a component tag references this method. The section Writing Properties Bound to Component Instances explains how to write the bean properties to which the components are bound.
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 javax.faces.component.ActionSource can refer to this method.
In the following example, a method from a backing bean named LocaleBean processes the event of a user clicking one of the hyperlinks on the 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, which indicates a region of the world. The method matches the ID against a HashMap object that contains the locales available for the application. Finally, the method sets the locale by using the selected value from the HashMap object.
Referencing a Method That Handles an Action Event explains how a component tag references this method.
Instead of implementing 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 an example of a backing bean method that validates user input:
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)); } }
Take a closer look at the preceding code segment:
The validateEmail method first gets the local value of the component.
The method then checks whether the @ character is contained in the value.
If not, 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.
A backing bean that handles a value-change event must use a public method that accepts a value-change event and returns void. This method is referenced using the component’s valueChangeListener attribute. This section explains how to write a backing bean method to replace the ValueChangeListener implementation.
The following example tag comes from Registering a Value-Change Listener on a Component, where the h:inputText tag with the id of name 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:
<h:inputText id="name" size="50" value="#{cashier.name}" required="true"> <f:valueChangeListener type="listeners.NameChanged" /> </h:inputText>
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 page:
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException { if (null != event.getNewValue()) { FacesContext.getCurrentInstance(). getExternalContext().getSessionMap(). put("name", event.getNewValue()); } }
To make this method handle the ValueChangeEvent generated by an input component, reference this method from the component tag’s valueChangeListener attribute. See Referencing a Method That Handles a Value-Change Event for more information.
Validating input received from the user to maintain data integrity is an important part of application logic. Validation of data can take place at different layers in even the simplest of applications, as shown in the guessnumber example application from an earlier chapter. The guessnumber example application validates the user input (in the h:inputText tag) for numerical data at the presentation layer and for a valid range of numbers at the business layer.
JavaBeans Validation (Bean Validation) is a new validation model available as part of Java EE 6 platform. The Bean Validation model is supported by constraints in the form of annotations placed on a field, method, or class of a JavaBeans component, such as a backing bean.
Constraints can be built in or user defined. User-defined constraints are called custom constraints. Several built-in constraints are available in the javax.validation.constraints package. Table 9–2 lists all the built-in constraints.
Table 9–2 Built-In Bean Validation Constraints
In the following example, a constraint is placed on a field using the built-in @NotNull constraint:
public class Name { @NotNull private String firstname; @NotNull private String lastname; }
You can also place more than one constraint on a single JavaBeans component object. For example, you can place an additional constraint for size of field on the firstname and the lastname fields:
public class Name { @NotNull @Size(min=1, max=16) private String firstname; @NotNull @Size(min=1, max=16) private String lastname; }
The following example shows a method with a user-defined constraint that checks for a predefined email address pattern such as a corporate email account:
@ValidEmail public String getEmailAddress() { return emailAddress; }
For a built-in constraint, a default implementation is available. A user-defined or custom constraint needs a validation implementation. In the above example, the @ValidEmail custom constraint needs an implementation class.
Any validation failures are gracefully handled and can be displayed by the h:messages tag.
Any backing bean that contains Bean Validation annotations automatically gets validation constraints placed on the fields on a JavaServer Faces application’s web pages.
See Validating Persistent Fields and Properties for more information on using validation constraints.
The Java programming language distinguishes between null and empty strings. An empty string is a string instance of zero length, whereas a null string has no value at all.
An empty string is represented as "". It is a character array of zero characters. A null string is represented by null. It can be described as the absence of a string instance.
Backing bean elements represented as a JavaServer Faces text component such as inputText are initialized with the value of the empty string by the JavaServer Faces implementation. Validating these strings can be an issue when user input for such fields is not required. Consider the following example, where the string testString is a bean variable that will be set using input typed by the user. In this case, the user input for the field is not required.
if (testString.equals(null)) { doSomething(); } else { doAnotherThing(); }
By default, the doAnotherThing method is called even when the user enters no data, because the testString element has been initialized with the value of an empty string.
In order for the Bean Validation model to work as intended, you must set the context parameter javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL to true in the web deployment descriptor file, web.xml:
<context-param> <param-name> javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL </param-name> <param-value>true</param-value> </context-param>
This parameter enables the JavaServer Faces implementation to treat empty strings as null.
Suppose, on the other hand, that you have a @NotNull constraint on an element, meaning that input is required. In this case, an empty string will pass this validation constraint. However, if you set the context parameter javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL to true, the value of the backing bean attribute is passed to the Bean Validation runtime as a null value, causing the @NotNull constraint to fail.
Shortly after 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 the same purpose. Initially, Common Gateway Interface (CGI) server-side scripts were the main technology used to generate dynamic content. Although widely used, CGI scripting technology had many 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.
The following topics are addressed here:
A servlet is a Java programming language class 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 lifecycle 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.
The lifecycle 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.
If an instance of the servlet does not exist, the web container
Loads the servlet class.
Creates an instance of the servlet class.
Initializes the servlet instance by calling the init method. Initialization is covered in Creating and Initializing a Servlet.
Invokes the service method, passing request and response objects. Service methods are discussed in Writing Service Methods.
If it needs to remove the servlet, the container finalizes the servlet by calling the servlet’s destroy method. For more information, see Finalizing a Servlet.
You can monitor and react to events in a servlet’s lifecycle by defining listener objects whose methods get invoked when lifecycle events occur. To use these listener objects, you must define and specify the listener class.
You define a listener class as an implementation of a listener interface. Table 10–1 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 10–1 Servlet Lifecycle 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 |
Use the @WebListener annotation to define a listener to get events for various operations on the particular web application context. Classes annotated with @WebListener must implement one of the following interfaces:
javax.servlet.ServletContextListener javax.servlet.ServletContextAttributeListener javax.servlet.ServletRequestListener javax.servlet.ServletRequestAttributeListener javax.servlet..http.HttpSessionListener javax.servlet..http.HttpSessionAttributeListener
For example, the following code snippet defines a listener that implements two of these interfaces:
import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener() public class SimpleServletListener implements ServletContextListener, ServletContextAttributeListener { ...
Any number of exceptions can occur when a servlet executes. When an exception occurs, the web container generates a default page containing the following message:
A Servlet Exception Has Occurred |
But you can also specify that the container should return a specific error page for a given exception.
Web components, like most objects, usually work with other objects to accomplish their tasks. Web components can do so by
Using private helper objects (for example, JavaBeans components).
Sharing objects that are attributes of a public scope.
Using a database.
Invoking 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.
Collaborating web components share information by means of objects that are maintained as attributes of four scope objects. You access these attributes by using the getAttribute and setAttribute methods of the class representing the scope. Table 10–2 lists the scope objects.
Table 10–2 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. |
In a multithreaded server, shared resources can 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:
Multiple web components accessing objects stored in the web context.
Multiple web components accessing objects stored in a session.
Multiple threads within a web component accessing instance variables. A web container will typically create a thread to handle each request. To ensure that a servlet instance handles only one request at a time, a servlet can implement the SingleThreadModel interface. If a servlet implements this interface, no two threads will execute concurrently in the servlet’s service method. A web container can implement this guarantee by synchronizing access to a single instance of the servlet or by maintaining a pool of web component instances and dispatching each new request to a free instance. This interface does not prevent synchronization problems that result from web components’ accessing shared resources, such as static class variables or external objects.
When resources can be accessed concurrently, they can be used in an inconsistent fashion. You prevent this by controlling the access using the synchronization techniques described in the Threads lesson at http://download.oracle.com/javase/tutorial/essential/concurrency/index.html in The Java Tutorial, Fourth Edition, by Sharon Zakhour et al. (Addison-Wesley, 2006).
Use the @WebServlet annotation to define a servlet component in a web application. This annotation is specified on a class and contains metadata about the servlet being declared. The annotated servlet must specify at least one URL pattern. This is done by using the urlPatterns or value attribute on the annotation. All other attributes are optional, with default settings. Use the value attribute when the only attribute on the annotation is the URL pattern; otherwise use the urlPatterns attribute when other attributes are also used.
Classes annotated with @WebServlet must extend the javax.servlet.http.HttpServlet class. For example, the following code snippet defines a servlet with the URL pattern /report:
import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @WebServlet("/report") public class MoodServlet extends HttpServlet { ...
The web container initializes a servlet after loading and instantiating the servlet class and before delivering requests from clients. To customize this process to allow the servlet to read persistent configuration data, initialize resources, and perform any other one-time activities, you can either override the init method of the Servlet interface or specify the initParams attribute of the @WebServlet annotation. The initParams attribute contains a @WebInitParam annotation. If it cannot complete its initialization process, a servlet throws an UnavailableException.
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. 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 do the following:
Retrieve an output stream from the response.
Fill in the response headers.
Write any body content to the output stream.
Response headers must always be set before the response has been committed. The web container will ignore any attempt to set or add headers after the response has been committed. The next two sections describe how to get information from requests and generate responses.
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:
Parameters, which are typically used to convey information between clients and servlets
Object-valued attributes, which are typically used to pass information between the servlet container and a servlet or between collaborating servlets
Information about the protocol used to communicate the request and about the client and server involved in the request
Information relevant to localization
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:
Context path: A concatenation of a forward slash (/) with the context root of the servlet’s web application.
Servlet path: The path section that corresponds to the component alias that activated this request. This path starts with a forward slash (/).
Path info: The part of the request path that is not part of the context path or the servlet path.
You can use the getContextPath, getServletPath, and getPathInfo methods of the HttpServletRequest interface to access this information. Except for URL encoding differences between the request URI and the path parts, the request URI is always comprised of the context path plus the servlet path plus the path info.
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.
A query string can explicitly appear in a web page.
A query string is appended to a URL when a form with a GET HTTP method is submitted.
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
Retrieve an output stream to use to send data to the client. To send character data, use the PrintWriter returned by the response’s getWriter method. To send binary data in a Multipurpose Internet Mail Extensions (MIME) body response, use the ServletOutputStream returned by getOutputStream. To mix binary and text data, as in a multipart response, use a ServletOutputStream and manage the character sections manually.
Indicate the content type (for example, text/html) being returned by the response with the setContentType(String) method. This method must be called before the response is committed. A registry of content type names is kept by the Internet Assigned Numbers Authority (IANA) at http://www.iana.org/assignments/media-types/.
Indicate whether to buffer output with the setBufferSize(int) method. By default, any content written to the output stream is immediately sent to the client. Buffering allows content to be written before anything is sent back to the client, thus providing the servlet with more time to set appropriate status codes and headers or forward to another web resource. The method must be called before any content is written or before the response is committed.
Set localization information, such as locale and character encoding.
HTTP response objects, javax.servlet.http.HttpServletResponse, have fields representing HTTP headers, such as the following:
Status codes, which are used to indicate the reason a request is not satisfied or that a request has been redirected.
Cookies, which are used to store application-specific information at the client. Sometimes, cookies are used to maintain an identifier for tracking a user’s session (see Session Tracking).
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:
Query the request and act accordingly.
Block the request-and-response pair from passing any further.
Modify the request headers and data. You do this by providing a customized version of the request.
Modify the response headers and data. You do this by providing a customized version of the response.
Interact with external resources.
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.
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.
Use the @WebFilter annotation to define a filter in a web application. This annotation is specified on a class and contains metadata about the filter being declared. The annotated filter must specify at least one URL pattern. This is done by using the urlPatterns or value attribute on the annotation. All other attributes are optional, with default settings. Use the value attribute when the only attribute on the annotation is the URL pattern; use the urlPatterns attribute when other attributes are also used.
Classes annotated with the @WebFilter annotation must implement the javax.servlet.Filter interface.
To add configuration data to the filter, specify the initParams attribute of the @WebFilter annotation. The initParams attribute contains a @WebInitParam annotation. The following code snippet defines a filter, specifying an initialization parameter:
import javax.servlet.Filter; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; @WebFilter(filterName = "TimeOfDayFilter", urlPatterns = {"/*"}, initParams = { @WebInitParam(name = "mood", value = "awake")}) public class TimeOfDayFilter implements Filter { ....
The most important method in the Filter interface is doFilter, which is passed request, response, and filter chain objects. This method can perform the following actions:
Examine the request headers.
Customize the request object if the filter wishes to modify request headers or data.
Customize the response object if the filter wishes to modify response headers or data.
Invoke the next entity in the filter chain. If the current filter is the last filter in the chain that ends with the target web component or static resource, the next entity is the resource at the end of the chain; otherwise, it is the next filter that was configured in the WAR. The filter invokes the next entity by calling the doFilter method on the chain object, passing in the request and response it was called with or the wrapped versions it may have created. Alternatively, the filter can choose to block the request by not making the call to invoke the next entity. In the latter case, the filter is responsible for filling out the response.
Examine response headers after invoking the next filter in the chain.
Throw an exception to indicate an error in processing.
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.
There are many ways for a filter to modify a request or a response. For example, a filter can add an attribute to the request or can insert data in 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.
To override request methods, you wrap the request in an object that extends either ServletRequestWrapper or HttpServletRequestWrapper. To override response methods, you wrap the response in an object that extends either ServletResponseWrapper or HttpServletResponseWrapper.
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 by either using NetBeans IDE or coding the list by hand with XML.
If you want to log every request to a web application, you map the hit counter filter to the URL pattern /*.
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 10–1, 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.
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.
Expand the application’s project node in the Project pane.
Expand the Web Pages and WEB-INF nodes under the project node.
Double-click web.xml.
Click Filters at the top of the editor pane.
Expand the Servlet Filters node in the editor pane.
Click Add Filter Element to map the filter to a web resource by name or by URL pattern.
In the Add Servlet Filter dialog, enter the name of the filter in the Filter Name field.
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.
Click OK.
To constrain how the filter is applied to requests, follow these steps.
Expand the Filter Mappings node.
Select the filter from the list of filters.
Click Add.
In the Add Filter Mapping dialog, select one of the following dispatcher types:
REQUEST: Only when the request comes directly from the client
ASYNC: Only when the asynchronous request comes 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.
Web components can invoke other web resources both indirectly and directly. A web component indirectly invokes another web resource by embedding a URL that points to another web component in content returned to a client. While it is executing, a web component directly invokes another resource by either including the content of another resource or forwarding 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 by 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.
It is often useful to include another web resource, such as 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 is limited in what it can do with the response object.
It can write to the body of the response and commit a response.
It cannot set headers or call any method, such as setCookie, that affects the headers of the response.
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 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.
The context in which web components execute is an object that implements the ServletContext interface. You retrieve the web context by using the getServletContext method. The web context provides methods for accessing
Initialization parameters
Resources associated with the web context
Object-valued attributes
Logging capabilities
The counter’s access methods are synchronized to prevent incompatible operations by servlets that are running concurrently. A filter retrieves the counter object by using the context’s getAttribute method. The incremented value of the counter is recorded in the log.
Many applications require that a series of requests from a client be associated with one another. For example, a web application can save 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.
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, this method creates one.
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.
Recall that your application can notify web context and session listener objects of servlet lifecycle events (Handling Servlet Lifecycle Events). You can also notify objects of certain events related to their association with a session such as the following:
When the object is added to or removed from a session. To receive this notification, your object must implement the javax.servlet.http.HttpSessionBindingListener interface.
When the session to which the object is attached will be passivated or activated. A session will be passivated or activated when it is moved between virtual machines or saved to and restored from persistent storage. To receive this notification, your object must implement the javax.servlet.http.HttpSessionActivationListener interface.
Because an HTTP client has no way 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 getMaxInactiveInterval and setMaxInactiveInterval methods.
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.
To set the timeout period in the deployment descriptor using NetBeans IDE, follow these steps.
Open the project if you haven’t already.
Expand the project’s node in the Projects pane.
Expand the Web Pages node and then the WEB-INF node.
Double-click web.xml.
Click General at the top of the editor.
In the Session Timeout field, type an integer value.
The integer value represents the number of minutes of inactivity that must pass before the session times out.
To associate a session with a user, a web container can use several methods, 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, the method returns the URL unchanged.
A servlet container may determine 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). In such a case, 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 destroy method releases the database object created in the init method .
A servlet’s service methods should all 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 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 explains how to do the following:
Keep track of how many threads are currently running the service method.
Provide a clean shutdown by having the destroy method notify long-running threads of the shutdown and wait for them to complete.
Have the long-running methods poll periodically to check for shutdown and, if necessary, stop working, clean up, and return.
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(); } }
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) { } } }
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) { ... } } }
The mood example application, located in tut-install/examples/web/mood, is a simple example that displays Duke’s moods at different times during the day. The example shows how to develop a simple application by using the @WebServlet, @WebFilter, and @WebListener annotations to create a servlet, a listener, and a filter.
The mood example application is comprised of three components: mood.web.MoodServlet, mood.web.TimeOfDayFilter, and mood.web.SimpleServletListener.
MoodServlet, the presentation layer of the application, displays Duke’s mood in a graphic, based on the time of day. The @WebServlet annotation specifies the URL pattern:
@WebServlet("/report") public class MoodServlet extends HttpServlet { ...
TimeOfDayFilter sets an initialization parameter indicating that Duke is awake:
@WebFilter(filterName = "TimeOfDayFilter", urlPatterns = {"/*"}, initParams = { @WebInitParam(name = "mood", value = "awake")}) public class TimeOfDayFilter implements Filter { ...
The filter calls the doFilter method, which contains a switch statement that sets Duke’s mood based on the current time.
SimpleServletListener logs changes in the servlet’s lifecycle. The log entries appear in the server log.
You can use either NetBeans IDE or Ant to build, package, deploy, and run the mood example.
Select File->Open Project.
In the Open Project dialog, navigate to:
tut-install/examples/web/ |
Select the mood folder.
Select the Open as Main Project check box.
Click Open Project.
In the Projects tab, right-click the mood project and select Build.
Right-click the project and select Deploy.
In a web browser, open the URL http://localhost:8080/mood/report.
The URL specifies the context root, followed by the URL pattern specified for the servlet.
A web page appears with the title “Servlet MoodServlet at /mood” a text string describing Duke’s mood, and an illustrative graphic.
In a terminal window, go to:
tut-install/examples/web/mood/ |
Type the following command:
ant |
This target builds the WAR file and copies it to the tut-install/examples/web/mood/dist/ directory.
Type ant deploy.
Ignore the URL shown in the deploy target output.
In a web browser, open the URL http://localhost:8080/mood/report.
The URL specifies the context root, followed by the URL pattern.
A web page appears with the title “Servlet MoodServlet at /mood” a text string describing Duke’s mood, and an illustrative graphic.
For more information on Java Servlet technology, see
Java Servlet 3.0 specification:
Java Servlet web site:
http://www.oracle.com/technetwork/java/index-jsp-135475.html