在Tomcat中使用来自Java Web应用程序的OSGi Bundle

时间:2011-08-31 12:47:42

标签: java tomcat eclipse-plugin osgi equinox

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

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

为了获得Equinox环境的上下文,我从应用程序启动它并从内部安装了bundle。此外,上下文用于检索正在运行的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;
}

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

提前多多感谢。 干杯,尼克

4 个答案:

答案 0 :(得分:2)

在将EclipseStarter内容与桥接器一起使用之前,我已经完成了这项工作,并且要获得正确的类路径内容是很重要的。您还必须使用反射调用EclipseStarter。从那时起,他们似乎已将其标准化,因此您无需使用EclipseStarter

这里的关键(正如Felix article中简要提到的那样,你必须在Tomcat环境和OSGi环境之间有一个共享的类路径。如果你在“使用提供的服务”一节中查看那篇文章通过Bundles“,它似乎暗示了你想要的东西。

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

答案 1 :(得分: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也是标准化的)。

答案 2 :(得分:0)

我通过覆盖JasperClass Loader克服了这个挑战,因为它自己的类加载器classdeffnotfound是因为正在使用tomcat加载器,所以每个bundle发生了什么。网上有更多资源。

答案 3 :(得分:0)

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