Level: Intermediate Richard Hightower (rhightower@arc-mind.com), CTO, ArcMind
03 Feb 2005 For such an indispensable technology, Java™Server Faces (JSF) has generated an undue amount of FUD. Hearsay has it that JSF development is difficult, more demanding than some mainstream approaches, and dependent on WYSIWYG tools to work at all. In this new four-part series, frequent developerWorks contributor Rick Hightower separates FUD from fact to show you that, actually, JSF can be easier to use than MVC Model 2 frameworks such as Struts. If you know what you're doing, that is.
Editor's notes: Since publication, Sun has open sourced JSF 1.2 under their CDDL license. See Resources for a link to the new project page.
For details on getting started with JSF 1.2, now integrated in JEE 5, see Richard Hightower's tutorial series.
Fear, uncertainty, and doubt (FUD) has been circulating about J2EE's
JavaServer Faces (JSF) technology for a while now and I've decided the
time has come to put a stop to it; or at least offer a balancing
perspective. The first myth about JSF is that you need a WYSIWYG
drag-and-drop tool to do JSF development. The second is that JSF doesn't
support MVC Model 2 frameworks like Struts. And the final, most
all-encompassing myth about JSF development is that it's just plain
difficult.
In this four-part series, I'll do my best to dispel all three myths
in the most practical way possible: by teaching you to work around them.
The fact is, if you think JSF development is difficult you're probably
not doing it right, and fortunately that's pretty easy to fix. I'll get
you started this month with an architectural overview of JSF and a
working example demonstrating the fundamentals of MVC and JSF. But
before we get into all that, I'll take just a minute to separate some JSF
FUD from fact.
 |
JEE WARTAC blog
Author Rick Hightower takes his discussion of JSF one step further in JEE WARTAC, a blog that focuses on topics related to the tools he uses in his daily development, including JSF, Facelets, Hibernate, Spring, Tomahawk, MyFaces, RDBMS systems, and iBatis.
|
|
Don't believe the FUD!
As previously mentioned, there are three big myths about JSF and the
first is that it requires WYSIWYG tools to work. Well, that's bunk. Just
like many Swing developers don't use WYSIWYGs to build Swing
applications, you don't need WYSIWYG editors to build JSF applications.
In fact, JSF development without WYSIWYG tools is much easier than
development with traditional Model 2 frameworks like Struts and WebWork.
I'll explain why in detail later in this article, but for now just
remember that you read it here first: JSF development is much easier
than Struts, even without the WYSIWYG tools!
The next myth about JSF is that it doesn't support the Model 2
architecture. Now, this is actually partially true. The fact is that
Model 2 is a watered down version of MVC (Model-View-Controller) for Web
development built on top of Servlets. Whereas Model 2 is geared
towards a stateless protocol (HTTP), JSF supports a richer MVC
model, a much closer approximation of a traditional GUI application.
While the basis in MVC does make JSF framework implementations harder
to build than other frameworks, the upside is that a lot of the real work
of implementing JSF has already been done for you, so your net effort
is less and your net gain is considerably more.
 |
