3

我正在尝试开发一个将从 HTTP OSGi 服务启动的 Web 应用程序,该应用程序需要使用其他 OSGi 服务(db4o OSGi),因为我需要引用一个BundleContext. 我尝试了两种不同的方法来获取 Web 应用程序中的 OSGi 上下文:

  1. BundleContext将的存储在ActivatorWeb 服务可以导入和使用的类的静态字段中。
  2. 使用FrameworkUtil.getBundle(this.getClass()).getBundleContext()(作为Web 应用程序this的一个类的实例MainPage)。

我认为第一个选项是完全错误的,但无论如何我在两个选项中的类加载器都有问题。在第二个中,它提出了一个LinkageError

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"

也尝试过Equinox,我有一个类似的错误:

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为不引发异常,但它作为一个没有用Object:)

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

4

3 回答 3

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 正在检测来自另一个包 ( Db4oService) 的已加载类将由此类加载器加载。

于 2010-04-01T05:43:15.787 回答
0

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

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

于 2010-04-01T11:20:14.270 回答
0

使用环境 felix-server 和运行 web 服务的码头,您可以轻松地在任何 web 服务中使用任何 OSGi 服务。

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

请在http://blog.meyerdaniel.ch/2012/08/accessing-osgi-services-from-servlets.html上找到完整示例

于 2012-12-12T09:19:01.477 回答