在 Tomcat 中使用 Java Web 应用程序中的 OSGi 捆绑包

发布于 2024-12-02 07:22:55 字数 1783 浏览 0 评论 0原文

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

我已经编写了一个普通的 Java 应用程序,它调用 OSGi 包中的方法,如本网站所述: 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;
}

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

预先非常感谢。 干杯,尼克

I am trying to invoke a method of an OSGi bundle from a Java Web Application. Both are supposed to run on Tomcat 7.

I already wrote a normal Java application that invokes methods from the OSGi bundle, as described on this site: http://drupal.osgibook.org/node/37.

To get the context of the Equinox environment I started it from the application and installed the bundles from within. Furthermore the context was used to retrieve a service reference of the running bundle and getting its service.

The runEquinox method of the EquinoxRunner class:

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;
}

and the invokeMethod of the ServiceRunner class:

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;
}

Now, on Tomcat using the eclipse bridge, I don't know how to retrieve the right context of the Equinox environment. When I try running it on Tomcat with Equinox I get NoClassDefFound Exceptions. I would appreciate any advice on how to solve this problem.

Thanks a lot in advance.
Cheers, Nic

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

厌味 2024-12-09 07:22:55

当您嵌入这样的 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 是标准化的)。

When you embeds an OSGi framework like that and then want to access an OSGi service from the outer environment, you need to be sure that the service interface are the same inside and outside of OSGi.

So, configure your OSGi container to export the package of your service interface from Tomcat to OSGi. To achieve this, configure your OSGi framework with the 'FRAMEWORK_SYSTEMPACKAGES_EXTRA' property.

More info on http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html#ApacheFelixFrameworkLaunchingandEmbedding-hostservices (even if it's for Apache Felix, the embedding API is standardized).

铃予 2024-12-09 07:22:55

在将 EclipseStarter 与桥接器一起使用之前,我已经完成了此操作,并且需要做大量工作才能获得正确的类路径内容,这是关键。您还必须使用反射调用 EclipseStarter。看起来他们从那时起就对此进行了标准化,因此您不需要使用 EclipseStarter。

这里的关键(正如 Felix 文章中简要提到的 是您的 Tomcat 环境和 OSGi 环境之间必须有一个共享类路径,如果您查看该文章中以“使用捆绑包提供的服务”开头的部分,它似乎会建议您需要什么

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

I have done this before using the EclipseStarter stuff with the bridge, and it was a lot of work to get the classpath stuff right which is the key. You also have to call EclipseStarter using reflection. It looks like they have standardized this since then so you don't need to use the EclipseStarter.

The key here (as briefly mentioned in the Felix article is that you have to have a shared classpath between your Tomcat environment and your OSGi environment. If you look in that article at the section starting with "Using Services Provided by Bundles", it seems to suggest what you want.

You will need to have an interface to what you are calling in your Tomcat (parent) classpath, and then you need to start the framework such that it uses your parent classpath first (which is likely not their launcher stuff works), and you need to exclude the bundle that provides the interface from the OSGi bundles. I accomplished this by making a separate OSGi bundle (the API bundle) that just had the interfaces, so when I wanted to use this setup in a context where my code was called from outside OSGi I would not provide that API bundle.

日久见人心 2024-12-09 07:22:55

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

I overcame this challenge by overriding the JasperClass Loader what is happening each bundle as its own class loader classdeffnotfound is because the tomcat loader is being used. There are more resources online.

伴梦长久 2024-12-09 07:22:55

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

I am sorry I won't answer to your question directly...
From my point of view you don't take the good approach , do you have any valuable reason to use an existing Tomcat 7 instance ?
I would use a more OSGi centric approach , and use the standard Http Service to publish your web application... In such context both components are on the same level as standard OSGi bundles and then as a consequence the communication between 2 components is really easy (direct method invokation or asynchronous message using EventAdmin service)
HTH
my 2 cents
Jerome
PS:
this approach gives you much more flexibility, it can be used with Equinox or any other OSgi shell you want (felix, knopflerfish..)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文