Improving JSF by Dumping JSP
Pages: 1, 2
A Better Idea
Clearly there are many issues related to using JSP with JSF, but
fortunately, you don't have to use JSP to use JSF. Most of the
JSF infrastructure can be replaced with custom classes, and the
piece that handles view creation and rendering is called the
ViewHandler. With a custom ViewHandler,
you can create the view any way you like and have full control over
when and how it's rendered.
In my JavaServer
Faces book, I describe two custom implementations in detail. One
uses plain Java classes to create the components, similar to how it's
done in a Swing application. The second implementation uses an
XML file to represent the component structure and a separate pure
HTML file as a template, binding the JSF components in the XML file to
the corresponding HTML elements in the template with the help of
id attributes. The source code for both
ViewHandler implementations is included as part of the
book examples available at
my web site. Note that
they are intended only as starting points; both implementations
require more work before they are usable for real applications.
Without going into the implementation details, let's take a closer look at how the second approach solves the problems discussed earlier. It's inspired by the Tapestry framework, but it doesn't have all of the bells and whistles in its current incarnation. Because it's similar to Tapestry, I use the hangman game example described in Chapter 2 of Howard M. Lewis Ship's Tapestry in Action (Manning) to illustrate how it can be used. You can download the complete JSF version of the hangman game from the Articles section of my web site if you like to look at the details and try it out.
The most interesting part of the hangman application is the Guess page, where the user guesses letters in the word. It contains four dynamic areas: the number of guesses left, a scaffold where a new body part is added for each incorrect guess, the letters guessed so far, and the letters available for new guesses. Figure 1 shows the Guess page after a few guesses.

