f you’ve worked on more than one Web application with different teams, you’ve probably worked with more than one Web application framework. J2EE always provided Web technologies, but never defined a Web application framework for managing page navigation, request lifecycle, request validation, etc. Developers had to develop these features themselves or utilize one of many open-source frameworks such as Struts and Spring MVC. Enter JavaServer Faces.
JSF is specified in JSR 127 (see Related Resources section in the left column) and “defines an architecture and APIs that simplify the creation and maintenance of Java Server application GUIs.” This article will discuss the basic ideas behind JavaServer Faces and then show you an example using the Apache MyFaces JSF implementation.
What is JavaServer Faces?
JavaServer Faces (JSF) is a Web application framework that can be used to link and manage user interface events. A JSF application is just like any other Java Web application in that it runs in a servlet container (such as Tomcat, WebLogic, WebSphere, etc.).
JSF is different than most Java Web-application frameworks, such as Struts, which treat each page request as a single event. JSF pages are comprised of multiple components that can each trigger individual events. Each component represents one or more Web page elements capable of generating dynamic output or providing user input. In JSF parlance, an individual component such as a text box or a button is said to be a simple component. A compound component is one that is comprised of multiple elements such as a table. The JSF component model is similar to the component model that traditional non-Web MVC frameworks such as Swing use. One benefit of this component model is that it should foster the creation of development tools that allow user interface designers to drag and drop components into a layout. Then, after creating a visual layout of the components, the developer(s) can write event-handling code that will allow the view components to interact with the application model. This could allow for faster GUI creation for prototyping and while doing rapid application development (RAD).
Other Web frameworks are usually tightly coupled to JSP as the view-rendering technology, but JSF is not bound to JSP. JSF calls for a strict decoupling of components from their view rendering. Rendering is done by using a rendering kit. JSP is a required rendering kit specified in the JSF specification and can be used to render JSF components into HTML, but developers can also use custom rendering kits to render views.
At the time of writing this article, there were a few JSF implementations available for use: a reference implementation available from Sun, Apache MyFaces, Smile, and ECruiser. Thus far, it looks like Apache MyFaces is the most widely used (or at least most widely referenced) implementation, so I’ll use it for my example.
I’m going to show you an example JSF application using the MyFaces JSF implementation and JSP as the rendering technology. I will create an application that will play HiLo with you. HiLo is a game where the computer picks a random number and you must guess what the number is. Each time you guess, it will tell you if you’ve guessed too high or too low, until you guess the exact number.
The application will have a greeting screen that will ask you your name and the highest possible number that the computer can pick. After submitting this page, you will go into the main game page where you can start guessing numbers. If you guess a number that is out of range, it will give you an error. The game will keep a count of how many guesses you’ve made.
In order to run the application, you’ll need to have a Servlet engine. I wrote and tested the example using Tomcat 5.0.28 and the MyFaces 1.0.7. Unfortunately, I could not get MyFaces to work with Tomcat 5.5, though I was able to get a few JSF examples to work on Tomcat 5.5 using Sun’s reference implementation.
|What You Need
| You can download Tomcat and MyFaces from the following Web sites:
|Author’s Note: If you want to try the Sun reference implementation, you can download it at http://java.sun.com/j2ee/javaserverfaces/download.html.
The code for the application (download it here or from the link in the left-hand column) is packaged as a war file with source code included, so you can deploy the application immediately to see it in action, and you have the source available so that you can look through it. The war file includes all the jar files from the MyFaces distribution.
Looking at the HiLo Code
Take a look at the code in Listing 1. My Web deployment descriptor, web.xml, tells my container about the JSF controller Servlet.
The servlet-mapping and servlet blocks specify that any URL that ends in a .jsf extension should be redirected through a servlet called javax.faces.webapp.FacesServlet. This is a controller servlet that manages the request processing lifecycle for the Web application. All JSF requests will route through this controller servlet.
The servlet architecture allows for custom classes to be registered as event listeners. A context listener is one such listener that is triggered when application-context lifecycle events occur. As you can see, there is a context listener that is registered in the deployment descriptor. This listener is required in order to initialize the JSF application framework.
There are two context-param blocks. The javax.faces.CONFIG_FILES parameter defines where the JSF configuration file exists. The faces-config.xml file contains all of the configuration information for a JSF application. This is where you define how one page will navigate to the next as well as where you specify managed beans, which are model objects that JSF uses to get and set data from the UI. The second parameter specifies whether state should be maintained on the client side or on the server side.
The application has four JSPs:
- index.jsp?This JSP exists in the root of the Web application and merely routes the user to the greeting page
- greeting.jsp?This page greets the user, asks their name, and asks them for the upper limit with which they want to play HiLo
- game.jsp?The main game page asks the user for a guess and tells the user if they’ve guessed high or low
- win.jsp?This is the page that the user is directed to if they win the game
The way that these JSPs link together is defined in the faces-config.xml file, which is shown in Listing 2.
The root-element is faces-config. There are three navigation-rule blocks and a managed-bean block. The navigation rules specify a from-view-id and one or more navigation-case blocks. The from-view-id is the page that you are currently on. Each navigation-case tells the framework where it should forward the user depending on the from-outcome that results from the action taken. For example, to get from the greeting page to the game page, a play action must occur.
The managed bean (also known as a form-backing bean) is the model of the Model View Controller pattern. The views interact with the managed bean, and the framework maintains all the necessary state for the scope defined in this definition. The managed-bean-name is the name that the views will use to reference the bean. The managed-bean-class is the fully-qualified class name for the bean. Have a look at the managed bean code shown in Listing 3.
The JSF framework will use the managed bean to store state information for the user. The bean has a reference to our actual domain object HiLoGame. This is a good layer separation to try to maintain when developing Web applications, because it helps keep view logic and properties out of your domain classes. This allows your domain classes to remain generic enough to be used by multiple views. It also makes it easier to introduce a service layer (perhaps stateless session EJBs) into your applications, because you don’t have to go back and refactor the view code out of your domain.
When the framework sets the maxValue, the game is reset, and when it sets the guess, the HiLoGame domain object is called and the return value is stored in guessOutcome for retrieval by JSP components. The guess outcome will either be high, low, or correct. This outcome will be used both to display to the user, and to determine which navigation path to take based on the outcome of the guess. This will become more clear when I explain the game JSP.
Now let’s look at the JSPs. The first JSP I’ll look at is index.jsp:
This forwarding JSP will direct control to the controller servlet because the URL it is forwarding ends in .jsf. No navigation rules need to be setup for this forward to work. The controller will determine that it needs to forward the user to the greeting page by looking at the URL. The controller will render the greeting.jsp page, using the data from the managed-bean.
Now let’s look at the greeting page (see Listing 4 and Figure 1). The first thing you’ll notice is that I’ve included two tag libraries: html and core. These custom tag libraries are a JSP implementation of a JSF rendering kit.
|Figure 1. Greeting.jsp: The greeting page gets you started with the HiLo game.
The core tags are provided to developer to perform core actions that are independent of a rendering kit. These tags will not display anything to the user. The html tag library is mainly used to render html elements (text, form elements, etc.).
The first tag you see is a core tag called
JSF uses a templating mechanism to provide variables. Any attribute value that starts with a hash sign and is wrapped in brackets is dynamically substituted in.
The tag represents a form element. The form action is defined in the
Validation can be achieved in a few ways. The
|Figure 2. Game.jsp: The HiLo game is a good example of how variable results can be handled dynamically.
Game.jsp (see Listing 5 and Figure 2) is similar to greeting.jsp except for a few things. The first thing is the
|Figure 3. Win.jsp: The final .jsp page in the game is designed to be able to restart the game by sending the user back to index.jsp.
The other thing to notice about this JSP is that the command button action is not hard coded. The gameBean provides a method called getGuessOutcome that is called when the action is invoked. Note that an action must reference the actual name of the method, not just using the property name like other HTML components do. This is because an action can call any method on a managed bean, not just JavaBean style methods. The getGuessOutcome method will return a String that the framework will compare to the navigation-rule in the faces-config.xml file to determine where to forward the user.
If the user wins, they are forwarded to win.jsp (see Figure 3):
This JSP is very simple. It simply has a command button that triggers the restart navigation case, which forwards the user back to the greeting page.
JSF and JSTL
Though it is supported, many people are now advocating that JSF tags should not be mixed with Java Standard Tag Library (JSTL) tags in the same JSP. The reason for this is that JSF provides a slightly different model for separating the view from the view logic. Using standard JSTL tags, a lot of the programmatic flow is actually embedded in the JSP itself. With JSF, the goal is to push most of the programmatic logic into the bean classes rather than in the JSP itself, so your JSPs tend to remain more declarative in nature. One advantage to abiding by this separation of view and view logic is that it makes it simpler to switch rendering kits if the need arises. There are equivalent ways to accomplish most things in JSF that you may have previously done using JSTL.
This said, a pragmatic approach to introducing JSF into an application is to incrementally add new JSPs or change existing JSPs to use JSF custom tags instead of standard custom tags. This DevX article, “Mixing JSTL and JSF in Web Applications,” discusses this approach.
Is JSP the right choice?
Server page technologies (like JSP) have always been a little difficult to work with because of their in between nature. A server page is a concoction of HTML embedded with Java code. Custom tags help to minimize the amount of code in JSPs, but there is still a fundamental problem in that somebody has to write the JSP. This JSP author must either be a UI designer or a developer that learns how to convert UI mock-ups into JSPs.
In my experience, the creation of JSPs never seems natural to either the developer or the UI designer. Developers don’t want to have to deal with problems involved with text and images not lining up right, and UI designers don’t want to deal with case-sensitive variables and iteration logic. JSPs also seem to be a recurring point of failure because they are hard to unit test and they are affected by both code changes and look-and-feel changes. These are all indications that JSP does not give you a true separation of view from view logic.
People have been using JSP because it is a standard and because there is a lot of support for it. Both are obviously great reasons, but not too many people even question using JSP as a view technology because they are used to it and/or because they have never worked with any other view technologies.
JSP is a required part of the JSF specification because the specification writers wanted to ensure an easy transition into JSF for Web developers who are familiar with existing Java technologies. But, as some people have discovered, the combination of the two technologies has its own set of problems. Hans Bergsten, author of “JavaServer Faces” (O’Reilly) has written an article about some of the technical issues that arise when using the technologies together (see Related Resources, left column).
Some highlights of the article are:
- JSPs are processed in order from top to bottom in order, but for JSF to work well components should be created, processed, and rendered separately. Mixing the two causes JSF component rendering to behave erratically.
- It’s not safe to assume that a construct that is valid in a JSP page is necessarily valid in a JSF.
- JSP is supported in JSF to allow an easier segue into JSF development, but the complications of mixing the two don’t necessarily make JSP the best choice.
As an alternative to using JSPs, Bergsten shows how one can almost entirely separate the view from the underlying view logic by creating a custom rendering kit.
A mockup is a UI prototype that a graphic designer or a Web designer puts together so that people can get an idea of what the Web application will look like. I’ve heard one too many developer wish that they could just read the mockup and programmatically change the elements inside of it, without having to manually “translate” it into a JSP. Bergsten’s template-based rendering kit allows you to do exactly that. The HTML mockup need only be injected with identifiers specified in span tags and id attributes. These identifiers represent JSF components. An XML file is provided that tells the rendering engine which component to replace the identified HTML elements with. The rendering kit will parse the HTML page using a DOM parser, replace identified tags with matching components that are specified in the XML file, and then translate the DOM back into HMTL using XSLT.
Using this model, UI designers are free to modify the layout of the page using their favorite WYSIWYG editor and the changes can be reflected in the system immediately. The only thing that they must worry about is to leave the id attributes and span elements intact. Developers would no longer have to worry about UI layout and can focus on developing the view logic and view components.
I would like to see this kind of rendering kit become more popular, if not become the de facto standard for Web development. I’m sure that it has its limitations as well, but I think it facilitates easier cooperation between UI designers and developers and it provides a better separation of layers.
Is JSF Ready for the Mainstream?
Today, if a client asked me to give them a recommendation on whether or not to use JSF for a mission critical application, my answer would be no. If a client asked me to build a small Web application that would be used for internal operations, I would probably build it using JSF. My point here is that I think JSF has potential to become the framework of choice for Web developers in the next several years, but it is not quite there today. The specification is still being updated and existing implementations are not mature yet. It is also unclear how developers will react to the integration problems that exist with JSP and JSF. It’s uncertain whether developers will be willing to shift to a different view technology, whether they will just chose to abandon JSF, or whether JSF and JSP will undergo changes in order to facilitate better integration.
What about Struts?
Craig McClanahan is the original creator of Struts and is also the specification lead for JSR-127. McClanahan talks about how Struts and JSF will work together on the Struts Web page (see Related Resources, left column). It seems that the short-term vision for Struts is for it to easily integrate with JSF by providing a custom-tag-based rendering kit. The long-term vision is unclear, though I envision future versions of Struts becoming pure JSF implementations, and eventually dropping support for the existing MVC framework. But this is all speculation, so don’t bet money on it.