如何将 Eclipse 插件公开为 Web 服务?

发布于 2024-12-19 11:13:50 字数 1298 浏览 4 评论 0原文

我一直在研究将 Eclipse 插件公开为 Web 服务,但我感到很困惑。

我的要求基本上是为一组 Web 服务构建 Equinox 后端。 我将大量使用 EMF 和相关项目,因此考虑到这个目标,我一直在阅读有关 Equinox/OSGI 以及构建我需要的选项的信息。

然而,也有一些神秘的地方,而且周围有大量的项目。鉴于以下发现,我想听听您的建议。也许我缺少一个选项,或者您以前已经这样做过。 提名者 (drumroll)

以下是在 Web 容器中托管 Equinox 的 。使用bridge.war,插件可以公开servlet。问题是,要使用良好的 REST 框架,例如 RestEasy(我最喜欢的),REST 框架需要是位于 Equionox 运行时中的 osgi 包。我花了 3 天,由于类加载器问题,这不起作用。我现在确信我将无法在 Equinox 中使用 RestEasy。我可以在 Web 容器中使用 RestEasy,并使用 XML 序列化/反序列化使 Web 容器中的代码与 Equionox 中的代码进行对话,但这感觉像是浪费资源。不过,这可能有效。

另一个选项似乎是ECF,它是分布式OSGI的实现,它似乎支持SOAP/Rest。但是,我找不到仅将 Equinox 托管功能公开为 Web 服务的清晰教程。所以这仍然迫使我不使用 RestEasy,但至少它似乎给了我一个与 Equinox 对话的适当框架。为了可扩展性,我可能仍然需要将其保存在网络容器中。

然后是 Eclipse Virgo,它似乎支持与 OSGI 运行时一起托管 Web 应用程序,并且显然 Web 容器托管代码可以与 OSGI 运行时代码对话。不过,我不确定是否可以传递类,因为在 Web 容器下创建的 Jaxb 带注释的类型 A 可能使用与 OSGI 运行时插件不同的类加载器。另外,这个设置将我锁定在 Virgo,我宁愿使用 JBoss 等进行生产使用。

因此,考虑到这些选项,以及可能还有更多我目前不知道的选项,您将如何将 EMF 和其他基于 Eclipse 框架的项目公开为 Web 服务?

编辑: 基于大家的热烈响应,我想补充更多内容。部分是问题的细节,部分是不适合评论部分的评论。

问题后的研究让我得出了与公认答案完全相同的观点:Apache CXF 现在是分布式 OSGI 的实现,这很好。我已经放弃了 RestEasy。我当前担心的是,我已经有一个创建了我的类的 XSD。 RestEasy 使暴露这些变得非常容易,我也必须在这里做同样的事情。我的插件必须使用这些基于 JAXB 的类。在最坏的情况下,我可能会尝试使用提供 JAXB 支持的 Eclipse Link 项目来创建 XML 内容,并通过基本 servlet 使用或基于 CXF 的字符串值传递它。因此,这里讨论的解决方案感觉并不完美,但我想这是目前可以做的最好的解决方案。

I've been doing my research about exposing Eclipse plugins as web services, but I'm getting confused.

My requirement is basically to build an Equinox back end for a set of web services.
I'll be using EMF and related projects heavily, so with this goal in mind I've been reading about Equinox/OSGI and options to build what I need.

However, there are some mysterious points and in general an abundance of projects around. Given the findings below, I'd like hear your suggestions. Maybe there is an option I'm missing, or maybe you've done this before. Here are the nominees (drumroll)

Hosting Equinox in a web container. Using bridge.war, the plugins can expose a servlet. The problem is, to use nice REST frameworks such as RestEasy (my favourite), the REST framework needs to be a osgi bundle that'd live in the Equionox runtime. I've spend 3 days, and due to classloader issues, this is not working. I am now convinced that I won't be able to have RestEasy in Equinox. I can have RestEasy in web container, and use XML serialization/deserialization to make code in web container talk to code in Equionox, but this feels like such a waste of resources. Still, this may work.