Figure 1. JSF version of the hangman game
Portions of the HTML template for the Guess page looks like this:
<html>
<head>
<title>JSF Hangman</title>
<link rel="stylesheet" type="text/css" href="css/hangman.css"/>
</head>
<body>
<table>
<tr>
...
<td width="70" align="right">
<img id="guessesLeft" height="36" src="images/Chalkboard_3x8.png"
width="36" border="0"/>
</td>
...
<tr>
<td>
<img id="scaffold" alt="[Scaffold]" src="images/scaffold.png"
border="0"/>
</td>
</tr>
</table>
<table>
<tr valign="center">
...
<td>
<span id="letters">
<img height="36" alt="_" src="images/Chalkboard_5x3.png"
width="36" border="0"/>
<img height="36" alt="A" src="images/Chalkboard_1x1.png"
width="36" border="0"/>
...
</span>
</td>
</tr>
<tr>
...
<td width="330">
<form id="selectForm">
<span id="selectForm:selections">
<img height="36" alt="-" src="images/letter-spacer.png"
width="36" border="0"/>
<a class="select-letter" href="#">
<img height="36" alt="B" src="images/Chalkboard_1x2.png"
width="36" border="0"/></a>
...
</span>
</form>
</td>
</tr>
</table>
</body>
</html>
Note that there are no special elements here -- just plain old HTML -- so
you can preview this template directly in an HTML browser and work
with it in any standard HTML authoring tool; no special IDE or
runtime environment required. The only thing that's a bit out of
the ordinary is that some of the HTML elements have id
attributes. This is how the dynamic parts of the page are bound to
JSF components.
The JSF component tree is defined in an XML document like this:
<view-specification>
<component id="guessesLeft" type="javax.faces.Graphic"
value="#{guessesLeftImages[visit.game.incorrectGuessesLeft]}" />
<component id="scaffold" type="javax.faces.Graphic"
value="#{scaffoldImages[visit.game.incorrectGuessesLeft]}" />
<component id="letters" type="javax.faces.Data"
rendererType="com.mycompany.Bar"
value="#{visit.letters}" var="letter">
<component type="javax.faces.Column">
<component type="javax.faces.Graphic"
value="#{letterImages[letter]}" height="36" width="36" border="0" />
</component>
</component>
<component id="selectForm" type="javax.faces.Form">
<component id="selections" type="javax.faces.Data"
rendererType="com.mycompany.Bar"
value="#{visit.guesses}" var="guess">
<component type="javax.faces.Column">
<component id="l" type="javax.faces.Command"
rendererType="javax.faces.Link"
styleClass="select-letter" action="#{guess.makeGuess}"
rendered="#{guess.letter != '#'}">
<component type="javax.faces.Graphic"
value="#{letterImages[guess.letter]}" height="36" width="36"
border="0" />
</component>
<component id="g" type="javax.faces.Graphic"
value="#{letterImages[guess.letter]}" height="36" width="36"
border="0" rendered="#{guess.letter == '#'}"/>
</component>
</component>
</component>
</view-specification>
Each component is defined by a <component>
element, sometimes with child components defined by nested
elements. Note how the id attributes of most
<component> elements match the id
attributes of the HTML elements in the template file.
The custom ViewHandler processes the XML file to
create the component tree for the view in one pass. It then renders
the response by processing the template, adding all content not bound
to JSF components to the response as is. When it finds an element in
the template with an id attribute matching the ID of
a JSF component defined in the XML document, it asks the JSF component
to generate itself in place of the HTML element.
All <component> elements must have a type
attribute with a value that identifies a JSF component type name, and
may optionally have other attributes, such as value and
rendererType.
JSF EL expression attribute values bind the components to bean
properties and methods, just as when you use the default JSP
ViewHandler. For instance, the graphics component with
the ID guessesLeft has a value attribute
with an EL expression that gets the incorrectGuessesLeft
property of a bean available as the game property of
the a managed bean named visit, and uses it as an index
into a list of image files configured as managed bean named
guessesLeftImages:
<faces-config>
<managed-bean>
<managed-bean-name>visit</managed-bean-name>
<managed-bean-class>hangman1.Visit</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>guessesLeftImages</managed-bean-name>
<managed-bean-class>java.util.ArrayList</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<list-entries>
<value>images/Chalkboard_1x7.png</value>
<value>images/Chalkboard_1x8.png</value>
<value>images/Chalkboard_2x7.png</value>
<value>images/Chalkboard_2x8.png</value>
<value>images/Chalkboard_3x7.png</value>
<value>images/Chalkboard_3x8.png</value>
</list-entries>
</managed-bean>
</faces-config>
The visit managed bean is an instance of a slightly
modified version of the Visit class from the
Tapestry example, acting as an interface between the JSF components
and the Game class. This class is exactly the same class
as is in the Tapestry example, implementing the core application
logic in an interface-independent way.
The JSF hangman game uses additional faces-config.xml
declarations for the custom ViewHandler, navigation
rules, and all the other images. For details, please download the
example application and look at the source code and configuration
files.
Even though the example here shows that JSF can be used in a manner
similar to Tapestry, please note that I'm not making any claims that
the current version of the custom ViewHandler is anywhere
near Tapestry in terms of features; it barely scratches the surface.
What I want you to note, however, is that with a custom
ViewHandler, all of the issues described for the default
JSP layer are resolved. The creation and rendering of components
happen in two separate, distinct steps, so all components exist
when the view is rendered; only JSF writes the response, eliminating
the content reordering surprises; and only JSF artifacts are used,
avoiding the issues related to the mixing of different component types.
Conclusion
I've tried to make a number of points in this article. First, be
aware that the JSF JSP layer is flawed in many ways. Second,
don't give up on JSF just because the JSP layer is flawed; using a
custom ViewHandler resolves all of the issues, and at the
core, JSF is a great technology for complex web application interfaces.
Most importantly, I'm trying to build support for an alternative
to JSP for a future version of the JSF specification. The JSR for
JSP 2.1 focuses on bridging the gap between JSF and JSP. While
good things may come out of this (like alignment of the two ELs),
I don't see JSP ever becoming a good template language for JSF;
JSP has a completely different purpose, and trying to "fix it" for
JSF would likely just make it more complicated and less useful
for simple, dynamic content. Instead, I hope to see experimentation
with custom ViewHandler implementations in the open
source community (for instance, within the
MyFaces project, and maybe
even within the Tapestry project) as well as in the corporate world. I hope that the best ideas from these efforts will be incorporated
into a future version of the JSF specification as an official
alternative to JSP.
Hans Bergsten is the founder of Gefion Software and author of O'Reilly's JavaServer Pages, 3rd Edition.
Return to ONJava.com.
-
JSTL in general is ok with RichFaces and JSF 1.2
2009-11-11 02:46:35 Sargis [View]
-
hybridserverpages@yahoo.com
2006-10-25 00:32:06 Nick-HJ [View]
-
Unified Expression Language Fix?
2006-05-08 06:53:47 kss45 [View]
- Trackback from http://jasigch.princeton.edu:9000/display/UPC/Portlet+Development+Framework
Portlet Development Framework
2005-09-01 13:19:12 [View]
- Trackback from http://weblogs.java.net/blog/edburns/archive/2005/08/javaserver_face_3.html
JavaServer Faces 1.2 and JavaServer Pages 2.1 Proposed Final Draft Specifications available
2005-08-25 17:57:30 [View]
-
facelets
2005-08-18 06:46:41 brondsem [View]
- Trackback from http://weblogs.java.net/blog/wiverson/archive/2005/07/comments_on_aja.html
Comments on Ajax and Web Frameworks
2005-07-20 14:41:40 [View]
- Trackback from http://weblogs.java.net/blog/wiverson/archive/2005/06/planning_for_a.html
Planning for A Decade
2005-06-25 14:10:51 [View]
- Trackback from http://weblogs.java.net/blog/johnreynolds/archive/2004/08/echoing_the_tap.html
Echo-ing the Tapestry Hangman example
2005-06-24 07:06:27 [View]
-
Nice article
2004-10-22 15:10:31 roberto.nucera@informatica.com [View]
-
About JSF
2004-06-16 05:39:00 koolsasa [View]
-
Response to some of your issues
2004-06-15 08:45:22 edburns [View]
- Trackback from http://squizlog.keithpitty.org/archives/000204.html
JSF and Tapestry Debate
2004-06-14 20:29:14 [View]
-
Some responses to this
2004-06-11 11:17:54 hlship [View]
- Trackback from http://www.ryanripley.com/archives/000052.html
Tapestry vs. JSF -- Round 1
2004-06-10 18:52:38 [View]
-
What to do?
2004-06-10 13:51:52 edsmithed [View]
-
Attributing blame
2004-06-10 12:28:23 BigBadaboom [View]
-
Similar to WebOnSwing Template Engine
2004-06-10 07:35:02 paton [View]
-
Just one problem...
2004-06-10 07:31:24 Kamau [View]
-
Fantastic!
2004-06-10 05:26:18 erikhatcher [View]
-
Dropping View-Specification file
2004-06-10 04:03:32 Seyyed Jamal [View]
-
YASL?
2004-06-09 23:05:42 jwenting [View]