Probleme beim Laden von Klassen in OSGi und Bibliotheken von Drittanbietern, die den Thread-Kontext verwenden

Problem

Wenn Sie Bibliotheken von Drittanbietern in einem OSGi-Paket verwenden, bekommen Sie Klassenladefragen wie die folgende:

Angeforderte factory mypackage.FooBar kann nicht gefunden werden. Classloader =java.net.URLClassLoader@6aa8d01c

Hinweis: Diese Fehlermeldung ist nur ein Beispiel. Das Problem ist, dass Klassen, die von Bibliotheken von Drittanbietern geladen werden, nicht gefunden werden, obwohl die entsprechende Klasse definitiv importiert wurde.

Beispiel in Echtzeit

Apache Axis2 könnte folgenden Stacktrace ohne Grund verwerfen:

18.02.2010 17:04:30.153 *INFO* [10.43.97.19 [1266509048609] POST /path/to/servlet HTTP/1.1] org.apache.axis2.transport.http.HTTPSender Unable to sendViaPost to url[xy] org.apache.axis2.AxisFault: Requested factory com.ctc.wstx.stax.WstxOutputFactory cannot be located. Classloader =java.net.URLClassLoader@6aa8d01c at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:96) at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499) ...

Lösung

Die Art und Weise, wie Bibliotheken von Drittanbietern ihre Klassen laden, ist veraltet. In den meisten Fällen ist es ausreichend, wenn die Bibliothek den normalen Classloader aus dem Paket verwendet. Aber manchmal kann eine Bibliothek wie Apache Axis2 versuchen. Laden Sie eine Klasse wie im
Thread.currentThread().getContextClassLoader().loadClass("mypackage.FooBar");
Standardmäßig kennt der Threadkontext-Klassenlader OSGi nicht und sieht daher keine der im Bündel importierten Klassen. Daher schlägt das Laden der Klasse fehl.

Bevor der Code des Drittanbieters ausgeführt wird, können Sie im aktuellen Code festlegen, dass der aktuelle Thread den Klassenlader aus dem Bündel verwenden soll. Führen Sie diesen Vorgang vorübergehend für Quellcode von Drittanbietern aus, die keine Klassen hochladen:

ClassLoader tccl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); try { // execute 3rd party code } finally { Thread.currentThread().setContextClassLoader(tccl); }

 

Gilt für

CQ5.x, AEM6.x

Adobe-Logo

Bei Ihrem Konto anmelden