qualifier example beans application java-ee jpa java-ee-6 cdi

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.