Skip to main content

skip to main content

developerWorks  >  Java technology | XML  >

JSF for nonbelievers: Clearing the FUD about JSF

JavaServer Faces is easier than you think

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


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.



Back to top


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.



Back to top


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.



Back to top


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.



Back to top


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
Application from an MVC point of view

And that's enough fluff: let's get started with JSF!



Back to top


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
MVC Picture


Back to top


Building the application

To build the Calculator application in JSF you'll need to do the following:

  1. Collect the web.xml and faces-config.xml file, found under the example application's src/webapp/WEB-INF directory.

  2. Declare the Faces Servlet, and Faces Servlet mapping in the web.xml file.

  3. Specify the faces-config.xml file in the web.xml file.

  4. Declare what beans get managed by JSF in the faces-config.xml file.

  5. Declare the navigation rules in the faces-config.xml file.

  6. View the model object Calculator.

  7. Use the CalculatorController to talk to the Calculator model.

  8. Create the index.jsp page.

  9. Create the calculator.jsp page.

  10. 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
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
Calculator page


Back to top


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!




Back to top


Downloads

DescriptionNameSizeDownload method
Source code with JAR filesjsf-simple.zip2051 KBHTTP
Source code without JAR filesjsf-simple-no-jars.zip33 KBHTTP
Information about download methods


Resources



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


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Back to top