我想将我的EE应用程序迁移到OSGi。我的应用程序由业务库、数据库JPA/实体和一个REST/WS接口组成。它还有一个web客户端。
我首先对结构进行了原型设计,并使所有的接口和包以OSGi的方式相互通信。我希望尽可能多地使用干净的规范,而不需要任何特定的供应商或框架。
我使用bnd maven插件来生成清单和声明性服务。我想使用注入从我的rest资源调用一个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 bundle:
<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: *发布于 2012-05-30 06:43:46
OSGi规范中有一部分叫做远程服务。简而言之,它的工作方式是您可以注册具有特殊服务属性的服务,并且基于这些属性,技术应该选择您的服务并从它们创建一个端点。它不仅与REST有关,还与处理远程调用的任何技术有关。您可以在“远程服务”一章的OSGi核心规范中找到相关信息。
好吧,它是一个规范,但是谁实现了它呢?目前,我尝试过两个更大的项目。CXF、DOSGi和Eclipse ECF。它们提供了几种支持远程服务规范的技术。基于Jax-RS在服务器端和客户端的实现,CXF特别支持Jax-RS。
因为我不想在OSGi中使用特定于spring的解决方案,所以最后我没有使用CXF,而是创建了自己的解决方案。它基于Jersey和远程服务规范。当使用service.exported.interfaces=*和service.exported.configs=org.everit.osgi.remote.jersey指定rest服务时,它将使用HttpService在/ OSGi /路径下创建一个rest端点。您的捆绑包不必是wab,它可以是一个简单的捆绑包。
我必须指出的是,如果您通过任何远程服务实现公开您的服务,您应该将Jax-RS注释带入由您的原始类实现的接口中,并基于该接口公开您的服务。
我建议您应该使用与OSGi惊人地相似的蓝图( OSGi规范的一部分),而不是使用Spring中的@Resource和@Component注释。目前,Apache Aries和Gemini Blueprint实现了它。使用blueprint,您可以轻松地创建bean并将它们彼此连接起来。如果以这种方式注册您的远程服务,则可以在blueprint的帮助下设置任何属性(就像spring applicationcontext.xml中bean的属性一样)。
您可以在https://source.everit.biz/svn/everit-osgi/trunk/samples/jaxrs/ (user/passwd: guest/guest)上找到我制作的示例应用程序。有一份指南解释了如何在http://cookbook.everit.org上启动和开发这些示例
我希望示例应用程序能帮助您开始学习远程服务规范一章。
要了解如何使用JPA和注入(蓝图),您应该查看OSGi compendium规范的可能性,并找到您喜欢的实现。我还制作了一个基于blueprint和hibernate-jpa的示例项目,您可以找到它作为我已经提供的示例url的兄弟。
更新
还有一个我在https://github.com/everit-org/osgi-remote-jersey上做的JAXRS扩展器实现。有关文档,请参阅自述文件。它与第一个的不同之处在于,它基于白板服务属性工作。
发布于 2012-06-26 18:58:05
我在使用OSGi、声明性服务和Jersey时遇到过类似的问题。
资源可以用@Component和@Reference注解。这将指示DS创建SomeResource类的实例,并在满足所有依赖项(引用)时将有效引用注入到此实例中。
引用为空的原因是因为JAX-RS实现将为每个web请求创建一个新的SomeResource类实例。此SomeResource类实例与DS创建的实例不同。
我用Java static关键字将引用变量设为static,从而解决了这个问题:
private static SomeService service = null;这确保了依赖项引用绑定到类对象,而不是绑定到实例,然后所有实例都可以看到注入的值。
这个解决方案引入了一个新问题。此引用必须在解除绑定事件时清除(当服务不可用时),因为销毁实例时不会销毁此引用。
发布于 2012-08-28 16:34:03
当@Path注释的类型被注册为服务本身时,这个问题就会得到解决。使用DS,您可以不仅仅是注入其他服务。近一年前,我自己也曾遇到过这个问题。这就是为什么我写了一个小的OSGi JAX-RS连接器,它提供了我所描述的内容。如果你喜欢,可以试一试:https://github.com/hstaudacher/osgi-jax-rs-connector
https://stackoverflow.com/questions/10200347
复制相似问题