Wednesday, March 18, 2015

Contexts and Dependency Injection (CDI) - Eager Extension

CDI does not provide eager extensions out of the box. Even though there is @ApplicationScoped that is intended to work in a similar way to eager instantiation - It does not behave in the specified fashion. 

I am going to describe how to use CDI extensions to get eagerly instantiated beans following the CDI lifecycle, inside the container. I have used this in Wildfly 8.0. 


Step 1: First, write the @Eager Annotation
 package me.sumithpuri.test.cdi.annotation;  
 import java.lang.annotation.ElementType;  
 import java.lang.annotation.Retention;  
 import java.lang.annotation.RetentionPolicy;  
 import java.lang.annotation.Target;  
 import javax.inject.Qualifier;  
 @Qualifier  
 @Retention(RetentionPolicy.RUNTIME)  
 @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})  
 public @interface Eager  
 {  
 }  

Step 2: Next, develop the Eager Extension to parse the Annotations.
 package me.sumithpuri.test.cdi.extension;  
 import java.util.ArrayList;  
 import java.util.List;  
 import javax.enterprise.context.ApplicationScoped;  
 import javax.enterprise.event.Observes;  
 import javax.enterprise.inject.spi.AfterDeploymentValidation;  
 import javax.enterprise.inject.spi.Bean;  
 import javax.enterprise.inject.spi.BeanManager;  
 import javax.enterprise.inject.spi.Extension;  
 import javax.enterprise.inject.spi.ProcessBean;  
 import me.sumithpuri.test.cdi.annotation.Eager;  
 public class EagerExtension implements Extension {  
   private List<Bean<?>> eagerBeansList = new ArrayList<Bean<?>>();  
   public <T> void collect(@Observes ProcessBean<T> event) {  
     if (event.getAnnotated().isAnnotationPresent(Eager.class)  
       && event.getAnnotated().isAnnotationPresent(ApplicationScoped.class)) {  
          System.out.println("debug: found an eager annotation");  
       eagerBeansList.add(event.getBean());  
     }  
   }  
   public void load(@Observes AfterDeploymentValidation event, BeanManager beanManager) {  
     for (Bean<?> bean : eagerBeansList) {  
          System.out.println("debug: eager instantiation will be performed - " + bean.getBeanClass());  
       // note: toString() is important to instantiate the bean  
       beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean)).toString();  
     }  
   }  
 }  

Step 3: Next, configure the extension, using this single line of code, placed inside META-INF/services/javax.enterprise.inject.spi.Extension
 me.sumithpuri.test.cdi.extension.EagerExtension  

Step 4: Develop other parts of the application 
You can refer to the attached code to develop other parts of the application to test CDI (@Eager)

You may download the code from here. Also, note that even though all lifecycle methods are performed such @PostConstruct, @PreDestroy, etc. - no @Inject is being performed. My assumption is that we have to write another extension to perform this. My request to the CDI creators to provide an @Eager out of the box, so that it can help to develop (and sometime help in test) applications where Dependency Injection can be performed outside of Servlets, Web Services, etc.

[credits to: http://ovaraksin.blogspot.in/2013/02/eager-cdi-beans.html]

No comments: