You are on page 1of 7

This article is meant to acquaint the reader with JavaServer Faces, commonly known as JSF.

JSF technology simplifies building the user interface for web applications. It does this by
providing a higher-level framework for working with your web app, representing the page as
event-aware components rather than raw markup.

At this time, there are two JSF variants: JSF early access 4 (which is included in the Java Web
Services Developer Pack 1.3), and JSF 1.0 Beta. It's important to remember that JSF is a
specification, much like J2EE. And like J2EE, there is a reference implementation from Sun,
along with other implementations of the interface, such as the open source MyFaces. This
article is concerned with the distinctive features of the JSF specification and its ideas, not with
a particular implementation. After all, since JSF is not yet final, the specifics might yet change.

We assume the reader is already somewhat familiar with Java programming, servlets,
JavaServer Pages (JSPs) and custom tag technologies. The reader should be experienced with
servlet/JSP containers such as Tomcat, and design patterns such as model-view-controller
(MVC).

Roles in Web-Application Development

In developing web applications, we often deal with the same problems. First off, the interface
is the most frequently updated part of the application, so we want to simplify modification of
the interface as much as possible. Secondly, those developing the application have
significantly different skill sets — server-side programmers, HTML coders, graphic designers,
etc. — and we want their work to be as independent as possible. This leads to a model-view-
controller design to separate the roles.

In many organizations, the development of a web application works in a familiar manner. The
designer creates a prototype, the HTML coder does everything in HTML, and the server-side
programmer achieves his or her needed functionality in Java. This approach often fails badly.
The designer, when creating the prototype, is limited only by his or her imagination,
inadvertently causing problems for the other participants, often forcing them to start from
scratch when developing a new application.

Reusable Components

Even if the problem of role division can be solved in existing frameworks (for example, by
using custom tags or XML/XSL transformations), there can still be a problem with code reuse.
So what's so different between creating the GUI for a Swing application and a web application?
It's obvious: in Swing, there is a set of standard GUI components and an entire infrastructure
for tweaking and extending the functionality. A Swing developer works with the concept of a
Component — an element of the user interface, such as a panel, button, list, or table — and
can either set values to use the default behavior or extend the component to provide new
behavior.

Some of these components, specifically Containers allow combinations of components, such


as a panel with a table that contains buttons in some of its cells. As an added bonus, the
developer gets to work with high-level concepts: when the button is clicked, an event is
generated.

Meanwhile, for the web developer to know the button has been pressed, he has to analyze the
HTTP request and try to determine what has happened. This is not ideal. The programmer
shouldn't have to work so hard to figure out if a button, image, or hyperlink was clicked, or
how these pieces were implemented in HTML. Ideally, the developer just wants to know that
an event occurred. In other words, the developer needs to be able to see the web interface in
terms of familiar high-level concepts.
This is the problem JSF aims to solve.

The JSF Approach

The following presentation of JSF concepts is based on the most recent specification (dated
Dec. 18, 2003).

The core JSF architecture is designed to be independent of communication protocols or


markup language specifics. However, it's also meant to solve the problems experienced
working with HTML clients communicating via HTTP with a Java application server that
supports Servlet/JSP applications. JSF aims to provide the following features to simplify
application development:

• Handling of UI components between requests.


• Consideration of markup features supported by the client/browser.
• Support for processing forms.
• Strictly-typed event model.
• Transformation of data on the page (Strings) into the models' corresponding data
types.
• User-friendly exception handling.
• Navigation between pages based on UI events and interaction with data models.

Of course, when developing web applications today, everyone has to deal with these problems,
and everyone solves them in their own way, increasing development time and hurting
maintainability. JSF tries to offer a unified way to deal with these issues.

The specification understands the importance of dividing software development roles and
assigns responsibilities to these roles.

Page Authors

Page authors are responsible for the appearance of the application. They should understand
client-side markup (HTML and JavaScript) and also page structure during development (such
as JSP). Page authors usually create pages from ready-made components delivered by
component developers, modifying them to achieve the desired appearance.

Component Writers

Component writers (a.k.a. Component Developers) are responsible for creating reusable UI
components. They are thus responsible for:

