2012-04-17 10 views
6

Quiero migrar mi aplicación EE a OSGi. mi aplicación consiste en bibliotecas comerciales, bases de datos JPA/Entidades y una interfaz REST/WS. también tiene un cliente web.OSGi JAX-RS y servicio declarativo Bnd

Empiezo creando un prototipo de la estructura y haciendo que todas las interfaces y paquetes se comuniquen entre sí en una forma limpia de OSGi. Quiero utilizar una especificación limpia tanto como sea posible sin ningún proveedor o marco específico.

Estoy usando el complemento bnd maven para generar el manifiesto y los servicios declarativos. Quiero hacer una llamada de mis recursos de descanso a un servicio OSGi (en otro paquete) mediante la inyección de este modo:

@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 
    } 
    ... 

} 

¿Puedo anotar el recurso con BND @Component y se la @Resource inyectar? todo funciona bien, pero el servicio siempre es nulo.

¿Cuál debería ser la forma de declarar mi paquete para que BND lo convierta en un paquete web/wab?

utilizo paquete experto:

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

... 

con las instrucciones del BND

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

Recientemente me encontré con un problema similar (servicio no consiguió obligado) y lo rastreó a la [paquete dividido] (http://wiki.osgi.org/wiki/ Split_Packages) problema. ¿Has intentado poner tu interfaz de servicio en un paquete separado? –

+0

gracias @ BjörnPollex por la sugerencia. Tengo 3 paquetes, uno con interfaces solamente, uno con la implementación del servicio y el bundel REST. De hecho, lo moví de vuelta al bundel REST para ver si funcionaba, pero no tuve suerte. Si lo que estoy haciendo es correcto, quizás el problema esté en que el SCR no encuentre mi DS xml. – Gadi

+0

gracias por editar @donalfellows – Gadi

Respuesta

5

OSGi tiene una parte de la especificación llamada de servicios remotos. En resumen, funciona de la manera en que puede registrar servicios con propiedades de servicio especiales y, en función de las propiedades, las tecnologías deben elegir su servicio y crear un punto final a partir de ellos. No se trata solo de REST sino de cualquier tecnología que maneje llamadas remotas. Puede encontrar información en la especificación de OSGi Core en el capítulo "Servicios remotos".

Bueno, es una especificación, pero ¿quién lo implementa? Actualmente hay dos proyectos más grandes que probé. CXF DOSGi y Eclipse ECF. Ofrecen varias tecnologías que admiten la especificación de servicios remotos. CXF especialmente upports Jax-RS basado en su implementación en el lado del servidor y del cliente.

Como no quería utilizar soluciones específicas de Spring dentro de OSGi, no usé CXF al final, sino que creé mi propia solución. Se basa en Jersey y la especificación de servicios remotos. Cuando se especifica un servicio OSGi con el servicio.exported.interfaces = * y el servicio.exported.configs = org.everit.osgi.remote.jersey creará un punto final de reposo en/rest/path con HttpService. Su paquete no tiene que ser un wab, puede ser un paquete simple.

Debo mencionar que si expone sus servicios a través de cualquiera de las implementaciones de Servicios remotos, debe tomar las anotaciones Jax-RS en una interfaz implementada por su clase original y exponer su servicio basado en esa interfaz.

En lugar de las anotaciones @Resource y @Component dentro de OSGi, sugiero que debe usar Blueprint (parte de la especificación OSGi) que es sorprendentemente similar a Spring. Actualmente, Apache Aries y Gemini Blueprint lo implementan. Con blueprint puede crear fácilmente frijoles y conectarlos entre sí. Si registra su servicio remoto de esta manera, puede configurar cualquiera de las propiedades con la ayuda de blueprint (al igual que la propiedad de un bean en la primavera applicationcontext.xml).

Puede encontrar una aplicación de muestra que hice en https://source.everit.biz/svn/everit-osgi/trunk/samples/jaxrs/(user/passwd: guest/guest).Existe una guía que explica cómo se pueden iniciar y desarrollar estas muestras en http://cookbook.everit.org

Espero que la aplicación de muestra lo ayude a comenzar con el capítulo de especificaciones de Servicios remotos.

Para ver cómo utilizar JPA e Inyección (Blueprint) debe comprobar la especificación OSGi compendio de posibilidades y encontrar la aplicación que desee. También hice un proyecto de muestra basado en blueprint e hibernate-jpa que puede encontrar como el hermano de la URL de ejemplo que ya proporcioné.

actualización

También hay una aplicación extensor JAXRS que hice en https://github.com/everit-org/osgi-remote-jersey. Ver el LÉAME para la documentación. Es diferente del primero en la forma en que funciona en función de las propiedades del servicio de pizarra.

2

he experimentado un problema similar con OSGi, Servicios declarativos y Jersey.

Un recurso puede ser anotado con @Component y @Reference anotaciones. Esto le indicará a DS que cree una instancia de la clase SomeResource e inyecte una referencia válida en esta instancia cuando se satisfagan todas las dependencias (referencias).

La razón por la que sus referencias son nulos se debe a la implementación de JAX-RS creará una nueva instancia de la clase unRecurso para cada solicitud Web. Esta instancia de la clase SomeResource no es la misma que la creada por DS.

I resuelto este problema al hacer variable de referencia estático con Java palabra clave estática:

private static SomeService service = null; 

Esto aseguró que una referencia dependencia está ligado a un objeto de clase en lugar a una instancia y luego todos los casos podría ver el valor inyectado .

Esta solución presenta un nuevo problema. Esta referencia debe borrarse en el evento de desvinculación (cuando el servicio deja de estar disponible) porque no se destruirá cuando se destruya una instancia.

+0

Almacenar referencias estáticas a los componentes de osgi no es una buena idea. –

0

El problema se resolvería cuando el tipo de @Path anotada se registra como un servicio en sí. Con DS puedes simplemente inyectar otros servicios. Me enfrenté a este problema yo mismo hace casi un año. Es por eso que escribí un pequeño conector OSGi JAX-RS que le da exactamente lo que he descrito. Darle una oportunidad si te gusta: https://github.com/hstaudacher/osgi-jax-rs-connector

Cuestiones relacionadas