java-ee - beans - javax inject example
@ApplicationScoped CDI bean y @PersistenceContext-¿esto es seguro? (1)
¿Es seguro hacer algo como esto con CDI?
@Named
@ApplicationScoped
public class DAO {
@PersistenceContext
private EntityManager entityManager;
}
Entiendo que EntityManager
sí mismo no es seguro para subprocesos y, por lo tanto, no se debe usar en un contexto global compartido como @ApplicationScoped
. Sin embargo, dado que el objeto inyectado con @PersistenceContext
es en realidad un contenedor consciente de hilos alrededor de un EntityManager
subyacente, ¿eso lo hace correcto?
He visto otras publicaciones sobre el tema, pero no he podido encontrar una respuesta autorizada para este caso específico. Por ejemplo:
Java CDI @PersistenceContext y seguridad de subprocesos
Parece que es seguro usarlo con @Stateless
, por ejemplo, pero no estoy seguro de si es por la forma en que funciona @Stateless
, o por algo intrínseco a @PersistenceContext
.
EDITAR El origen de mi confusión es que el @PersistenceContext
EntityManager
@PersistenceContext
inyectado parece conocer el hilo actual, para averiguar si ya hay una transacción en curso. Así que tal vez estoy confundiendo el conocimiento de hilos con seguridad de hilos y son dos cosas diferentes.
Estoy bastante seguro de que, en este caso, CDI no crea un proxy contextual para el administrador de entidades. Después de todo, ¿en qué ámbito sería? Puede querer algo parecido a un hipotético @ThreadScoped
o simplemente @RequestScoped
, pero @PersistenceContext
no es una anotación CDI y el CDI no modifica su semántica.
Entonces, lo que está sucediendo aquí es la inyección de la plataforma "Java Bean" de la plataforma Java EE 6, que es similar a inyectar el administrador de entidades en un Servlet. Ambos casos le dan una instancia que no es segura para la ejecución de subprocesos directamente.
Parece que es seguro usarlo con @Stateless, por ejemplo, pero no estoy seguro de si es por la forma en que funciona @Stateless, o por algo intrínseco a @PersistenceContext.
Es por la forma en que funciona @Stateless
. Cada solicitud (llamada) a un método en un bean sin estado es enrutada por el contenedor a una instancia única. El contenedor garantiza que no hay dos subprocesos activos en el mismo bean.
Con CDI puede obtener un efecto similar por solicitud encapsulando el administrador de entidades en un bean con ámbito de solicitud e inyectándolo en el ámbito de la aplicación:
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@RequestScoped
public class EntityManagerProvider {
@PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
}
Inyecte esto en el bean donde previamente inyectó el administrador de la entidad:
@Named
@ApplicationScoped
public class DAO {
@Inject
private EntityManagerProvider entityManagerProvider;
}
Esto le dará un administrador de entidad único por solicitud. También puede convertir esto fácilmente en un método productor, por lo que no tendrá que llamar a getEntityManager()
en el proveedor inyectado.