Creando aplicaciones OSGI con Apache Felix

17-05-2016
 
OSGI Architecture

OSGI Architecture

OSGI(Open Services Gateway initiative) es la solución que aporta Java a la programación modular. Un módulo es un componente auto-contenido con una funcionalidad perfectamente delimitada dentro de un sistema mayor.

Los módulos OSGI pueden ser arrancados y parados en caliente(Sin tener que para y reiniciar un servidor), pueden comunicarse entre ellos y además pueden recibir avisos cuando otro módulo es arrancado o parado.

En el siguiente ejemplo vamos a ver como crearíamos un módulo OSGI y como interactuaría con el contenedor OSGI.

Arrancando Apache Felix

Lo primero que necesitamos para crear nuestra aplicación OSGI es un contenedor de módulos OSGI. En este caso me he decantado por Apache Felix. Para arrancar nuestro contenedor los podemos descargar de la web y ponerlo en marcha mediante el siguiente comando(Importante hacerlo en la misma carpeta FELIX_HOME):

<FELIX_HOME>/java -jar bin/felix.jar

Esto nos abre una consola desde donde podemos manejar el contenedor: Consultar los módulos ejecutando el comando ‘lb'(List Boundles), arrancar/parar módulos con ‘start <module ID>’/’stop <module ID>’, instalar un nuevo módulo con ‘install <path al .jar>’ o ver el listado de comandos con ‘help’ entre otros.

Creando nuestro primer módulo OSGI

Nuestro primer módulo(Bundle) OSGI, será básicamente, una aplicación que se arrancará, parará y mantendremos escuchando cuando se activen o desactiven nuevos módulos. La classe principal de nuestro proyecto será:

package com.lostsys.osgi1;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceEvent;

public class Activator implements BundleActivator, ServiceListener {

    public void start(BundleContext context) {
        System.out.println("Arrancando!");
        context.addServiceListener(this);
    	}

    public void stop(BundleContext context) {
        context.removeServiceListener(this);
        System.out.println("Parando!");
    	}

    public void serviceChanged(ServiceEvent event) {
        String[] objectClass = (String[])
            event.getServiceReference().getProperty("objectClass");

        if (event.getType() == ServiceEvent.REGISTERED)
        {
            System.out.println(
                "Ex1: Service of type " + objectClass[0] + " registered.");
        }
        else if (event.getType() == ServiceEvent.UNREGISTERING)
        {
            System.out.println(
                "Ex1: Service of type " + objectClass[0] + " unregistered.");
        }
        else if (event.getType() == ServiceEvent.MODIFIED)
        {
            System.out.println(
                "Ex1: Service of type " + objectClass[0] + " modified.");
        }
    }
}

El fichero ‘manifest.mf’

Un módulo OSGI es básicamente una aplicación Java con un fichero ‘manifest.mf’ donde se configura el módulo. En nuestro caso:

Bundle-Name: Mi proyecto OSGI 1
Bundle-Description: Mi proyecto OSGI 1
Bundle-Vendor: Apache Felix
Bundle-Version: 1.0.0
Bundle-Activator: com.lostsys.osgi1.Activator
Import-Package: org.osgi.framework

Compilamos y empaquetamos el JAR

Ahora ya solo nos queda compilar el proyecto(Teniendo en cuenta que necesitamos Apache Felix) y empaquetarlo en un jar:

# compilamos
javac -cp "../../bin/felix.jar" -d ./classes src/com/lostsys/osgi1/Activator.java

# empaquetamos el jar
jar cfm osgi1.jar manifest.mf -C ./classes .

Desplegamos en Apache Felix

Finalmente, desde la consola de Apache Felix instalamos el módulo y lo arrancamos:

# Instalamos el jar
install /path-al-fichero/osgi1.jar

# Vemos el listado de módulos instalados
lb

# Arrancamos el módulo(El ID lo vemos en el listado de arriba)
start <ID de módulo>
Apache Felix OSGI Console

Apache Felix OSGI Console

Conclusiones

OSGI es una genialidad que nos va a permitir crear productos mas configurables y permitirá que mas equipos de desarrolladores que no se conozcan trabajen juntos en esto productos.

Leave a Reply

© Albert Coronado Calzada