Search code examples
jsfjsf-2composite-component

How is an instance of composite component created and how can I get it


I'm using Mojarra 2.1. Reading this answer about when to use custom tags and composite components, I came across with the question about internals of the components.

So, the most important difference between custom tags and composite components is that every composite component has a single UIComponent instance, representing it in the component tree after view build time's finshed. Custom tag, in turn doesn't have a single UIComponent instance representing it in the tree.

So, what is that class, representing the composite component in the tree? How is it created? Is that some anonymous class? Let's consider an example from the wiki-page:

    <ui:component
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:cc="http://java.sun.com/jsf/composite"
>
    <cc:interface>
        <!-- Define component attributes here -->
    </cc:interface>
    <cc:implementation>
        <!-- Define component body here -->
    </cc:implementation>
</ui:component>

How can I get the instance of UIComponent, representing that composite component?

Digging into the source code of the UIComponent I found the following method:

public static boolean isCompositeComponent(UIComponent component) {

        if (component == null) {
            throw new NullPointerException();
        }
        boolean result = false;
        if (null != component.isCompositeComponent) {
            result = component.isCompositeComponent.booleanValue();
        } else {
            result = component.isCompositeComponent =
                    (component.getAttributes().containsKey(
                               Resource.COMPONENT_RESOURCE_KEY));
        }
        return result;

    }

I suspect that it's implementation details how the composite-component class is created. In fact, I'd like to find where the Mojarra implemenattion generates the composite component class instance.

UPD: The defintion of the composite compoent's replaced with one that doesn't explicitly defines the componentType attribute.


Solution

  • It's basically a UIPanel instance which you can just get via UIComponent#findComponent() the usual way, passing the composite component client ID. In case of Mojarra, you can find the code responsible for creating it in com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler which has in Mojarra 2.2.11 the below logic:

    360        if (ComponentHandler.isNew(c)) {
    361            facetComponent = (UIPanel)
    362            facesContext.getApplication().createComponent("javax.faces.Panel");
    363            facetComponent.setRendererType("javax.faces.Group");
    364            c.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facetComponent);
    365        }                                                                                 
    366        else {
    367            facetComponent = (UIPanel) 
    368                    c.getFacets().get(UIComponent.COMPOSITE_FACET_NAME);
    369        }