Only Software matters

Experiences in software development

Archive for the ‘jsf’ Category

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)

{

}

Posted in java, jsf, software | 3 Comments »

Injecting Lists with CDI in Managed Beans and JSF compoments

Posted by Patroklos Papapetrou on July 10, 2011


It’s been 18 months since the first official release of “JSR 299: Contexts and Dependency Injection for the JavaTM EE platform” and Java is now more than ever ready to be compared (in Dependency Injection) with Google Guice, Spring or PicoContainer because CDI includes the best features of all of the above mentioned frameworks. Moreover, JSR-299 is now a standard so by following it you have no risk finding yourself dependant of third party solutions. Now you can enjoy dependency injection as a native / core feature of J2EE.

In this article I demonstrate how easy has become with CDI to use/share common lists in managed beans as well as in JSF components. Let’s assume that you would like to create and use an employee list (that rarely changes) in a web application. Before CDI you would probably create an ApplicationScoped global static bean with a private attribute employeeList (with relevant setter and getter) and a method to initialize it. Whenever a bean had to access this list you should write a code that seems like the following:

GlobalBean.getEmployeeList();

Quite ugly code for three reasons. Your code is dependent on the definition of getEmployeeList method and secondly you are obliged to use the static class to get a reference to the list. Finally there is no possible way to use this list directly within an XHTML page without accessing it through a managed bean.

Thanks to CDI, things become less complicated. First take a look at the simple Employee Class ( it could be as well an Entity in a real application ).

public class Employee {

    private String name;
    private String surname;
    private Long birthYear;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public Long getBirthYear() {
        return birthYear;
    }

    public void setBirthYear(Long birthYear) {
        this.birthYear = birthYear;
    }

    @Override
    public String toString() {
        return this.getSurname() + " " + this.getName();
    }
}

Now let’s get to some interesting parts. With CDI we can create our custom annotations and use them in our injected class exactly the same way as with predefined annotations. In our case we have created the following annotation to annotate an employee List.

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface EmployeeList {
}

But wait, the annotation itself is completely useless if there is no method that creates some how the employee list.  The ApplicationInitializationBean, shown just below includes a public method that returns an Employee list and this method is annotated with @Produces, @Named and @EmployeeList. All three annotations are very imporant and I explain why. By annotating a method with @Produces we have a producer method, that acts as a source of bean instances. The method declaration itself describes the bean and the container invokes the method to obtain an instance of the bean when no instance exists in the specified context. We can use it as well in a field.

@ApplicationScoped
public class ApplicationInitializationBean implements Serializable{

    private static final long serialVersionUID = 1L;

    @Produces
    @Named(value="employeeNamedList")
    @EmployeeList
    public List<Employee> getEmployees(){
        return this.generateEmployees();
    }

    private List<Employee> generateEmployees(){

        List<Employee> employees = new ArrayList<Employee>(5);

        for (int i=1 ; i<=5 ; i++){
            Employee emp = new Employee();
            emp.setName("Name_" + i);
            emp.setSurname("Surname_" + i);
            emp.setBirthYear(Long.valueOf(1976) + i);
            employees.add(emp);
        }
        return employees;
    }
}

As you have noticed we have also used the named annotation and the custom @EmployeeList. Each one has its own purpose.
By using @Named we can access directly from any xhtml / jsf page the list with its provided name (in our case is employeeNamedList) as shown in the following example

<h:dataTable id="employeesTable" value="#{employeeNamedList}" var="employee">
<h:column>
<f:facet name="header">
<h:outputText value="Surname" />
</f:facet>
<h:outputText value="#{employee.surname}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{employee.name}"></h:outputText>
</h:column>
</h:dataTable>

By using @EmployeeList we can access from any other Bean the list with injection as follows

@Inject
@EmployeeList
List<Employee> employeeList;

As you can see we don’t care about who is responsible to hold the list, or even how is beeing populated. We just use its name ( in a jsf component or its custom annotation to inject it in a managed bean )

In conclusion, CDI provides a very powerful way to increase abstraction and have your code clear and readable. Of couse the above example is not the only use of a producer method and it is not limited only in lists. You can create producer methods for any kind of object you would like to inject in your application.

Thanks for reading this post and as always any comments are welcome and valuable!

P.S. You can find a working example of the above here

Posted in cdi, jsf, software | 6 Comments »

 
%d bloggers like this: