【问题标题】:Unable to add jar to OSGi bundle无法将 jar 添加到 OSGi 包
【发布时间】:2012-10-30 14:57:51
【问题描述】:

又一个愚蠢的问题。我确信这很容易,但这已经花了我很多时间而且我没有让它工作;(

我已经编写了一个工作原型来对服务器进行休息调用。为此,我使用“jersey-client-1.14.jar”。通过将其添加到 eclipse 项目类路径中效果很好。

现在我正在尝试在 OSGi 包中做同样的事情。这些是我做的步骤:

  1. 我在我的 OSGi 捆绑项目中创建了一个 /lib 文件夹。
  2. 在该文件夹中添加了 jersey-client-1.14.jar。
  3. 在类路径中的 MANIFEST.MF 中添加了 jar:Bundle-ClassPath: ., lib/jersey-client-1.14.jar
  4. 检查它是否也正确添加到项目类路径中。
  5. 在 Eclipse 工作区中我没有编译错误。

在运行时,我有一个现象,即使用 Client.create(); 创建球衣客户端时出现 classdef not found 异常;

!ENTRY org.eclipse.equinox.event 4 0 2012-11-08 23:14:43.975 将事件 org.osgi.service.event.Event [topic=openhab/command/Hue_Bulb_2] 调度到处理程序 org.openhab.binding.hue.internal.HueBinding@70f5f42b 时出现 !MESSAGE 异常 !堆栈 0 java.lang.NoClassDefFoundError:无法初始化类 com.sun.jersey.spi.service.ServiceFinder 在 com.sun.jersey.api.client.Client.init(Client.java:213) 在 com.sun.jersey.api.client.Client.access$000(Client.java:118) 在 com.sun.jersey.api.client.Client$1.f(Client.java:191) 在 com.sun.jersey.api.client.Client$1.f(Client.java:187) 在 com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193) 在 com.sun.jersey.api.client.Client.(Client.java:187) 在 com.sun.jersey.api.client.Client.(Client.java:159) 在 com.sun.jersey.api.client.Client.create(Client.java:669) 在 org.openhab.binding.hue.internal.bridge.HueBridge.getSettingsJson(HueBridge.java:64) 在 org.openhab.binding.hue.internal.bridge.HueBridge.pairBridgeIfNecessary(HueBridge.java:19) 在 org.openhab.binding.hue.internal.HueBinding.receiveCommand(HueBinding.java:37) 在 org.openhab.core.events.AbstractEventSubscriber.handleEvent(AbstractEventSubscriber.java:62) 在 org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197) 在 org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197) 在 org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1) 在 org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) 在 org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) 在 org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135) 在 org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78) 在 org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39) 在 org.openhab.core.internal.events.EventPublisherImpl.sendCommand(EventPublisherImpl.java:76) 在 org.openhab.ui.webapp.internal.servlet.CmdServlet.service(CmdServlet.java:115) 在 org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61) 在 org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:128) 在 org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:60) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:848) 在 org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598) 在 org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486) 在 org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231) 在 org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065) 在 org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413) 在 org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192) 在 org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999) 在 org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) 在 org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) 在 org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) 在 org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111) 在 org.eclipse.jetty.server.Server.handle(Server.java:350) 在 org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454) 在 org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890) 在 org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944) 在 org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:630) 在 org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230) 在 org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77) 在 org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:606) 在 org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46) 在 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603) 在 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538) 在 java.lang.Thread.run(Thread.java:680) 23:14:43.992 错误 OSGi[:98] - 将事件 org.osgi.service.event.Event [topic=openhab/command/Hue_Bulb_2] 调度到处理程序 org.openhab.binding.hue.internal.HueBinding@70f5f42b 时出现异常 java.lang.NoClassDefFoundError:无法初始化类 com.sun.jersey.spi.service.ServiceFinder 在 com.sun.jersey.api.client.Client.init(Client.java:213) 在 com.sun.jersey.api.client.Client.access$000(Client.java:118) 在 com.sun.jersey.api.client.Client$1.f(Client.java:191) 在 com.sun.jersey.api.client.Client$1.f(Client.java:187) 在 com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193) 在 com.sun.jersey.api.client.Client.(Client.java:187) 在 com.sun.jersey.api.client.Client.(Client.java:159) 在 com.sun.jersey.api.client.Client.create(Client.java:669) 在 org.openhab.binding.hue.internal.bridge.HueBridge.getSettingsJson(HueBridge.java:64) 在 org.openhab.binding.hue.internal.bridge.HueBridge.pairBridgeIfNecessary(HueBridge.java:19) 在 org.openhab.binding.hue.internal.HueBinding.receiveCommand(HueBinding.java:37)

