在Karaf OSGI中,我得到一个类的ClassNotFoundException,该类在抛出异常的bundle中

时间:2013-07-29 23:10:38

标签: java glassfish osgi classloader apache-karaf

背景:在karaf中,我有两个功能,每个功能使用不同版本的Jersey(1.17和2.0)。

它们彼此分开,并且没有可以同时导入它们的包。

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 /服务/ 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]

请注意,这发生在捆绑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

我不知道如何在不破坏平针织核心普通罐的情况下实施他们的解决方案。

1 个答案:

答案 0 :(得分:2)

哦,当我们想要避免使用服务时,我们编织的网络纠结:-(这完全混乱是由于Java缺乏服务注册表造成的。

我认为你的问题是,泽西试图从你的捆绑包中加载,因为它找到了该捆绑包中的服务目录。由于你没有这些课程,泽西岛正确地说。

最初的解决方案是将这些文件放在jersey包中的services目录中,要求您打开该捆绑包。如果jersey bundle导出实现包(模块化的诅咒,但通常在不了解OSGi的代码中完成),即使你不直接使用它们,也可以在bundle中导入这些包。

另一个我没有检查过的替代方案是使用OSGi hack:片段。您可以为包含services目录的jersey bundle创建一个片段。但是,不确定这是否有效。

最后但并非最不重要的一点是,您可以私下将自己的套装代码包含在自己的套装中。有了bnd,这很容易做到。