JavaServer Faces (JSF) has been dubbed the next big thing in Java web programming. With JSF, you use
web components on your web pages and capture events caused by user actions. In
the near future, Java tools will support this technology. Developing web
applications will be similar to the way we write Swing applications today: dragging and dropping controls and writing event listeners. This article is an introduction to
JSF. It highlights the most important aspect of JSF: JSF applications are
event-driven. Also, it offers a sample JSF application that illustrates the
event-driven-ness of JSF. To understand this article, you need to be familiar
with servlets, JSP, JavaBeans, and custom tag libraries.
First of all, a JSF application is a servlet/JSP application. It has a
deployment descriptor, JSP pages, custom tag libraries, static resources, et
cetera. What makes it different is that a JSF application is event-driven.
You decide how your application behaves by writing an event listener class.
Here are the steps you need to take to build a JSF application:
Author JSP pages, using JSF components that encapsulate HTML elements.
Write a JavaBean as the state holder of user-input and component data.
Write an event listener that determines what should happen when an event
occurs, such as when the user clicks a button or submits a form. JSF supports
two events: ActionEvent and ValueChangedEvent.
ActionEvent is fired when the user submits a form or clicks a
button, and ValueChangedEvent is triggered when a value in a JSF
component changes.
Now, let's take a look at how JSF works in detail.
How JSF Works
JSP pages are the user interface of a JSF application. Each page contains
JSF components that represent web controls, such as forms, input boxes, and
buttons. Components can be nested inside of another component; an input box can
reside inside a form. Each JSP page is represented by its component tree.
JavaBeans store the data from user requests.
Here is the interesting part: every time the user does something, such as
clicking a button or submitting a form, an event occurs. Event notification is
then sent via HTTP to the server. On the server is a web container that employs
a special servlet called the Faces servlet. The Faces servlet, represented by
the javax.faces.webapp.FacesServlet class, is the engine of all
JSF applications. Each JSF application in the same web container has its own
Faces servlet. Another important object is
javax.faces.context.FacesContext, which encapsulates all necessary
information related to the current request.
In the background, the processing performed by the Faces servlet is
complex. However, you don't need to know all the details. Just bear in mind
that the Faces servlet builds a component tree of the JSP page whose control
fires an event. The Faces servlet knows how to build the tree because it has
access to all JSP pages in the application. The Faces servlet also creates an
Event object and passes it to any registered listener. You can
obtain the component tree of a JSP page from the FacesContext
object associated with the request.
An event fired by a web control on the client browser is encapsulated in an
HTTP request, alongside other information such as
the browser type, the request URL, etc. Therefore, all requests that need Faces servlet processing must be directed to this servlet. How do you invoke
the Faces servlet with every HTTP request? Easy. Just use a servlet-mapping
element in your deployment descriptor to map a particular URL pattern with the
Faces servlet. By convention, you use the /faces/* pattern, such
as the following.
The request URL must contain the pattern in the
<url-pattern> element. This is not hard to achieve. Note also that
the <servlet> element, which contains the Faces servlet, has a
<load-on-startup> element, to make sure the servlet is loaded
when the application is first started.
To capture the event fired by a component, you must write an event listener
for that component and register it with the component. Do this by enclosing the
<action_listener> element in the custom tag representing the
component. For example, to allow a listener named
jsfApp.MyActionListener to capture the action event fired by a
command button called submitButton, write the following code in
your JSP page:
An action listener must implement the
javax.faces.event.ActionListener interface and a value-changed
listener must implement javax.faces.event.ValueChangedListener.
Let's build a simple JSF application that illustrates how event-driven
JSF is.
A Simple JSF Application
We'll build a simple JSF application that can add two numbers. To run this
application, you need Tomcat 5 and JSF v1.0 EA4 (included in the Java Web Services
Developer Pack (JWSDP) 1.2. The application consists of:
adder.jsp, a JSP page
NumberBean, a JavaBean for storing user data
MyActionListener, an action listener
web.xml, a deployment descriptor
For your JSF application to work, it needs a set of .jar files containing
the JSF reference implementation and other libraries. Once you install the
JWSDP 1.2, you can find these files under its jsf/lib directory.
Copy these .jar files to the WEB-INF/lib directory. Here is the
list of all .jar and .tld files.
jsf-api.jar contains the Faces servlet and related classes in
the javax.faces package.
jfs-ri.jar is the reference implementation of JSF.
jstl_el.jar handles JSTL expression language syntax.
standard.jar is required to use JSTL tags and is referenced by
JFS reference implementation classes.
In addition, a JSF application will need the following libraries, which are
part of the Apache Jakarta project. These libraries are included in the
application accompanying this article.
commons-beanutils.jar contain utilities for defining and
accessing JavaBeans component properties.
commons-digester.jar is the library containing the Apache
Common Digester classes.
commons-logging.jar is a general-purpose, flexible logging
facility.
The following subsections discuss each part of the sample JSF application.
The final subsection, "Compiling and Running the Application," explains how the
JSF application works.
Creating the Directory Structure
Start by creating a directory structure for your JSF application. In
Tomcat, this goes under webapps. Figure 1 depicts the directory
structure for an application called myJSFApp.
Figure 1. The directory structure of the JSF
application
Writing the Deployment Descriptor
Just like any other servlet/JSP application, this application needs a
deployment descriptor, as shown in Listing 1.
Listing 1. The deployment descriptor (the web.xml file)
There are two sections in the deployment descriptor. The
<servlet> element registers the Faces servlet, and the
<servlet-mapping> element states that any request containing
the pattern /faces/ in the URL must be passed to the Faces
servlet.