Download PDF Home History |  | API Search Feedback FAQ

> ## Creating the Component Tag Handler

> If you've created your own JSP custom tags before, creating a component tag and tag handler should be easy for you.

> In JavaServer Faces applications, the tag handler class associated with a component drives the render response phase of the JavaServer Faces life cycle. For more information on the JavaServer Faces life cycle, see The Life Cycle of a JavaServer Faces Page.

> The first thing that the tag handler does is to retrieve the type of the component associated with the tag. Next, it sets the component's attributes to the values given in the page. Finally, it returns the type of the renderer (if there is one) to the JavaServer Faces implementation so that the component's encoding can be performed when the tag is processed.

> The image map custom component includes two tag handlers: `AreaTag` and `MapTag`. To see how the operations on a JavaServer Faces tag handler are implemented, let's take a look at `MapTag`:

>     public class MapTag extends UIComponentTag {
>       private String current = null;
>       public void setCurrent(String current) {
>         this.current = current;
>       }
>       private String actionListener = null;
>       public void setActionListener(String actionListener) {
>         this.actionListener = actionListener;
>       }
>       private String action = null;
>       public void setAction(String action) {
>         this.action = action;
>       }
>       private String immediate = null;
>       public void setImmediate(String immediate) {
>         this.immediate = immediate;
>       }
>       private String styleClass = null;
>       public void setStyleClass(String styleClass) {
>         this.styleClass = styleClass;
>       }
>       public String getComponentType() {
>         return ("DemoMap");
>       }
>       public String getRendererType() {
>         return ("DemoMap");
>       }
>       public void release() {
>         super.release();
>         current = null;
>         styleClass = null;
>         actionListener = null;
>         action = null;
>         immediate = null;
>       }
>       protected void setProperties(UIComponent component) {
>         super.setProperties(component);
>         MapComponent map = (MapComponent) component;
>         if (styleClass != null) {
>           if (isValueReference(styleClass)) {
>             ValueBinding vb =
>               FacesContext.getCurrentInstance().
>                 getApplication().
>                   createValueBinding(styleClass);
>             map.setValueBinding("styleClass", vb);
>           } else {
>             map.getAttributes().put("styleClass", styleClass);
>           }
>         }
>         if(actionListener != null) {
>           if(isValueReference(actionListener)) {
>             Class args[] = {ActionEvent.class};
>             MethodBinding mb =
>               FacesContext.getCurrentInstance().
>                 getApplication().
>                   createMethodBinding(actionListener, args);
>             map.setActionListener(mb);
>           } else {
>             Object params[] = {actionListener};
>             throw new javax.faces.FacesException();
>           }
>         }
>         if (action != null) {
>           if (isValueReference(action)) {
>             MethodBinding vb = FacesContext.
>               getCurrentInstance().getApplication().
>                 createMethodBinding(action, null);
>             map.setAction(vb);
>           } else {
>             map.setAction(
>               Util.createConstantMethodBinding(action));
>           }
>         }
>         if (immediate != null) {
>           if (isValueReference(immediate)) {
>             ValueBinding vb = FacesContext.
>               getCurrentInstance().getApplication().
>                 createValueBinding(immediate);
>             map.setValueBinding("immediate", vb);
>           } else {
>             boolean _immediate =
>               new Boolean(immediate).booleanValue();
>             map.setImmediate(_immediate);
>           }
>         }
>     }

> The first thing to notice is that `MapTag` extends `UIComponentTag`, which supports `jsp.tagext.Tag` functionality as well as JavaServer Faces-specific functionality. `UIComponentTag` is the base class for all JavaServer Faces tags that correspond to a component. Tags that need to process their tag bodies should instead subclass `UIComponentBodyTag`.

> As explained earlier, the first thing `MapTag` does is to retrieve the type of the component. It uses the `getComponentType` operation to do this:

>       public String getComponentType() {
>         return ("DemoMap");
>       }

> The value returned from `getComponentType` must match the value configured for the component with the `component-type` element of the application's application configuration resource file. Registering a Custom Component explains how to configure a component.

> Next, the tag handler sets the component's attribute values to those supplied as tag attributes in the page. The `MapTag` handler gets the attribute values from the page via JavaBeans properties that correspond to the attributes. `MapComponent` has several attributes. Here is the property that is used to access the value of `immediate`:

>       private String immediate = null;
>       public void setImmediate(String immediate) {
>         this.immediate = immediate;
>       }

> To pass the value of the tag attributes to `MapComponent`, the tag handler implements the `setProperties` method.

> Some tag attributes can refer to literal values or use value-binding expressions, which point to values typically stored in a bean. It is recommended that you enable your component attributes to accept value-binding expressions because this is what a page author expects.

> If you do make your tag attributes accept value-binding expressions then the component property must also be enabled for value-binding expressions. See Enabling Value-Binding of Component Properties for more information. In addition, an attribute that accepts a value-binding expression must be of type `String`. This is why `immediate` is of type `String`, as shown in the preceding code snippet.

> For each `MapComponent` attribute that accepts a JavaServer Faces EL expression, the `setProperties` method must get either a `MethodBinding` or a `ValueBinding` for it from the `Application` instance. A `ValueBinding` object is used to evaluate value-binding expressions that refer to backing bean properties. A `MethodBinding` object is used to evaluate method-binding expressions that refer to backing bean methods.

> For example, the value of the `actionListener` attribute must be a method-binding expression that points to a method on a backing bean that takes an `ActionEvent` object as its argument. The `setProperties` method of `MapTag` creates a `MethodBinding` for the `actionListener` attribute, passing in the signature that this method must have, and it sets the `MethodBinding` object as the value of the `actionListener` attribute of `MapComponent`.

> The `action` attribute can take a literal `String` or a method-binding expression that points to a backing bean method that takes no parameters and returns a literal `String`. To handle the case of the literal `String`, the `setProperties` method creates a special constant method binding around the literal `String` in order to satisfy the requirement that the argument to the `action` attribute of `MapComponent` be a `MethodBinding` instance. To handle the method-binding expression, `setProperties` creates the `MethodBinding` object as it does for the `actionListener` attribute.

> The `MapComponent` object's `immediate` attribute value is a value-binding expression. This expression points to a backing bean property. Therefore, `setProperties` must obtain a `ValueBinding` instance for it. After obtaining the `ValueBinding` instance, the `setProperties` method sets the value of the property on `MapComponent` by calling the `MapComponent` class's `setValueBinding` method, passing in the `ValueBinding` instance obtained from the `Application` and the name of the attribute.

> The following piece of `setProperties` sets the `immediate` property of `MapComponent`:

>     ...
>     if (immediate != null) {
>       if (isValueReference(immediate)) {
>         ValueBinding vb = FacesContext.
>           getCurrentInstance().getApplication().
>             createValueBinding(immediate);
>         map.setValueBinding("immediate", vb);
>       } else {
>         boolean _immediate =
>           new Boolean(immediate).booleanValue();
>         map.setImmediate(_immediate);
>       }
>     }

> Finally, the tag handler provides a renderer type--if there is a renderer associated with the component--to the JavaServer Faces implementation. It does this using the `getRendererType` method:

>       public String getRendererType() {return "DemoMap";}

> The renderer type that is returned is the name under which the renderer is registered with the application. See Delegating Rendering to a Renderer for more information. If your component does not have a renderer associated with it, `getRendererType` should return `null`.

> It's recommended practice that all tag handlers implement a `release` method, which releases resources allocated during the execution of the tag handler. The release method of `MapTag` as follows:

>     public void release() {
>       super.release();
>       current = null;
>       styleClass = null;
>       actionListener = null;
>       immediate = null;
>       action = null;
>     }

> This method first calls the `UIComponentTag.release` method to release resources associated with `UIComponentTag`. Next, the method sets all attribute values to `null`.

Download PDF Home History |  | API Search Feedback FAQ

All of the material in The J2EE(TM) 1.4 Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.