Gestión de servicios en OSGi
22 diciembre 2008 at 9:47 pm Deja un comentario
Anteriormente hemos visto en este blog la gestión de dependencias en OSGi. En esta entrada vamos a ver OSGi desde el punto de vista de un servicio.
Un servicio lo podemos declarar como un interface que debe implementar el proveedor de ese servicio y que utilizarán los consumidores del servicio. Lógicamente, ese interface debe ser accesible tanto al proveedor como al consumidor. Aquí lo voy a poner en el módulo proveedor del servicio y dicho módulo lo exportará, pero podría estar en un módulo aparte para separarlo de la implementación.
Para esta entrada utilizaré un teórico servicio proveedor de mensajería SMS, cuyo interface será:
package org.tcymu.osgi.sms.interfaces; public interface ISmsProvider { public void sendMessage(String number, String text); }
Los servicios en OSGi se registran manualmente, es decir, no se resuelven automáticamente como las dependencias. Para registrar un servicio nos valemos del interface BundleActivator
ya visto en entradas anteriores. De esta forma, al iniciarse el proveedor de un servicio lo registraremos y al pararse desharemos el registro. Vamos a ver el código:
package org.tcymu.osgi.sms; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.tcymu.osgi.sms.interfaces.ISmsProvider; public class SmsBundleActivator implements BundleActivator { private SmsProvider smsProvider; private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { System.out.println("Starting SmsProvider"); smsProvider = new SmsProvider(); serviceRegistration = bundleContext.registerService(ISmsProvider.class.getName(), smsProvider,null); } public void stop(BundleContext bundleContext) throws Exception { System.out.println("Stopping SmsProvider"); serviceRegistration.unregister(); } }
La parte importante es el registro mediante el BundleContext
que se nos pasa en el start
de nuestro servicio. Para ello llamamos al método registerService
(guardando el ServiceRegistration
que nos devuelve) con los siguientes parámetros:
String
que representa el nombre de la clase que representa el servicio.- Proveedor del servicio. En este caso una simple implementación que sólo hace un
System.out
(esta implementación va también en este módulo). - Instancia de
java.util.Dictionary
(básicamente unaHashtable
) que representa unas propiedades del servicio. En este caso no pasamos nada, pero se podría pasar una versión o cualquier otro dato que pudiera ser necesario.
También podemos apreciar que en el stop
, deshacemos el registro mediante el método unregister
del ServideRegistration
que hemos guardado.
Como hemos visto en entradas anteriores, necesitamos declarar las propiedades del módulo en el MANIFEST.MF
. No hay novedades respecto a lo ya visto en otras entradas. Las líneas más interesantes son:
Bundle-Activator: org.tcymu.osgi.sms.SmsBundleActivator Export-Package: org.tcymu.osgi.sms.interfaces;version="1.0.0"
Si creamos el jar y lo instalamos en Felix (en este caso la versión 1.4.0) recibimos el mensaje esperado.
La parte interesante viene con el comando de Felix services
, que nos lista los servicios disponibles en el contenedor. En su salida podemos ver entre algunos servicios propios de Felix, el nuestro:
Ahora es el turno de crear el cliente para nuestro servicio. Lo pongo todo en una sencilla clase:
package org.tcymu.osgi.smsclient; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.tcymu.osgi.sms.interfaces.ISmsProvider; public class SmsClient implements BundleActivator { public void start(BundleContext bundleContext) throws Exception { System.out.println("Starting SmsClient"); ServiceReference smsServiceRef = bundleContext.getServiceReference(ISmsProvider.class.getName()); ISmsProvider smsProvider = (ISmsProvider)bundleContext.getService(smsServiceRef); smsProvider.sendMessage("555555555", "Tus ceros y mis unos"); } public void stop(BundleContext bundleContext) throws Exception { System.out.println("Stopping SmsClient"); } }
Como podemos ver, primero se obtiene el ServiceReference
a través del contexto de módulos (BundleContext
). Y con esa referencia ya obtenemos la implementación del servicio también a través del contexto.
Si lo empaquetamos y arrancamos vemos que efectivamente se está utilizando el servicio.
Esta no será la última entrada dedicada a OSGi en este blog, o sea que todos los interesados… ¡a suscribirse!.
Trackback this post | Subscribe to the comments via RSS Feed