2012-04-17 78 views
6

我想将我的EE应用程序迁移到OSGi。我的应用程序由业务库,数据库JPA /实体和REST/WS接口组成。它也有一个网络客户端。OSGi JAX-RS和bnd声明式服务

我首先进行原型构造,并使所有接口和包以OSGi干净的方式彼此交谈。我希望尽可能使用清晰的规范,而无需任何特定的供应商或框架。

我使用bnd maven插件来生成清单和声明性服务。我想用注射像这样,使我从剩下的资源OSGi服务的呼叫(在另一个bundle):

@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: * 
+0

我最近遇到了类似的问题(服务没有被绑定),并追踪到[split package](http://wiki.osgi.org/wiki/ Split_Packages)问题。您是否尝试将您的服务接口放入单独的包中? – 2012-04-18 07:22:51

+0

谢谢@BjörnPollex的建议。我有3个软件包,一个只有接口,一个带有服务实现和REST bundel。我实际上将它移回到REST bundel,看看这样做是否有效,但没有运气。如果我正在做的事情是正确的,那么可能问题在于SCR找不到我的DS xml。 – Gadi 2012-04-18 07:29:20

+0

感谢编辑@donalfellows – Gadi 2012-04-18 07:30:51

回答

5

的OSGi有一个叫做远程服务规范的一部分。在很短的时间内,它的工作方式就是您可以使用特殊服务属性注册服务,并且基于属性技术应该提取服务并从中创建端点。它不仅关于REST,而且关于处理远程呼叫的任何技术。您可以在“远程服务”一章下的OSGi Core规范中找到相关信息。

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

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

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

取代OSGi中的@Resource和@Component注解,我建议您应该使用与Spring非常相似的Blueprint(OSGi规范的一部分)。目前Apache Aries和Gemini Blueprint实现它。借助蓝图,您可以轻松创建豆类并将它们连接到彼此。如果以这种方式注册远程服务,您可以借助蓝图设置任何属性(就像spring applicationcontext.xml中的bean属性一样)。

你可以在https://source.everit.biz/svn/everit-osgi/trunk/samples/jaxrs/(user/passwd:guest/guest)找到一个示例应用程序。有一本指南解释了如何在http://cookbook.everit.org

上启动和开发此样本。我希望示例应用程序可以帮助您开始使用远程服务规范章节。

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

更新

还有我在https://github.com/everit-org/osgi-remote-jersey做了JAXRS扩展实现。请参阅自述文件以获取文档。这与基于白板服务属性的第一种方式不同。

2

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

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

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

我通过参考静态变量与Java static关键字解决了这个问题:

private static SomeService service = null; 

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

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

+0

存储对osgi组件的静态引用不是一个好主意。 – 2016-10-10 17:16:42

0

将@Path注释类型注册为服务本身时,问题就会解决。有了DS,您可以注入其他服务。我近一年前就遇到过这个问题。这就是为什么我写了一个小的OSGi JAX-RS连接器,它给你我所描述的。试试看如果你喜欢:https://github.com/hstaudacher/osgi-jax-rs-connector

相关问题