About this series
This four-part series is dedicated to dispelling FUD about JavaServer
Faces (JSF) technology, mainly by giving you a chance to get to know it
for yourself in a step-by-step, easy-to-follow format. Over the course
of four articles I'll provide a series of examples to introduce you to
the basic architecture, features, and functionality of JSF. Once you're
familiar with the JSF way of doing things, I think you'll find it
hard to go back to Struts Model 2-style development. After all, who
would want to revisit XML configuration Hades after experiencing JSF's
event-driven, GUI component model?
To get the most out of this series you should be familiar
with Java programming, JavaBeans components (namely event model and properties),
JavaServer Pages technology, the JSP Standard Tag Library Expression Language,
and all basic Web development concepts.
|
|
The broadest and most widespread myth about JSF development is that
it's hard. I hear this most often from people who have read a lot about
the technology but haven't actually tried it out for themselves, so I think I can
clear it up pretty easily. The fact is, if you based your opinion of JSF on its
admittedly extensive specification -- with all its lifecycle diagrams and pictures -- then
the technology could easily scare the mess out of you. The thing to
remember, though, is that the spec is for the implementers of the tools,
not for application developers per se. As previously mentioned, the JSF
framework is designed to be remarkably easy on the application
developer.
In fact, although the component-based, event-driven GUI development
model of JSF is somewhat new to the Java world, it has existed for quite
some time elsewhere. Apple's WebObjects is a similar architecture to JSF
and so is ASP.net. Tapestry is an open source Java-based Web component
framework that takes a somewhat different approach from JSF's but is also
founded on a Web GUI component model.
And that's probably enough talk about FUD, for now anyway. The
easiest way to dissolve your preconceptions about JSF is to delve right
into the technology, and we'll do that in just a few minutes. But just in case this
is your first-ever look at JSF, I'll start with an architectural overview.
JSF for beginners
Like Swing and AWT JSF is a development framework that provides a set
of standard, reusable GUI components. JSF is used for building Web application
interfaces. JSF provides the following development advantages:
- Clean separation of behavior and presentation
- Component-level control over statefulness
- Events easily tied to server-side code
- Leverages familiar UI-component and Web-tier concepts
- Offers multiple, standardized vendor implementations
A typical JSF application consists of the following parts:
- JavaBeans components for managing application state and behavior
- Event-driven development (via listeners as in traditional GUI development)
- Pages that represent MVC-style views; pages reference view roots via the JSF component tree
While you will need to overcome some conceptual hurdles to use JSF,
doing so is well worth the effort. JSF's component state management, easy to
use user input validation, granular, component-based event handling, and
easily extensible architecture will greatly simplify your Web development
efforts. I'll explain the most important of these features in greater
detail in the next several sections.
A component-based architecture
JSF provides component tags for every input field available in
standard HTML. You can also write your own custom components for
application-specific purposes or for combining multiple HTML components
together to form a composite -- for example a Data Picker component that
consists of three drop-down menus. JSF components are stateful. The
statefulness of the components is provided through the JSF framework.
JSF uses components to produce HTML responses.
JSF's component set includes an event publishing model; a lightweight
IoC container; and components for just about every other common GUI
feature, including pluggable rendering, server-side
validation, data conversion, page navigation management, and more. Being
a component-based architecture, JSF is extremely configurable and
extensible. Most JSF functions -- such as navigation and managed bean
lookup -- can be replaced with pluggable components. This degree of
pluggability gives you considerable flexibility in building your Web
application GUIs and allows you to easily incorporate other
component-based technologies into your JSF development efforts; for
example, you could replace JSF's built-in IoC framework with the more
full-featured IoC/AOP Spring framework for managed bean lookups.
JSF and JSP technology
The user interface of a JSF application is comprised of JSP
(JavaServer Pages) pages. Each JSP page contains JSF components that
represent the GUI functionality. You use JSF custom tag libraries inside JSP pages to render the UI components, to register event handlers, to
associate components with validators, to associate components with data
converters, and more.
That said, the truth is that JSF is not bound to JSP technology inherently. In
fact, the JSF tags used by JSP pages merely reference the components so they
can be displayed. You'll realize this the first time you modify a JSP
page to change the attributes of a JSF component and reload the page,
and nothing happens. This is because the tag looks up the component in
its current state. Thus, if the component already exists the custom tag
will not modify its state. The component model allows your controller
code to change the state of a component (for example, disable a text field),
and when that view is displayed the current state of your component
tree will be displayed.
A typical JSF application needs no Java code and very little JSTL EL
(JSP Standard Tag Library, Expression Language) code in the UI. As
previously noted, there are lots of IDE tools for building and
assembling applications in JSF, and there seems to be a growing
third-party market for JSF GUI components. It is also possible to code
JSF without the use of WYSIWYG tools.
 |
