使用CDI注入PersistenceContext

时间:2014-12-16 14:18:37

标签: java java-ee glassfish ejb cdi

目前,我正在使用PersistenceContext注入EntityManager。 EM被完美地注入。

@Stateless
public StatelessSessionBean implements StatelessSessionBeanLocal {

    @PersistenceContext(unitName = "MyPersistenceUnit")
    private EntityManager em;

    @Override
    public Collection<MyObject> getAllObjects(){
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriqQuery<MyObject> query = cb.createQuery(MyObject.class);
        query.from(MyObject);
        return em.createQuery(query).getResultList();
    }
}

现在我尝试装饰豆子,突然间em不会被注射。我得到一个NullPointerException。

@Decorator
public StatelessSessionBeanDecorator implements StatelessSessionBeanLocal {

    @Inject
    @Delegate
    @Any
    StatelessSessionBeanLocal sb

    @Override
    public Collection<MyObject> getAllObjects(){
        System.out.println("Decorated method!");
        return sb.getAllObjects();
    }
}

我知道EJB和CDI是两个完全不同的管理器,所以那个人不了解另一个。我期望@PersistenceContext是一个EJB注入点,而@Inject是一个CDI注入点。我该怎么做才能解决这个问题并让EntityManager按照它应该注入?

2 个答案:

答案 0 :(得分:9)

持久化上下文和CDI的最佳实践是使它们成为CDI bean以避免这类问题。

public class MyProducers {
    @Produces
    @PersistenceContext(unitName = "MyPersistenceUnit")
    private EntityManager em;
}

之后,您将能够以CDI方式注入EntityManager。拿你的EJB吧:

@Stateless
public StatelessSessionBean implements StatelessSessionBeanLocal {

    @Inject
    private EntityManager em;

    @Override
    public Collection<MyObject> getAllObjects(){
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriqQuery<MyObject> query = cb.createQuery(MyObject.class);
        query.from(MyObject);
        return em.createQuery(query).getResultList();
    }
}

这样,您就可以毫无问题地装饰CDI。

如果您有多个EntityManagers,则可以使用CDI限定符来区分它们

答案 1 :(得分:2)

  

@PersistenceContext是一个EJB注入点,而@Inject是一个CDI注入点

实际上,没有。 @PersistenceContext注释可以在CDI中使用,并且不与EJB连接。你可以这样做:

@Named
public class EntityDAO {
    @PersistenceContext
    private EntityManager manager;

    ...

}

EJB使用@EJB注释来注入其他EJB,但它可以使用相同的注释注入任何CDI bean或持久化上下文。