@ ApplicationScoped CDI bean y @PersistenceContext - ¿es seguro?


¿Es seguro hacer algo así con CDI?

@Named
@ApplicationScoped
public class DAO {

   @PersistenceContext
   private EntityManager entityManager;

}

Entiendo que EntityManager en sí mismo no es seguro para hilos, y por lo tanto no debe usarse en un contexto global compartido como @ApplicationScoped. Sin embargo, dado que el objeto inyectado con @PersistenceContext es en realidad una envoltura consciente de hilo alrededor de un EntityManager subyacente, ¿eso hace que esto esté bien?

He visto otras publicaciones sobre el tema, pero no he sido capaz de encontrar una respuesta autorizada para este caso específico. Para ejemplo:

Java CDI @PersistenceContext and thread safety

Parece que es seguro de usar con @Stateless, por ejemplo, pero no estoy seguro de si eso es debido a la forma en que @Stateless funciona, o debido a algo intrínseco a @PersistenceContext.

EDITAR La fuente de mi confusión es que el @PersistenceContext wrapper inyectado EntityManager parece ser consciente del hilo actual, con el fin de averiguar si ya hay una transacción en progreso. Así que tal vez soy confundir la conciencia del hilo con la seguridad del hilo y son dos cosas diferentes.

Author: Martijn Pieters, 2012-12-15

1 answers

Estoy bastante seguro de que en este caso CDI no crea un proxy contextual para el entity manager. Después de todo, ¿en qué ámbito estaría? Es posible que desee algo similar a un hipotético @ThreadScoped o simplemente @RequestScoped, pero @PersistenceContext no es una anotación CDI y CDI no modifica su semántica.

Así que lo que está sucediendo aquí es la inyección de Java EE 6 platform "managed bean", que es similar a inyectar el entity manager en un Servlet. Ambos casos le dan una instancia que no es segura para el uso de subprocesos directamente.

Parece que es seguro usarlo con @Stateless, por ejemplo, pero no estoy seguro de si eso es debido a la forma en que funciona @Stateless, o debido a algo intrínseco al propio @PersistenceContext.

Es por la forma en que @Stateless funciona. Cada petición (llamada) a un método en un bean sin estado es enrutada por el contenedor a una instancia única. El contenedor garantiza que no haya dos hilos activos en el mismo frijol.

Con CDI se puede obtener un efecto similar por solicitud encapsulando el entity manager en un bean con ámbito de solicitud e inyectándolo en el ámbito de 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 entity manager:

@Named
@ApplicationScoped
public class DAO {

   @Inject
   private EntityManagerProvider entityManagerProvider;

}

Esto le dará un administrador de entidad único por solicitud. Usted puede fácilmente convertir esto en un método productor, así, por lo que no tendrá que llamar getEntityManager() en el proveedor inyectado.

 24
Author: Arjan Tijms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-15 14:47:31