Modularizzare Java con JBoss

IV parte: Il modulo OSGi di JBossdi

Continuiamo a illustrare i concetti di modularizzazione presenti in JBoss. Uno dei moduli più interessanti è quello OSGi, che risulta molto interessante poiché il framework OSGi definisce un ciclo di vita per ogni modulo, permette di esporre anche versioni differenti dello stesso modulo che possono anche convivere contemporaneamente nello stesso contenitore OSGi. Dopo l'introduzione di questa parte, nel prossimo articolo vedremo un esempio in pratica.

Introduzione

Le specifiche OSGi [1] definiscono un ambiente di servizi modulari che permettono di implementare servizi in maniera standardizzata seguendo l'approccio component-oriented. Si tratta dunque di uno standard che permette di implementare dei servizi definiti mediante dei moduli che espongono solamente il codice inerente il contratto da implementare.

Non tutte le classi/interfacce pubbliche possono essere esportare agli altri moduli: è la definizione del modulo stesso che determina cosa esportare e cosa deve rimanere privato; inoltre il framework OSGi definisce un ciclo di vita per ogni modulo, permette di esporre anche versioni differenti dello stesso modulo che possono anche convivere contemporaneamente nello stesso contenitore OSGi.

Ogni modulo definisce inoltre delle dipendenze da altri moduli mediante nomi di pacchetti o mediante nomi di moduli e versioni; le dipendenze vengono risolte dal contenitore che permette così di isolare correttamente le classi al loro interno e di gestire la convivenza di stesse classi di versioni diverse nello stesso runtime.

In questo articolo, vedremo una panoramica su OSGi e nel prossimo articolo presenteremo un esempio.

Il framework OSGi

Il framework OSGi è diviso in moduli, ognuno dei quali offre dei servizi. I layer (livelli) in cui è suddiviso sono i seguenti:

  • Security Layer (opzionale)
  • Module Layer
  • Life Cycle Layer
  • Service Layer
  • Actual Services

 

Figura 1 - La struttura del framework OSGi.

 

Security layer

Il livello per la sicurezza è opzionale, e non è stato implementato nel framework JBoss-OSGi.

Questo livello permette di determinare se un modulo può essere caricato o meno basandosi sulla firma digitale dei moduli o anche sulla locazione dove si trovano (locali/remoti e su quale macchina girano). Inoltre per ogni modulo può essere specificato che tipo di operazioni possono fare (per esempio solo controllare il ciclo di vita di altri moduli).

Questo livello non è stato implementato in JBoss; inoltre il container OSGi può caricare solo codice (moduli) in locale e non in remoto, di conseguenza questo layer può effettivamente risultare superfluo.

Module layer

In questo layer vengono definiti cosa sono i moduli e come possono interagire tra loro.

Secondo lo standard OSGi, un modulo viene chiamato bundle, e è composto da classi Java e altre risorse, tra cui il descrittore di modulo.

Il descrittore contiene una serie di informazioni sul modulo, tra i quali i seguenti.

  • Bundle activator: è la classe che implementa il ciclo di vita del bundle;
    Bundle symbolic name: è il nome simbolico del bundle;
  • Bundle version: è la versione di questo bundle;
  • Export/import packages: sono le proprietà che indicano quali sono i pacchetti che questo modulo esporta ad altri moduli, e da quali pacchetti dipende. Inoltre per ogni pacchetto da importare vengono specificate anche le versioni valide, cioè un range di valori numerici accettati dal bundle.

In un recente articolo su JBossModules, abbiamo parlato di dipendenze tra moduli specificate in base al nome dei moduli: per esempio un modulo A definisce una sua dipendenza da un modulo B (con una certa versione).

Quando si parla di modularità offerta da OSGi si parla invece di pacchetti e non di moduli; il motivo è semplice: definendo la dipendenza di un modulo da un certo numero di pacchetti si permette di disaccoppiare in maniera pressocchè assoluta due moduli tra loro. L'idea che sta dietro questa scelta è di dire da quali servizi dipende un modulo, indipendentemente da quali siano i moduli che implementano tali servizi.

Inoltre le versioni vengono specificate con un range di valori validi, per esempio

[versioneMinima, versioneMassima)

dove le parentesi tonde vengono usate per indicare un limite non incluso, mentre  la parentesi quadra un limite incluso. Ecco un esempio di dipendenza:

Import-Package: org.moka.osgi;version="[1.2, 4.0)", 
org.moka.jboss;version="[2.0, 4.0]"

