Only Software matters

Experiences in software development

Creating composite JSF components

Posted by Dimitra Konstantinidou on August 30, 2011


A composite component is a component that consists of other components and it can be reused with a minimal effort. JSF 2.0 simplifies the creation of custom components.

In this post, we describe the steps in creating a simple composite custom component with child components using JSF 2.0. We also show how we can pass methods and event listeners as attributes to a custom composite component.

1. We create a .xhtml page that consists of two main sections: a) the section where the attributes of the component are declared and b) the implementation of the component. For example:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:composite="http://java.sun.com/jsf/composite">


<composite:interface componentType="customComponent">
<composite:attribute name="id" required="true"/>
<composite:attribute name="columns" required="false" default="4"/>
<composite:attribute name="columnClasses" required="false" default="labelColumn,dataColumn,labelColumn,dataColumn"/>

</composite:interface>
<composite:implementation>
<h:panelGrid id="#{cc.attrs.id}_panel" columns="#{cc.attrs.columns}" width="100%" columnClasses="#{cc.attrs.columnClasses}" >
<h:outputLabel value="#{general['label']}:"/>

 <composite:insertChildren/>
</h:panelGrid>
</composite:implementation>
</html>

2. For each attribute of the component we specify a name, whether it is required or not, and possibly a default value. Thus, the above component has three attributes (id, columns and columnClasses) one of which is required (id), while for the remaining two we define default values. As a result, the columns attribute has the value 4, unless a different value is specified in the page where the component is used.

In the section where the implementation of the component is defined (composite: implementation) we refer to its attributes using expressions of the form: cc.attrs.AttributeName.

The element <composite:insertChildren/> places any child components declared within the composite component tag in the using page, at the specified point within the <composite:implementation> section. This element can be used only once within the <composite:implementation> section.

3. We create a new folder named components inside the folder resources of a .war file or alternatively in the folder META-INF/resources of a .jar file. We place the above page (customComponent.xhtml) in the folder components.

4. In order to use the component in a .xhtml page at first we specify the url of the library to which it belongs:
xmlns:e=http://java.sun.com/jsf/composite/components

the part http://java.sun.com/jsf/composite notifies JSF that this is a custom component that consists of other JSF components. The second part /components has the same name with the name of the folder where the implementation page of the component is stored.

We then insert a statement like the following:

<e:customComponent id="componentId" >
    <h:outputLabel value="Child component/>
</e:customComponent>                                                                   or

<e:customComponent id="componentId" />

where the name of the component is the same as the name of the page defining its implementation (customComponent.xhtml in our case).

Attributes that correspond to simple methods


In order to set a method as an attribute of a composite component, we do the following:
a. In the attributes section of the component we insert a statement like this:
<composite:attribute name="handleChanges" method-signature="void handleChanges(Object)" required="false"/>

In the definition of the method signature we can use any name for the method.

b. In the implementation section of the component we use the above attribute like this:

<p:ajax event="change" listener="#{cc.attrs.handleChanges}" update="#{cc.attrs.id}_panel" />

Attributes that correspond to JSF event listeners

(The described workaround is based on the following post http://stackoverflow.com/questions/6453842/jsf-2-how-can-i-add-an-ajax-listener-method-to-composite-component-interface/6454339#6454339.)

In order to set a method that is an event listener, as an attribute of the composite component, we work as follows:
a. In the attributes section of the component we insert a statement like the following:
<composite:attribute name="handleChanges" method-signature="void handleChanges(org.primefaces.event.SelectEvent)" />

b. We create a Java class (CustomComponent) which inherits from the base class UIComponentBase (or another class that represents a JSF component ) and also implements the interface javax.faces.component.NamingContainer. The annotation @FacesComponent results in the automatic registration of the class CustomComponent with the JSF runtime as a UIComponent.


The value attribute corresponds to the name of the component.

@FacesComponent(value = "customComponent")

public class CustomComponent extends UIComponentBase implements NamingContainer {

@Override

public String getFamily() {

return "javax.faces.NamingContainer";

}

public void handleChanges(SelectEvent event) {

FacesContext context = FacesContext.getCurrentInstance();

MethodExpression handleChanges = (MethodExpression) getAttributes().get("handleChanges"); (1)
handleChanges.invoke(context.getELContext(), new Object[]{event}); (2)

}

}

The class CustomComponent contains one method which: gets the attribute of the component that contains the declaration of the listener method (1) and then
calls the listener passing the appropriate number of parameters (2).

c. On the implementation page of the component, at first we specify the type of the component as customComponent:
<composite:interface componentType="customComponent">

<composite:attribute name="id" required="true"/>
................................................
</composite:interface>

Then, with a statement like the following we define that each time an item is selected from the list of the primefaces’s autocomplete component, the method handleChanges is called, which in turn calls the listener that is passed as an attribute to our component.

<p:autoComplete>

<p:ajax event="itemSelect" listener="#{cc.handleChanges}" update="#{cc.attrs.id}_panel"/>

</p:autoComplete>

d. In order to use the component on a .xhtml page , we insert a statement like the following:

<e:customComponent handleChanges="#{handler.handleSelectionChanges}" id="componentId" />

The method handleSelectionChanges is defined as follows:

public void handleSelectionChanges(SelectEvent event)

{

}

3 Responses to “Creating composite JSF components”

  1. JavaPins said

    Creating composite JSF components…

    Thank you for submitting this cool story – Trackback from JavaPins…

  2. Thank you Dimitra for posting this great article. Extremely useful for Web Development that unleash the power of JSF 2.0 framework. I am looking forward for more posts from you!

  3. JL said

    Hi im get an error:

    WARNING: javax.el.PropertyNotFoundException: /test.xhtml @35,68 handleChanges=”#{equivalentesMBean.handleSelectionChanges}”: The class ‘TestClassMBean’ does not have the property ‘handleSelectionChanges’.

    i have this in my managed bean: public void handleSelectionChanges(SelectEvent event)

    what can be?

    i try to do:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: