6

我想将我的 EE 应用程序迁移到 OSGi。我的应用程序由业务库、数据库 JPA/Entities 和一个 REST/WS 接口组成。它还有一个网络客户端。

我首先对结构进行原型设计,并使所有接口和包以 OSGi 干净的方式相互通信。我想尽可能使用干净的规范,而不需要任何特定的供应商或框架。

我正在使用 bnd maven 插件来生成清单和声明性服务。我想使用注入从我的其余资源调用 OSGI 服务(在另一个包上),如下所示:

@Path("some-resources")
@Component
public class SomeResources{

   private SomeService service = null;

   @Reference
   public void setController(SomeService service) {   // <- this is never called
    this.service = service;
   }

   @GET
   @Produces(javax.ws.rs.core.MediaType.APPLICATION_XML)
   public Object getSomeService() {                  // <- called 
    try {
        service.process("Hello World");              // <- Error null object
   }
    ...

}

我可以用 bnd 注释资源@Component并且可以@Resource注入吗?一切正常,但服务始终为空。

应该如何为 BND 声明我的捆绑包以使其成为 web/wab 包?

我使用 Maven 包:

<packaging>bundle</packaging>

...

        <plugin>                    
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.3.7</version>
                <extensions>true</extensions>
                <dependencies>
                    <dependency>
                        <groupId>biz.aQute</groupId>
                        <artifactId>bndlib</artifactId>
                        <version>1.50.0</version>
                    </dependency>
                </dependencies> 
                <configuration>
                    <supportedProjectTypes>
                        <supportedProjectType>ejb</supportedProjectType>
                        <supportedProjectType>war</supportedProjectType>
                        <supportedProjectType>wab</supportedProjectType>
                        <supportedProjectType>bundle</supportedProjectType>
                        <supportedProjectType>jar</supportedProjectType>
                    </supportedProjectTypes>
                    <instructions>
                        <_include>-osgi.bundle</_include>
                    </instructions>
                </configuration>
                <executions>
                    <execution>
                        <id>bundle-manifest</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>manifest</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>bundle-install</id>
                        <phase>install</phase>
                        <goals>
                            <goal>install</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>                    

 ...

带 bnd 指令

Web-ContextPath: my-root-http/rest/
Service-Component: *
4

3 回答 3

5

OSGi 有一部分规范称为远程服务。简而言之,它的工作方式是您可以使用特殊的服务属性注册服务,并且基于属性技术应该选择您的服务并从中创建一个端点。它不仅与 REST 有关,还与任何处理远程调用的技术有关。您可以在“远程服务”一章下的 OSGi 核心规范中找到信息。

好吧,它是一个规范,但谁来实现它?目前我尝试了两个更大的项目。CXF DOSGi 和 Eclipse ECF。他们提供了多种支持远程服务规范的技术。CXF 特别支持 Jax-RS,基于它在服务器端和客户端的实现。

因为我不想在 OSGi 中使用 spring 特定的解决方案,所以我最终没有使用 CXF,而是创建了我自己的解决方案。它基于 Jersey 和远程服务规范。当使用 service.exported.interfaces=* 和 service.exported.configs=org.everit.osgi.remote.jersey 指定 OSGi 服务时,它将使用 HttpService 在 /rest/ 路径下创建一个休息端点。您的捆绑包不必是 wab,它可以是简单的捆绑包。

我必须提到,如果您通过任何远程服务实现公开您的服务,您应该将 Jax-RS 注释带入由您的原始类实现的接口,并基于该接口公开您的服务。

我建议您应该使用与 Spring 惊人地相似的 Blueprint(OSGi 规范的一部分),而不是 OSGi 中的 @Resource 和 @Component 注释。目前 Apache Aries 和 Gemini Blueprint 实现了它。使用蓝图,您可以轻松创建 bean 并将它们相互连接。如果以这种方式注册您的远程服务,您可以在蓝图的帮助下设置任何属性(就像 spring applicationcontext.xml 中 bean 的属性一样)。

您可以在https://source.everit.biz/svn/everit-osgi/trunk/samples/jaxrs/ (user/passwd: guest/guest)找到我制作的示例应用程序。在http://cookbook.everit.org上有一个指南解释了如何启动和开发这些示例

我希望示例应用程序可以帮助您开始使用远程服务规范一章。

要了解如何使用 JPA 和注入(蓝图),您应该查看 OSGi 纲要规范以了解可能性并找到您喜欢的实现。我还制作了一个基于 blueprint 和 hibernate-jpa 的示例项目,您可以将其作为我已经提供的示例 url 的兄弟找到。

更新

我在https://github.com/everit-org/osgi-remote-jersey还做了一个 JAXRS 扩展器实现。有关文档,请参阅自述文件。它与第一个不同之处在于它基于白板服务属性的工作方式。

于 2012-05-29T22:43:46.133 回答
2

我在 OSGi、Declarative Services 和 Jersey 遇到过类似的问题。

可以使用 @Component 和 @Reference 注释对资源进行注释。这将指示 DS 创建 SomeResource 类的实例,并在满足所有依赖项(引用)时将有效引用注入此实例。

您的引用为空的原因是因为 JAX-RS 实现将为每个 Web 请求创建 SomeResource 类的新实例。SomeResource 类的这个实例与 DS 创建的实例不同。

我通过使用 Java 静态关键字将引用变量设为静态来解决了这个问题:

private static SomeService service = null;

这确保了依赖引用绑定到类对象而不是实例,然后所有实例都可以看到注入的值。

这个解决方案引入了一个新问题。必须在取消绑定事件(当服务不可用时)清除此引用,因为当实例被销毁时它不会被销毁。

于 2012-06-26T10:58:04.953 回答
0

当 @Path 注释类型注册为服务本身时,问题将得到解决。使用 DS,您不仅可以注入其他服务。大约一年前,我自己也遇到了这个问题。这就是为什么我编写了一个小的 OSGi JAX-RS 连接器,它可以为您提供我所描述的内容。如果您愿意,请尝试一下:https ://github.com/hstaudacher/osgi-jax-rs-connector

于 2012-08-28T08:34:02.683 回答