Only Software matters

Experiences in software development

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

About these ads

6 Responses to “Injecting Lists with CDI in Managed Beans and JSF compoments”

  1. Thanks for the excellent CDI content – keep up the good work!

  2. Andrew said

    While this example shows nicely how to use CDI, in practice this approach is a bit problematic. You will find that in a real world example that the employees will have been retrieved from a persistence context. Injecting these into another bean undoubtibly will cause them to become detached.
    Secondly, you do not need to declare your ApplicationInitializationBean as @ApplicationScoped in this case as you are not holding the list as a class member. Removing the annotation will cause the bean to be “Dependent scope”. Each time the list is injected the producer method will fire.

    • Hi Andrew,
      Thank you for reading this post and your helpful comments. In a real time application, it is true that your employees will be a list of entities and yes, they are going to be detached since you retrieve them in another been. Since you don’t have to persist them again this is not an issue though. If you only want to display them or assign an Employee entity as a reference to another entity ( i.e. ManyToOne attribute ) that is no problem. For the @ApplicationScoped declaration I think both ideas are still working. It depends on how you want to implement list initialization :-)
      Thanks again for posting your comments!!
      Regards

  3. JavaPins said

    Injecting Lists with CDI in Managed Beans and JSF compoments « Only Software matters…

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

  4. Excellent! Keep it up. :-D

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

 
Follow

Get every new post delivered to your Inbox.

Join 629 other followers

%d bloggers like this: