The AjaxComponent strategy for JSF: The best of both worlds

Ajax-enable your components with a phase listener

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

The tag handler class and taglib descriptor

Before you can use your new AjaxComponent tag in a JSP, you need to create a tag handler for it, and also declare it in a taglib file.

The AjaxComponentTag class, shown in Listing 7, is very simple, because there are no attributes to manage on the tag. If there were, this is where you'd pass them on to the component itself.

Listing 7. The tag handler: AjaxComponentTag

public class AjaxComponentTag extends UIComponentTagBase {
  private static final transient Log log = LogFactory.getLog(tutorial.jsf.ajax.component.AjaxComponentTag.class);

  public AjaxComponentTag() {
  }

  public String getComponentType() {
    return AjaxComponent.COMPONENT_TYPE;
  }

  public String getRendererType() {
    return AjaxComponent.DEFAULT_RENDERER_TYPE;
  }
}

You do have to declare here the component type that the handler is for, and what the renderer type is. This will become important later when you declare the component in faces-config.xml.

Now you declare the tag in a taglib entry, as in Listing 8.

Listing 8. The tag library descriptor

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">

  <tlib-version>1.3</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>tut</short-name>
  <uri>http://www.tutorial.org/jsf</uri>

  <description>JSF Tutorial - Ajax</description>
  <tag>
    <name>ajaxComponent</name>
    <tag-class>tutorial.jsf.ajax.component.AjaxComponentTag</tag-class>

    <body-content>JSP</body-content>
    <description>
      The AjaxComponent example.
    </description>
    <!-- UIComponent attributes -->
    <attribute>

      <name>id</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
      <type>java.lang.String</type>

      <description>
        The developer-assigned ID of this component. The ID must
        be unique within the scope of the tag's enclosing naming
        container (e.g. h:form or f:subview). This value must be
        a static value.
      </description>
    </attribute>
    <attribute>
      <name>binding</name>

      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
      <type>java.lang.String</type>
      <description>

        Identifies a backing bean property (of type UIComponent
        or appropriate subclass) to bind to this component
        instance. This value must be an EL expression.
      </description>
    </attribute>
    <attribute>
      <name>rendered</name>
      <required>false</required>

      <rtexprvalue>false</rtexprvalue>
      <type>java.lang.String</type>
      <description>
        A boolean value that indicates whether this component
        should be rendered. Default value: true.
      </description>

    </attribute>
  </tag>
</taglib>

Listing 8 includes the entire taglib file from the example app. You just need to place this somewhere on the classpath, usually in the WEB-INF directory.

You might wonder what all these attributes are doing in the listing, given I just said that we don't have any, and that's why the tag handler class is so simple. Those attributes belong to the UIComponent interface and are handled by the base classes you've extended (UIComponentBase and UIComponentTagBase). Because tag descriptors do not support inheritance, you must declare them here for your tag.

faces-config.xml

Now you are finally ready to declare the component for use in the application.

You can see in the example application that the faces-config.xml file, part of which is shown in Listing 9, is also deployed inside the WEB-INF folder. JSF automatically searches for that file to configure itself. (It also looks for the file inside the META-INF folder of JAR files, which allows you to package your component descriptors along with the components).

Listing 9. faces-config.xml component and phase listener entries

<?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>
    <component>
           <component-type>tutorial.jsf.ajax.component.AjaxComponent</component-type>
           <component-class>tutorial.jsf.ajax.component.AjaxComponent</component-class>

      </component>
  <render-kit>
    <renderer>
            <component-family>tutorial.jsf.ajax.component.AjaxComponent</component-family>
            <renderer-type>tutorial.jsf.ajax.component.AjaxComponentRenderer</renderer-type>

            <renderer-class>tutorial.jsf.ajax.component.AjaxComponentRenderer</renderer-class>
        </renderer>
    </render-kit>

<!-- LIFECYCLE -->

  <lifecycle>

    <phase-listener>tutorial.jsf.ajax.AjaxListener</phase-listener>
  </lifecycle>

</faces-config>

In Listing 10, you first declare the component along with its fully qualified class. After that, you define the renderer for it. Notice that these strings correspond to properties that have also been defined on the component.

Listing 10. Component-family and renderer on the Component class

public static final String DEFAULT_RENDERER_TYPE = "tutorial.jsf.ajax.component.AjaxComponentRenderer";
public static final String COMPONENT_FAMILY = "tutorial.jsf.ajax.component.AjaxComponent";
public static final String COMPONENT_TYPE = "tutorial.jsf.ajax.component.AjaxComponent"; // Used by Tag Handler

public AjaxComponent() {
  this.setRendererType(AjaxComponent.DEFAULT_RENDERER_TYPE);
}

public String getFamily() {
  return COMPONENT_FAMILY;
}

Remember also that you declared the type and renderer-type in the tag handler. Getting this configuration step just right, though simple, can sometimes be a little touchy. Make sure the strings you use on the component and tag handler match what you declare in faces-config.xml, and also that the classnames are exactly right.

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