Facelets Using RichFaces
Russell Bateman |
Table of Contents |
PrefaceThese 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:
|
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.
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...
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.
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 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>
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.
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.
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.
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.
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.
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)
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, ...
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).
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
Here is the project in Eclipse, with most of the important files and subdirectories visible.
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 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: | ? | ? |
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. |
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. |
|
|
|
|
Here's where I've found downloads for all or most of the JARs in this article.