Sunday, 13 November 2011

JavaEE revisits the Design Patterns: Dependency Injection

On dark days of J2EE, one of the highlights of Spring Framework was Dependency Injection (or Inversion of Control). Instead of highly complicated and error prone xml configurations and JNDI lookups, Spring offered an easier way of injecting resources (still with the help of xml until Spring 2.0).

JavaEE5 already introduced injection of EJBs via @EJB annotation but JavaEE6 takes this one step forward introducing CDI (Contexts and Dependency Injection). Actually CDI offers a wide range of possibilities (some you may see in following posts) including cdi extensions.

Lets start with seeing some DI in action. Although I have been familiar with JSF from first beta version, I have never been a quite fan of it and prefered either flex or gwt as the front end. However with JSF 2.0, everything is much simpler and tightly integrated with the backend. Just like the previous post, start with an empty JavaEE6 Web profile project in the IDE of your choice. With JSF 2.0 the web pages can be named with extension 'xhtml'. Start with creating a simple index.xhtml file in your web source folder with the following content.


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Trying Dependency Injection</title>
    </h:head> 
    <h:body>
        Expecting myModel to be injected!
        <h:form>
            <h:commandButton value="Ok" action="#{myModel.doEvent()}"/>
        </h:form>
    </h:body>
</html>


Although our backing bean is not there yet, this xhtml file is expecting a bean named myModel (which would be a class name of MyModel) and a method doEvent. Now we can continue with creating the backing bean. Navigate to the source folder of the project and create a class named MyModel.class.


package com.devchronicles.injection;


import javax.enterprise.inject.Model;
import javax.inject.Inject;
/**
 *
 * @author Murat
 */
@Model
public class MyModel {
    
    public Object doEvent(){
        return null;
    }      
}


This class will be the model for the xhtml page. Since the page has already defined the doEvent method of the injected bean for the action of the command button, every click will fire the doEvent method. Let's continue with adding some functionality to the doEvent method by calling startService from another service bean which would be injected to the model bean.


@Model
public class MyModel {
    
    @Inject
    EventService service;
            
    public Object doEvent(){
        service.startService();
        return null;
    }      
}


You may have noticed there is no new keyword and a constructor call for the EventService class which will be created and injected seamlessly by the time the model bean wants to use it.

Now it is time to add the stateless session EJB which our model bean will be using.


package com.devchronicles.injection;


import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.event.Event;
import javax.inject.Inject;
/**
 *
 * @author Murat
 */
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class EventService
    public void startService(){
        System.out.println("Doing something very important!!");
    }
}


You may deploy the war file on a test server and navigate to index.xhtml. By the time the page is displayed MyModel class is created and injected into the page which would call its doEvent method when the button is clicked. Also the EventService bean has been created and injected to the MyModel class, thus allowing the model to call startService method.

As you may noticed there is no single new keyword or any constructor call but the two classes has been created and injected by the time they were needed which would let you deal with the real programing work while the cdi is handling the creation.