0

背景: karaf には、それぞれ異なるバージョンの Jersey (1.17 と 2.0) を使用する 2 つの機能があります。

それらは互いに分離されており、両方をインポートするバンドルはありません。

Jersey の 1.17 と 2.0 の間のパッケージ名が変更されました (com.sun.jersey 対 org.glassfish.jersey)。

とにかく、jersey 1.17 を使用するバンドルは問題なく動作します。

2.0 を機能させるために (おそらく)、jar/bundle の META-INF ディレクトリにある "services" というディレクトリ内のファイルで、メッセージ リーダーのプロバイダーの FQN を指定できることをどこかで読みました。( http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Providerによる)

それは次のようになります。

META-INF/services/javax.ws.rs.ext.MessageBodyReader:

org.glassfish.jersey.message.internal.XmlRootObjectJaxbProvider.App
org.glassfish.jersey.message.internal.SourceProvider.StreamSourceReader
org.glassfish.jersey.message.internal.SourceProvider.SaxSourceReader
org.glassfish.jersey.message.internal.SourceProvider.DomSourceReader
org.glassfish.jersey.message.internal.XmlRootObjectJaxbProvider.Text
org.glassfish.jersey.message.internal.XmlRootObjectJaxbProvider.General

私の org.glassfish.jersey.core.jersey-common 2.0 バンドルが最初のクラスをロードしようとするため、機能しているようです。しかし、それは ClassNotFoundException をスローします。

2013-07-29 14:36:45,334 | WARN  | Executor: 2      | OsgiRegistry                     | egistry$BundleSpiProvidersLoader  222 | 207 - org.glassfish.jersey.core.jersey-common - 2.0.0 | [] | Exception caught while loading SPI providers.
java.lang.ClassNotFoundException: org.glassfish.jersey.message.internal.XmlRootObjectJaxbProvider.App
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)[osgi-3.8.0.v20120529-1548.jar:]
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)[osgi-3.8.0.v20120529-1548.jar:]
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)[osgi-3.8.0.v20120529-1548.jar:]
    at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)[osgi-3.8.0.v20120529-1548.jar:]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)[:1.7.0_21]
    at org.eclipse.osgi.internal.loader.BundleLoader.loadClass(BundleLoader.java:340)[osgi-3.8.0.v20120529-1548.jar:]
    at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:229)[osgi-3.8.0.v20120529-1548.jar:]
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadClass(AbstractBundle.java:1212)[osgi-3.8.0.v20120529-1548.jar:]
    at org.glassfish.jersey.internal.OsgiRegistry$BundleSpiProvidersLoader.call(OsgiRegistry.java:217)[207:org.glassfish.jersey.core.jersey-common:2.0.0]
    at org.glassfish.jersey.internal.OsgiRegistry$BundleSpiProvidersLoader.call(OsgiRegistry.java:189)[207:org.glassfish.jersey.core.jersey-common:2.0.0]
    at org.glassfish.jersey.internal.OsgiRegistry.locateAllProviders(OsgiRegistry.java:468)[207:org.glassfish.jersey.core.jersey-common:2.0.0]

これは bundle 207 jersey-common 2.0 で発生していることに注意してください。

私が走れば

karaf@root> osgi:find-class XmlRootObjectJaxbProvider

jersey-core-common (207)
org/glassfish/jersey/message/internal/XmlRootObjectJaxbProvider$App.class
org/glassfish/jersey/message/internal/XmlRootObjectJaxbProvider$General.class
org/glassfish/jersey/message/internal/XmlRootObjectJaxbProvider$Text.class
org/glassfish/jersey/message/internal/XmlRootObjectJaxbProvider.class

クラスは同じバンドルに含まれています。独自のバンドルでクラスを見つけることができません。

これは、glassfish が何らかの形で他のクラス ローダーを使用していない限り、私には意味がありません。誰でもこれに光を当てることができますか?

ありがとう。

更新 このバグを見つけました:

https://java.net/jira/browse/GLASSFISH-16970

この問題に関するこのwikiに私を導きました:

https://wikis.oracle.com/display/GlassFish/JdkSpiOsgi

jersey-core-common jar をハッキングせずに回避策を実装する方法がわかりません。

4

1 に答える 1

2

ああ、サービスの使用を避けたいときに織り成す複雑な網 :-( この完全な混乱は、Java のサービス レジストリの欠如によって引き起こされます。

あなたの問題は、 jersey がバンドル内の services ディレクトリを見つけるため、バンドルからロードしようとすることだと思います。これらのクラスがないため、Jersey は正しくボークします。

元の解決策は、これらのファイルを jersey バンドルの services ディレクトリに配置することであり、そのバンドルを開く必要があります。jersey バンドルが実装パッケージをエクスポートする場合 (モジュール性の嫌悪感ですが、OSGi を理解しないコードで行われることがよくあります)、それらのパッケージを直接使用しなくても、バンドルにインポートできます。

私がチェックアウトしていない別の代替手段は、OSGi ハックであるフラグメントを使用することです。サービス ディレクトリを含む jersey バンドルへのフラグメントを作成できます。ただし、これが機能するかどうかはわかりません。

最後になりましたが、ジャージのコードを独自のバンドル内に非公開で含めることができます。bnd を使用すると、これは非常に簡単に実行できます。

于 2013-07-30T06:49:35.720 に答える