Ein EJB in ein dynamisch zugeordnetes Servlet einfügen

8

Ich habe einen Filter, in dem ich Servlet-Klassen dynamisch abdecke:

%Vor%

Wenn ich dann auf ein gegebenes Mapping zugreife, wird das EJB nicht injiziert.

%Vor%

Wenn ich manuell ein Mapping in der web.xml erzeuge, funktioniert das angegebene EJB in diesem Servlet. Ich frage mich, ob die Tatsache, dass ich die Servlets zur Laufzeit des Containers registriere, diese Servlets nicht als verwaltet ansehe.

Wenn das der Fall ist, was ist der richtige Weg, die EJBs in meine Servlets zu injizieren, ohne die Art und Weise zu ändern, wie sie über den Filter dynamisch registriert werden?

Ist via JNDI die einzige Möglichkeit, meine EJBs zu injizieren?

EDIT 1: Ich habe versucht, eine ServletContextListener -Klasse wie von "Will" vorgeschlagen mit dem folgenden Code in der web.xml :

zu implementieren %Vor%

Und der relevante Teil der Implementierung:

%Vor%

Leider lässt der Container die EJBs nicht injizieren und der Nullzeiger bleibt. Ich mache derzeit einen benutzerdefinierten Typ sichere JNDI Lookup für den Dienst. Offensichtlich ist das viel teurer als die richtige Injektion (korrigiere mich, wenn ich falsch liege, habe noch keine Experimente bezüglich der Leistung gemacht).

Verwendung:
Java EE 6
JBoss AS 7.1

    
Fagner Brack 05.05.2013, 22:49
quelle

3 Antworten

3

Das Problem scheint mit diesem gemeldeten Fehler zu tun zu haben, der noch nicht behoben ist. Die Ressourcenauflösung eignet sich für Managed Beans gemäß der JSF-Spezifikation, nicht jedoch für CDI Managed Beans. Einfach die dynamischen Servlet-Klassen mit @javax.faces.bean.ManagedBean annotieren, sollte das Problem beheben (ja, es ist eine ziemlich hässliche Lösung):

%Vor%

Getestet mit JEE6 (ofc) und JBoss 7.1.1 und 7.2.0 (EAP 6.1.0 Alpha).

Bearbeiten :

Das Problem mit dynamisch gemappten Servlets ist ziemlich tief in der JBoss-Basisarchitektur. Sie verwenden JBossWeb (eine gegabelte Version von Tomcat) als Servlet-Implementierung, und in den Innereien des Kontextmanagement-Codes wird festgelegt, ob neue Komponenten durch Injektion oder regulär neu instanziiert werden. Afaik ab dem Datum, Ihre Servlets müssten in irgendeiner Weise kommentiert werden, damit sie durch Injektion verarbeitet werden: Ich hatte @ManagedBean in meiner ursprünglichen Antwort erwähnt, aber es sieht so aus, als ob Annotationen mit @WebServlet ebenfalls funktionieren.

    
Perception 08.05.2013, 14:35
quelle
3

Servlet 3.0 Spezifikation, Sekt. 4.4.3.5

Ressourceninjektion [z.B. @EJB] für alle Komponenten (Servlets, Filter und Listener) hinzugefügt programmatisch oder programmgesteuert erstellt, andere als die, die über die Methoden, die eine Instanz verwenden, wird nur unterstützt, wenn die Komponente a ist Managed Bean . Einzelheiten zu einer Managed Bean finden Sie in der Managed Bean-Spezifikation als Teil von Java EE 6 und JSR 299 definiert.

Verwaltete Bean-Deklaration

Eine Java EE 6-verwaltete Bean ist mit @javax.annotation.ManagedBean versehen und hat einen Konstruktor ohne Argumente. Eine JSR 299 (CDI) -verwaltete Bean benötigt lediglich einen no-arg-Konstruktor oder einen mit @javax.inject.Inject annotierten Konstruktor.

Antwort

Um die Ressourceninjektion zu aktivieren, müssen Sie:

  • place @ManagedBean Annotation auf dynamisch hinzugefügtes Servlet

    ODER

  • aktivieren CDI & amp; Fügen Sie ein leeres beans.xml

  • ein

Bearbeiten

Obwohl Sie das Servlet dynamisch erstellen, ist es wichtig, dass der Container die Erstellung durchführt. Denken Sie nicht, dass die Erstellung in ServletContext die Injektion unterstützt. Servlet Doc ist hier sehr vage.

Mit CDI versuchen:

%Vor%     
Glen Best 08.05.2013 01:25
quelle
0

Erstens funktionierte das in meinem Test mit einer Version von Glassfish V3.

Aber, zweitens, könnten Sie mit dieser Klausel der Spezifikation Servlet 3.0 in Konflikt geraten.

  

Die folgenden Methoden wurden dem ServletContext seit Servlet 3.0 hinzugefügt   Aktivieren Sie die programmatische Definition von Servlets, Filtern und der URL   Muster, denen sie zuordnen. Diese Methoden können nur während der   Initialisierung der Anwendung entweder von der contexInitialized   Methode einer ServletContextListener-Implementierung oder von der   onStartup-Methode einer ServletContainerInitializer-Implementierung.

Insbesondere können diese Methoden NICHT von einer Filter.init() Methode aufgerufen werden. Ich habe das ursprünglich in einer Servlet.init() -Methode versucht, und die init -Methode ist fehlgeschlagen, weil der Kontext bereits initialisiert wurde.

Also, mein Experiment hat Ihren Test nicht exakt dupliziert - ich habe dafür keine Filter.init() -Methode verwendet, stattdessen habe ich den Code in ServletContextListener eingefügt. Und als ich das gemacht habe, wurde meine @EJB Annotation geehrt.

Bearbeiten:

So wenig hilfreich es klingt, ich würde vorschlagen, dass dies ein Bug in JBoss ist. Als ich anfänglich den ursprünglichen Code mit der Injektion aus dem Filter ausprobierte, warf Glassfish eine Ausnahme auf, da es dir nicht erlaubt ist, die Injektion dort zu speichern, wo ich bereits erwähnt habe. Nun, vielleicht ist das ein "zusätzliches Feature" von JBoss, aber anscheinend funktioniert die @ EJB-Injektionsverarbeitung einfach nicht. Laut Spezifikation sollte dies wie angekündigt funktionieren.

    
Will Hartung 06.05.2013 05:02
quelle

Tags und Links