Using CDI to manage EJB dependencies

weld tutorial @alternatives qualifierIn this tutorial we will illustrate how to use CDI to choose between different EJB implementation at deployment time, or at injection point.

 

 

 

CDI stands for Context Dependency Injection and can be used to for injecting Context and Dependencies into your application. This concept is not at all new for Java developers. Spring developers for example use dependencies by naming beans and binding them to their injection points by their names.
Although Spring is the major player in this field, what makes particularly attractive CDI is that it's part of the Java EE 6 stack, thus any container which is Java EE 6 compatible can run an application using CDI.

If you want to have an introduction to CDI you can look at this former tutorial.

In this one, we will show how you can choose between two different EJB implementations using CDI. Supposing you have a Java EE 6 application which has got two different EJB to handle a cache of keys/values.

    
package com.packtpub.chapter4.ejb;
 
import java.util.List;
import com.packtpub.chapter4.entity.Property;

public interface SingletonBean {
 
 public void initCache();

 public void delete();
 
 public void put(String key,String value);
 
 public List<Property> getCache();
 
}

And the two different EJB implementation classes:

This is SingletonBeanDB which persists the cache on the database (although cache is queried only once at startup. Subsequent calls use an in-memory List. Yet this optimisazion is just a detail for our example):
    
package com.packtpub.chapter4.ejb;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.packtpub.chapter4.entity.Property;

@Singleton
public class SingletonBeanDB implements SingletonBean {

 private List<Property> cache;
 @PersistenceContext(unitName = "persistenceUnit")
 private EntityManager em;

 @PostConstruct
 public void initCache() {
   System.out.println("Inited DB Cache");
   this.cache = queryCache();
   if (cache == null) cache = new ArrayList<Property>();
 }

 public void delete() {
   Query query = em.createQuery("delete FROM com.packtpub.chapter4.entity.Property");
   query.executeUpdate();
    this.cache.clear();
 }

 public void put(String key, String value) {
   Property p = new Property();
   p.setKey(key);
   p.setValue(value);
   em.persist(p);

   this.cache.add(p);
 }

 public List<Property> getCache() {
   return cache;
 }

 private List<Property> queryCache() {
   Query query = em.createQuery("FROM com.packtpub.chapter4.entity.Property");

   List<Property> list = query.getResultList();
   return list;
 }

}

And this is SingletonBeanMemory which stores in memory the cache of keys-values:
    
package com.packtpub.chapter4.ejb;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import com.packtpub.chapter4.entity.Property;


@Singleton
public class SingletonBeanMemory implements SingletonBean   {

 private  List<Property> cache;
 @PersistenceContext(unitName = "persistenceUnit")
 private EntityManager em;
 
 @PostConstruct
 public void initCache(){
   System.out.println("Inited Memory Cache");
   cache = new ArrayList<Property>();
 }

 public void delete(){
   this.cache.clear();
 }
 public void put(String key,String value){
   Property p = new Property();
   p.setKey(key);
   p.setValue(value);

   this.cache.add(p);
 }
 public List<Property> getCache() {
   return cache;
 }

}


Have you noticed the com.packtpub.chapter4 package ? as a matter of fact this example extends one other example found in JBoss AS 7 book at chapter 4

The Property class is a basic Entity which will be used to map a corresponding table on the DB:
    
package com.packtpub.chapter4.entity;

import javax.persistence.*;

@Entity
public class Property {

 @Id( )
 @Column(name="id")
 private String key;
 
 @Column(name="value")
 private String value;

 // getter/setter omitted for brevity

}


And this is the JSF Bean which wires the front-end to the EJBs. As you can see there is a tight dependency with one EJB in the init() method of the Bean:
    
package com.packtpub.chapter4.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import javax.inject.Named;

import com.packtpub.chapter4.ejb.SingletonBean;
import com.packtpub.chapter4.ejb.SingletonBeanDB;

@Named(value="manager")
@SessionScoped
public class PropertyManager implements Serializable {

 SingletonBean ejb;
 
 @PostConstruct
 public void init() {
   // Tight dependency with the SingletonBeanDB
   ejb = new SingletonBeanDB();
 }
 ArrayList  cacheList  = new ArrayList ();

 private String key;
 private String value;

 // Getters and Setters omitted for brevity
 
 public void save(ActionEvent e) {
   ejb.put(key, value);
 }

 public void clear(ActionEvent e) {
   ejb.delete();
 }
 public List getCacheList() {
   return ejb.getCache();
 }


 public void get(ActionEvent e) {
   String msg = "Added key = " + key;
   FacesContext.getCurrentInstance().addMessage(null,
       new FacesMessage(FacesMessage.SEVERITY_WARN, msg, null));

 }
}

Follow us on Twitter