3

HTTP OSGi service から起動される Web アプリケーションを開発しようとしています。このアプリケーションは、BundleContext. Web アプリケーションで OSGi コンテキストを取得するために、次の 2 つの異なる方法を試しました。

  1. のを、Web サービスがインポートして使用できるクラスの静的フィールドにBundleContext格納します。Activator
  2. FrameworkUtil.getBundle(this.getClass()).getBundleContext()( Web アプリケーションのクラスであるthisのインスタンス) を使用します。MainPage

最初のオプションは完全に間違っていると思いますが、とにかく両方のオプションでクラスローダーに問題があります。2番目のものでは、次のようになりますLinkageError

java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/felix/framework/ModuleImpl$ModuleClassLoader) previously initiated loading for a different type with name "com/db4o/ObjectContainer"

Equinox でも試してみましたが、同様のエラーが発生しました。

java.lang.LinkageError: loader constraint violation: loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) previously initiated loading for a different type with name "com/db4o/ObjectContainer"

例外を引き起こすコードは次のとおりです。

ServiceReference reference = context.getServiceReference(Db4oService.class.getName());
Db4oService service = (Db4oService)context.getService(reference);
database = service.openFile("foo.db");

最後の行で例外が発生します。databaseクラスはObjectContainer、この変数の型をObject例外に変更すると、発生しませんが、Object:)としては役に立ちません

更新: db4o の代わりに他のサービスを使用しようとしましたが、期待どおりに機能しました。おそらく、db4o OSGi バンドルが独自のクラスをロードするときに奇妙な動作をするか、正しく使用していない可能性があります。非 Web バンドルから使用する場合にも機能します。

4

3 に答える 3

0

サーブレットクラスのコンストラクタでBundleContextを渡してみませんか?バンドルが停止すると(そしてBundleContextが無効になると)サービスが停止するため、そのクラスはコンテキストを安全に格納できます。

OSGiでクラスローダーを使用することは絶対に避けてください。a)OSGiフレームワークは、バンドルを相互に分離するために多くのクラスローダーマジックを実行し、b)OSGiとJava2のセキュリティで多くの問題が発生する可能性があるためです。有効になっています。これにより、バンドルの再利用性が低下する可能性があります。

于 2010-04-01T11:20:14.270 に答える
0

これが役立つとは 100% 確信が持てませんが、他のバンドルのクラスにアクセスする前に、スレッドのコンテキスト クラス ローダーを設定してみてください。

Thread currentThread = Thread.currentThread ();
ClassLoader origLoader = currentThread.getContextClassLoader ();

currentThread.setContextClassLoader (Db4oService.class.getClassLoader ());

ServiceReference reference = context.getServiceReference(Db4oService.class.getName());
Db4oService service = (Db4oService)context.getService(reference);
database = service.openFile("foo.db");

currentThread.setContextClassLoader (origLoader);

OSGi は、別のバンドル ( Db4oService) から既にロードされているクラスがこのクラス ローダーによってロードされることを検出しているようです。

于 2010-04-01T05:43:15.787 に答える