The other option seems to be ECF, which is an implementation of distributed OSGI, which seems to support SOAP/Rest. However, I could not find a clear tutorial that just exposes Equinox hosted functionality as a web service. So this still forces me no not to use RestEasy, but at least it seems to give me a proper framework to talk to Equinox. I'd probably still have to keep this in a web contaner for scalability.

Then there is Eclipse Virgo, which seems to support hosting web applications alongside OSGI runtime, and apparently web container hosted code can talk to OSGI runtime code. Still, I am not sure if I can pass around classes since a Jaxb annotated type A created under web container is likely to use a differnet classloader than the OSGI runtime plugin. Also, this setup locks me into Virgo, and I would rather go with JBoss etc for production use.

So given these options, and possibly more I do not know about at the moment, how would you expose EMF and other Eclipse framework based projects as web services?

Edit:
based on the great response I'd like to add more. Partially details of the question, partially comments which did not fit into comment section.

My research after the question let me to the exact same point with the accepted answer: Apache CXF is now an implementation of Distributed OSGI, which is good. I have given up on RestEasy. My current concern is, I already have a XSD that has created my classes. RestEasy made it very easy to expose these, and I'd have to do the same here. My plugins would have to use these JAXB based classes. In the worst case, I may attempt to use Eclipse Link project which offers JAXB support, in order to create XML content, and pass it through either basic servlet use or as string values based on CXF. So solutions discussed here don't feel perfect, but I guess this is the best one can do at the moment.

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

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

发布评论

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

评论(2

围归者 2024-12-26 11:13:50

我正在开发一款可以做到这一点的产品。我们的 Web 容器中有 Equinox。我们使用 Apache CXF 公开 SOAP 和 REST Web 服务。需要一些黑魔法才能正确连接所有东西。我发现 CXF 文档不太好,特别是对于 OSGI。

我相信您知道,在 Web 容器中托管 Equinox 并不是一种推荐的做法,尽管如果您想使用 OSGI,这是很难避免的做法。我们也遇到了许多类加载问题。事实上,我们从未真正享受过 OSGI 所宣传的好处(模块化等)。现在我们想回头已经太晚了。 OSGI 不应轻易进入。

下面简要概述了我们如何使用 CXF 启用 SOAP/REST。希望这至少能为您指明正确的方向。

1) 安装 CXF OSGI 捆绑包,包括核心和 DOSGI - 我们使用以下内容:
cxf-bundle-minimal-2.2.12.jar
cxf-dosgi-ri-discovery-local-1.1.jar
cxf-dosgi-ri-dsw-cxf-1.1.jar
链接:
http://cxf.apache.org/download.html

2) 安装 JAX-RS (REST ) 和 JAX-WS (SOAP) API
- API 定义位于 org.apache.servicemix.specs.jsr311-api-1.0-1.3.0.jar 和 org.apache.servicemix.specs.jaxws-api-2.1-1.1.1.jar 中(这些是版本我们有)
- 这些可能会也可能不会与 CXF 捆绑在一起。在我们的例子中,仅包含 JAX-WS jar。我们必须寻找 JAX-RS 捆绑包。
- 除了在 web 应用程序 (WEB-INF/eclipse/plugins) 中安装捆绑包之外,我们还必须将它们添加到 ECLIPSE/plugins 目录中进行编译。

3) 告诉 Equinox 加载 CXF 插件。可能还有其他方法可以做到这一点。我们通过 WEB-INF/eclipse/configuration/config.ini 中的条目来完成此操作。
-如果此文件存在,请将新 jar 添加到 osgi.bundles 属性中:
osgi.bundles=... org.apache.servicemix.specs.jaxb-api-2.1-1.1.1.jar@start, org.apache.servicemix.specs.jaxws-api-2.1-1.1.1.jar@start ,org.apache.servicemix.specs.jsr311-api-1.0-1.3.0.jar@start,\
cxf-dosgi-ri-discovery-local-1.1.jar@5:开始,\
cxf-bundle-minimal-2.2.12.jar@5:开始,\
cxf-dosgi-ri-dsw-cxf-1.1.jar@5:start

