如何从Web应用程序使用OSGi服务?

时间:2010-03-29 15:52:44

标签: java osgi classloader db4o

我正在尝试开发一个将成为launched from a HTTP OSGi service的Web应用程序,此应用程序需要使用其他OSGi服务(db4o OSGi),因为我需要对BundleContext的引用。我尝试了两种不同的方法来获取Web应用程序中的OSGi上下文:

  1. BundleContext的{​​{1}}存储在Web服务可以导入和使用的类的静态字段中。
  2. 使用ActivatorFrameworkUtil.getBundle(this.getClass()).getBundleContext() this的实例,这是一个Web应用程序类。
  3. 我认为第一个选项是完全错误的,但无论如何我在两个选项中都遇到了类加载器的问题。在第二个中它引发了MainPage

    LinkageError

    还尝试使用Equinox,我也有类似的错误:

    java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/felix/framework/ModuleImpl$ModuleClassLoader) previously initiated loading for a different type with name "com/db4o/ObjectContainer"
    

    引发异常的代码是:

    java.lang.LinkageError: loader constraint violation: loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) previously initiated loading for a different type with name "com/db4o/ObjectContainer"
    

    在最后一行引发异常,ServiceReference reference = context.getServiceReference(Db4oService.class.getName()); Db4oService service = (Db4oService)context.getService(reference); database = service.openFile("foo.db"); 类为database,如果我将此变量的类型更改为ObjectContainer,则不会引发异常,但它不起作用Object:)

    更新:我尝试使用其他服务而不是db4o,它们按预期工作。也许db4o OSGi包在加载自己的类时会做一些奇怪的事情,或者我可能没有正确使用它。如果我从非Web包中使用它,它也可以工作。

3 个答案:

答案 0 :(得分:0)

我不是100%肯定这会对你有所帮助,但你可以尝试在尝试访问另一个包中的类之前设置线程的上下文类加载器:

Thread currentThread = Thread.currentThread ();
ClassLoader origLoader = currentThread.getContextClassLoader ();

currentThread.setContextClassLoader (Db4oService.class.getClassLoader ());

ServiceReference reference = context.getServiceReference(Db4oService.class.getName());
Db4oService service = (Db4oService)context.getService(reference);
database = service.openFile("foo.db");

currentThread.setContextClassLoader (origLoader);

看起来OSGi正在检测这个类加载器是否会加载来自另一个bundle(Db4oService)的已加载类。

答案 1 :(得分:0)

为什么不在Servlet类的构造函数中传递BundleContext?该类可以安全地存储上下文,因为当bundle停止时服务停止(并且BundleContext变得无效)。

我建议完全避免在OSGi中使用类加载器,因为a)OSGi框架为了将bundle彼此分开而做了很多类加载器魔术,并且b)当OSGi和OSGi时你可能遇到很多问题启用了Java 2安全性。这很可能会降低捆绑包的可重用性。

答案 2 :(得分:0)

使用环境felix-server和jetty运行webservices,您可以轻松地在任何Web服务中使用任何OSGi服务。

首先,您必须在Web服务中注入ServletContext,以便通过调用servletContext.getAttribute(“osgi-bundlecontext”)来访问OSGi上下文。结果是您的OSGi-bundle上下文。

请在http://blog.meyerdaniel.ch/2012/08/accessing-osgi-services-from-servlets.html

上找到完整示例