JSF Component Library Integration

Integrating multiple component libraries can provide a project many advantages but can also be a challenge to make all components live and work in harmony. This article explains how to integrate many popular component libraries into one app. Combining libraries gives developers an array of components to pick and choose from. But, knowing which components play well together and which ones don?t, will save you time and I will explain the pros and cons of each here. The following component libraries were used:


Libs

  • Myfaces 1.1.4
  • Tomahawk 1.1.4
  • Ajax4JSF 1.0.3
  • Trinidad m1 Nightly Build
  • IceFaces 1.0.1
  • Facelets 1.0.11

Environment

  • JDK 1.5 +
  • Jboss 4.0.4 (or Tomcat is better/lighter)
  • IntelliJ Idea

Software Needed

  • Subversion
  • CVS
  • Maven 2

It's worth the effort to go ahead and get yourself acquainted with downloading the source for most of your component libraries, starting with Myfaces. I use Tortoise SVN or you can download the binaries using the command line. Once you have Subversion setup, checkout Myfaces here. After that, this guide This will give you a quick how to on compiling the libraries with Maven 2. If you use IntelliJ Idea you can get a plugin that will generate your project files. This will allow you to edit the source and change things around if needed, it also helps when you are trying to follow this guide.

For the impatient, the short and sweet steps are:

  1. Download Maven 2 and add bin dir to path
  2. checkout code for project
  3. navigate to root dir (or dir with pom.xml file)
  4. run mvn install
  5. This will build the target directory for the project which will contain compiled jars, examples wars, etc.

Myfaces

Checkout: http://svn.apache.org/repos/asf/myfaces

Each servlet container has its own configuration in which details can be found here. Overall the latest version of Tomcat and Jboss had no major issues with the out-of-box Myfaces configuration. If you are integrating Myfaces with an existing JSF RI, there are steps with the ExtensionsFilter that must be taken located on the Myfaces wiki.

Viewing this up to date compatibility matrix, will ensure you are working with compatible libraries.

There are a number of performance settings you can make with Myfaces, but with integration of components being the focus for this article, performance tuning will be discussed in part 2 of this series.

Tomahawk

Checkout: Checkout: http://svn.apache.org/repos/asf/myfaces/tomahawk

Once you have the latest Tomahawk build checked out, you can find almost all of the Myfaces and Tomahawk configuration and performance settings in the sandbox/examples/src/main/webapp/WEB-INF/web.xml file. All of the settings are applicable to this article, and it is a great starting point that is well commented.

When using Facelets, each project requires its own tag library. Unfortunately Tomahawk does not include Facelet integration built into their jar(as of 1.1.4). This requires you to put together tomahawk.taglib.xml and point to it from settings in your web.xml.

<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/tomahawk.taglib.xml</param-value>
</context-param>

This provides pass-through getters and setters to the tomahawk library. You can write a *.taglib.xml for any library, but you may need to write a Facelets TagHandler.

Ajax4jsf

Checkout (use cvs): cvs -d :pserver:yourName@cvs.dev.java.net:/cvs checkout ajax4jsf

One of the largest hurdles with this library was integration with Trinidad. Trinidad and Ajax4JSF use their own ViewHandler with Facelets and both are very picky about how and where they are loaded.

Web.xml

<filter>
<display-name>Ajax4jsf Filter</display-name>
<filter-name>ajax4jsf</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>

<filter-mapping> <filter-name>ajax4jsf</filter-name> <servlet-name>FacesServlet</servlet-name> </filter-mapping>

faces-config.xml

<application>
<default-render-kit-id>org.apache.myfaces.trinidad.core</default-render-kit-id>
<view-handler>org.ajax4jsf.framework.ajax.AjaxViewHandler</view-handler>
</application>

Initially I tried to use Neko HTML for the component XML rendering and had to abandon it because of one extra tag at the end of the response. Neko is known for not trying to "over" correct the code, but in this case it did not work. With the default Ajax4Jsf filter, you get Tidy cleaning up the response and that seemed to work just fine. Tidy is also configurable through a .properties file with various parser settings.

As of version 1.0.3, there have been many improvements and I was able to get everything working together from the settings above. This version also includes the integration jar for working with Trininad released after September 29, 2006.

One very nice debugging helper for this library is the logConsole div:

<div style="padding: 5px; overflow: auto; font-size: 9px; height: 150px; width: 100%;" id="logConsole"></div>