4) 就是这样。您现在应该能够开始编写 SOAP 和 REST 服务。这是 Java 优先的方法(与 XML 模式优先相反)。这意味着您:
- 定义Java接口
- 配置 CXF 将您的接口发布为 REST 或 SOAP 端点。

这是一个非常简单的 REST 示例。它带有标准免责声明,表明它特定于我们的环境。 YMMV。

a) 我们使用声明式服务,因此首先我们在捆绑包的清单中定义 DS 文件
服务组件:META-INF/ds/helloworld.xml
b) 这是 DS 文件:META-INF/ds/helloworld.xml。 DS 文件定义了 OSGI 包中的服务及其依赖项。为简洁起见,这些条目已被省略。

<?xml version="1.0"?>
<components xmlns="http://www.osgi.org/xmlns/scr/v1.0.0">

<component name="hello_world_service" xmlns="http://www.osgi.org/xmlns/scr/v1.0.0">

   <!-- Defines this as a REST service --->
   <property name="service.exported.configs" value="org.apache.cxf.rs"/>
   <!-- This is the URI of your REST resource.  
    It is realtive to the Equinox bridge servlet in your webapp -->
   <property name="org.apache.cxf.rs.httpservice.context" value="/helloworld" /> 
   <!-- This is the java interace that will be exposed .  You
   will use JAX-RS annotations to map these java methods to HTTP verbs. -->  
   <property name="service.exported.interfaces" value="com.foo.IHelloWorldService"/>        
... 

</components>

c) 这是接口类:

package com.foo;

@Path("/greeting")
public Interface IHelloWorldService {

   @GET
   @Produces("application/xml")
   public Greeting getGreeting();

}

public class HelloWorldService implements IHelloWorldService {
   @override
   public Greeting getGreeting() {
      Greeting g = new Greeting();
      g.message = "Hello World";
      return g;
   }
}

d) 因此,一旦一切就绪,您应该能够获取以下 URL:

   /<web-app-name>/bridge/helloworld/greeting

并收到以下响应:

   <Greeting>
      <message>Hello World</message>
   </Greeting>

祝你好运。希望这有帮助。

I work on a product that has done this. We have Equinox inside the web container. We expose SOAP and REST web services using Apache CXF. It took some black magic to get everything wired up correctly. I found the CXF documentation to be not so great, especailly for OSGI.

As I am sure you know, hosting Equinox in the web container is not a recommended practice, although it is a hard one to avoid if you want to use OSGI. We too experienced a number of classloading issues. In fact we never really enjoyed the advertised benefits from OSGI (modularity, etc). It's too late for us to turn back now. OSGI should not be entered into lightly.

So here is a quick overview of how we have enabled SOAP/REST using CXF. Hopefully this will at least point you in the right direction.

1) Install CXF OSGI bundles, both core and DOSGI - We are using the following:
cxf-bundle-minimal-2.2.12.jar
cxf-dosgi-ri-discovery-local-1.1.jar
cxf-dosgi-ri-dsw-cxf-1.1.jar
Links:
http://cxf.apache.org/download.html

2) Install JAX-RS (REST) and JAX-WS (SOAP) APIs
-The API definition are in org.apache.servicemix.specs.jsr311-api-1.0-1.3.0.jar and org.apache.servicemix.specs.jaxws-api-2.1-1.1.1.jar (these are the versions we have)
-These may or may not be bundled with CXF. IN our case, only the JAX-WS jar was included. We had to hunt down the JAX-RS bundle.
-In addition to installing the bundles in the webapp (WEB-INF/eclipse/plugins), we also had to add them to the ECLIPSE/plugins directory for compilation.