【问题讨论】:

  • 你能告诉我们你的清单文件吗?我建议您使用 Maven-Bundle-Plugin 来帮助您构建清单文件,而不是手动编辑它。

标签: java jar jersey osgi classpath


【解决方案1】:

您还需要将 jersey-core 添加到捆绑包的类路径中,因为 jersey-client 将其作为依赖项。

如果需要,您可能还必须添加其他依赖项。如果不愉快,这个过程相当容易:

  1. 添加一个罐子
  2. 运行应用程序
  3. 查看什么类没有找到,找到那个类所在的jar,添加到bundle classpath,回到2

但有一件事:Jersey jar 已支持 OSGi,因此您不妨将 jersey-client.jar 和 jersey-core.jar 添加到您的 taget 平台并导入所需的包。

【讨论】:

  • 我通过将以下 jar 添加到目标平台来“解决”问题: jersey-client-1.15.jar jersey-core-1.15.jar jsr311-api-1.0.jar 这允许我添加它们作为我捆绑包中的依赖项......感谢您的提示。
【解决方案2】:

查看您的辅助查询,我想您只是想知道发生了什么:-)

OSGi fences 用于创建模块的 JAR。默认情况下,栅栏是不可穿透的,捆绑包(jar)之外的任何类对于内部的类都是可见的(能够从中加载类),并且外人看不到捆绑包内的任何东西。优势应该是显而易见的:你可以改变内心,让你内心愉悦,因为外面一无所知。

但是,在现实生活中,您需要在栅栏上留一些洞才能与他人协作。在您的情况下,捆绑包尝试加载 com.sun.jersey.spi.service.ServiceFinder 但由于没有合适的孔而遇到了障碍。

OSGi 中的“漏洞”是包,它们是共享原子。您在清单中列出这些包。 Import-Package 标头指示您需要从外部世界看到的包,而 Export-Package 标头定义了哪些包(以及在什么版本下)这些包对其他包可见。

显然您不想手动计算导入,因为这些已经在您的类文件中,因此有一个工具 bnd(我是作者)可以从 maven、ant、gradle 等中使用。它获取配方并使用适当的元数据计算生成的捆绑包。此工具得到 bndtools Eclipse 插件的广泛支持,这是一个非常好的环境,可以进一步了解 OSGi 和这些问题。

【讨论】:

    【解决方案3】:

    先生,在 Eclipse 中,您添加了不同的包,例如。 com.sun.jersey.spi.service.ServiceFinder 。要启动您的服务,您必须启动其他服务。你捆绑的依赖。 就像我有一个 jar,它依赖于 rxtxcomm_api-2.1.7.jar。 我必须初始化它,或者你可以说它是 intiat。在我服务之前。请检查一下。

    【讨论】:

    • 这不是我想要做的。我不想让 Jersey 作为一个单独的包运行,而是作为一个 jar 文件在我自己的包中运行......
    • hmm .. 这里也一样.. 我的 rstxconn jar 实际上是一个单独的包。但在我的主要文件中。 ia hd 添加了它的路径。这意味着当我启动我的服务时它应该对我的 jar 有用。
    【解决方案4】:

    在 OSGi 中嵌入 jars 是一种不好的风格。通常,只有在没有其他方法的情况下才应该这样做。嵌入 jar 很容易导致类路径问题,因为包可能来自不同的包。你想嵌入罐子有什么特殊原因吗? Jersey 从 1.2 版开始就完全支持 OSGi。使用方法见documentation for examples

    【讨论】:

    • 那是正确的,但我仍然想知道如何解决这个问题......只是为了了解我做错了什么......只是为了教育。 ;)
    • 我认为彼得的评论应该有所帮助。如果您查看 Client 的代码,您会发现 ServiceFinder 甚至使用 ContextClassLoader 的一些类加载器魔法。这些是 lib 不完全符合 OSGi 的情况。针对这些情况调整导入并不容易。所以依赖库的预打包版本总是更好的选择。
    【解决方案5】:

    大多数 OSGi 容器都带有开箱即用的 JAX-RS 实现 - 无论是 Jersey 还是其他。例如,我们使用的是 Apache ServiceMix,它可以方便地提供 Apache CXF。

    • 您使用的是什么容器?
    • 您真的必须将 Jersey 与您的应用程序捆绑在一起吗?

    如果您出于某种原因需要捆绑 Jersey,请提供清单文件示例。

    • 您是否考虑过使用 Maven-Bundle-Plugin?

    【讨论】:

    • 感谢您的帮助。我想到了 Maven,但我只是想了解发生了什么,用于教育目的。 ;)
    猜你喜欢
    • 2017-08-17
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2016-08-20
    • 2012-06-12
    • 1970-01-01
    • 2018-09-22
    相关资源
    最近更新 更多