IDEA 7, MyFaces, Tomahawk, Facelets, and RichFaces

-         Damodar Chetty

-         Feb 10, 2008

 

 

Its time we tackled a more complex Faces setup. For starters we're going to use a different implementation of the JSF specification - Apache MyFaces Core. Then, we'll throw in third party component libraries, i.e., MyFaces Tomahawk and JBoss RichFaces; and finally crown it all by replacing the JSP templating framework with Facelets.

As with the previous tutorials, I originally intended to focus on just what was required to get these disparate libraries to work together within a development environment (in my case, IDEA 7.0).

However, the journey ended up being more complex than I had anticipated. Even determining the minimal set of changes (i.e., JARs and configuration file entries) required was a significant challenge.

As a result, this article began to delve into some of the magic that goes on behind the scenes in terms of the wiring magic that is required.

I've tried to document all my learnings in here, but I'm sure I've missed something - or even more likely, assumed something that I shouldn't have. In any case, do let me know if you have any corrections, (damodarchetty [#] softwareengineeringsolutions.com).

Step 1: Setup a plain vanilla web project

If you are using IDEA 7, then see my earlier blogs regarding setting up a web project.

The current project is named dc-MyFaces-Facelets-RichFaces (to reflect all the pieces that comprise it); has a source directory named src; and is identified as a web application (which lets IDEA add in the servlet and EL Jars as included within javaee.jar, generates a blank web.xml deployment descriptor, sets up the folder structures, etc.)

The resulting project looks as follows:

Note that IDEA marks javaee.jar as not to be deployed to the container. Tomcat 6.0.14's lib directory has all the API jars (e.g., servlet.jar) that it needs.

The rest of the article should be relatively IDE-agnostic. I.e., once you set up a basic web project in your IDE of choice, the rest of the steps are not unique to IDEA. I do have screenshots of IDEA 'libraries', but you can achieve the same in either JDeveloper or Eclipse, so make the appropriate mental substitutions and you should be good to go.

 

Step 2: Install MyFaces Support

I initially tried documenting the everything-but-the-kitchen-sink approach, but that didnt' turn out to be such a bright idea with all the interconnecting pieces that are present. So, we're going to take the scenic route, and install support for one component at a time.

We begin with installing the MyFaces JSF implementation.

Note that this tutorial uses Java 5 and Tomcat 6 with IDEA 7. There are certain gotchas with Tomcat 5 (such as the EL Jars) that I haven't exercised sufficiently. Again, give me a shout with any learnings, and i'll update this document.

I chose not to use IDEA's support for the JSF Facet, which lets you automatically add support for MyFaces, to keep this article independent of IDE specific helper tools. (And, real programmers don't need no IDE).

Step 2a: Download the libraries

        MyFaces project (http://myfaces.apache.org/download.html)
This is an alternative JavaServer Faces 1.2 implementation. It comprises the myfaces-api JAR which contains an implementation of the the classes defined in the specification, and the ones that you are likely to use as an application developer; and the myfaces-impl JAR which contains the support classes with which you will not typically interact. These two JARs need to be deployed into a web application built on JSF.

The MyFaces project is actually comprised of multiple sub projects. For today we will discuss:

o       MyFaces Core, which is the actual JSF implementation provided by the project; This comes packaged with a number of commons projects (beanutils, codec, collections, digester, discovery, and logging).

o       Tomahawk which provides new third party JSF components that can be run using a completely different JSF implementation (such as Mojarra).

        JSTL (http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi):
The standard template tag libary. Facelets supports a subset of the JSTL action tags.

        Unified Expression Language:
This definitely has to be the most confusing issue ever (at least for my not-so-complex brain). The drive to standardize on a unified expression language across JSPs and JSF, resulted in a standard Unified Expression Language (JSR 245) in JSP 2.1. This new UEL can now even be used independent of a web container. Well, so far this is all common knowledge.

What's not quite so straight forward, is that Tomcat 5.5 comes with commons-el.jar (in common\lib), Tomcat 6 comes with el-api.jar, the spec, and jasper-el.jar, the implementation, (in its lib), and the Facelets distribution comes with el-api.jar and el-impl.jar (in its lib). So which one do you use? You can see a pretty live exchange here about the history behind some of the EL decisions.

My recommendation is to use the commons EL which can be downloaded from the Apache Commons EL sub project especially if you plan on using Tomahawk (see below for details on installing the Tomahawk libraries).

Step 2b: Add libraries to your project

Make sure these JARs will be copied out to your WEB-INF/lib (using the Web facet's configuration tab ):

 

 

Step 2c: Edit your deployment descriptor, web.xml

Much of this is standard, but to recap, all JSF pages must be processed by the FacesServlet. This servlet is configured to load when its container is started, rather than when it is first requested.

<servlet>

  <servlet-name>Faces Servlet</servlet-name>

  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

  <load-on-startup>1</load-on-startup>

</servlet>

 

A servlet is mapped to logical URLs (i.e., URLs used by end users, not developers) using <servlet-mapping> elements that define mappings either by extensions or prefixes.

The simplest form is extension (or, suffix) mapping, where all requests for resources that end with a particular extension are mapped to the named servlet. In this case, FacesServlet will strip off the .jsf extension and replace it with a .jsp when locating the desired resource.

<servlet-mapping>

  <servlet-name>Faces Servlet</servlet-name>

  <url-pattern>*.jsf</url-pattern>

</servlet-mapping>

When using a prefix mapping, the named servlet strips off the specified prefix when locating the desired resource (e.g., http://localhost/myApp/faces/index.jsp actually loads http://localhost/myApp/index.jsp).

 

<servlet-mapping>

  <servlet-name>Faces Servlet</servlet-name>

  <url-pattern>/faces/*</url-pattern>

</servlet-mapping>

 

This parameter tells JSF how it should save state across requests. When set to server (the default), the view is serialized and is stored in the session, and a unique key that identifies this session attribute is sent down to the client. When set to client, the serialized view is sent to the client in a hidden input field (for HTML). It is interesting to note that this setting does not affect session scoped managed beans, which will remain in the HttpSession; this flag only affects where the state of the components in the component tree is  held.

<context-param>

  <param-name>javax.faces.STATE_SAVING_METHOD</param-name>

  <param-value>server</param-value>

</context-param>

Note that client side state saving is easier on your server since no memory is required to hold state. However, it does increase the network traffic, and also requires compression, encryption, and decryption of the state information - causing additional server overhead.

You may also set the javax.faces.CONFIG_FILES context parameter, which specifies a comma separated list of Faces configuration files that should be loaded before /WEB-INF/faces-config.xml is loaded. This is a good way to reduce the size of your configuration file, for e.g., by moving your managed beans and navigation rules out to separate files.

 

Sun's reference implementation defines additional context parameters that are not included in the JSF 1.2 specification (sec 10.1.3):

        com.sun.faces.validateXml validates the XML in your faces-config.xml resources;

        com.sun.faces.verifyObjects verifies that all of the application objects you have configured (components, converters, renderers, and validators) can be successfully created;

        com.sun.faces.NUMBER_OF_VIEWS_IN_SESSION, lets you override the default of 15 top level (or root) views that are allowed to exist in a session;

        com.sun.faces.NUMBER_OF_LOGICAL_VIEWS_IN_SESSION, lets you override the default of 15 logical views that may exist per root view in a session, where a logical view is a subview of a top level view.

        com.sun.faces.COMPRESS_STATE, causes view state to be compressed before it is sent to the client.

This <env-entry> modifies the effects ofjavax.faces.STATE_SAVING_METHOD. (Ref the Java EE Tutorial).

        com.sun.faces.ClientStateSavingPassword, lets you specify a password that will be used to generate keys and ciphers to encrypt view state before it is transmitted to the client.
<env-entry>
  <env-entry-name>com.sun.faces.ClientStateSavingPassword</env-entry-name>
  <env-entry-value>somePassword</env-entry-value>
  <env-entry-type>java.lang.String</env-entry-type>
</env-entry>

 

[Also see: New Features in JavaServer Faces 1.2 Technology.]

 

Step 2.d:The following are required by MyFaces:

Listeners were added in Servlet 2.3 specification, and let you respond to various events in your web application's life cycle. There are 8 listeners that let you listen for events relating to sessions, request attributes, the servlet context, etc. You can declare your listener in the deployment descriptor using the <listener> element. You use a servlet context listener to hook into the events when a new servlet context is either created or destroyed.

With JSP 1.2, the container automatically loads any listeners defined in TLD files, without needing a web.xml entry. The My Faces Install Documentation notes that you should add the following <listener> element to the web.xml of containers that do not support registering of listeners from within TLD files. Tomcat 6 should be able to read this entry straight from the META-INF\myfaces_core.tld file in myfaces-impl-1.2.2.jar.

<listener>

  <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>

</listener>

 

Next, come the context configuration parameters required by MyFaces. Note that these entries are not recognized by the JSF RI (Mojarra).

        org.apache.myfaces.SERIALIZE_STATE_IN_SESSION
If true (default) and if state is being saved on the server, the state is serialized to a byte stream before it is written to the session. Note that serialization and deserialization of the component tree can be a major performance hit.

        org.apache.myfaces.COMPRESS_STATE_IN_SESSION
If true (default) and if state is being saved on the server and if state is being serialized in the session, then the serialized state is compressed before it is written to the session. This can also be a performance hit.

        org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION
This is the same as the similarly named Mojarra context param. When server state saving is used and memory is tight, it can limit the number of views stored in the session. The default is 20.

        org.apache.myfaces.VALIDATE
Performs validation of entries in the Faces configuration files. At startup, the logs/console will display errors that indicate missing non existing templates used in navigation rules, managed beans not on the classpath, etc.

 

<context-param>

  <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>

  <param-value>true</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>

  <param-value>true</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>

  <param-value>20</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.VALIDATE</param-name>

  <param-value>true</param-value>

</context-param>

 

        org.apache.myfaces.SECRET
When using client side state saving, the view is serialized and rendered as a hidden input field (HTML). This context parameter enables encryption, using the specified secret key (the value is actually the base 64 encoded value of the actual key - required so that your secret key may contain non printable character values). The default algorithm is DES, so the secret must have a size of 8.

        org.apache.myfaces.algorithm
Specifies alternative encryption algorithms. E.g., Blowfish, with a secret of size 16; or Triple DES (DESede) or AES (Advanced Encryption Standard) with a secret of size 24.

        org.apache.myfaces.parameters and org.apache.myfaces.iv
The default encryption mode is the Electronic Code Book (ECB) mode. To use the stronger Cipher Block Chaining (CBC) mode, you can specify the mode as well as the initialization vector (to be used when encrypting the very first block).

Additional notes:

The secret key NzY1NDMyMTA3NjU0MzIxMA== translates to 7654321076543210. You can generate the base65 encoded value of any string using:

java -cp .\myfaces-all.jar;.\commons-logging.jar;commons-codec.jar org.apache.myfaces.util.StateUtils abcd1234

Much of the information on the encryption parameters comes from the MyFaces Wiki.

 

<context-param>

  <param-name>org.apache.myfaces.secret</param-name>

  <param-value>MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.algorithm</param-name>

  <param-value>AES</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.algorithm.parameters</param-name>

  <param-value>CBC/PKCS5Padding</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.algorithm.iv</param-name>

  <param-value>NzY1NDMyMTA3NjU0MzIxMA==</param-value>

</context-param>

 

 

        org.apache.myfaces.ALLOW_JAVASCRIPT
If true, command_link anchors will be rendered using javascript code that submits the corresponding form. Else, the state saving information and nested parameters are added as url parameters.

        org.apache.myfaces.DETECT_JAVASCRIPT
This is labeled an "Experimental" feature, and ostensibly also affects how command link anchros are rendered.

        org.apache.myfaces.PRETTY_HTML
This parameter tidies up the rendered HTML to make it easier to read. However, the MyFaces FAQ  indicates that this feature may be deprecated.

        org.apache.myfaces.AUTO_SCROLL
Causes pages with long lists to automatically scroll to your previous location, rather than starting at the top, when you trigger a link or button action that stays on the same page. It causes javascript to be added to each generated page.

<context-param>

  <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>

  <param-value>true</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>

  <param-value>false</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.PRETTY_HTML</param-name>

  <param-value>true</param-value>

</context-param>

<context-param>

  <param-name>org.apache.myfaces.AUTO_SCROLL</param-name>

  <param-value>true</param-value>

</context-param>

 

Step 2.e: Setup a Run/Debug Configuration

Setup a quick test to verify our JSF configuration.

Edit index.jsp (generated by IDEA under our static content folder) to say:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>

  <head><title>Simple jsp page</title></head>

  <body>

    <f:view>

      Hello <h:outputText value="#{someConstants.ownerName}

        from #{someConstants.companyName}!"/>

    </f:view>

  </body>

</html>

 

Our test page relies on a dummy managed bean, again just to verify our setup rather than demonstrate some major architectural cleverness.

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE faces-config PUBLIC

  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"

  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

  <managed-bean>

    <managed-bean-name>someConstants</managed-bean-name>

    <managed-bean-class>java.util.HashMap</managed-bean-class>

    <managed-bean-scope>application</managed-bean-scope>

    <map-entries>

      <value-class>java.lang.String</value-class>

      <map-entry>

        <key>companyName</key>

        <value>Software Engineering Solutions, Inc.</value>

      </map-entry>

      <map-entry>

        <key>ownerName</key>

        <value>Damodar Chetty</value>

      </map-entry>

    </map-entries>

  </managed-bean>

</faces-config>

Step 2.f: Setup a Run/Debug Configuration

I'm using Tomcat 6.0.14 (as setup in a previous article). If you're using earlier versions of Tomcat, some sections of this document may not apply.

 

 

Now click Run to run the configuration.

 

You should now see your dummy index.jsp page being displayed (even though you requested index.jsf).

 

 

 

 

Okay, that wasn't earth shattering, but it should give us confidence that JSF is functional. So, next lets add in Tomahawk support.

Step 3: Install Tomahawk Components

Tomahawk not only provides new components, but it also extends some standard components (in the core and html tag libraries) to support additional attributes. E.g., <t:inputText> is similar to <h:inputText> but supports a forceId attribute.

The Tomahawk components include the usual list of components such as:

        a calendar

        a tabbed pane,

        and, a couple of Trees
        

Step 3a: Install the Tomahawk library

Get the Tomahawk binary from (http://myfaces.apache.org/download.html) and add it to your project. Tomahawk has a dependency on the following Commons projects - FileUpload, EL, and Lang, so make sure that you add them as well.

 

As before, make sure that the JAR is deployed to your WEB-INF/lib.

 

Step 3b: Add an extensions filter to your web.xml

A Tomahawk extensions filter allows its components to access the resources that they need to render themselves (such as scripts, stylesheets, images etc.) from within the Tomahawk JAR. It also implements a caching mechanism for these resources. When a component needs a resource, it adds a marker attribute to the request. The extensions filter will then retrieve the requested resource, and include it in the generated HTML for your page.

This extension filter is defined in your web.xml.

  <filter>

    <filter-name>extensionsFilter</filter-name>

    <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>

    <init-param>

      <description>Size limit for uploaded files.

        10 - 10 bytes, 10k - 10 KB, 10m - 10 MB, 1g - 1 GB</description>

      <param-name>uploadMaxFileSize</param-name>

      <param-value>100m</param-value>

    </init-param>

    <init-param>

      <description>Set the threshold size - files below this limit are stored in memory,

        files above this limit are stored on disk.

        10 - 10 bytes, 10k - 10 KB, 10m - 10 MB, 1g - 1 GB

      </description>

      <param-name>uploadThresholdSize</param-name>

      <param-value>100k</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>extensionsFilter</filter-name>

    <servlet-name>Faces Servlet</servlet-name>

  </filter-mapping>

  <!--

    <filter-mapping>

        <filter-name>extensionsFilter</filter-name>

        <url-pattern>*.jsf</url-pattern>

    </filter-mapping>

  -->

  <filter-mapping>

    <filter-name>extensionsFilter</filter-name>

    <url-pattern>/faces/myFacesExtensionResource/*</url-pattern>

  </filter-mapping>

[If you've noticed the commented entry for the filter mapping ... remember that a filter mapping may either have a servlet name or a url pattern, but cannot have both.]

Extensions resources are identified by the URL pattern /faces/myFacesExtensionResource/*.

The extensions filter buffers the whole response in memory before writing it out to the client - and so increases memory usage on the server. You can disable this buffering while still retaining the functionality of the extensions filter by setting the ADD_RESOURCE_CLASS context parameter, and setting it to the StreamingAddResource implementation of AddResource; and replace the HTML <html>,<head>, and <body> tags by Tomahawk's <t:document> , <t:documentHead>, and <t:documentBody> tags respectively in your template. Of course, your <f:view> tag would have to enclose your <t:document> tag.

        org.apache.myfaces.CHECK_EXTENSIONS_FILTER
If true, will verify that the extensions filter is configured correctly. If you get errors even after you have configured it correctly, you can silence the messages by setting this to false.

        org.apache.myfaces.ADD_RESOURCE_CLASS
Specifies an implementation of the AddResource interface, responsible for placing scripts and CSS on the right position in your HTML document. The two implementations available are DefaultAddResource and StreamingAddResource (supposedly for better performance).

 

<context-param>

  <param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>

  <param-value>org.apache.myfaces.renderkit.html.util.DefaultAddResource</param-value>

  <!--
  <param-value>org.apache.myfaces.component.html.util.StreamingAddResource</param-value>
  -->

</context-param>

<context-param>

  <param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>

  <param-value>true</param-value>

</context-param>

Step 3c: Verify that Tomahawk components are available for use

Add the tomahawk namespace to your template page. The Tag Library Descriptor is contained in the JAR's META-INF\tomahawk.TLD file which is automatically picked up by Tomcat 6.

 

If everything goes well, here's your displayed page:

 

If things go south, then verify that you have all your required Commons components.

The following error means you haven't included the commons FileUpload component:

java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileUpload

  org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:117)

 

The following error means you haven't included the commons EL component:

java.lang.NoClassDefFoundError: org/apache/commons/el/Logger

  at org.apache.myfaces.shared_tomahawk.util.ClassUtils.<clinit>(ClassUtils.java:44)

 

And, the following error means you haven't included the commons Lang component:

java.lang.NoClassDefFoundError: org/apache/commons/lang/builder/HashCodeBuilder

 

 

Step 4: Install Facelets

Even with all the other inconsistencies between JSP and JSF having been fixed, Facelets still brings something to the party. In addition to the templating support; you can freely mix regular HTML inside of the component tags without <f:verbatim> tags; you don't need to use <f:view> tags; etc.

However, do note that the JSP spec is evolving, and at JSP 2.1 addresses a number of the shortcomings that were widely publicized when JSF 1.0 was first released. In fact, the list of complaints has grown progressively smaller, and now sounds more like nitpicks than when Hans Bergsten first published his list of issues with JSP and JSF integration.

Of course, there still is that issue of whether JSP is a good templating option in the first place (ask any Velocity or Freemarker user for their opinions).

Step 4a: Install the Facelets library

Download the Facelets distribution from https://facelets.dev.java.net/, and install it as a library for your Web module, and verify that it will be deployed to WEB-INF/lib as before.

 

Step 4b: Update your web.xml

By default, JSF implementations come with a ViewHandler that can render JSP pages that contain JSF components. To support Facelets, we need to configure the custom FaceletViewHandler as described in Step 5 above.

We must also allow for the extension used by Facelets template documents, i.e., XHTML. With extension mapping, the extension of the resource as specified on the URL, is replaced by value of the DEFAULT_SUFFIX context parameter. If not specified, the default value is .jsp. We override the default to have JSF replace the extension with .xhtml instead. In other words, accessing a resource such as http://localhost/myApp/myFile.faces will be translated to http://localhost/myApp/myFile.xhtml when the FacesServlet tries to locate the requested resource.

<context-param>

  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>

  <param-value>.xhtml</param-value>

</context-param>

 

The following parameters may be optionally supplied.

        facelets.REFRESH_PERIOD
When a page is requested, the time in seconds that the compiler should check for changes (default is 2 seconds). This is a useful setting while in development, but in production this should probably be set to -1, which means that the compiler will not check for changes once the page is compiled.

        facelets.DEVELOPMENT
If true, the FaceletViewHandler will print out debug information in an easy to use screen when an error occurs during the rendering process.

        facelets.SKIP_COMMENTS
If true, the compiler will remove all comments completely from the document (otherwise EL in comments is still evaluated.)

 

<context-param>

  <param-name>facelets.REFRESH_PERIOD</param-name>

  <param-value>1</param-value>

</context-param>

<context-param>

  <param-name>facelets.DEVELOPMENT</param-name>

  <param-value>true</param-value>

</context-param>

<context-param>

  <param-name>facelets.SKIP_COMMENTS</param-name>

  <param-value>true</param-value>

</context-param>

 

Step 4.c: Tell Facelets about your Tomahawk components

To use Tomahawk tags from within Facelets, you need the following context param:

        facelets.LIBRARIES
It identifies the location of the taglib file that describes each of the Tomahawk components (see here for the contents of the taglib file).
Note that the aliasBean's handler class is required to be provided by you. For now, simply comment it out. Also, note that the entry for the updateActionListener tag is commented out for you.

 

    <context-param>

      <param-name>facelets.LIBRARIES</param-name>

      <param-value>/WEB-INF/tomahawk.taglib.xml</param-value>

    </context-param>

 

According to the Tomahawk documentation there are certain incompatibilities with Facelets that require the use of custom component handler implementations (e.g., for the tree2, scheduler, extended data table, and panelTabbedPane components).

 

Step 4.d: Edit faces-config.xml

Note that if you are using RichFaces with Facelets, this step is modified somewhat. Instead of editing faces-config.xml, you need to edit web.xml to add a org.ajax4jsf.VIEW_HANDLERS context parameter as described in the earlier step.

JSF uses a ViewHandler component to build (or restore) component trees, and to render views for display. The default ViewHandler that comes with JSF supports a Java Server Pages implementation.

This single entry that we make in this file enables us to replace the default ViewHandler with a Facelets specific view handler. This FaceletViewHandler can construct views from XHTML templates.

 

<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"

      version="1.2">

  <application>

    <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>

  </application>

</faces-config>

Step 4.e: Verify that Facelets is ready for use

Rename your index.jsp file to old-index.jsp.

Here's what your project should look like at the end of this step.

Create a new file, index.xhtml under your resource root with the following contents:

 

<!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:c="http://java.sun.com/jstl/core"

      xmlns:f="http://java.sun.com/jsf/core"

      xmlns:h="http://java.sun.com/jsf/html"

      xmlns:t="http://myfaces.apache.org/tomahawk">

  <head>

    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

    <title>Facelets: Proof of Concept Tutorial</title>

  </head>

  <body>

    <h:form>

      Hello #{someConstants.ownerName} from #{someConstants.companyName}!

      <p>

        Here is my Tomahawk calendar component:

      </p>

      <p>

        <h:outputLabel value="Calendar input"/>

        <t:inputCalendar id="secondOne" monthYearRowClass="yearMonthHeader"

          weekRowClass="weekHeader" popupButtonStyleClass="standard_bold"

          currentDayCellClass="currentDayCell" renderAsPopup="true"

          popupDateFormat="MM/dd/yyyy"

          helpText="MM/DD/YYYY" />

      </p>

    </h:form>

  </body>

</html>

 

 

So far, we've managed to get our environment running with MyFaces, Tomahawk, and Facelets. The next and final step is to incorporate RichFaces/Ajax4JSF into the mix.

 

 

Step 5: Install RichFaces

RichFaces provides one of the most nicely documented and packaged component libraries available for JSF. RichFaces adds Ajax capabilities to JSF applications without requiring you to write JavaScript code. It is important to note that RichFaces indicates support for IE 6+, Firefox 1.5+, Safari 2, Opera 8.5+ and Netscape 7.

Step 5.a: Download RichFaces and install the library

Get the library from http://labs.jboss.com/jbossrichfaces/downloads/, and add it to your project.

As before, ensure that this library will be deployed.

Step 5.b: Edit your web.xml for RichFaces

 

All of the web.xml context parameters used by RichFaces are optional. Some that you might use are:

        org.richfaces.SKIN
The name of the skin to be used in an application. The choices are DEFAULT, plain, emeraldTown, blueSky, wine, japanCherry

        org.ajax4jsf.LOGFILE
A URL to a log file. Content from this URL is shown on a Debug error page in the iframe window.

        org.ajax4jsf.VIEW_HANDLERS
A comma separated list of custom ViewHandler instances that are inserted before RichFaces handlers. E.g., in a Facelets application, this parameter must contain com.sun.facelets.FaceletViewHandler. The RichFaces AjaxViewHandler will then be called moments before the FaceletViewHandler.
In this case, we do not need to declare the FaceletViewHandler in faces-config.xml.

 

<context-param>

  <param-name>org.richfaces.SKIN</param-name>

  <param-value>blueSky</param-value>

</context-param>

<context-param>

  <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>

  <param-value>com.sun.facelets.FaceletViewHandler</param-value>

</context-param>

 

When using MyFaces components with RichFaces, the RichFaces filter must be the first one among other filters in web.xml. In this case, we want this filter to be invoked for all client requests (the default), as well as when using a RequestDispatcher to include or forward to a resource.

<filter>

  <display-name>RichFaces Filter</display-name>

  <filter-name>richfaces</filter-name>

  <filter-class>org.ajax4jsf.Filter</filter-class>

</filter>

<filter-mapping>

  <filter-name>richfaces</filter-name>

  <servlet-name>Faces Servlet</servlet-name>

  <dispatcher>REQUEST</dispatcher>

  <dispatcher>FORWARD</dispatcher>

  <dispatcher>INCLUDE</dispatcher>

</filter-mapping>

 

Step 5.c: Edit your faces-config.xml

As we stated before, when using Ajax4Jsf, we need to remove the application entry that we added to faces-config.xml earlier in the tutorial.

Delete the following lines:

<application>

  <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>

</application>

Step 5.d: Verify that you can use RichFaces components

At this point, here's what your project should look like:

Lets' update our test page, index.xhtml, to include a RichFaces calendar component.

index.xhtml

<!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:c="http://java.sun.com/jstl/core"

      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"

      xmlns:t="http://myfaces.apache.org/tomahawk">

  <head>

    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

    <title>Facelets: Proof of Concept Tutorial</title>

  </head>

  <body>

      <h:form>

        Hello #{someConstants.ownerName} from #{someConstants.companyName}!

      <p>

      Here is my Tomahawk calendar component:

      </p>

      <p>

      <h:outputLabel value="Calendar input"/>

      <t:inputCalendar id="secondOne" monthYearRowClass="yearMonthHeader"

          weekRowClass="weekHeader" popupButtonStyleClass="standard_bold"

          currentDayCellClass="currentDayCell" renderAsPopup="true"

          popupDateFormat="MM/dd/yyyy"

          helpText="MM/DD/YYYY" />

      </p>

      <p>

      Here is my RichFaces Calendar:

      <a4j:outputPanel id="calendar" layout="block">

        <rich:calendar popup="false" datePattern="dd/mm/yyyy"/>

      </a4j:outputPanel>

      </p>

      </h:form>

  </body>

</html>

 

Conclusion

The focus of this article was to show how you might configure all of these libraries to live peacefully in a single project. I haven't even scratched the surface on what you can do with each of these - esp. Facelets and RichFaces. That's probably the subject of future essays.

 

One unique feature of using MyFaces as the JSF implementation is the ability to plug in encryption algorithms, which might make it worth your while to explore this further.

 

Tomahawk needed a little bit of TLC to get it to work right with the mix I had going here, with the extensions filter to be configured, and the taglib definition that needed to be present. There were a few areas that I've added to my tickler file as needing more research - e.g., the performance implications of the extensions filter, and the custom handlers to get some components working with Facelets.

 

Finally, what I thought might be a project that might take an hour or so, ended up taking almost three times as much, and even longer to write up in a reasonable fashion. This is a testament to the complexity of the J2EE web development environments (and, I suppose, a guarantee of job security.)

 

In any event, I think there's enough information here to help you make up your own mind about how you might choose to proceed.

 

 

References:

Much of this information was gleaned from mind numbing trial and error, as well as multiple Google searches. Some of the major references are listed below, but if you believe this needs to be expanded, please let me know and I'll make the appropriate notations.

1. MyFaces Wiki

2. MyFaces dependencies

3. Example Tomahawk components at Irian.at

4. MyFaces compatibility matrix

5. The definitive source for Facelets documentation (esp. context parameters, etc.)

6. A Plethora of EL implementations.

7. Woodstock JSF components

8. RichFaces component demos