CDI-Injektion funktioniert nicht in Servlets

8

Ich brauche wirklich deine Hilfe. Ich arbeite jetzt seit Wochen oder Monaten an diesem Problem. Ich entschuldige mich für den langen Post, aber ich möchte das Problem und meine Einstellungen so genau wie möglich erklären.

Meine JAVA EE 6-Webanwendung enthält hauptsächlich drei Servlets: ein javax.faces.webapp.FacesServlet , ein StreamingServlet, das javax.servlet.http.HttpServlet erweitert, und ein ClientServlet Erweitern von org.eclipse.jetty.websocket.WebSocketServlet . Ich möchte CDI mit diesen Servlets verwenden, aber es funktioniert nur für das FacesServlet, genauer gesagt, für die Beans, zu denen die JSF-Aktionen geroutet werden. CDI-Injektion funktioniert nicht mit den anderen 2 Servlets.

Das Setup für mein Projekt ist wie folgt: Maven 3.0.4, Jetty 8.1.4 (jetty-maven-plugin), MyFaces 2.1.6, Weld 1.1.8.

Die Datei pom.xml enthält die Abhängigkeiten für CDI:

%Vor%

Die Datei src / main / webapp / WEB-INF / beans.xml enthält nur ein leeres beans-Element zum Aktivieren von CDI:

%Vor%

Die Datei scr / main / webapp / WEB-INF / jetty-env.xml enthält die Jetty-spezifische Konfiguration zum Abrufen des Bean-Managers über JNDI:

%Vor%

Die Datei src / main / webapp / WEB-INF / web.xml enthält den Servlet-Listener und die BeanManager-Referenz für das Bootstrapping von CDI:

%Vor%

Mit diesen Einstellungen habe ich immer den folgenden Fehler erhalten, wenn ich die Anwendung mit mvn jetty ausführen: run (erste Zeile ist am wichtigsten):

%Vor%

Die Anwendung wurde ausgeführt, aber die Ausnahmebedingungsnachricht besagt: CDI-Injektion ist in Servlets nicht verfügbar.

Vor ein paar Tagen fand ich den Artikel Starten einer CDI-Webapp von Maven mit Weld-Servlet und Jetty-Plugin und speziell dem Abschnitt Letzter Trick, um die Injektion in Servlets zu ermöglichen . Der Autor erklärt, dass Weld einige interne Jetty-Klassen dekorieren muss, um die @Inject-Annotation in Servlets zu verwenden, und dass wir dem Jetty-Classloader mitteilen müssen, wo diese Klasse zu finden ist, damit das Weld-Servlet sie dekorieren kann.

>

Ich habe so lange auf diese spezielle Information gewartet. Also habe ich die Datei src / main / webapp / WEB-INF / jetty-context.xml hinzugefügt:

%Vor%

Ich habe auch die pom.xml aktualisiert, um die Datei jetty-context.xml (letzte Zeile) einzubinden:

%Vor%

Nun ist der obige Fehler verschwunden. Ich war so glücklich für diesen kurzen Moment:)

In src / main / resources / log4j.properties habe ich den Log-Level für Weld erhöht:

%Vor%

Beim Starten der Anwendung erhalte ich die folgenden Schweißprotokollmeldungen:

%Vor%

Ich verwende die Servlet 3.0 API , das StreamingServlet und das ClientServlet werden über Annotationen konfiguriert. Das Problem besteht darin, dass die Anwendungsbereichsbeans connectionTable und dataReader nicht injiziert werden:

%Vor%

Aufruf der (nicht) injizierten Eigenschaften, ich bekomme immer NullPointerExceptions. Das Problem bleibt auch beim Konfigurieren der Servlets über web.xml bestehen. Ich habe keine Ideen mehr darüber, was ich falsch mache. Wenn ich alle Artikel über CDI in Verbindung mit Jetty und Maven lese, frage ich mich, ob ich der Einzige bin, der diese Injektionsprobleme hat.

In meiner JSF-Bean-Klasse UserBean.java muss die Injektion funktionieren, ich muss keine Setter-Methoden für die Eigenschaften connectionTable und dataReader verwenden, die initialisiert werden sollen.

Verwenden Sie die folgenden output-Anweisungen im DataReader-Konstruktor (und auch in der ConnectionTable-Klasse)

%Vor%

Ich wundere mich über die 2 DataReader-Instanzen, die auf stdout angezeigt werden:

