I'm using Java EE 7. I would like to know what is the proper way to inject a JPA EntityManager
into an application scoped CDI bean. You can't just inject it using @PersistanceContext
annotation, because EntityManager
instances are not thread safe. Let's assume that we want our EntityManager
to be created at the beginnig of every HTTP request processing and closed after the HTTP request is processed. Two options come into my mind:
1.
Create a request scoped CDI bean which has a reference to an EntityManager
and then inject the bean into an application scoped CDI bean.
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@RequestScoped
public class RequestScopedBean {
@PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
}
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
@ApplicationScoped
public class ApplicationScopedBean {
@Inject
private RequestScopedBean requestScopedBean;
public void persistEntity(Object entity) {
requestScopedBean.getEntityManager().persist(entity);
}
}
In this example an EntityManager
will be created when the RequestScopedBean
is created, and will be closed when the RequestScopedBean
is destroyed. Now I could move the injection to some abstract class to remove it from the ApplicationScopedBean
.
2.
Create a producer that produces instances of EntityManager
, and then inject the EntityManager
instance into an application scoped CDI bean.
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class EntityManagerProducer {
@PersistenceContext
@Produces
@RequestScoped
private EntityManager entityManager;
}
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
@ApplicationScoped
public class ApplicationScopedBean {
@Inject
private EntityManager entityManager;
public void persistEntity(Object entity) {
entityManager.persist(entity);
}
}
In this example we will also have an EntityManager
which is created every HTTP request, but what about closing the EntityManager
? Will it also be closed after the HTTP request is processed? I know that the @PersistanceContext
annotation injects container-managed EntityManager
. This means that an EntityManager
will be closed when a client bean is destroyed. What is a client bean in this situation? Is it the ApplicationScopedBean
, which will never be destroyed until the application stops, or is it the EntityManagerProducer
? Any advices?
I know I could use a stateless EJB instead of application scoped bean and then just inject EntityManager
by @PersistanceContext
annotation, but that's not the point :)