Il primo di una serie di articoli sulla tecnologia OSGi’. Partiremo da una descrizione generale e approfondiremo come può essere impiegata nello sviluppo e nella gestione di Web Application.
La tecnologia OSGi™ fornisce un ambiente modulare orientato ai servizi. Librerie e applicazioni sono contenute in moduli detti bundle. I bundle sono in esecuzione all’interno di un’unica istanza della Java™ Virtual Machine (JVM). Le operazioni di gestione del ciclo di vita dei bundle avvengono dinamicamente, ovvero senza la necessità, tranne casi particolari, di riavviare la JVM grazie alle API fornite dall’ambiente di sviluppo.
I vantaggi sono evidenti: riduzione dell’occupazione di memoria grazie alla condivisione delle risorse (librerie, ecc.), incremento delle prestazioni grazie all’unica istanza della JVM, semplificazione delle comunicazioni tra applicazioni.
Il deploy dei bundle avviene in Java™ ARchive file (JAR). Il Manifest (META-INF/MANIFEST.MF) conterrà oltre alle informazioni previste dal formato, il nome simbolico del bundle, la versione, i package utilizzati dalle Classi in esso contenute, i package che è necessario rendere visibili per rendere tali Classi fruibili da altri bundle. Per maggiori dettagli fare riferimento alla documentazione ufficiale scaricabile dal sito della OSGi™ Alliance [1].
Vediamo un esempio di come si presenta il Manifest di un bundle:
Bundle-SymbolicName: f06.osgi.webapp.wicket.test Bundle-Name: Wicket Test Application Bundle-Version: 0.3.0 Bundle-Activator: f06.osgi.webapp.wicket.test.Activator Bundle-Copyright: (c) 2007-2008 Davide Raccagni Bundle-Vendor: Davide Raccagni Import-Package: javax.servlet, javax.servlet.http, org.apache.commons.logging, f06.osgi.service.http_jetty DynamicImport-Package: * Bundle-ClassPath: .,slf4j-api-1.5.0.jar, slf4j-jcl-1.5.0.jar, wicket-1.4-m2.jar, wicket-extensions-1.4-m2.jar Export-Package: f06.osgi.webapp.wicket.test, it.wicketosgi, it.wicketosgi.model, it.wicketosgi.page, org.slf4j, org.slf4j.helpers, (...)
Come si può notare, è possibile specificare il nome della classe di attivazione del bundle, che implementa l’interfaccia BundleActivator:
public interface BundleActivator { public void start(BundleContext context) throws Exception; public void stop(BundleContext context) throws Exception; }
i cui metodi saranno invocati rispettivamente all’avvio ed all’arresto del bundle.
Web Application in ambiente OSGi
Supponiamo che esista un componente in grado di gestire le operazioni di deploy/undeploy/start/stop di Web Application impacchettate in bundle. Supponiamo che esse usufruiscano di Classi e risorse (immagini filmati e quant’altro) messe a diposizione da altri bundle.
I vantaggi sono legati alla condivisione delle risorse, alla semplicità di comunicazione tra Web Application, che non necessariamente deve avvenire via protocollo TCP/IP, e alla possibilità di compiere operazioni di aggiornamento senza dover riavviare il Server.
Vediamolo in pratica. Il primo passo è installare il framework OSGi™. In questo articolo è stato utilizzato il framework F06, ma è abbastanza semplice configurare altri prodotti quali Apache Felix [4] o Eclipse Equinox [5] per ottenere lo stesso risultato. È sufficiente scaricare l’ultima versione dal sito ufficiale [3], installarla e lanciare il comando f06.bat (Windows) o f06.sh (Linux) dalla directory bin.
Si deve quindi procedere con l’installazione del bundle del Web Server (a questo proposito si è utilizzato Jetty6 web server [6], che viene già distribuito in un bundle), e infine del bundle che contiene il componente di gestione delle Web Application, il WebAppService, esposto dall’istanza della Classe di attivazione come servizio.
Il bundle deve contenere una classe di attivazione che provvederà, nel metodo start, al deploy e all’avvio della Web Applicaton, nel metodo stop al suo arresto. Si veda a titolo di esempio quanto riportato qui di seguito:
public class Activator implements BundleActivator { private Context webAppContext; public void start(BundleContext context) throws Exception { webAppContext = new WebAppContext(context, "/wicket", "/wicket"); ServiceReference reference context.getServiceReference( WebAppService.class.getName() ); WebAppService webAppService = (WebAppService) context.getService( reference ); webAppService.addContext(webAppContext); context.ungetService(reference); } public void stop(BundleContext context) throws Exception { ServiceReference reference = context.getServiceReference( WebAppService.class.getName() ); WebAppService webAppService = (WebAppService) context.getService( reference ); webAppService.removeContext(webAppContext); context.ungetService(reference); } }
Sarà presente il file WEB-INF/web.xml attraverso il quale è possibile configurare la Web Application: Servlet, Filter, Listener ecc. In figura 2 è proposta l’alberatura del bundle file.
Figura 2. Struttura del bundle file di OSGi
A questo punto non resterà che installare e avviare il bundle e la Web Application sarà disponibile.
Le operazioni di installazione e avvio avvengono tramite file di configurazione o via console. Nel caso del framework da noi utilizzato, il file di configurazione config.ini è contenuto nella directory etc. Per garantire il corretto funzionamento del Web Server e del componente di gestione del ciclo di vita delle Web Application è necessario installare ed avviare i bundle come specificato qui di seguito:
# # Framework lifecycle # load file:bundles/f06.commons.util.jar -startlevel=2 -start=eager load file:bundles/servlet-api-2.5-6.1.9.jar -startlevel=2 -start=eager load file:bundles/jetty-util-6.1.9.jar -startlevel=2 -start=eager load file:bundles/jetty-6.1.9.jar -startlevel=2 -start=eager load file:bundles/f06.osgi.service.http_jetty.jar -startlevel=3 -start=eager load file:bundles/f06.osgi.webapp.wicket.test.jar -startlevel=4 -start=eager startlevel 5
Come si può osservare, è possibile specificare sia l’ordine di installazione che la sequenza di avvio (mediante il parametro startlevel) garantendo così la disponibilità di tutte le risorse necessarie quando richieste.
Conclusioni
La versatilità garantita dalle specifiche OSGi™ ne consente l’applicazione in contesti eterogenei, che spaziano dai dispositivi mobili alle applicazioni desktop (si pensi ad esempio alla Client Platform (RCP) di Eclipse, basata sul framework OSGi™ inox). In questo articolo abbiamo analizzato una sua applicazione lato server per la gestione semplificata di Web Application, che sfrutta però a pieno titolo questa geniale tecnologia.
L’esempio completo citato nell’articolo è scaricabile da http://www.davideraccagni.com/index.php?q=node/8 Le immagini contenute in figura 1 appartengono alla Tango Icon Library [7].
Riferimenti
[1] OSGi Alliance
http://www.osgi.org
[2] the OSGi Service Platform
http://www.osgi.org/wiki/uploads/Links/OSGiTechnicalWhitePaper.pdf
[3] F06
http://www.davideraccagni.com/index.php?q=node/8
[4] Apache Felix
http://felix.apache.org/
[5] Eclipse Equinox
http://www.eclipse.org/equinox/
[6] Jetty Web Server
http://www.mortbay.org/jetty-6/
[7] Tango Icon Library
http://tango.freedesktop.org/Tango_Icon_Library