• Making components "understandable" to the final client (e.g., providing HTML to a


browser). This process involves encoding information from the application.
• Making the application understand the request form, by decoding the information in a
request.
• Reacting to events received by a component and understanding when such an even
has occurred.

Application Developers

Application developers are responsible for the server-side tasks, such as creating an
application's business logic, its persistence layer, etc. They should develop appropriate Java
objects to represent the desired functionality, and make these objects accessible from
servlets.

Tool Providers

Tool providers supply tools like IDEs that facilitate creating JSF-based applications, or even
higher-level frameworks that might use JSF to create their user interface.

JSF Implementors

JSF implementors are responsible for implementing all the required specifications of JSF. For
example, they might provide a JSF implementation within their J2EE server.

Note that most developers will not perform either of the latter two roles. But they indicate the
seriousness of Sun's intentions with respect to role-division: for JSF to succeed, it's necessary
to follow the role-division guidelines.

JSF in Detail

Let's look in detail at what JSF provides us. As noted above, the highlight of JSF is the
availability of reusable server components for creating GUI's. From JSF's point of view, all
components should inherit from javax.faces.component.UIComponent (note that in the
EA4 release this was an interface). Any page or screen of the application will consist of a set of
such components. A set of hierarchically ordered components is called the JSF Tree (EA4's
term) or the View (1.0 beta's term). This tree of components represents the structure of the
onscreen page. Each element of a tree is UIComponent, with some components being
composites and thus having child components.

In JSF there is a set of standard components. The UML diagram shows the notation structure
of these standard components. The developer can create new components based on existing
components (for example, by inheriting from UIOutput), or by a completely new subclass of
UIComponent. To make creating components easier, it's possible to inherit from
UIComponentBase, which contains default implementations for the methods in
UIComponent along with some convenience methods.

If a hypothetical page will contain a form with an input field and a button, then the JSF
components' structure will be of the form UIViewRoot → UINamingContainer → UIForm →
(UIInput, UICommand, where the "→" character is understood to show a parent-child
relationship. This means the UIViewRoot has a single child, a UINamingContainer (used
by JSF for automatic assignment of unique identifiers), which has a UIForm child, which in
turn has two children: a UIInput and a UICommand. Each component can find its parent with
getParent() and its children with getChildren().

Figure 1 shows the relationship of the JSF component classes.


Figure 1. Standard JSF components.

The most interesting methods of UIComponent are the following:

• decode(javax.faces.context.FacesContext context)
• encodeBegin(javax.faces.context.FacesContext context)
• encodeChildren(javax.faces.context.FacesContext context)
• encodeEnd(javax.faces.context.FacesContext context)

These methods are responsible for the translation of data from a request to a component and
from forming a reply based on the state of a component. Naturally, implementations of these
methods should be coordinated — if the encode() stores the condition of a component, then
decode() should have an opportunity to read it. Despite the fact that these methods are in
the components themselves, the responsibility for encoding and decoding is usually relegate to
special classes inherited from javax.faces.renderer.Renderer.

These renderer classes bear the responsibility for how a given component will be presented to
the user. For example, UICommand might be displayed as either a button or a link. This
arrangement allows the UICommand class to remain fairly constant, while its presentation
varies with the associated Renderer. Related Renderer functionality can be united in a
RenderKit.

For example, if you know that the client will be rendering HTML you can use the
HTMLRenderKit. In fact, there are multiple kits, including SimpleHTMLRenderKit for
browsers that don't fully support HTML 4.0, and AdvancedHTMLRenderKit for modern
browsers. Of course, this means a given page may look different in different browsers, but the
page structure (the View) does not need to be modified. It's only necessary to define a rule to
determine which RenderKit to use.

However, this may not be enough in some cases. The important part is the component model,
which encapsulates the data with which the component works. As an example, we'll consider
the javax.faces.model.DataModel that appeared in JSF 1.0 Beta. This abstract class is a
wrapper for data representing Strings, accessed by index. If, for example, we needed to
represent records in a database table, we could use JSF's
javax.faces.model.ResultSetDataModel, an implementation of DataModel. This
arrangement of a component in terms of a DataModel, its Renderer and its UIComponent
represent the model, view, and controller from the familiar MVC pattern.

A component can generate events and notify all interested listeners. All event classes need to
inherit from javax.faces.event.FacesEvent, while all listeners implement
javax.faces.event.FacesListener. So, to track the change in a component's value, we
have javax.faces.event.ValueChangeEvent, which is handled by a
javax.faces.event.ValueChangeListener. A concrete UIComponent provides an
opportunity to register listeners on this type of event. For example,
javax.faces.component.UIInput contains the method addValueChangeListener,
which takes a ValueChangeListener.

JSF also provides the concepts of a Validator and a Converter. The former is used to
check the status of a component (for UIInput), and in the case of an error it provides a
message to be shown to the user, such as "invalid phone number" or "username should only
contain letters and numbers." A Converter is used to transform data from a String to some
kind of object and back.

For example, a model may store a date as a java.util.Date, but the Renderer changes it
to a String at some stage of encoding, and at decoding time it's necessary to convert the
String back into a Date. For this common purpose, JSF provides the standard converter
javax.faces.convert.DateTimeConverter.

JSF defines not only the possible actions involving components, but also the order of these
actions. At the moment a request is received by FacesServlet, the entry-point to JSF, a
lifecycle of JSF request processing begins, which consists of a set of phases, each with its own
specialization:

1. Restore View (previously "Restore Component Tree") -- restores a tree of components.


2. Apply Request Values -- applies data from the request.
3. Process Validations -- executes any validations.
4. Update Model Values -- updates values of model.
5. Invoke Application -- executes application.
6. Render Response -- generates a response to the user.

For additional information about the JSF actions at each phase of the cycle, consult the details
of the JSF specification.

A JSF Example

Currently, JSP is used as the basic mechanism for formatting a page. With special JSF custom
tags, we can create the structure, the component tree, and the parameterization of each
component. Here's what a basic JSF page looks like:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>


<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<HTML>
<HEAD>
<title>Hello</title>
</HEAD>
<body bgcolor="white">
<h2>Enter number</h2>
<f:view>
<h:form >
<h:graphicImage id="logo" url="/logo.gif" />
<h:inputText id="num" required="true" size="4">
<f:validateLength maximum="4" minimum="1" />
</h:inputText>
<h:commandButton value="submit" action="success" title="Submit" />
</h:form>
</f:view>
</body>
</HTML>

This page consists of a form in which we have a graphic image, an input field, and a submit
button. We've also added a validator to the input field. Note that the form does not have an
ACTION attribute. This is because JSF has its own navigation system. The target where the
form will be submitted is defined by the button, with help from a configuration file, faces-
config.xml, which specifies that if a page transition is successful (i.e., the action = "success"),
then we'll be redirected to a certain URL. Notice that this arrangement is similar to the Struts
framework; developers already familiar with Struts will see the analogy between the JSF
configuration file and struts-config.xml.

Conclusions

JSF was developed to handle everything required for developing web-oriented applications. It's
meant to be an all-encompassing solution. But it's interesting to compare the technology to
existing alternatives. Struts is a well-known web framework that is something of a standard
for similar projects. Much like JSF, it is based on MVC principles. However, Struts itself doesn't
provide a View construction mechanism. But to its credit, Struts has a nicely implemented
concept of controllers. Thus, Struts is often used in combination with other frameworks that
deal with the presentation.

Also, there are many frameworks available that are similar to JSF, such as UIX from Oracle. In
fact, this particular framework is very similar to JSF and probably reflects Oracle's interest in
web GUIs. The Oracle JDeveloper IDE supports UIX, but reportedly plans to add JSF support.
IBM's WebSphere Application Developer also supports JSF. One other framework, similar in
spirit to JSF, is Tapestry, in which we can see the concepts of a lifecycle, reusable components,
and rigid division of roles.

In conclusion, my own opinion about JSF is that while it has incorporated the advantages of
many custom tag libraries and frameworks, it has also inherited the difficulties of adjusting to
a new way of coding. Granted, Struts arguably has the same problem. But since JSF isn't yet
final, it's possible that it will be further improved before it's done.

You might also like