2010-03-08 2 views
6

Wir haben eine staatenlose JavaE5-EJB-Bean, die den injizierten EntityManager an seine Helfer weiterleitet.Ist es in Ordnung, injizierte EntityManager an die Hilfsklassen von EJB Bean zu übergeben und sie zu benutzen?

Ist das sicher? Es hat bis jetzt gut funktioniert, aber ich habe ein Oracle-Dokument gefunden, das besagt, dass die Implementierung von EntityManager Thread-sicher ist. Jetzt frage ich mich, ob der Grund, warum wir bis jetzt keine Probleme hatten, nur darin lag, dass die Implementierung, die wir verwendeten, Thread-sicher war (wir verwenden Oracle).

@Stateless 
class SomeBean { 
    @PersistenceContext 
    private EntityManager em; 

    private SomeHelper helper; 

    @PostConstruct 
    public void init(){ 
     helper = new SomeHelper(em); 
    } 

    @Override 
    public void business(){ 
     helper.doSomethingWithEm(); 
    } 

} 

Eigentlich ist es sinnvoll .. Wenn EntityManager faden unsicher ist, wäre ein Container

inercept business() 
this.em = newEntityManager(); 
business(); 

, die an seine Hilfsklassen propagieren nicht zu tun haben.

Wenn ja, was ist die beste Vorgehensweise in dieser Art von Situation? EntityManagerFactory anstelle von EntityManager übergeben?

EDIT: This question ist sehr interessant, wenn Sie also in dieser Frage interessiert sind, haben Sie wahrscheinlich diese prüfen wollen, auch:

EDIT: Mehr Info. ejb3.0 spec

4.7.11 nichtablaufinvarianten Instances muss der Behälter sicherzustellen, dass nur ein Thread eine Instanz bei jederzeit ausführen können. Wenn eine Clientanforderung für eine Instanz eintrifft, während die Instanz eine andere Anforderung ausführt, kann der Container die javax.ejb.ConcurrentAccessException an den zweiten Client [24] werfen. Wenn die Ansicht EJB 2.1 -Client verwendet wird, kann der Behälter die java.rmi.RemoteException zu wirft die zweite Anforderung, wenn der Kunde ein Remote-Client ist, oder die javax.ejb.EJBException, wenn der Kunde ein lokal Kunde. [25] Beachten Sie, dass ein -Sitzungsobjekt nur einen einzigen Client unterstützen soll . Daher wäre ein Anwendungsfehler, wenn zwei Clients versuchten, dasselbe Sitzungsobjekt aufzurufen. Eine Implikation von diese Regel besteht darin, dass eine Anwendung keine Loopback-Aufrufe an eine Session-Bean-Instanz vornehmen kann.

Und

4.3.2 Dependency Injection Eine Session-Bean Dependency Injection Mechanismen verwenden kann Hinweise auf Ressourcen oder andere Gegenstände in seiner Umgebung (siehe Kapitel 16, zu erwerben "Enterprise Bean-Umgebung"). Wenn eine Session Bean Verwendung der Abhängigkeit Injektion macht, spritzt der Behälter diese Referenzen nach der Bean-Instanz ist erstellt, und vor jedem Geschäft Methoden basieren auf der Bohne Instanz aufgerufen.Wenn eine Abhängigkeit vom SessionContext deklariert ist oder wenn die Bean-Klasse die optionale SessionBean-Schnittstelle implementiert (siehe Abschnitt 4.3.5), wird zu diesem Zeitpunkt auch der SessionContext eingefügt. Wenn die Abhängigkeit Injektion fehlschlägt, wird die Bean-Instanz verworfen. Unter der EJB 3.0-API kann die Bean-Klasse die SessionContext-Schnittstelle über Dependency Injection erfassen, ohne die SessionBean-Schnittstelle implementieren zu müssen ( ). In diesem Fall wird die Ressourcenannotation (oder ressource-env-ref deployment Deskriptorelement) verwendet, um die Bean-Abhängigkeit vom SessionContext zu bezeichnen. Siehe Kapitel 16, "Enterprise Bean-Umgebung".

+0

Jetzt ist das interessant "Die EJB 3.1 Spezifikation besagt, dass Abhängigkeitsinjektion nur zur Konstruktionszeit durchgeführt wird, so dass alle Aufrufer von MyRepository die gleiche Instanz von EntityManager verwenden würden." : http: //stackoverflow.com/questions/2015184/how-is-threadsafty-guranteed-with-persistencecontext –

+0

FYI, lesen Sie auch § 4.1.13, oder sehen Sie diese Antwort http: // stackoverflow.com/questions/1954137/Wie-ist-das-Instanz-Pooling-mit-ejbs-kann-verbessern-Leistung/1954229 # 1954229. So wird auf jeden Helfer jeweils nur ein Thread zugegriffen. – ewernli

+0

Dies ist genau das Muster, das ich implementieren wollte. Ich bin sehr glücklich zu sehen, dass es möglich ist. Guter Eintrag. Vielen Dank. – b3bop

Antwort

2

Ich verwendete ein ähnliches Muster, aber der Helfer wurde in erstellt und der injizierte Entity Manager wurde im Konstruktor als Parameter übergeben. Jede EJB-Instanz hatte ihren eigenen Helfer und Thread-Sicherheit war dann garantiert.

Ich hatte auch eine Variante, wo der Entity-Manager nicht injiziert wurde (weil der EJB es nicht ganz benutzte), also muss der Helfer es mit InitialContext nachschlagen. In diesem Fall muss die Persistenz Kontext noch mit @PersistenceContext in der übergeordneten EJB „importiert“ werden:

@Stateless 
@PersistenceContext(name="OrderEM") 
public class MySessionBean implements MyInterface { 
    @Resource SessionContext ctx; 
    public void doSomething() { 
    EntityManager em = (EntityManager)ctx.lookup("OrderEM"); 
    ... 
    } 
} 

Aber es ist tatsächlich einfacher, es zu injizieren (auch wenn die EJB es nicht verwenden), als es zu sehen insbesondere für die Testbarkeit.

Aber um zu Ihrer Hauptfrage zurückzukehren, denke ich, dass der Entity Manager, der injiziert oder nachgeschlagen wird, ein Wrapper ist, der an den zugrunde liegenden aktiven Entity Manager weiterleitet, der an die Transaktion gebunden ist.

Ich hoffe, es hilft.

EDIT

Der Abschnitt § 3.3 und § 5.6 in der spec decken das Thema ein wenig.

+0

Danke, ich bin froh zu hören, dass wir unseren Produktionscode nicht durchforsten müssen! –

2

Ich habe mit Helfer Methoden und bestehen die EntityManager dort, und es ist völlig in Ordnung.

So würde ich empfehlen, entweder Methoden an Methoden, wann immer erforderlich, oder machen Sie den Helfer eine Bohne selbst, injizieren Sie es (unter Verwendung @EJB) und injizieren Sie die EntityManager dort auch.

+0

Helper Methoden klingt wirklich einfach und gut. Vielen Dank! –

0

Nun, persönlich möchte ich nicht den Entity Manager an alle meine POJOs in meinen Konstruktoren oder Methoden weitergeben müssen. Insbesondere für nicht-triviale Programme, bei denen die Anzahl der POJOs groß ist.

Ich würde versuchen, POJOs/HelperClasses zu erstellen, die mit den Entities arbeiten, die vom EntityManager zurückgegeben werden, anstatt den Entitymanager direkt zu verwenden.

Wenn nicht möglich, würde ich wahrscheinlich eine neue EJB Bean erstellen.