The AjaxComponent strategy for JSF: The best of both worlds

Ajax-enable your components with a phase listener

Adding Ajax capability to JSF applications is easy to talk about but not so simple to do. Developing a custom lifecycle phase is too complex for most needs; putting the handler code in the component's decode() method doesn't give you enough control; and using a phase listener by itself breaks encapsulation. In this article, Matt Tyson demonstrates the AjaxComponent strategy -- an effective and practical way of integrating Ajax into your JSF applications, and easily extensible to boot.

If you want to handle Ajax requests in JavaServer Faces (JSF) applications, you'll probably start with a handful of popular approaches and quickly realize that each one has its advantages and disadvantages. For instance, if you use a component to set up and handle an Ajax request, you remain within the JSF component model and keep all the code related to the request encapsulated. If you use a phase listener as a kind of proxy to delegate to the component, you can invoke a specific method on the component, avoid invoking other components unnecessarily, and avoid issues with the immediate attribute.

Normally, if you just use a component to handle an Ajax request, you would put the Ajax code in one of the component's standard JSF methods (like decode()) and allow JSF to execute it in the normal course of the request processing lifecycle, but this doesn't give you enough control. On the other hand, if you were to use a phase listener alone, you would break encapsulation by putting unrelated logic in the phase listener. You can think of the component as achieving the where that you want, and of the phase listener as getting you the when that you want.

If you combine the component and phase listener approaches, you get both the when and the where, and you can also add new Ajax-enabled components to your application with ease. Moreover, you keep the components' standard request processing and Ajax processing nicely separated. The JSF Ajax component implements an interface with a single method, handleAjaxRequest(), which the phase listener invokes. This component interface, and the combined strategy, is called the AjaxComponent. Using it, you gain the simplicity of a component and the power of a phase listener. The combined approach you'll learn about in this article is very effective and practical for most applications, and is easily extensible, too.

When you need to Ajax-enable a JSF component, AjaxComponent is a solid strategy for doing it. AjaxComponent also works seamlessly with the JSF AjaxCommand strategy described in my previous JavaWorld article.

The pieces of the puzzle

Building a JSF component involves a fair amount of overhead. It might even bring to mind the process of creating EJBs. It looks as if this problem will be addressed in JSF 2.0, but for now, with JSF 1.1, we're still stuck with a multi-step process. On the positive side, these steps bring you a reusable component that can be accessed with a simple tag in your JSPs. Moreover, components can be, and are, shared among developers -- just take a look at the Apache Tomahawk Trinidad and Tobago projects.

The following elements are required to build a JSF component, and the AjaxComponent is no exception. The file in parentheses is the element as it exists for the example AjaxComponent that you'll see built in the course of this article. (See Resources to download the complete code for this application.)

  • A Component class (
  • A Renderer (
  • A tag handler class (
  • A tag descriptor file entry (Tutorial.tld)
  • An entry in faces-config.xml

The sample application includes an AjaxComponent with all of the above elements. Note that the application uses MyFaces 1.1.5 and the Dojo JavaScript library.

The best way to get a good understanding of how the AjaxComponent strategy works is to examine each of the elements listed above in turn. After that, I'll wrap up by describing how to deploy the sample application and some changes that a production component might require.

1 2 3 4 5 6 7 Page 1
Page 1 of 7