Este documento describe OSGi, una plataforma de servicios modular para Java. OSGi define un framework que permite la instalación, actualización y eliminación dinámica de módulos o bundles. Los bundles son archivos JAR que pueden publicar y consumir servicios. El ciclo de vida de los bundles está controlado por el framework OSGi.
4. Modularidad
OOP
Paquetes/Librerías
Cohesion
Acoplamiento
División del trabajo
Abstracción
Reutilización
Mantenimiento
5. Modularidad
Ejemplo:
Sistema de gestión de películas
6. Ficheros JAR
¿Son módulos?
Classpath compartido
No restringible
No admite versiones
No hay dependencias
Condicionado por el orden
Problemas de visibilidad
…
7. Inversión del Control
Contenedor
Control de las dependencias
Classpath específico de cada JAR
Gestionar las Clases compartidas
9. Bundle
Implica modularidad física de Clases
Implica unidades de despliegue
Permite restringir el acceso externo a Clases
10. ¿Qué es OSGi?
Open Service Gateway initiative
Plataforma de Servicios
OSGi Framework
OSGi Standart Services
OSGi Alliance (www.osgi.org)
Versión 4
11. ¿Qué es OSGi?
OSGi Framework
Entorno de ejecución Java
Portable y seguro
Gestor de servicios
Sistema de módulos
Escalable y ligero
Dinámicamente instalables y actualizables
13. ¿Qué es OSGi?
Implementaciones
Apache Felix (http://felix.apache.org)
Eclipse Equinox (www.eclipse.org/equinox)
Knopflerfish (www.knopflerfish.org)
14. ¿Qué es OSGi?
Eclipse Equinox (www.eclipse.org/equinox)
Muy ligero
java –jar org.eclipse.osgi_3.8.0.v20120529-1548.jar
–console
Integrado en Eclipse
Run Configurations > OSGi Framework
15. ¿Qué es OSGi?
Apache Felix (http://felix.apache.org)
Ligero
Intérprete de Comandos Gogo
No integrado con Eclipse
Configurable con Pax Runner
http://www.ops4j.org/pax/eclipse/update/
Entorno de ejecución embebido
Run Configurations > OSGi Framework
Entorno Felix v2.0.1
23. Tecnologías relacionadas
Spring
Contenedor ligero
Inyección de dependencias
Sin módulos dinámicos
Portando infraestructura a OSGi
24. Tecnologías relacionadas
JSR
JSR 277: Java Module System
Propuesta de Sun alternativa a OSGi
JSR 291: Dynamic Component Support for Java
Mejora apoyada en OSGi
JSR 294: Improved Modularity Support
Intento de mejorar la visibilidad de módulos
25. Tecnologías relacionadas
Service Component Architecture
Modelo de componentes para SOA
Integra BPEL, SOAP, JMS, JCA,..
No define formato de módulos
26. ¿Cómo funciona?
MANIFEST.MF
Formato “nombre: valor”
Admite atributos y directivas
Máximo 72 caracteres/línea
Información legible
Identificación del bundle
Visibilidad externa del código (paquetes)
Dependencias de paquetes
30. ¿Cómo funciona?
Resolución de dependencias
Transitiva
Restringida en importación
vendor
version
…
Prioridad a la versión
Prioridad a la instalación
Prioridad a la resolución
31. ¿Cómo funciona?
Resolución de dependencias
Directiva uses
Restringe las importaciones de los clientes
Export-Package: org.osgi.service.http;
uses:="javax.servlet"
Import-Package: javax.servlet; version=2.3.0
32. Ejercicio
Desplegar un bundle
public class Dao {
public void sql(String message) {
System.out.println(message + " v1");
}
}
Un cliente del bundle y su activador
public class Cliente {
public void listar() {
new Dao().sql("SELECT * FROM Tabla");
}
}
33. Ejercicio
Crear una nueva versión del bundle
public class Dao {
public void sql(String message) {
System.out.println(message + " v2");
}
}
Desplegar y refrescar el bundle y su cliente
Modificar la interfaz del bundle
Restringir la versión máxima del cliente
34. Ejercicio
Crear una nueva versión del cliente
Ejecutarla con la 1.0 en ejecución
Restringirla al bundle 1.1
Ejecutar cliente y bundle 1.0
Ejecutar cliente y bundle 1.1
Refrescar cliente 1.0
35. Ciclo de Vida
El Framework OSGi controla el ciclo de vida
de los bundle
install
update
start
stop
uninstall
36. Interacción con el Lifecycle
Lifecycle Layer gestiona los bundles
Resolviendo dependencias
Permitiendo
install
update
uninstall
start
stop
37. BundleActivator
Interfaz de control del ciclo de vida
Implementar y referenciar en el manifest.mf
Métodos start y stop de retorno rápido
Acceso al contexto del bundle
BundleContext
Instalar/desinstalar bundles
Obtener todos o uno por id
…
38. Eventos
BundleListener
Recibe eventos de los bundles
bundleChanged()
BundleEvent
INSTALLED
RESOLVED
STARTED
STOPED
UPDATED
UNINSTALLED
UNRESOLVED
39. Eventos
FrameworkListener
Recibe eventos de OSGi
FrameworkEvent
STARTED
INFO
WARNING
ERROR
STARTLEVEL_CHANGED
PACKAGES_REFRESHED
40. Eventos
SynchronousBundleListener
Recibe eventos antes que BundleListener
bundleChanged()
BundleEvent
STARTING
STOPING
41. Eventos
Se registran contra el BundleContext
Método addListener()
Se eliminan mediante
removeBundleListener()
removeFrameworkListener()
42. Ejercicio
Crear un observador de eventos
Que muestre mensajes del bundle y el
evento implicados
Recargar los bundles
Desinstalar 1.1
Refrescar cliente 1.1
47. Ejercicio
Convertir en Servicio
Crear una interfaz Dao
Crear una implementación en distinto paquete
Se exportará el de la interfaz
No se exportará el de la implementación
Crear un Activador que registre la implementación
Y desregistre en el stop
48. Ejercicio
Crear un consumidor
Crear un Thread implementando Runnable
Que utilice la interfaz
void start() { public void run() {
stop = false; while (!stop) {
new Thread(this) printer.print("Hola...");
.start(); try {
} Thread.sleep(TWO_SECS);
} catch (InterruptedException e) {
void stop(){ stop = true;
stop = true; }
} }
}
49. Ejercicio
Crear un activador del consumidor
Que instancie el cliente
Que busque el servicio
getServiceReference()
getService()
Castear a la interfaz de servicio
Arrancar el Consumidor
Detenerlo en el stop
50. ServiceFactory
Instanciación de servicios
Registrarla en lugar del servicio
Métodos getService() y ungetService()
Permite implementar patrones creacionales
Y modificar el ciclo de vida
52. Consejos y trucos
Mantener los paquetes privados
Si SOLO se va a usar desde un bundle
Incluir la librería en éste META-INF/MANIFEST.MF
lib/mylegacy.jar
Bundle-Classpath manning/osgi/MyClass.class
Bundle-ClassPath: .,lib
Si se va a usar desde más bundles
Crear un bundle propio y referenciarlo
53. Consejos y trucos
Evitar los bundles requeridos
Ven todos los Exported-Packages del requerido
Incluso de manera transitiva
Bundle-SymbolicName: B1
Require-Bundle: B2; visibility:=reexport
Restringir las clases exportadas
Directivas include y exclude de Export-Package
Export-Package: manning.osgi.test;
include:="Foo*, Bar"; exclude:=FooImpl
54. Consejos y trucos
Desacoplar Bundles mediante servicios
Importar únicamente interfaces
Publicar Bundle-implementaciones
Mediante su propio Activador
Restringir la resolución del consumidor con
propiedades
md4Properties.put("PERFORMANCE", "FAST");
55. Consejos y trucos
Desacoplar Bundles mediante servicios
Usar filtros para restringir por propiedades
String filter =
"(&(objectClass=" + Servicio.class.getName() + ")" +
"(PERFORMANCE=FAST))";
Usar la Propiedad de ranking para priorizar
md5Properties.put(Constants.SERVICE_RANKING, 10);
Usar la Propiedad de PID para identificar
servicios de manera unívoca
properties.put(Constants.SERVICE_PID, "10.0.0.1");
56. Consejos y trucos
Uso de fragmentos
Bundles degenerados
Se resuelven después del Bundle Host
Pero deben instalarse antes que éste
No pueden tener Activador
Permiten aumentar el manifiesto
Añadir un Import-Package propio
Fragment-Host: symbolic-name-del-host-bundle
57. Consejos y trucos
Carga dinámica de bundles
Por ej.: Acceso a BBDD con reflexión
DynamicImport-Package
Último recurso de resolución que admite *
Se carga en ejecución, no en resolución
DynamicImport-Package: org.apache.derby.jdbc
Paquetes opcionales
Import-Package: x.y.z;resolution:=optional
58. Consejos y trucos
Acceso a detalles del bundle
OSGi 4.3 tiene un Wiring Framework
BundleRevision revision =
bundle.adapt(BundleRevision.class);
List<BundleCapability> exportPackage =
revision.getDeclaredCapabilities(
BundleRevision.PACKAGE_NAMESPACE);
List<BundleRequirement> importPackage =
revision.getDeclaredRequirements(
BundleRevision.PACKAGE_NAMESPACE);
59. Consejos y trucos
Acceso a detalles del bundle
OSGi 4.3 tiene un Wiring Framework
Recorrer detalles de especificación
for (BundleCapability capability : capabilities) {
Map<String, Object> attributes =
capability.getAttributes();
System.out.println(
attributes.get("osgi.wiring.package") +
" version " + attributes.get("version")
);
}
60. Consejos y trucos
Acceso a detalles del bundle
OSGi 4.3 tiene un Wiring Framework
Obtener enlaces/resoluciones en ejecución
List<BundleWire> providedWires =
revision.getWiring().getProvidedWires(
BundleRevision.PACKAGE_NAMESPACE);
for (BundleWire bundleWire : providedWires) {
Bundle cliente =
bundleWire.getRequirerWiring().getBundle();
Bundle proveedor =
bundleWire.getProviderWiring().getBundle();
}
63. Clientes Remotos
Bundle de comunicación
Clase ServiceTracker
Equivalente al ServiceReference
Método open() para iniciar el tracking
Método addingService() al encontrar servicios
Fichero XML de endpoints
OSGI-INF/remote-services/remote-services.xml
64. Clientes Remotos
Service Tracker
Clase asociada al contexto y a la interfaz
open() y close() registran Listeners internos
Instanciarlo en un Activador
Ejecutar el open() en start()
Invocar a getService()
Admite ServiceTrackerCustomizer
Eventos del servicio
addingService() y removedService()
67. OSGi y J2EE
2 opciones
Embeber un servidor ligero en OSGi (Jetty)
Práctico en fase de desarrollo
Embeber OSGi en una aplicación Web
Eficiente en fase de despliegue
68. OSGi y J2EE
Crear un bundle con su activador
Crear un Servlet
Crear un directorio para las páginas Web
Extender ServiceTracker
Obtener el servicio HttpService de contexto
Registrar recursos y servlets
Liberarlos en removedService()
Instanciarlo, abrirlo y cerrarlo en el activador
69. OSGi y J2EE
Equinox tiene un bridge.war
http://www.eclipse.
org/equinox/server/http_in_container.php
Plantilla de AppWeb con contexto /sp_test
Con un OSGi embebido en la consola Tomcat
BridgeServlet que hace de FrontController
Desplegar los bundle web en
WEB-INFEclipseplugins
Y arrancarlos desde consola
70. Depuración
Arrancar el framework en modo remoto
java –Xdebug -Xrunjdwp:transport=
dt_socket,address=8787,server=y,suspend=n
-jar framework.jar
Suspend indica que se pare en arranque
Crear un Debug Configuration en Eclipse
Remote Java Application
Indicar el puerto
Poner los puntos de ruptura y ejecutar OSGi
71. Eclipse Plugins
Formato de bundle especial
Con un activador estandart: AbstractUIPlugin
Métodos getDefault() y getImageDescriptor()
Configurado mediante plugin.xml
Extensiones de la interfaz de Eclipse
Views, ayuda contextual, menús,…
72. Eclipse Plugins
Ejemplo
Plugin con Custom Templates
Seleccionar Popup Menu y View
Asociar el Popup con org.eclipse.ui.IEditorInput
Configurar la categoría de la vista
Finish
Añadir más opciones al menú
Invocarán al método run() de la clase asociada