在Tomcat中从Java Web应用程序中使用OSGi Bundle

15
我正在尝试从一个Java Web应用程序中调用一个OSGi bundle的方法,二者都应该在Tomcat 7上运行。
我已经编写了一个普通的Java应用程序,按照这个网站描述的方式调用OSGi bundle的方法:http://drupal.osgibook.org/node/37
为了获取Equinox环境的上下文,我从应用程序中启动它并从内部安装bundles。此外,上下文被用来检索正在运行的bundle的服务引用并获取其服务。
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;
}

现在,在Tomcat上使用eclipse bridge时,我不知道如何检索Equinox环境的正确上下文。当我尝试在带有Equinox的Tomcat上运行它时,会出现NoClassDefFound异常。我将非常感谢任何关于如何解决这个问题的建议。

提前感谢您。 谢谢,Nic


我认为关键是控制OSgi框架的启动。虽然我不熟悉Equinox的确切工作方式,但我相信他们有类似于Felix在这里描述的东西:http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html。 - forty-two
感谢您的评论。这也是我尝试过的方法。但由于我需要在Tomcat服务器上运行我的项目,似乎需要上述描述的桥接器 - 而我无法手动启动它。或者有没有办法绕过这个桥接器并使用手动启动的OSGi框架? - Nicolas
我不明白使用Tomcat如何将您绑定到特定的servlet桥实现。为什么不从自定义org.eclipse.equinox.servletbridge项目开始呢? - forty-two
4
你是否需要一定要运行OSGi框架呢?或许你只需要将你的bundle jar文件放在WEB-INF/lib文件夹中,像使用其他jar文件一样使用它。一个bundle只是一个带有额外信息的jar文件。任何OSGi bundle都可以作为普通的Jar文件在OSGi之外使用。 - dlaidlaw
在许多情况下,我会同意@dlaidlaw的评论,但原始问题提到了检索服务引用,因此该包很可能具有几个运行时依赖项。试图在OSGi框架之外设置它们通常是徒劳的。 - Chris Dolan
只是一个想法:JBoss AS7包括OSGi运行时和Tomcat。 - Chris Dolan
4个回答

2

我以前使用EclipseStarter与桥接完成过这个操作,但是正确设置类路径需要很多工作,这是关键。你还需要使用反射调用EclipseStarter。看起来自那时起它们已经将其标准化了,所以你不需要使用EclipseStarter

关键在于(在Felix文章中简要提到),你需要在Tomcat环境和OSGi环境之间共享一个类路径。如果你看一下“使用bundles提供的服务”这一部分,它似乎建议了你想要的内容。

你需要拥有一个接口连接你在Tomcat(父)类路径中调用的内容,然后你需要启动框架以使用你的父类路径(这不太可能是他们启动器的工作方式),并且你需要排除提供接口的bundle免受OSGi bundles的干扰。我通过制作一个单独的OSGi bundle(API bundle),只包含接口来实现这一点,因此当我想在调用我的代码的外部OSGi上下文中使用此设置时,我不会提供该API bundle。


2

当您嵌入像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已标准化)。


一个最新的链接:http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html - FableBlaze

0
我通过覆盖Jasper类加载器来克服了这个挑战,每个bundle都作为自己的类加载器来处理,因为出现classdeffnotfound的问题是由于使用了tomcat加载器。网上还有更多的资源可供参考。

0
抱歉,我不会直接回答你的问题... 从我的角度来看,你没有采取正确的方法,你有任何有价值的理由使用现有的Tomcat 7实例吗? 我会使用更加OSGi中心化的方法,并使用标准的Http服务来发布您的Web应用程序...在这种情况下,两个组件都处于标准OSGi捆绑包的同一级别,因此两个组件之间的通信非常容易(直接方法调用或使用EventAdmin服务进行异步消息) 希望对你有所帮助 我的建议是 Jerome 附言: 这种方法给您带来了更多的灵活性,可以与Equinox或任何其他您想要的OSgi shell一起使用(felix,knopflerfish..)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接