3) Tell Equinox to load CXF plugins. There are probably other ways to do this. We accomplished this with entries in WEB-INF/eclipse/configuration/config.ini.
-If this file exists, add your new jars to the osgi.bundles property:
osgi.bundles=... org.apache.servicemix.specs.jaxb-api-2.1-1.1.1.jar@start, org.apache.servicemix.specs.jaxws-api-2.1-1.1.1.jar@start, org.apache.servicemix.specs.jsr311-api-1.0-1.3.0.jar@start, \
cxf-dosgi-ri-discovery-local-1.1.jar@5:start, \
cxf-bundle-minimal-2.2.12.jar@5:start, \
cxf-dosgi-ri-dsw-cxf-1.1.jar@5:start

4) That's it. You should now be able to start writing SOAP and REST services. This is a Java-first approach (as opposed to XML-schema first). What this means is that you:
-Define a Java interface
-Configure CXF to publish you interface as either REST or SOAP endpoint.

Here's a very simple example for REST. It comes with the standard disclaimer that it is specific to our environment. YMMV.

a) We use declarative services, so first we define the DS file in our bundle's manifest
Service-Component: META-INF/ds/helloworld.xml
b) Here is the DS file: META-INF/ds/helloworld.xml. The DS file defines the services in your OSGI bundle and their dependencies. Those entries have been omitted for brevity.

<?xml version="1.0"?>
<components xmlns="http://www.osgi.org/xmlns/scr/v1.0.0">

<component name="hello_world_service" xmlns="http://www.osgi.org/xmlns/scr/v1.0.0">

   <!-- Defines this as a REST service --->
   <property name="service.exported.configs" value="org.apache.cxf.rs"/>
   <!-- This is the URI of your REST resource.  
    It is realtive to the Equinox bridge servlet in your webapp -->
   <property name="org.apache.cxf.rs.httpservice.context" value="/helloworld" /> 
   <!-- This is the java interace that will be exposed .  You
   will use JAX-RS annotations to map these java methods to HTTP verbs. -->  
   <property name="service.exported.interfaces" value="com.foo.IHelloWorldService"/>        
... 

</components>

c) Here is the interface class:

package com.foo;

@Path("/greeting")
public Interface IHelloWorldService {

   @GET
   @Produces("application/xml")
   public Greeting getGreeting();

}

public class HelloWorldService implements IHelloWorldService {
   @override
   public Greeting getGreeting() {
      Greeting g = new Greeting();
      g.message = "Hello World";
      return g;
   }
}

d) So, once this is all in place, you should be able to GET the following URL:

   /<web-app-name>/bridge/helloworld/greeting

and receive the following response:

   <Greeting>
      <message>Hello World</message>
   </Greeting>

Good luck. Hope this helps.

情深如许 2024-12-26 11:13:50

不幸的是,我认为 RESTeasy 是这里的问题。根据您在另一个问题中的评论,RESTeasy 使用 Java ServiceLoader API 动态查找类,不幸的是,这对类加载做出的假设在任何非平面(即模块化)类加载架构中都是不正确的。

我鼓励您在 RESTeasy 论坛上询问有关 ServiceLoader 查找这些类的方法的替代方法。例如,可以显式注册这些类。

然而,如果没有允许您继续使用 RESTeasy 的解决方案,则有其他 REST API 在 OSGi 中运行良好。例如,Restlet 具有明确的 OSGi 支持。我也成功地使用了泽西岛。

Unfortunately I think that RESTeasy is the problem here. As per your comment in another question, RESTeasy uses the Java ServiceLoader API to lookup classes dynamically, which unfortunately makes assumptions about classloading that are untrue in any non-flat (i.e. modular) classloading architecture.

I would encourage you to ask on the RESTeasy forums about alternatives to the ServiceLoader approach to looking up these classes. It may be possible to explicitly register those classes, for example.

However failing a solution that allows you to continue using RESTeasy, there are alternative REST APIs that do work very well in OSGi. Restlet for example has explicit OSGi support. I have successfully used Jersey as well.

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