Problema
Quando si utilizzano librerie di terze parti in un bundle OSGi, si ottengono problemi di caricamento delle classi, come ad esempio i seguenti:
La factory richiesta mypackage.FooBar non può essere localizzata. Classloader =java.net.net.URLClassClassLoader@6aa8d01c
Nota: Questo errore è solo un esempio di messaggio di errore. Il problema è che le classi caricate da librerie di terze parti non sono state trovate, anche se la classe corrispondente è stata sicuramente importata.
Esempio reale:
Apache Axis2 potrebbe generare la seguente stacktrace senza motivo:
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 Impossibile inviare ViaPost a url[xy] org.apache.axis2.AxisFault: La factory richiesta com.ctc.wstx.wstx.stax.WstxOutputFactory non può essere localizzata. Classloader =java.net.net.URLClassLoader@6aa8d01c a org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) a org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:96) a org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499) ...
Soluzione
Il modo in cui le librerie di terze parti caricano le loro classi è fuori dal tuo controllo. Nella maggior parte dei casi va bene, se la libreria di terze parti usa il normale classloader dal bundle. Però, a volte una libreria, come Apache Axis2, potrebbe provare a caricare una classe come la seguente:
Thread.currentThread().getContextClassLoader().loadClass("mypackage.FooBar");
per impostazione predefinita, il caricatore di classe Thread non riconosce OSGi e quindi non vede nessuna delle classi importate nel bundle. Ecco perché il caricamento della classe fallisce.
Nel proprio codice, prima che il codice di terze parti venga eseguito, si può dire al thread corrente di utilizzare il caricatore di classe dal bundle. Farlo temporaneamente per il codice di terze parti che non carica delle classi:
ClassLoader tccl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); try { // execute 3rd party code } finally { Thread.currentThread().setContextClassLoader(tccl); }
Per i prodotti:
CQ 5.x, AEM6.x