問題点
OSGi バンドルでサードパーティーのライブラリを使用すると、次のようなクラスロード問題を取得します。
要求されたファクトリーの mypackage.FooBar が見つかりません。Classloader =java.net.URLClassLoader@6aa8d01c
注意:このエラーは、エラーメッセージの一例です。この問題は、対応するクラスが明確に読み込まれた場合でも、サードパーティのライブラリによって読み込まれたクラスが見当たらないことです。
実例
Apache Axis2 は理由を問わず、以下のスタックトレースを実行することができます。
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) ...
解決策
サードパーティライブラリが行うクラスの読み込みは、コントロールすることができません。サードパーティライブラリがバンドルより標準の classloader を使用する場合は、ほとんど問題になりません。しかし、Apache Axis2などのライブラリは、次のようなクラスを読み込むことも可能です。
Thread.currentThread().getContextClassLoader().loadClass("mypackage.FooBar");
デフォルトでは、スレッドコンテキストクラスローダーは、OSGi を認識していないため、バンドルで読み込まれたクラスは一切表示されません。このため、クラスの読み込みが失敗します。
コードでは、サードパーティのコードが実行される前に、バンドルからクラスローダーを使用するように現在のスレッドを指定できます。一部のクラスを読み込まないサードパーティコードに対して、一時的にこれをおこないます。
ClassLoader tccl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); try { // execute 3rd party code } finally { Thread.currentThread().setContextClassLoader(tccl); }
適用対象
CQ5.x、AEM6.x
アカウントにログイン