【问题标题】:Using an OSGi Bundle from a Java Web Application in Tomcat在 Tomcat 中使用来自 Java Web 应用程序的 OSGi Bundle
【发布时间】:2011-11-07 14:18:56
【问题描述】:

我正在尝试从 Java Web 应用程序调用 OSGi 包的方法。两者都应该在 Tomcat 7 上运行。

我已经编写了一个从 OSGi 包调用方法的普通 Java 应用程序,如本网站所述:http://drupal.osgibook.org/node/37

为了获得 Equinox 环境的上下文,我从应用程序中启动它并从内部安装包。此外,上下文用于检索正在运行的捆绑包的服务引用并获取其服务。

EquinoxRunner类的runEquinox方法:

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

public BundleContext runEquinox([...]) throws Exception {
    [...]

    BundleContext bundleContext = EclipseStarter.startup(new String[]{"-console"}, null);
    bundleContext.installBundle("file:C:/.../plugins/myosgiclass.interface_1.0.0.201108301327.jar");
    Bundle bundleTranslationImpl =  bundleContext.installBundle("file:C:/.../plugins/myosgiclass.impl_1.0.0.201108301327.jar");
    bundleTranslationImpl.start();

    [...]
    return bundleContext;
}

以及ServiceRunner类的invokeMethod:

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

[...]

public Object invokeMethod(BundleContext bundleContext, Object value, [...]){
    ServiceReference serviceReference = bundleContext.getServiceReference(MyOSGiClass.class.getName());
    Object result = null;
    if (serviceReference != null) {
        MyOSGiClass myOSGiClass = (MyOSGiClass) bundleContext.getService(serviceReference);
        if (myOSGiClass != null) result = myOSGiClass.method(value);
        bundleContext.ungetService(serviceReference);
    }
    return result;
}

现在,在使用 eclipse bridge 的 Tomcat 上,我不知道如何检索 Equinox 环境的正确上下文。当我尝试使用 Equinox 在 Tomcat 上运行它时,我得到了 NoClassDefFound 异常。我将不胜感激有关如何解决此问题的任何建议。

提前非常感谢。 干杯,尼克

【问题讨论】:

  • 我认为关键是控制 OSgi 框架的启动。我不熟悉 Equinox 的确切工作原理,但我确信它们与 Felix 的描述类似,这里:felix.apache.org/site/…
  • 感谢您的评论。这也是我尝试过的方法。虽然由于我需要在 Tomcat 服务器上运行我的项目,但似乎需要上述 Bridge - 我无法手动启动。或者有什么方法可以绕过这个 Bridge 并使用手动启动的 OSGi 框架?
  • 我不明白使用 Tomcat 如何将您与特定的 servlet 桥实现联系起来。为什么不从自定义org.eclipse.equinox.servletbridge 项目开始呢?
  • 您是否需要运行 OSGi 框架?也许您只需要将捆绑 jar 文件放在您的 WEB-INF/lib 文件夹中,然后像使用任何其他 jar 一样使用它。捆绑包只是一个 jar,其中包含 jar 清单中的额外信息。任何 OSGi 包都可以作为普通 Jar 文件在 OSGi 之外使用。
  • 在许多情况下,我会同意@dlaidlaw 的评论,但最初的问题提到了检索服务引用,因此有问题的包可能具有多个运行时依赖项。试图在 OSGi 框架之外设置这些通常是徒劳的。

标签: java tomcat eclipse-plugin osgi equinox


【解决方案1】:

在将EclipseStarter 与桥接器一起使用之前,我已经完成了这项工作,要正确设置类路径内容需要做很多工作,这是关键。您还必须使用反射调用EclipseStarter。从那时起,他们似乎已经对此进行了标准化,因此您无需使用EclipseStarter

这里的关键(正如Felix article 中简要提到的那样,您必须在 Tomcat 环境和 OSGi 环境之间拥有一个共享的类路径。如果您查看那篇文章,请查看以“使用捆绑提供的服务”开头的部分",它似乎暗示了你想要什么。

您需要有一个接口来连接您在 Tomcat(父)类路径中调用的内容,然后您需要启动框架,以便它首先使用您的父类路径(这可能不是他们的启动器的东西),并且您需要排除从 OSGi 包中提供接口的包。我通过制作一个仅具有接口的单独 OSGi 包(API 包)来实现这一点,因此当我想在从外部 OSGi 调用我的代码的上下文中使用此设置时,我不会提供该 API 包。

【讨论】:

    【解决方案2】:

    我通过覆盖 JasperClass 加载器克服了这个挑战,每个包作为其自己的类加载器 classdeffnotfound 发生的情况是因为正在使用 tomcat 加载器。网上资源比较多。

    【讨论】:

      【解决方案3】:

      很抱歉,我不会直接回答您的问题... 从我的角度来看,您没有采取好的方法,您有任何有价值的理由使用现有的 Tomcat 7 实例吗? 我会使用更以 OSGi 为中心的方法,并使用标准 Http 服务来发布您的 Web 应用程序......在这种情况下,两个组件都与标准 OSGi 捆绑包处于同一级别,因此两个组件之间的通信非常容易(使用 EventAdmin 服务的直接方法调用或异步消息) 高温高压 我的 2 美分 杰罗姆 PS: 这种方法为您提供了更大的灵活性,它可以与 Equinox 或您想要的任何其他 OSgi shell 一起使用(felix、knopflerfish..)

      【讨论】:

        【解决方案4】:

        当您嵌入这样的 OSGi 框架,然后想要从外部环境访问 OSGi 服务时,您需要确保服务接口在 OSGi 内部和外部相同

        因此,配置您的 OSGi 容器以将服务接口的包从 Tomcat 导出到 OSGi。为此,请使用“FRAMEWORK_SYSTEMPACKAGES_EXTRA”属性配置您的 OSGi 框架。

        有关http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html#ApacheFelixFrameworkLaunchingandEmbedding-hostservices 的更多信息(即使是用于 Apache Felix,嵌入 API 也是标准化的)。

        【讨论】:

        猜你喜欢
        • 2011-04-23
        • 1970-01-01
        • 1970-01-01
        • 2013-04-10
        • 1970-01-01
        • 1970-01-01
        • 2013-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多