About MVC
The model-view-controller (MVC) architecture provides a set of design
patterns that help you separate the areas of concern involved in
building and running a GUI-based application. The model
encapsulates the business logic and persistence code for the
application. The model should be as view-technology-agnostic as
possible. For example, the same model should be usable with a Swing
application, a Struts application, or a JSF application. The view
should display model objects and contain presentation logic only. There
should be no business logic or controller logic in the view. The
controller (along with its attending logic) acts as the mediator between
the view and the model. The controller talks to the model and delivers
model objects to the view to display. In an MVC architecture
the controller always selects the
next view.
|
|
JSF and MVC
JSF is the result of lessons learned over several years of evolving
Web development techniques on the Java platform. This trend started with
JSP technology, which was nice but made it too easy to mix Java code in with HTML
(and HTML-like) pages. The next step up was the Model 1 architecture,
which had developers pushing most backend code into JavaBeans components and then
importing the JavaBeans components into Web pages with the <jsp:useBean> tag. This worked well for simple Web
apps, but many Java developers disliked JSP technology's incorporation of C++ features
such as static includes. So the Model 2 architecture was introduced.
Essentially, the Model 2 architecture is a watered-down version of
MVC for Web applications (see "About MVC"). In
the Model 2 architecture the controller is represented by Servlets and display
is delegated to JSP pages. Struts is a simplified Model 2 implementation
wherein Actions take the place of Servlets. In Struts the application's
controller logic is separated from its data (represented by ActionForms).
The main complaint against Struts is that it can feel more procedural than
object-oriented. WebWork and Spring MVC are two other Model 2 architectures
that improve on Struts by being less procedural, but neither is as
widely accepted (nor as mature, some would argue) as Struts. Plus
neither offers a component model like JSF does.
The real issue with most Model 2 frameworks is that the event
model is too simplistic (essentially a very scaled down MVC), which
leaves too much of the work to the developer. A richer event model makes
it easier to create the kind of interactions most users expect. Like JSP technology,
most Model 2s also make it too easy to mix HTML layout and formatting
with GUI custom tags, which act loosely like components. And some Model
2 architectures (like Struts) make the mistake of separating
behavior and state, which leaves many Java developers feeling like
they're programming COBOL.
A richer MVC environment
JSF provides a component model and a richer MVC environment than most
Model 2 implementations. Essentially, JSF is much closer to a true MVC
programming environment than the Model 2 architectures, although
it's still a stateless protocol. JSF also facilitates building more fine-grained
event-driven GUIs than the Model 2 frameworks. Whereas JSF gives you a
host of event options -- menu item selected, button clicked, etc. --
most Model 2s rely on the more simple "request received."
 |
