Facelets Using RichFaces

Russell Bateman
15 February 2011
last update:

Table of Contents

Preface
Why Facelets?
Prepare Eclipse for Facelet work
The set-up
Facelets JAR
The definitive JAR list
web.xml additions
Servlet mappings
Mapping order
Parameters
xHTML document header
Sample project
Creating the project
Application resources
Launch the application
Appendices
Eclipse project layout
Apache Tomcat deployment (layout)
Tag libraries
Facelets templating tags
Compositing tags
Appendix: Useful links
Appendix: Whence JAR downloads

Preface

These are my notes on writing Facelets applications using RichFaces. As noted in my recent article, RichFaces for JSF Use, I'm now going to pursue a similar study of libraries and set-up that will reliably produce a Facelets application. In this, I'm following an IBM developerWorks® article, An introduction to RichFaces.

Facelets is an open-source web template systems, under Apache license. It's the default view handler technology for JavaServer Faces (JSF) beginning in JSF 2.0. It supports all of the JSF user interface components and focuses on building the JSF component tree, reflecting the view for a JSF web application.

Why Facelets?

The biggest advantage of using Facelets for web applications, especially large-scale projects, are:

  • Code reuse by templating and composite components
  • Extensibility of components and other server-side objects by customization
  • Faster compilation time
  • Compile-time element validation
  • High-performance rendering

Prepare Eclipse for Facelet work