La modularità espressa da OSGi è quindi molto più flessibile di quella offerta da JBossModules, permette quindi di poter sostituire a run-time dei moduli a patto che esportino gli stessi pacchetti in modo tale da poter sempre validare le dipendenze di altri moduli. Questo meccanismo è molto utile quando si vuole testare un modulo senza dover installare i moduli di produzione e quindi utilizzando delle classi di test.

In questo esempio si vede come le dichiarazioni di Import-Package ed Export-Package permettono di risolvere le dipendenze:

Modulo A: Import-Package: org.moka.osgi;version=[1.2, 4.0)
Modulo B: Export-Package: org.moka.osgi;version=1.4.1
Modulo C: Export-Package: org.moka.osgi;version=3

Da qui si vede che il modulo A importa il servizio espresso dal modulo B e non dal modulo C.

Figura 2 - Interazioni fra i servizi OSGi.

 

Life cycle layer

Questo livello definisce il ciclo di vita di ogni bundle: l'oggetto Bundle Activator risponde alle callback definite in questo livello (se presente nel modulo).

Gli stati in cui si può trovare il bundle sono:

  • installed: il bundle è installato nel contenitore;
  • resolved: il contenitore ha verificato le sue dipendenze e il modulo è pronto a partire;
  • starting: il modulo viene fatto partire;
  • active: il modulo è attivo, in "running";
  • stopping: il modulo è stato fermato;
  • uninstalled: il modulo è stato cancellato dal contenitore.

Figura 3 - Il ciclo di vita di un bundle.

 

Service layer

Il service layer si occupa di implementare quei servizi che devono essere interrogati quando cambia lo stato di un qualsiasi servizio senza dover interrogare direttamente il servizio stesso.

Il service layer è un servizio registrato nel contenitore OSGi e può essere interrogato proprio per ispezionare dinamicamente lo stato dei bundle installati nel contenitore. JBoss implementa non solo questo layer (che è obbligatorio), ma implementa anche due servizi aggiuntivi che semplificano di molto l'utilizzo del service layer, e che sono:

  • OSGi Declarative services;
  • OSGi Blueprint services.

Questi due servizi sono opzionali, e vanno sotto il nome di OSGi Service Compendium, fanno parte di tutta una serie di servizi opzionali che hanno lo scopo di integrare OSGi con Java EE e di definire (in maniera più generica) dei servizi di base che qualsiasi sviluppatore vorrebbe avere.

OSGi Service Compendium

Quindi nel compendium sono definiti una serie di servizi "standardizzati" di base che semplificano l'utilizzo di OSGi.

Log Service

Consiste in due servizi, uno per effettuare il logging e un altro per catturare il log efettuato.

Http Service

Permette di definire dei servizi HTTP all'interno di un bundle.

Configuration Admin Service

Definisce un servizio di amministrazione del container.

Metatype Service

Definisce un meccanismo standard per permettere d uno sviluppatore di bundle di definire dei metadati di un proprio servizio; in questa maniera un servizio può definire delle proprietà da esporre al servizio di amministrazione (Configuration Admin Service).

User Admin Service

Consiste in un servizio che permette di autenticare e autorizzare un bundle.

Declarative Services Specification (DS)

Questo servizio descrive un modello usato per creare e consumare dei servizi OSGi senza usare direttamente le API di OSGi stesso. In questa maniera un servizio utilizza dei servizi importati mediante semplicemente l'injection degli oggetti al proprio interno.

Blueprint Specification

Il Blueprint Specification (BS) è un servizio del tutto simile al DS; la realizzazione del BS è stata influenzata fortemente dal framework Spring. La differenza più importante tra BS e DS sta nel modo in cui il servizio consumatore di altri servizi si comporta quando il servizio produttore non è più visibile: nel caso del DS il servizio consumatore verrà fermato quando le sue dipendenze non sono più verificate, mentre nel caso del Blueprint, il servizio consumatore viene mantenuto e verrà di nuovo informato quando il servizio produttore sarà di nuovo disponible. Nel prossimo articolo analizzeremo più da vicino (con degli esempi) questi due servizi aggiuntivi.

Event Admin Service

È un servizio di produzione-consumazione di eventi. Si tratta di un servizio che implementa il modello publish-subscribe tra bundle.

Remote Service Specification

