JavaServer Faces – Find component recursively

In my current project I had to implement a jsf validator regarding 2 jsf-components. Unfortunately the validate method of the Validator Interface allows only one component as parameter.

To realise a validator for 2 fields I needed a way to get the value of the second involved component.

Therefore I added the id of the second component as parameter.

<t:inputTextarea id="comp1" ... >
    <f:validator validatorId="myValidator" />
    <f:attribute name="compId" value="comp2" />
</t:inputTextarea>
<t:inputTextarea id="comp2" ... />

The idea was to use the method

    UIViewRoot.findComponent(clientID)

to get the needed component.

To my surprise, sometimes null was returned, mainly when used in nested DataTables. So I walked through the complete component tree and looked “by hand” for the component … and no surprise – it exists!

To solve this problem (looks like a bug in JSF 1.1) I wrote a recursive variant of the findComponent method. This method walks through the complete JSF component tree searches for the component (via clientId) and returns it.

/**
 * Traverses the componenttree recursively and
 * returns the desired component
 *
 * @param context
 * @param comp
 * @param clientId
 * @return
 */
public UIComponent findComponentRecursively(FacesContext context, UIComponent comp, String clientId) {
 
    if (clientId.equals(comp.getClientId(context))) {
        return comp;
    } else {
        if (comp.getChildCount() &gt; 0) {
            for (Iterator it = comp.getChildren().iterator(); it.hasNext();) {
                UIComponent component = (UIComponent) it.next();
                UIComponent res = findComponentRecursively(context, component, clientId);
                if (res != null) {
                    return res;
                }
            }
        }
    }
    return null;
}

For performance reasons I use the following method. First it tries to look for the desired component directly and uses the recursive variant as fallback.

    /**
     * This method finds a component in the JSF-Tree by its
     * complete id. Due to a bug in JSF a component is not
     * always found by @link UIViewRoot.findComponent.
     * Therefore findComponentRecursively is called if needed.
     *
     * @param context
     * @param comp
     * @param clientId
     * @return
     */
    public UIComponent findComponent(FacesContext context, String clientId) {
        UIComponent newComp = (UIComponent) context.getViewRoot().findComponent(clientId);
        if (newComp == null) {
            newComp = (UIInput) JSFHelper.getInstance().findComponentRecursively(context, context.getViewRoot(),
                    clientId);
        }
        return newComp;
    }

I hope this saves you some time when struggling with the same problem.

Autor: Andreas Frey
Datum: Friday, 17. October 2008 12:03
Trackback: Trackback-URL Themengebiet: JavaServer Faces

Feed zum Beitrag: RSS 2.0 Diesen Artikel kommentieren

2 Kommentare

  1. 1

    There are people who think that JSF is broken, so broken that it cannot be fixed and has to be rewritten. How is your experience?

  2. 2

    I don’t think JSF is broken. It is a framework addressing most of the standard problems. Sure i miss some things, but it is great to develop fast Web Applications – and most problems can be solved – with some effort.

    Like all frameworks it addresses some problems and solves them … but nothing more

Kommentar abgeben