Struts and JSF
The Struts framework was a necessary evolution in the development of
Web frameworks on the Java platform. Struts pushed the limits of the
Model 2 framework. Ideas used in Struts evolved into JSTL and JSF. Many
projects that were spawned to address the Model 2 development model used
ideas first explored by Struts (usually with substantial improvements).
Furthermore, you can still see a lot of Struts DNA in the JSF project,
although they diverge architecturally. You can still use Tiles with JSF, for
example, or use the Struts validator framework to generate client-side
JavaScript. There's even some movement toward integrating Struts and
JSF. All that said, it is my opinion that JSF mostly replaces the need
for Struts (or at least in its current form). The next major version
of Struts, called Shale, abandons some of Struts core for JSF.
Keep reading this series and decide for yourself if JSF is a viable
alternative to Struts for your project.
|
|
JSF's fine-tuned event model allows your applications to be less tied
to HTTP details and simplifies your development effort. JSF also
improves somewhat on the traditional Model 2 architecture by making it
easier to move presentation and business logic out of your controller and move
business logic out of your JSP pages. In fact, simple
controller classes aren't tied to JSF at all, making them easier to
test. Unlike a true MVC architecture it is unlikely that the JSF model tier
is issuing many events that have to be resolved in more than one
viewport; again we are still dealing with a stateless protocol so this
would be unnecessary. The system event for changing or updating a view
is almost always (dare I say always?) a request from the user.
Details of JSF's MVC implementation
In JSF's MVC implementation, mapping backing beans mediate between
view and model. Because of this it's important to limit the business logic
and persistence logic in the backing beans. One common alternative
is to delegate business logic to the application model. In this case the backing beans
also map model objects where the view can display them. Another option is
to put the business logic in a Business delegate, a facade that acts as the model.
Unlike JSP technology, JSF's view implementation is a stateful component model.
The JSF view is comprised of two pieces: the view root and JSP pages. The view
root is a collection of UI components that maintain the state of the UI.
Like Swing and AWT, JSF components use the Composite design pattern to
manage a tree of components (simply put: a container contains
components; a container is a component). The JSP page binds UI components to
JSP pages and allow you to bind field components to properties of
backing beans (or properties of properties more likely), and buttons to
event handlers and action methods.
Here's an example application (the one you're about to get to know in
detail!) seen from an MVC point of view.
Figure 1. Example application from an MVC point of view
And that's enough fluff: let's get started with JSF!
A JSF example
For the remainder of the article I'll focus on the step-by-step
process of actually creating an application in JSF. The example
application is a very simple demonstration of JavaServer Faces
technology. It demonstrates the following:
- How to lay out a JSF application for deployment
- How to configure a web.xml file for JSF
- How to configure a faces-config.xml for an application
- Writing Model beans (a.k.a. backing beans)
- Constructing the view using JSP technology
- Using custom tag libraries to construct the component tree in the view root
- Default validation of form fields
 |