Update Helios to include the JavaServer Faces (JSF) Project. I'm not certain you have to do this; I'm still researching. It doesn't seem to make any difference in my observation. At least it doesn't hurt.

  1. Help -> Install New Software
  2. Type "Helios" into Work with:
  3. Select "Helios - http://download.eclipse.org/releases/helios"
  4. Type "jsf" into the text filter field (the empty one just below the Work with: field; don't press Enter, but wait
  5. Web, XML, and Java EE Development should appear; check JavaServer Faces (JSF) Project
  6. Click Next and Finish the installation

The set-up

As I'm not here trying to teach the "how" of Facelets, but only the set-up of a Facelets application, I was happy to see that the IBM author had taken some care to list the libraries crucial to this here. Note that this is identical, or nearly so, to the set of libraries I posited in my earlier RichFaces article which I'm reproducing here. I've added the names of the User Libraries I've created to hold them in Eclipse.

Apache Commons commons-beanutils-1.8.3.jar commons-codec-1.4.jar commons-collections-3.2.1.jar commons-digester-2.1.jar commons-discovery-0.4.jar commons-logging-1.1.1.jar JSTL 1.2 jstl-api-1.2.jar jstl-impl-1.2.jar MyFaces 2.0.4 myfaces-api-2.0.4.jar myfaces-impl-2.0.4.jar RichFaces 3.3.3 richfaces-api-3.3.3.Final.jar richfaces-impl-3.3.3.Final.jar richfaces-ui-3.3.3.Final.jar

And, according to the IBM article, I merely need to add...

Facelets JAR

jsf-facelets-1.1.14.jar

I found a later version, 1.1.15, though beta: jsf-facelets-1.1.15.B1.jar. You'll find ways to get this JAR in the links below.

The definitive JAR list

Just as for my RichFaces JSF work, I ended up with a definitive set of libraries to work with. This is a good thing. My set is almost identical to the original one. In fact, I lost the JSTL libraries (they're unnecessary) and gained a Facelets library. From my working WAR file:

Apache Commons commons-beanutils-1.8.3.jar commons-codec-1.4.jar commons-collections-3.2.1.jar commons-digester-2.1.jar commons-discovery-0.4.jar commons-logging-1.1.1.jar JSTL 1.2 jstl-api-1.2.jar jstl-impl-1.2.jar Facelets jsf-facelets-1.1.15.B1.jar MyFaces 2.0.4 myfaces-api-2.0.4.jar myfaces-impl-2.0.4.jar RichFaces 3.3.3 richfaces-api-3.3.3.Final.jar richfaces-impl-3.3.3.Final.jar richfaces-ui-3.3.3.Final.jar

See Appendix: Whence JAR downloads for whence to get some of these libraries.

web.xml additions

web.xml is the deployment descriptor in use by many server containers such as Tomcat, GlassFish, JBoss, etc.

The IBM article also says to add these lines to web.xml. There are no actual JSF files in the sample application, however, the web.xml wiring does make use of this. I would add the others in grey here, though I think I only needed the explicit path ("/faces/*"), the first one to match.

<servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping>

Servlet mappings

Servlets are registered with the container; this is done via web.xml.

When a servlet is defined, it's given a name and a supplying class. In this case, what comes out of javax.faces.webapp.FacesServlet is given the name Faces Servlet, which is used as the name in all servlet mapping references.

You can name the servlet anything you want, but unless every significant (read: consumed) occurrence of it is identical to what you used for <servlet><servlet-name>name</servlet-name> ... </servlet>, Tomcat will fail to start up or, at least, execution will fail.

A servlet mapping specifies the web container for which the servlet should be invoked for a URI given by the client. It maps (the end of) URI patterns to servlets. In this way, when there's a request from a client to the container, the latter decides which (if there is more than one) application will handle the request. Of course, the pattern given could fail to match any pattern and no servlet will be passed the request. When this happens, an HTTP Status 404 is issued.

Mapping order

The first successful match fires and no further attempt is made. So, it follows that a strict order must be made that will allow this.

Explicit (path) mappings "/name/*"
Implicit (extension) mappings "*.suffix"
Default mappings exactly "/"

In web.xml above, the *.jsf, *.xhmtl and *.faces are unnecessary for running guessnumber.xhtml.

Parameters

The following addition DOES make sense, and I expected it:

<context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param>

There is yet more. You'll need all the <filter ... /> statements learned about in the other, RichFaces article, plus the SKIN context parameter. What's new, however, in pursing a Facelet, is the VIEW_HANDLE context parameter:

<context-param> <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name> <param-value>com.sun.facelets.FaceletViewHandler</param-value> </context-param>

These are all admirably explained here, at the end of the web.xml listing in the IBM article.

xHTML document header

To use xHTML documents instead of JSP or JSF pages, you'll need to modify the usual HTML header thus:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:f="http://java.sun.com/jsf/core"
     xmlns:h="http://java.sun.com/jsf/html"
     xmlns:a4j="http://richfaces.org/a4j"
     xmlns:rich="http://richfaces.org/rich">
...
</html>

You'll note that all the tags are present: ui, f, g, a4j, rich.

Sample project

I'm going to take some direction from the IBM article project, however, I'm not going to re-create it. Once you've finished reading this article, feel free to download their WAR and play with it. You'll find a link to do this near the end of the article.

My purpose here is to do just enough to show the structure of a Facelets application and some Facelet-specific technology, so really, all I'm borrowing from that article is confirmation that my JAR set is accurate and how to do xHTML files.

Creating the project

This article assumes, as did my last one, that you already have certain prerequisites in place, including the Eclipse IDE for Java EE Developers, a Sun JDK and Apache Tomcat. Just as in that other article, as explained here, you'll use the new Dynamic Web Project wizard to create the project.

This is what you see during Apache Tomcat start-up if you don't have the jsf-facelets.jar:

SEVERE: Class com.sun.facelets.FaceletViewHandler not found java.lang.ClassNotFoundException: com.sun.facelets.FaceletViewHandler at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1645)

Application resources

A resource is anything that the application requires for display, including images, JavaScripts, cascading stylesheets, component libraries, etc. Typically, they are gathered into a standard location. In the xHTML sources, you're used to seeing

<h:graphicImage value="#{resource['images:java_duke.gif']}" />

In Eclipse, this puts the image above on the path project-name/WebContent/META-INF/resources/images/java_duke.gif. The resource identifier is images. So, as general rules, ...

  1. A resource packaged in the web application root must be in a subdirectory of a resources directory at the web application root: resources/resource-identifier. This refers to resources stored in the Eclipse project directly under WebContent.
  2. A resource packaged in the web application's classpath must be in a subdirectory of the META-INF/resources directory within a web application: META-INF/resources/resource-identifier. This refers to resources stored in the Eclipse project under WebContent/META-INF or under Java Resources: src down on the classpath (in a package, etc.).

Remember that Eclipse does the deployment and some of this will work "mysteriously" in that context. It's the finished deployment and not the Eclipse project structure on disk that is described here.

This means that you must study Eclipse deployment in order to know where to keep resources in the project.

Also, (and this must be made to agree with what's being said above), resource identifiers are unique strings that conform to the format:

[locale-prefix/][library-name/][library-version/]resource-name[/resource-version]

TODO: should probably include a write-up of EL (use Chapter 6 Expression Language).

Launch the application

Because I often use port 8080 (the default Tomcat port) for other projects, I change this in Eclipse and have changed it here. To change this port number, simply double-click the Tomcat server in the Eclipse Server view (tab), then find the port numbers on the page that comes up for editing (all three or so port numbers), then save the document.

http://localhost:9080/RichFaceletsTutorial/faces/guessnumber.xhtml


Appendices

Eclipse project layout

Here is the project in Eclipse, with most of the important files and subdirectories visible.

Apache Tomcat deployment (layout)

Here's what the Tomcat deployment done by Eclipse looks like. This is the path workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps.

RichFaceletsTutorial/ |-- footer.xhtml |-- guessnumber.xhtml |-- header.xhtml |-- META-INF | `-- MANIFEST.MF |-- numberresponse.xhtml |-- resources | `-- images | `-- java_duke.gif |-- templateClient.xhtml |-- template.xhtml |-- test.jsp `-- WEB-INF |-- classes | `-- com | `-- etretatlogiciels | `-- facelets | |-- HelloBean.class | `-- UserNumberBean.class |-- faces-config.xml |-- lib | |-- commons-beanutils-1.8.3.jar | |-- commons-codec-1.4.jar | |-- commons-collections-3.2.1.jar | |-- commons-digester-2.1.jar | |-- commons-discovery-0.4.jar | |-- commons-logging-1.1.1.jar | |-- jsf-facelets-1.1.15.B1.jar | |-- myfaces-api-2.0.4.jar | |-- myfaces-impl-2.0.4.jar | |-- richfaces-api-3.3.3.Final.jar | |-- richfaces-impl-3.3.3.Final.jar | `-- richfaces-ui-3.3.3.Final.jar `-- web.xml 9 directories, 25 files

Tag libraries

Tag libraries supported by Facelets include those below. This table is augmented from one I found on a Sun (Oracle) site.

Tag Library URI Prefix Example Contents
JavaServer Faces Facelets Tag Library http://java.sun.com/jsf/facelets ui: ui:component
ui:insert
Tags for templating
e.g.: richfaces-ui-3.3.3.Final.jar
JavaServer Faces HTML Tag Library http://java.sun.com/jsf/html h: h:head
h:body
h:outputText
h:inputText
JSF component tags for all UIComponents
JavaServer Faces Core Tag Library http://java.sun.com/jsf/core f: f:actionListener
f:attribute
Tags for JSF custom actions that are independent of any particular RenderingKit
JSTL Core Tag Library http://java.sun.com/jsp/jstl/core c: c:forEach
c:catch
JSTL 1.1 Core Tags
JSTL Functions Tag Library http://java.sun.com/jsp/jstl/functions fn: fn:toUpperCase
fn:toLowerCase
JSTL 1.1 Functions Tags
RichFaces Tag Library http://richfaces.org/rich rich: ? ?
RichFaces AJAX Tag Library http://richfaces.org/a4j a4j: ? ?

Facelets Templating Tags

I got this convenient list of templating-relevant tags from a Sun (Oracle) site.

Tag Function
ui:component Defines a component that is created and added to the component tree.
ui:composition Defines a page composition that optionally uses a template. Content outside of this tag is ignored.
ui:debug Defines a debug component that is created and added to the component tree.
ui:decorate Similar to the composition tag but does not disregard content outside this tag.
ui:define Defines content that is inserted into a page by a template.
ui:fragment Similar to the component tag but does not disregard content outside this tag.
ui:include Encapsulate and reuse content for multiple pages.
ui:insert Inserts content into a template.
ui:param Used to pass parameters to an included file.
ui:repeat Used as an alternative for loop tags, such as c:forEach or h:dataTable.
ui:remove Removes content from a page.

Compositing tags

Tag Function
composite:interface Declares the usage contract for a composite component. The composite component can be used as a single component whose feature set is the union of the features declared in the usage contract.
composite:implementation Defines the implementation of the composite component. If a composite:interface element appears, there must be a corresponding composite:implementation.
composite:attribute Declares an attribute that may be given to an instance of the composite component in which this tag is declared.
composite:insertChildren Any child components or template text within the composite component tag in the using page will be reparented into the composite component at the point indicated by this tag’s placement within the composite:implementation section.
composite:valueHolder Declares that the composite component whose contract is declared by the composite:interface in which this element is nested exposes an implementation of ValueHolder suitable for use as the target of attached objects in the using page.
composite:editableValueHolder Declares that the composite component whose contract is declared by the composite:interface in which this element is nested exposes an implementation of EditableValueHolder suitable for use as the target of attached objects in the using page.
composite:actionSource Declares that the composite component whose contract is declared by the composite:interface in which this element is nested exposes an implementation of ActionSource2 suitable for use as the target of attached objects in the using page.

Appendix: Useful links


Appendix: Whence JAR downloads

Here's where I've found downloads for all or most of the JARs in this article.