Ogni servizio definito all'interno di un container può essere solamente locale: questo servizio permette invece di poter risolvere un servizio anche se installato in un contentore remoto e quindi permette di standardizzare la definizione di un servizio di distributing computing per OSGi.

JTA Specification

È un servizio che permette di utilizzare il servizio JTA all'interno di OSGi.

JMX Specification

È un servizio che definisce una serie di Mbean per la gestione del contenitore OSGi.

JDBC Specification

Definisce un servizio di integrazione di OSGi con driver JDBC di database.

JNDI Specification

Definisce un servizio che permette di accedere a servizi OSGi mediante JNDI.

JPA Specification

Definisce come utilizzare JPA all'interno di un modulo OSGi.

WebApplications Specifications

Definisce un WAB, cioè un Web Archive (WAR) definito come Bundle (integrazione Servlet-OSGi).

Service Tracker Specifications

Definisce un servizio di tracciamento di tutti gli eventi del ciclo di vita dei bundle senza dover utilizzare le API OSGi, ma in maniera più semplice.

Figura 4 - OSGi a runtime.

 

JBoss e OSGi

JBoss [2] implementa un contenitore OSGi e i servizi del Compendium [4]. Il modulo OSGi è già incluso nel server AS7, e non c'è bisogno di scaricarsi ne' di installare nient'altro.

In ogni modo JBoss mette a disposizione un pacchetto che si chiama jboss-osgi-installer che, contrariamente a quanto si possa pensare, non contiene una implementazione di OSGi, ma la documentazione e una serie di esempi sull'utilizzo dei servizi del Compendium. Si tratta quindi del punto di partenza per chiunque volesse utilizzare OSGi all'interno di JBoss.

Inoltre, il tool di test Arquillan [3] è perfettamente integrato con OSGi: possiamo utilizzarlo per creare dei micro deploy di bundle OSGi e testarli allo stesso modo con cui si verificano i moduli Java EE.

Conclusioni

In questo articolo su OSGi abbiamo visto le definizioni principali dello standard OSGi, abbiamo visto i servizi opzionali che vengono offerti da JBoss e l'integrazione con Java EE e Arquillan.

Nel prossimo articolo faremo degli esempi su come utilizzare OSGi in un ambiente Java EE: quindi faremo vedere come integrare i due mondi, come accedere da un Session Bean a un modulo OSGi, come testare un bundle con Arquillan e, soprattutto, faremo degli esempi sui servizi Declarative Services e Blueprint services [5] [6].

Riferimenti

[0] Wiki page ufficiale di OSGi Alliance

http://wiki.osgi.org/wiki/Main_Page

 

[1] OSGi home page

http://www.osgi.org/Main/HomePage

 

[2] JBoss OSGi home page

http://www.jboss.org/jbossas/osgi

 

[3] Integrazione Arquillan con bundle OSGi

https://docs.jboss.org/author/display/JBOSGI/Arquillian+Test+Framework

 

[4a] Servizi implementati da JBoss-OSGi

http://docs.jboss.org/osgi/jboss-osgi-1.0.0.Beta9/userguide/html/ChapProvidedBundles.html

 

[4b] Esempi di utilizzo dei servizi OSGi

https://docs.jboss.org/author/display/JBOSGI/Provided+Examples

 

[5a] OSGi Blueprint Service

http://jbossosgi.blogspot.it/2009/04/osgi-blueprint-service-rfc-124.html

 

[5b] Come iniettare servizi OSGi dentro un modulo EE tramite il Blueprint

http://stackoverflow.com/questions/13836212/how-to-inject-osgi-service-to-ejb-with-blueprint

 

[5c] Wiki page sul servizio Blueprint

http://wiki.osgi.org/wiki/Blueprint

 

[6a] Un esempio con il servizio Declarative Service (DS)

https://docs.jboss.org/author/display/JBOSGI/Provided+Examples#ProvidedExamples-DeclarativeServices

 

[6b] Wiki page sui Declarative Services

http://wiki.osgi.org/wiki/Declarative_Services

 

 

 

Condividi

Pubblicato nel numero
185 giugno 2013
Michele Mazzei si è laureato in Scienze dell’Informazione nell’ormai lontano 1998. Si occupa di progettazione e scrittura di software in Java/Java EE e in C/C++ sul mondo Linux. Lavora a Roma in ambito spaziale maturando esperienze in ambito OGC, GIS, Map Server, Payload Data Ground Segment (PDGS). Si interessa di…
Articoli nella stessa serie
Ti potrebbe interessare anche