%Vor%

Die ersten fünf Zeilen werden nach der formularbasierten Authentifizierung gedruckt, und die letzten zwei Zeilen werden angezeigt, wenn meine JSF-Aktion zum ersten Mal behandelt wird, wenn die injizierte Eigenschaft "dataReader" verwendet wird. Da die Beans Anwendungsbereiche sind, frage ich mich wirklich nach den 2 Konstruktor-Pässen. Aber aus dem Verhalten der Anwendung, denke ich, ist nichts falsch daran.

Meine letzte Annahme ist, dass die Servlets irgendwie in getrennten, unabhängigen Kontexten oder Containern oder so ähnlich leben. Weil es auch nicht möglich ist, den FacesContext in den 2 anderen Servlets zu erhalten: FacesContext.getCurrentInstance () ergibt null . Aber ich weiß nicht, ob das irgendwie wichtig ist.

Ich hoffe, dass mir jemand helfen kann, das Problem zu lösen. Vielen Dank im Voraus

Sebastian

    
Sebastian S. 31.07.2012, 12:42
quelle

4 Antworten

6

Hm ... Ihre Konfiguration sieht mir sehr ähnlich. Was ich nicht wusste, war dieses "Java-Web-Api" -Maven-Artefakt. Ich habe das in einem neuen Projekt überprüft und voila ... es funktioniert. Dann habe ich sukzessive Unterstützung für JSF und WebSocket hinzugefügt und es hat nicht mehr funktioniert. Schließlich habe ich herausgefunden, was der Fehler war: Ich habe das 'Jetty-Server'-Artefakt als eine Abhängigkeit zu meiner pom.xml hinzugefügt, aber ich habe keinen Bereich festgelegt. Also benutzte ich die falschen Server-Bibliotheken oder so etwas. Jetzt bei Verwendung des 'bereitgestellten' Bereichs

%Vor%

scheint alles zu funktionieren und die Abhängigkeitsinjektion funktioniert auch in Servlets.

Ich habe zwei weitere Fragen zu Ihrem Pom:

  1. Müssen Sie nicht die & lt; jettyEnvXml & gt; Element des Jetty Maven Plugins?

  2. Wieder im Jetty Maven Plugin verwenden Sie die & lt; webAppConfig & gt; Element. Ich habe die & lt; webApp & gt; Element, weil dies durch die Eclipse-Code-Vervollständigung bekannt ist. Ist eines dieser Elemente für das andere veraltet?

Sebastian S. 04.09.2012, 17:03
quelle
8

Der Fehler ist offensichtlich:

%Vor%

Weld kann die obige Jetty-Serverklasse nicht finden. Der Grund, warum diese Klasse nicht gefunden werden kann, ist der Klassenlademechanismus von Jetty. Der WebAppClassloader von Jetty enthält eine Standardliste von Serverklassen, die nicht geladen werden: siehe Ссылка

%Vor%

Damit Jetty diese Klasse laden kann, müssen Sie "-org.eclipse.jetty.servlet" hinzufügen. zu der Server-Klassenliste in jetty-web.xml.

%Vor%

Oder rufen Sie die folgende Methode auf, wenn Sie Embedded Jetty verwenden:

%Vor%     
Roosevelt Lai 03.01.2014 05:11
quelle
1

Für jeden, der versucht, den Rat von @ Roosevelt Lai anzuwenden, habe ich den Namen der in jetty-web.xml genannten Methode in <Call name="addServerClass"><Arg>-org.eclipse.jetty.servlet.</Arg></Call> geändert, weil ich eine Ausnahme vom Typ NoSuchMethod erhalten habe.

Dies ist wie in Dokumentation hier

Bootsanleger (8.1.14.v20131031)

    
kosgeinsky 25.08.2014 13:51
quelle
1

Meine 3-Tage-Erfahrung mit dieser genauen Fehlermeldung,

  

java.lang.NoClassDefFoundError: javax / enterprise / inject / spi / InjectionTarget

war, dass die Datei cdi-api.jar in asinstall/glassfish/modules den Namen cdi-api-1.2.jar erhielt. Der Name wurde in cdi-api.jar geändert und der Fehler ist verschwunden.

Spezifikationen:

  • Glassfish 4.1 (heruntergeladen als Zip-Datei),
  • jdk1.8.0_45,
  • OS X 10.7.5
Mse 23.06.2015 08:56
quelle