@ApplicationScoped CDI bean et @PersistenceContext - est-ce sûr?

Est-il sécuritaire de faire quelque chose comme ceci avec le CDI?

@Named
@ApplicationScoped
public class DAO {

   @PersistenceContext
   private EntityManager entityManager;

}

je comprends que EntityManager lui-même n'est pas thread-safe, et ne devrait donc pas être utilisé dans un contexte mondial partagé comme @ApplicationScoped . Cependant, puisque l'objet injecté avec @PersistenceContext est en fait un enveloppement filaire autour d'un EntityManager sous-jacent , est-ce que cela rend cela correct?

j'ai vu d'autres messages sur le sujet mais n'ont pas été en mesure de comprendre une réponse qui fait autorité dans ce cas précis. Par exemple:

Java CDI @PersistenceContext et la sécurité des threads

on dirait qu'il est sûr à utiliser avec @Stateless , par exemple - mais je ne suis pas sûr si c'est à cause de la façon dont @Stateless fonctionne, ou à cause de quelque chose intrinsèque à @PersistenceContext lui-même.

EDIT La source de ma confusion est que le @PersistenceContext injected EntityManager wrapper semble être conscient du fil courant, afin de déterminer s'il y a déjà une transaction en cours. Donc peut-être que je confonds la conscience du fil avec la sécurité du fil et ce sont deux choses différentes.

26
demandé sur Martijn Pieters 2012-12-15 00:38:54

1 réponses

je suis assez sûr que dans ce cas le CDI ne crée pas de mandataire contextuel pour le gestionnaire d'entité. Après tout, dans quelle portée serait-elle? Vous pouvez vouloir quelque chose qui s'apparente à une hypothétique @ThreadScoped ou tout simplement @RequestScoped , mais @PersistenceContext n'est pas une annotation CDI et le CDI ne modifie pas sa sémantique.

donc ce qui se passe ici est la plateforme Java EE 6" managed bean " injection, qui est similaire à l'injection du gestionnaire d'entité dans un Servlet. Les deux cas donner vous avez une instance qui n'est pas thread-safe à utiliser directement.

on dirait que c'est sûr à utiliser avec @Stateless, par exemple - mais je ne suis pas sûr que ce soit à cause de la façon dont @Stateless fonctionne, ou à cause de quelque chose d'intrinsèque à @PersistenceContext lui-même.

c'est à cause de la façon dont @Stateless fonctionne. Chaque appel à une méthode sur un stateless bean est acheminé par le conteneur à une instance unique. Conteneur garantit qu'il n'y a jamais deux fils actifs dans la même fève.

avec CDI Vous pouvez obtenir un effet similaire par requête en encapsulant le gestionnaire d'entité dans une fève de requête scoped et en injectant cela dans l'application scoped one:

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;
    }

}

injectez ceci dans le haricot où vous avez précédemment injecté le directeur d'entité:

@Named
@ApplicationScoped
public class DAO {

   @Inject
   private EntityManagerProvider entityManagerProvider;

}

cela vous donnera un gestionnaire d'entité unique par demande. Vous pouvez facilement transformer cette dans une méthode de production aussi bien, de sorte que vous n'aurez pas à appeler getEntityManager() sur le fournisseur injecté.

24
répondu Arjan Tijms 2012-12-15 14:47:31