Build by Maven
The default build environment for the example Calculator application
is Maven. The Maven build system is similar to Ant. In these examples,
I've used the default layout for a Maven Web application. Therefore, the
application's Java class files are in the project root under
src/java. The Web applications files are contained under
src/webapp -- where I place files specifically for my Web
application, including the JSP pages, faces-config.xml, and web.xml.
A project.xml file in the root of the project folder describes
what I need and where my files are located for Maven to build and
package the war file. A project.properties file has additional
properties that tell Maven what to do and where to find things specific
to the local environment. I've also generated an Ant build.xml
for Ant users who don't want to try Maven. If you choose to use Ant you
can find more instructions on building the example and setting up your
environment in the build.xml file and in the Resources section.
|
|
The example is a simple Calculator application. The goal in creating
the application is to present a page to the end user that allows him or
her to enter two numbers. Therefore the page has two text fields, two
labels, two error-message locations, and a Submit button. The text
fields are for entering the numbers. The labels are for labeling the
text fields. The error message locations are to display validation or
data-conversion error messages for the text fields. There are three JSP
pages: index.jsp, which just redirects to calculator.jsp;
calculator.jsp, which present the GUI mentioned above; and
results.jsp, which displays the results. A managed bean
called CalculatorController serves as the
backing bean for calculator.jsp and results.jsp.
Figure 2 shows a second MVC view of the example Calculator application. You
can download the application source by clicking the Code icon at the top or
bottom of this page.
Figure 2. Second MVC view of the
sample application
Building the application
To build the Calculator application in JSF you'll need to do the following:
- Collect the web.xml and faces-config.xml file, found
under the example application's src/webapp/WEB-INF directory.
- Declare the Faces Servlet, and Faces Servlet mapping in the web.xml file.
- Specify the faces-config.xml file in the web.xml file.
- Declare what beans get managed by JSF in the faces-config.xml file.
- Declare the navigation rules in the faces-config.xml file.
- View the model object
Calculator.
- Use the
CalculatorController to talk to the
Calculator model.
- Create the index.jsp page.
- Create the calculator.jsp page.
- Create the results.jsp page.
Omitting step 1, which is really just setup, I'll go over each step in the process in detail.
Declare the Faces Servlet and Servlet mapping
In order to use Faces you first need to install the Faces Servlet in your web.xml file as shown here:
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup> 1 </load-on-startup>
</servlet>
|
This is very similar to most web.xml descriptors except that you're giving
control over to the JSF Servlet to handle requests instead of specifying
your own Servlet. All requests to JSP files that use f:view must go
through this Servlet. Therefore, you need to add a mapping and only load the
JSF-enabled JSP technology through that mapping, as shown here.
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/calc/*</url-pattern>
</servlet-mapping>
|
The above tells the Faces Servlet container to send all requests that map to
/calc/ to the Faces Servlet for processing. This
allows JSF to initialize the JSF context and the view root.
Specify the faces-config.xml file
If you name your faces configuration file faces-config.xml and place it in the
WEB-INF directory of your Web application then the Faces Servlet will pick it up
and use it automatically (since it's the default). Alternatively, you may load one or
more application configuration files through an initialization parameter in
your web.xml file -- javax.faces.application.CONFIG_FILES -- with a
comma-separated list of files as the argument. You will likely use the second approach for all
but the simplest JSF Web applications.
Declare bean management
Next, you will want to declare which beans get used by JSF GUI components. The example
application only has one managed bean. It is configured in faces-config.xml
as follows:
<faces-config>
...
<managed-bean>
<description>
The "backing file" bean that backs up the calculator webapp
</description>
<managed-bean-name>CalcBean</managed-bean-name>
<managed-bean-class>com.arcmind.jsfquickstart.controller.CalculatorController</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
|
The above config tells JSF that you want to add a bean to the JSF context called
CalcBean. You can call your managed bean anything you want. With
the beans declared, your next step is to state the high-level navigation rules for the application.
Declare navigation rules
For this simple application you need only to establish the navigation
path from the calculator.jsp page to the results.jsp page, as shown below.
<navigation-rule>
<from-view-id>/calculator.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/results.jsp</to-view-id>
</navigation-case>
</navigation-rule>
|
The above states that if an action returns the logical outcome "success" from
the /calculator.jsp view, then forward the user to the /results.jsp view.
View the model object
As my goal is to demonstrate how to get started with JSF, I've
kept the model object very simple. The model of this application is contained
within one model object, shown in Listing 1.
Listing 1. The Calculator app's model object
package com.arcmind.jsfquickstart.model;
/**
* Calculator
*
* @author Rick Hightower
* @version 0.1
*/
public class Calculator {
//~ Methods ----------------------------------------------------------------
/**
* add numbers.
*
* @param a first number
* @param b second number
*
* @return result
*/
public int add(int a, int b) {
return a + b;
}
/**
* multiply numbers.
*
* @param a first number
* @param b second number
*
* @return result
*/
public int multiply(int a, int b) {
return a * b;
}
}
|
With that, the business logic is all set up. Your next step is to glue it to the Web
application interface.
Gluing the model and view
The goal of the controller is to act as the glue from the model to
the view. One function of the Controller
object is to keep the model agnostic with regard to the view technology.
As you can see below, the controller specifies three JavaBeans properties
that will be used to collect input and display results. The properties
are results (output); firstNumber (input); and secondNumber (input). The Controller also presents two operations that
delegate to operations of the same name in the Calculator objects. Listing 2 shows the code for
the CalculatorController.
Listing 2. The CalculatorController
package com.arcmind.jsfquickstart.controller;
import com.arcmind.jsfquickstart.model.Calculator;
/**
* Calculator Controller
*
* @author $author$
* @version $Revision$
*/
public class CalculatorController {
//~ Instance fields --------------------------------------------------------
/**
* Represent the model object.
*/
private Calculator calculator = new Calculator();
/** First number used in operation. */
private int firstNumber = 0;
/** Result of operation on first number and second number. */
private int result = 0;
/** Second number used in operation. */
private int secondNumber = 0;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new CalculatorController object.
*/
public CalculatorController() {
super();
}
//~ Methods ----------------------------------------------------------------
/**
* Calculator, this class represent the model.
*
* @param aCalculator The calculator to set.
*/
public void setCalculator(Calculator aCalculator) {
this.calculator = aCalculator;
}
/**
* First Number property
*
* @param aFirstNumber first number
*/
public void setFirstNumber(int aFirstNumber) {
this.firstNumber = aFirstNumber;
}
/**
* First number property
*
* @return First number.
*/
public int getFirstNumber() {
return firstNumber;
}
/**
* Result of the operation on the first two numbers.
*
* @return Second Number.
*/
public int getResult() {
return result;
}
/**
* Second number property
*
* @param aSecondNumber Second number.
*/
public void setSecondNumber(int aSecondNumber) {
this.secondNumber = aSecondNumber;
}
/**
* Get second number.
*
* @return Second number.
*/
public int getSecondNumber() {
return secondNumber;
}
/**
* Adds the first number and second number together.
*
* @return next logical outcome.
*/
public String add() {
result = calculator.add(firstNumber, secondNumber);
return "success";
}
/**
* Multiplies the first number and second number together.
*
* @return next logical outcome.
*/
public String multiply() {
result = calculator.multiply(firstNumber, secondNumber);
return "success";
}
}
|
Notice in Listing 2 that the multiply and
add methods return "success." The string
success
signifies a logical outcome. Note that it is not a keyword.
You used the string success when specifying
navigation rules in faces-config.xml; therefore, after the add or multiply operation is
executed the application will forward the user to the results.jsp page.
With that, you're done with the backing code. Next you'll specify the JSP
pages and component trees that represent the application view.
Create the index.jsp page
The purpose of the index.jsp page in this application is to ensure
that the /calculator.jsp page loads in the JSF context so that the page
can find the corresponding view root. The index.jsp page looks as follows:
<jsp:forward page="/calc/calculator.jsp" />
|
All this page does is redirect the user to calculator.jsp under the
"calc" Web context. This puts the calculator.jsp page
under the JSF context, where it can find its view root.
Create the calculator.jsp page
The calculator.jsp page is the meat of the Calculator application's view.
This page takes two numbers input by the user, as shown in Figure 3.
Figure 3. The Calculator page
Because this page is complex, I'll show you how to build it step by step. You'll start off
by declaring the taglibs for JSF as follows:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
|
The above tells the JSP engine that you want to use the two JSF
taglibs html and core. The
html taglib contains all the tags for
dealing with forms and other HTML-specific goodies. The core taglib
contains all the logic, validation, controller, and other tags specific
to JSF.
Once you've laid out the page in normal HTML you want to tell the JSF
system that you're going to be using JSF to manage your components. You do
this by using the <f:view> tag, which
informs the container that you're using JSF to manage the components
contained inside of it. (When pronouncing this tag make sure you say
"f colon view"; it is very important to enunciate the colon lest you offend!)
Without <f:view>
JSF cannot build the component tree, and later cannot look up the
component tree that was already created. Use the <f:view> tag as follows:
<f:view>
<h:form id="calcForm">
...
</h:form>
</f:view>
|
The first line above is the declaration of <f:view>, telling the container that it is
managed by JSF. The next line is the <h:form>
tag telling JSF that you want an HTML form here. During the render phase
the components contained within the form component will be looked up and asked to
render themselves, whereupon they will generate standard HTML to the
output.
Next, you tell JSF what other components you want in the form.
Inside of the <h:form> you declare a
panelGrid. A panelGrid is
a composite component -- that is, a component that contains other components. The
panelGrid specifies the layout of the other
components. The panelGrid is declared as
shown in Listing 3.
Listing 3. Declaring the panelGrid
<h:panelGrid columns="3">
<h:outputLabel value="First Number" for="firstNumber" />
<h:inputText id="firstNumber" value="#{CalcBean.firstNumber}" required="true" />
<h:message for="firstNumber" />
<h:outputLabel value="Second Number" for="secondNumber" />
<h:inputText id="secondNumber" value="#{CalcBean.secondNumber}" required="true" />
<h:message for="secondNumber" />
</h:panelGrid>
|
The attribute column being set to 3 indicates that the components will be
laid out in a grid with three columns. You add six components to the
panelGrid, that is, two rows. Each row consists of an
outputLabel, an inputText,
and a message. The label and message are associated
with the inputText component; therefore, when a
validation error or error message is associated with the
textField, the message will show up in the
message component. Both of the text fields are
required, which means if their values are not present on submit an error message will
be created and control will return to this view; namely /calculator.jsp.
Notice that both inputFields use a JSF EL (JavaServer
Faces Expression Language) value binding for the value attribute (for example,
value="#{CalcBean.firstNumber}"). At first
blush this looks a lot like JSTL EL. However, the JSF EL code actually
associates the fields with the corresponding values of the backing beans
properties. This association is reflexive: that is, if
firstNumber was 100 then 100 would show up when the form
was displayed. Likewise, if the user submitted a valid value such as 200 then
200 would be the new value of the firstNumber property.
A more common (but also more involved) approach would be for the
backing bean to expose model objects via properties and bind those model
object properties to fields. You'll see an example of this approach in
later articles in the series.
In addition to the fields, the calcForm is associated with two actions
using two commandButtons inside of a panelGroup, as shown below.
<h:panelGroup>
<h:commandButton id="submitAdd" action="#{CalcBean.add}" value="Add" />
<h:commandButton id="submitMultiply" action="#{CalcBean.multiply}" value="Multiply" />
</h:panelGroup>
|
 |