This allows you to see the entire Ajax request/response going and coming back from the server. One thing you may want to create is a Facelets debugging template and add this along with the facelets debugging options into it.

Trinidad

Checkout: http://svn.apache.org/repos/asf/incubator/adffaces

Here we have the basic settings for Trinidad to integrate with your application. Because we are integrating with Ajax4Jsf, Trinidad is the only ViewHandler defined in the web.xml. In the a4j example above you see how the ViewHandler for Ajax4Jsf is defined in the faces-config.xml. Again, if you are not using these two libraries together then you need to follow the documentation from the libraries corresponding websites.

Web.xml

<context-param>
<param-name>org.apache.myfaces.trinidad.ALTERNATE_VIEW_HANDLER</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>

<filter> <filter-name>trinidad</filter-name> <filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class> </filter>

<filter-mapping> <filter-name>trinidad</filter-name> <servlet-name>FacesServlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping>

One important topic I would like to touch on is client-side state saving vs. server-side. Trinidad offers a unique strategy for JSF state saving which will allow tokens to be sent to the client allowing minimal performance drag. The default client-side state saving only saves a token to the client, and saves the real state in the HttpSession. MyFaces tells users to use server-side and Trinidad prefers client-side, but they are basically the same thing in terms of HttpSession. Also, failover is supported with the Trinidad state saving method.

As for components, Trinidad starts with more than 100 components which have already been documented and thoroughly tested. Now we have tags from 3-4 different libraries that overlap each other. We must decide which one to use where, why we are using them, and what is best for performance. Tag usage, along with state saving, will be discussed in part 2 of this series.

IceFaces

TODO - Update this section

**Note, since the writing of this article, Icefaces has been open sourced*** If you wish to make use of clustering and advanced asynchronous HTTP handling in a large-scale application, they want you to move up to the Enterprise Edition.

As of ICEfaces v1.0.1 release, they now have support for JSF integration. You can view configuration instructions here. In short, you can use the just-ice.jar, instead of the icefaces.jar, and use other JSF servlet mappings (ie. Faces Servlet) to handle non-ICEfaces pages. If you do this, you must use **only** standard JSF tags (f:) and ICEfaces tags (ice:) in you JSF pages.

ICEFaces doesn't have the same approach as ajax4jsf and DynaFaces have. You will have to follow their component-model to get the benefits of the Direct2Dom technology, so hooking up components of other libraries together with the ICEFaces components isn't possible (as of now), as they cannot re-render arbitrary components through their renderkit.

If you need to combine components from an open source library with IceFaces, one option is to use an iframe within an icefaces page. The iframe could point to the other JSF framework Servlet/ViewHandler. I haven't tried this yet myself, but according to the IceFaces support staff, it's worth a try.

For Facelets integration, along with the core jars, you will need icefaces-facelets.jar. There are minimal settings that take place for Facelet integration. The steps are located here

Facelets

The facelets ViewHandler configuration placement is critical to your application. If you are ONLY integrating Ajax4Jsf with Facelets, you should have you settings in web.xml as follows:

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

You need the above defined only if using Ajax4Jsf along with all other libraries besides Trinidad. If using Trinidad along with Ajax4Jsf and Facelets then follow the steps from the Trinidad section above.

One quick performance tip that will impact the foundational templating is the StreamingAddResource.

By adding:

<context-param>
<param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>
<param-value>org.apache.myfaces.component.html.util.StreamingAddResource</param-value>
</context-param>

...to the web.xml and using...

  • t:document as replacement for html
  • t:documentHead as replacement for head
  • t:documentBody as replacement for body

...this will allow the pages to be streamed which will result in faster page delivery.

For debugging Facelets, add the following to your web.xml:



<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>

Setting this to true will cause the FaceletViewHandler to print out debug information in an easy to use screen when an error occurs during the rendering process. Probably one of the coolest features for debugging is the tag. Of course you can?t have ?cool? without an expense, so be careful when using this option because of overhead. You can use the UIComponent rendered property to turn debugging on or off based on some expression. In this example, debugging is backed by an entry in the web.xml.

<ui:debug hotkey="d" rendered="#{initParam.debugMode}"/>

The debug tag will capture the component tree and variables when it is encoded, storing the data for retrieval later. You may launch the debug window at any time from your browser by pressing 'CTRL' + 'SHIFT' + 'D' (by default). Like I said earlier the best place to put this tag is in your site's main template, or in some kind of debugging template, where it can be enabled/disabled across your whole application.


Words by Wesley Hales