Hola Mundo con OSGI
Veamos un Hola Mundo con OSGI
El IDE[editar]
Dentro de las diversas distribuciones de eclipse, la adecuada para OSGI es la Eclipse RCP and RAP developers, pero también podemos usar el Eclipse IDE for Java EE developers, y seguramente muchos más de los otros. Así que si el que tenemos instalado lo soporta bien, si no, nos lo descargamos https://www.eclipse.org/downloads/
Crear el proyecto Plug-in[editar]
Creamos un proyecto nuevo de tipo Plug-in Project. Aparece una ventana en la que rellenaremos el nombre del proyecto, OSGIHelloWorld en nuestro ejemplo, y el framework en el que vamos a querer correr nuestro plugin (eclipse, equinox o estándar). Elegimos equinox para poder correrlo luego fuera de eclipse. El resto de opciones las dejamos por defecto o las cambiamos si queremos. Pulsamos Siguiente.
En la siguiente ventana aparecen unos datos para rellenar de nuestro plug-in, como se ve en la siguiente imagen
Algunos campos vienen rellenos, como el id, la versión y el nombre, que podemos dejar como están o cambiar. Rellenamos el vendor (proveedor) con nuestro nombre/marca si queremos. El plug-in (o bundle si usamos el vocabulario de OSGI) tiene una clase principal, que se denomina Activator. En esta ventana ponemos cual será esa clase, con su paquete y nombre de clase. En nuestro ejemplo será com.chuidiang.ejemplos.osgi.Activator. Aunque Activator es el nombre estándar, podemos poner el nombre que queramos a esta clase. Dejamos el resto de opciones como está y pulsamos Siguiente.
Aparece una nueva ventana en la que elegimos el tipo de plug-in/bundle que queremos crear. Para evitar escribir código, elegimos la opción Hello OSGI Bundle. Pulsamos Siguiente.
El bundle Hola Mundo mostrará dos mensajes, uno de bienvenida cuando arranque, otro de despedida cuando pare. La ventana nos pide ambos mensajes. Dejamos por defecto lo que pone o cambiamos los textos por otros de nuestra eleción y pulsamos Finish.
Ver qué tiene el proyecto Plug-in[editar]
Veamos las partes importantes que se han creado.
El Activator[editar]
Se ha creado la clase java que es la que habíamos indicado en la creación que queríamos que fuera nuestro Activator. Es la siguiente
package com.chuidiang.ejemplos.osgi; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ public void start(BundleContext context) throws Exception { System.out.println("Hello World!!"); } /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { System.out.println("Goodbye World!!"); } }
Es una clase que implementa la interface BundleActivator, que sólo tiene dos métodos, start() y stop(), a los que se llamará cuando el framework arranque o pare nuestro bundle. Ahí es donde se escriben los textos de bienvenida y despedida que habíamos puesto en las ventanas de creación del proyecto.
Los métodos reciben como parámetro un BundleContext, con el que nuestro Activator podría interactuar con el framework OSGI y a través de él con otros bundles. Pero esto va fuera del alcance de nuestro Hola Mundo.
El fichero de manifiesto[editar]
El fichero de manifiesto es un fichero manifiesto normal de un jar de java, pero para el caso de bundle, tiene algunas propiedades especiales que el framework OSGI es capaz de interpretar. El fichero generado es el siguiente
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: OSGIHelloWorld Bundle-SymbolicName: OSGIHelloWorld Bundle-Version: 1.0.0.qualifier Bundle-Activator: com.chuidiang.ejemplos.osgi.Activator Bundle-Vendor: com.chuidiang Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Import-Package: org.osgi.framework;version="1.3.0" Bundle-ActivationPolicy: lazy
Ahí vemos, como cosas interesantes:
- Bundle-Name es el nombre de nuestro bundle
- Bundle-SymbolicName es un identificador para nuestro Bundle, que debe ser único.
- Bundle-Version La versión de nuestro Bundle.
- Bundle-Activator El paquete y clase del Activator de nuestro bundle.
- Bundle-Vendor El proveedor del bundle.
- Bundle-RequiredExecutionEnvironment Entorno java requerido.
- Import-Package Paquetes externos requeridos, bien del entorno OSGI, bien de otros bundles. Nuestro bundle necesita el paquete org.osgi.framework, en su versión 1.3.0, porque es en ese paquete donde está el BundleContext que recibimos en nuestros métodos start() y stop().
- Bundle-ActivationPolicy Debemos poner esta línea y el único valor que admite es lazy. Si no la ponemos, el bundle no se arrancará de ninguna manera y necesitaremos hacerlo a mano desde alguna consola de comandos que nos ofrezca el framework OSGI (lo veremos más adelante).
Pudes ver todas estas propiedades en http://wiki.osgi.org/wiki/Category:Manifest_Header
build.properties[editar]
Si queremos exportar nuestro proyecto en un jar para poder correrlo fuera de eclipse, en este fichero están las indicaciones para eclipse sobre dónde están las cosas y qué se debe exportar.
source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .
Para generar el jar, en File -> export -> Deployable Plugin And Fragments, marcamos nuestro plug-in OSGIHelloWorld y Finish. Ya veremos más adelante cómo ejecutarlo.
Ejectuar desde Eclipse[editar]
Para ejecutar desde eclipse, debería bastar con darle al botón derecho del ratón sobre el proyecto para sacar el menú y Run As -> OSGI Framework. Pero esto, aunque arranca y funciona, da un montón de errores que posiblemente se deben a que el arranque que configura por defecto eclipse no es válido. Así que tendremos que configurar a mano nuestra propia configuración.
Para no partir de cero, ejecutamos como acabamos de indicar y podemos parar la ejecución, lo único que nos iteresa es que se cree una configuración de arranque, que se llamará automáticamente OSGI Framework. Ahora, con el menú de eclipse Run -> Run Configurations..., podemos editar y arreglar esta configuración.
En la ventana Bundles, aparece marcado nuestro Bundel OSGIHelloWorld y otro montón de Bundles en la parte inferior. Dejamos OSGIHelloWorld y desmarcamos temporalmente todos los demás. Se puede hacer fácilmente desmarcando la casilla Target Platform. Ahora, debajo de Target Platform, marcamos solo los siguientes
- org.apache.felix.gogo.command
- org.apache.felix.gogo.runtime
- org.apache.felix.gogo.shell
- org.eclipse.equinox.console
Usando la caja type filter text podemos encontrar estos bundles fácilmente para marcarlos. Nos debería quedar como la siguiente imagen
Ahora sí, podemos arrancar nuestro proyecto como OSGI Framework usando esta configuración y ya no tendremos errores. Al arrancar, saldrá la bienvenida de nuestro bundle OSGIHelloWorld, y un cursor de la consola de OSGI que nos permite arrancar o parar bundles.
Hello World!! osgi>
Si escribimos stop OSGIHelloWorld, veremos la despedida al pararse nuestro bundle y nuevamente el cursor
Hello World!! osgi> stop OSGIHelloWorld Goodbye World!! osgi>
Finalemente, escribiendo start OSGIHelloWorld, veremos nuevamente la bienvenida al ser arrancado de nuevo nuestro bundle.
Hello World!! osgi> stop OSGIHelloWorld Goodbye World!! osgi> start OSGIHelloWorld Hello World!! osgi>
Si no queremos esta consola, sino que nos interesa sólo arrancar nuestro bundle, sin posiblidad de pararlo o arrancarlo en caliente, podemos quitar los cuatro bundles que añadimos en la configuracion, pero en la pestaña de argumentos de la ventana de configuración, aparece la siguiente lista de argumentos
-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console
Debemos eliminar el -console que aparece, que es el que provoca el arranque de la consola de comandos. Si lo hacemos, al arrancar veremos nuestro Hello World!! y ninguna posibilidad de arrancar o parar nuestro bundle, salvo parando todo el framework OSGI.
Ejecutar sin eclipse[editar]
Para poder ejecutar nuestro bundle fuera de eclipse, debemos realizar un pequeño montaje. Puedes ver cómo queda todo en OSGI Stand Alone, fijándote en los ficheros txt para ver qué jars debería haber en cada directorio. Vamos a crear todo eso pasao a paso. Creamos un directorio en algún sitio para poner todo lo necesario, en nuestro ejemplo, lo llamaremos OSGIStandAlone. Dentro metemos el jar principal de osgi, que puede llamarse algo así como
org.eclipse.osgi_3.9.1.v20130814-1242.jar
y podemos buscarlo para copiarlo dentro del directorio plugins de donde tengamos instalado eclipse. El resto de jars necesarios, excepto el de nuestro bundle, también lo sacaremos de ahí. Por supuesto, los números de versión (__3.9.1.v20130814-1242) pueden ser distintos.
Ejecutar sin consola[editar]
En el directorio OSGIStandAlone, creamos dos subdirectorios más, uno llamado plugins donde meteremos todos los jar necesarios y el de nuestro bundle, y otro configuration donde meteremos el fichero de configuración de osgi.
Dentro de plugins, si sólo queremos ejecutar nuestro nuestro bundle y no queremos consola, sólo necesitaremos meter el jar de nuestro bundle, que obtenemos desde eclipse con el botón derecho del ratón del proyecto y Export... -> Deployable Plug-in and Fragments. A la hora de exportar elegimos un directorio, eclipse creará en ese directorio un subdirectorio plugins y meterá dentro nuestro jar. Por ello, a la hora de elegir el directorio, nos bastará elegir el directorio OSGIStandAlone.
Ahora vamos al directorio configuration, ahí debemos crear un fichero config.ini con el siguiente contenido
osgi.bundles=plugins/OSGIHelloWorld_1.0.0.201402161321.jar@start eclipse.application.launchDefault=false
Son dos propiedades, osgi.bundles en la que ponemos la ubicación del jar de nuestro bundle, con su path relativo plugins/ y terminado en @start para que sea arrancado.
La otra propiedad, eclipse.application.launchDefault, la ponemos a false para que osgi no intente buscar una aplicación por defecto para arrancar. Nuestro bundle es un bundle muy simple y no se registra como aplicación, así que no hay aplicación por defecto y obtendríamos error si no pusieramos esta propiedad a false (su valor por defecto es true).
Para arrancar esto, desde una ventana de comandos y en el directorio OSGIStandAlone escribimos
E:\PROYECTOS\OSGI\OSGIStandAlone>java -jar org.eclipse.osgi_3.9.1.v20130814-1242.jar -consoleLog Hello World!!
La opción -consoleLog es para que se muestre la salida de nuestro programa por pantalla. Si no lo ponemos, no habrá salida estándar y no veremos nuestro Hello World!!
Con Ctrl-C paramos la aplicación.
Arrancar con consola[editar]
Si queremos la consola que nos permita arrancar y parar nuestro bundle, debemos meter todos los jar de la consola que metimos en eclipse
org.apache.felix.gogo.command_0.10.0.v201209301215.jar org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar org.apache.felix.gogo.shell_0.10.0.v201212101605.jar org.eclipse.equinox.console_1.0.100.v20130429-0953.jar
y debemos añadir además los siguientes, de los que dependen los cuatro anteriores y que antes no poníamos porque eclipse ya los suministraba.
org.eclipse.core.contenttype_3.4.200.v20130326-1255.jar org.eclipse.core.jobs_3.5.300.v20130429-1813.jar org.eclipse.equinox.app_1.3.100.v20130327-1442.jar org.eclipse.equinox.common_3.6.200.v20130402-1505.jar org.eclipse.equinox.preferences_3.5.100.v20130422-1538.jar org.eclipse.equinox.registry_3.5.301.v20130717-1549.jar
Pudes ver la lista completa de jars necesarios en http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fconsole_shell.htm , en ella aparecen un par más de jars, pero no han sido necesarios para arrancar este ejemplo.
En resumen, dentro de plugins, debemos tener todo esto
Directorio de E:\PROYECTOS\OSGI\OSGIStandAlone\plugins 16/02/2014 14:01 <DIR> . 16/02/2014 14:01 <DIR> .. 19/09/2013 09:45 57.646 org.apache.felix.gogo.command_0.10.0.v201209301215.jar 19/09/2013 09:45 80.249 org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar 19/09/2013 09:45 60.827 org.apache.felix.gogo.shell_0.10.0.v201212101605.jar 19/09/2013 09:45 93.013 org.eclipse.core.contenttype_3.4.200.v20130326-1255.jar 19/09/2013 09:45 92.479 org.eclipse.core.jobs_3.5.300.v20130429-1813.jar 19/09/2013 09:45 73.635 org.eclipse.core.runtime_3.9.0.v20130326-1255.jar 19/09/2013 09:45 86.244 org.eclipse.equinox.app_1.3.100.v20130327-1442.jar 19/09/2013 09:45 106.701 org.eclipse.equinox.common_3.6.200.v20130402-1505.jar 19/09/2013 09:45 116.277 org.eclipse.equinox.console_1.0.100.v20130429-0953.jar 19/09/2013 09:45 127.170 org.eclipse.equinox.preferences_3.5.100.v20130422-1538.jar 19/09/2013 09:45 184.147 org.eclipse.equinox.registry_3.5.301.v20130717-1549.jar 16/02/2014 13:21 1.537 OSGIHelloWorld_1.0.0.201402161321.jar
En configuration, el fichero config.ini debe tener ahora el siguiente contenido
osgi.bundles=plugins/org.apache.felix.gogo.command_0.10.0.v201209301215.jar@start,\ plugins/org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar@start,\ plugins/org.apache.felix.gogo.shell_0.10.0.v201212101605.jar@start,\ plugins/org.eclipse.equinox.console_1.0.100.v20130429-0953.jar@start,\ plugins/OSGIHelloWorld_1.0.0.201402161321.jar@start,\ plugins/org.eclipse.equinox.common_3.6.200.v20130402-1505.jar@start,\ plugins/org.eclipse.core.jobs_3.5.300.v20130429-1813.jar@start,\ plugins/org.eclipse.equinox.registry_3.5.301.v20130717-1549.jar@start,\ plugins/org.eclipse.equinox.preferences_3.5.100.v20130422-1538.jar@start,\ plugins/org.eclipse.core.contenttype_3.4.200.v20130326-1255.jar@start,\ plugins/org.eclipse.equinox.app_1.3.100.v20130327-1442.jar@start eclipse.application.launchDefault=false
En la propiedad osgi.bundles hemos metido ahora todos los jar necesarios, separados por comas. Fíjate que se ha puesto el path relativo plugins/ para indicar que están dentro del directorio plugins y todos tienen un @start al final para que se los arranque. En realidad, este @start sólo es necesario en nuestro bundle, el resto se arrancarán cuando sean necesarios. Como todos ellos deberían estar en la misma línea del fichero, se pone el \ al final, justo delante del retorno de carro.
Una vez hecho todo esto, desde una ventana de comandos situda en el directorio OSGIStandAlone, ejecutamos el mismo comando de antes, pero añadiendo la opción -console
E:\PROYECTOS\OSGI\OSGIStandAlone>java -jar org.eclipse.osgi_3.9.1.v20130814-1242.jar -consoleLog -console
La ejecución nos mostrará lo mismo que veíamos en eclipse, pero esta vez en la vetana de comandos de nuestro sistema opearativo
E:\PROYECTOS\OSGI\OSGIStandAlone>java -jar org.eclipse.osgi_3.9.1.v20130814-1242.jar -consoleLog -console Hello World!! osgi> stop OSGIHelloWorld Goodbye World!! osgi> start OSGIHelloWorld Hello World!! osgi>