About style sheets
The look and feel of all JSF components is declared through style
sheet classes: each component has a style to associate inline styles,
and a styleClass to associate the component
with a styleSheet class. The panelGrid also has style attributes to associate
styles with rows and columns. In order to keep things simpler I've
steered clear of specifying any stylesheets in this first article.
|
|
The panelGroup is similar in concept to
the panelGrid with the exception that it lays
things out differently. The command buttons use the action="#{CalcBean.add}" to bind the button to a
method on the backing bean. Thus, when the form is submitted with the
button, the associated method gets invoked (assuming that all validation
is ok).
And with that -- whew! -- you're over the biggest hump of
coding a JSF application. The last couple of steps will be a breeze.
Create the results.jsp page
The results.jsp page is used to display the results of the last
calculator operation. It is defined as shown in Listing 4.
Listing 4. The results.jsp page
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
...
<f:view>
First Number: <h:outputText id="firstNumber" value="#{CalcBean.firstNumber}"/>
<br />
Second Number: <h:outputText id="secondNumber" value="#{CalcBean.secondNumber}"/>
<br />
Result: <h:outputText id="result" value="#{CalcBean.result}"/>
<br />
</f:view>
|
This results.jsp file is a relatively simplistic page that
displays the addition results to the user. It accomplishes this through
the <outputText> tag. The <outputText> tag takes an id and
value attribute. The value attribute outputs the bean value as a
string when rendered. The value attribute uses JSF to bind the output
value to your backing bean properties (namely, as you'll recall, firstNumber, secondNumber, and result).
Run the app!
To run this application go the page where the war file is mapped.
This causes the index.jsp file to load the calculator.jsp page. If you
enter some invalid text (for example, "abc") in either the firstNumber field or
the secondNumber field and submit, you will be taken back to the
/calculator.jsp view and an error message will be displayed next to the
corresponding field. If you leave either the firstNumber field or the
secondNumber field blank and submit, you will be taken back to the
/calculator.jsp view and an error message will be displayed next to the
corresponding field. Thus, you can see that some validation is nearly automatic in JSF
merely by specifying that the fields are required and binding the fields
to int properties.
Figure 4 shows how the application deals with validation and data conversion errors.
Figure 4. Validation and data
conversion errors
Conclusion
If this intro to JSF has left you shaking your head a little, don't worry:
you're over the worst hump. Getting into the conceptual framework of JSF
is more than half the battle with implementing this technology -- and you'll
soon see that it's well worth the trouble.
Just in case you're thinking that doing it with Struts would have
been easier, my estimate is that it would take at least twice the effort
to create the Struts version of the simple JSF application you built
here. To build the same example app in Struts you would need two action
classes for the two buttons, each requiring its own set of action
mappings. You would also need an action mapping to load the first page,
at least assuming you were following the Model 2 recommendation. To
mimic JSF's default error handling and validation you would have to
configure Struts to use the validator framework or implement the
equivalent in the validate method on an ActionForm. You would also have to either declare a
DynaValidatorForm in the Struts config or
create an ActionForm and override the validate method or use the subclass of the ValidatorForm with the hooks into validator
framework. And finally, you would probably need to configure some
forwards (possibly two sets for each action) or global forwards to be
used by all the actions.
In addition to doubling your coding, Struts takes a lot more effort
for new developers to learn. I know this because I've written both a
Struts course and a JSF course and I've taught them both. Developers
pick up JSF easily and struggle with Struts. I believe a lot more
forethought went into the design of JSF than Struts. JSF just makes more
logical sense; it is intuitive. Struts was collected and evolved. JSF
was specified and created. JSF development is simply more productive
than Struts development in my book.
This concludes the first article in the JSF series. The next article
will pick up where I've left off here. I'll cover the major phases of
the JSF request processing lifecycle and point out where the different
parts of the sample application fit into the lifecycle. I'll also
introduce the concepts of immediate event handling and try to give you a
fuller understanding of JSF's component event model, including a
discussion about many of the built-in components that ship with the technology.
I'll also talk some about combining JavaScript with JSF, so be sure to
check back in next month!
Downloads | Description | Name | Size | Download method |
|---|
| Source code with JAR files | jsf-simple.zip | 2051 KB | HTTP |
|---|
| Source code without JAR files | jsf-simple-no-jars.zip | 33 KB | HTTP |
|---|
Resources
- Click the Code icon at the top or bottom of this page to
download the article source.
- Read also Faheem Khan's "Using JSF for XForms applications" (developerWorks, February 2005).
- Visit the JSF project page to download the JavaServer Faces APIs, custom tag library,
and related documentation.
- You can download Maven from the Apache Maven Project
page.
- For detailed install and build instructions for Ant and Maven, see
the JSF
resources for this series.
- Learn more about Maven from the ground up, with Charles Chan's "Project
management: Maven makes it easy" (developerWorks, April
2003).
- Jackwind Li Guojie's "UI
development with JavaServer Faces" (developerWorks, September
2003) is an early-bird's look at the technology.
- Roland Barcia's five-part "Developing JSF Applications using WebSphere
Studio V5.1.1" (developerWorks, January 2004) tutorial is a
hands-on introduction to programming with JSF.
- Srikanth Shenoy and Nithin Mallya show you how to integrate the
features of Struts, Tiles, and JavaServer Faces in the advanced article,
"
Integrating Struts, Tiles, and JavaServer Faces"
(developerWorks, September 2003).
- David Geary's
Core JavaServer Faces
(Prentice Hall, June 2004) is the best possible book-length introduction to JavaServer Faces
technology.
- You might also want to check out the detailed
JSF tutorial from Sun Microsystems.
- You'll find articles about every aspect of Java programming in
the developerWorks Java technology
zone.
- Also see the Java technology zone tutorials page for a complete Listing of
free Java-focused tutorials from developerWorks.
About the author  | |  | Rick Hightower serves as chief technology officer for ArcMind Inc.
He is coauthor of the popular book Java Tools for Extreme Programming, about
applying extreme programming to J2EE development, as well as co-author of
Professional Struts. Rick worked on
JSF QuickStart
with Warner Onstine and some of the material in this series is based on
examples in that course. Contact Rick at rhightower@arc-mind.com. |
Rate this page
|