Fondé en 1999, l’OSGi Alliance est un consortium industriel qui à l’origine avait pour intention de définir des spécifications ouvertes pour développer et déployer des services sur des systèmes embarqués. Très vite, le périmètre d’application s’est élargi vers les marchés de la sécurité, de l’automobile. L’intégration d’Equinox au sein de l’écosystème Eclipse motive la communauté open source. Depuis cette dernière année, OSGi est en train de s’imposer côté serveur.
Le choix de java remonte à la création du consortium. En effet, les caractéristiques de la JVM et du langage interdisent certaines pratiques dangereuses tels que les pointeurs, les dépassements de buffer... La technologie OSGi est une plateforme orientée services de déploiement et d’exécution de services Java. Cette technologie est en phase de devenir un standard pour le déploiement, l’administration et l’exécution d’applications java grâce à la publication des JSR 277 (Java Module System), JSR 291 (Dynamic Component Support for Java SE) et JSR 294 (Improved Modularity Support in the Java Programming Language).
Les applications au sein du framework OSGi collaborent par le biais de services. La plateforme met à disposition un registre de services (recherche, notification des changements, etc.).
Une application OSGi est composée des éléments suivants :
Bundle : L’unité de déploiement versionnée de la plateforme OSGi est le bundle. Il se présente sous la forme d’un jar contenant du code binaire ainsi que d’autres ressources (exécutable, image ...). Les propriétés du bundle sont définies au niveau du fichier manifest du jar :
Le cycle de vie d’un bundle est le suivant :
Les bundles sont administrés via une interface locale ou distante cette dernière permet :
Un composant OSGi (bundle) peut importer/exporter des packages ainsi qu’exposer / consommer des services.
Package L’entité de partage du code (partage des classes) est le package, chaque package est versionné. Les packages ni importés ni exportés ont uniquement une portée locale au niveau du bundle (notion de namespace). Afin de pouvoir mettre à jour un package (l’exporter) sans impacter les utilisateurs, il faut conserver une compatibilité ascendante entre les versions.
Service Les implémentations du service sont définies au niveau du bundle. Les consommateurs de ce dernier n’ont connaissance que de l’interface. Lors de son enregistrement un service est caractérisé par son nom, son emplacement, son numéro de version ainsi que par un ensemble de propriétés typés. Ainsi par exemple le consommateur du service pourra effectuer la recherche du service d’impression ayant la caractéristique noir et blanc ou bien couleur.
Activator Le paramètre d’entré Bundle-Activator du fichier manifest du jar désigne la classe servant de point d’entrée lors de l’activation ou de l’arrêt du bundle. En général, le rôle de cette instance est de gérer les services consommés et/ou publiés.
public class Activator implements BundleActivator {
// package importé
private final Printer printer = new Printer("==> ");
private ServiceRegistration reg=null;
// service exposé
private PrinterService service =null;
// service consommé
private PaymentService payService = null;
private ServiceReference ref = null;
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
this.printer.print("Start Bundle...");
service = new PrinterServiceImpl();
// propriétés typées du service
Dictionary props=new Properties();
props.put("color", false);
// enregistrement du service
reg=context.registerService(
service.getClass().getName(), service, props);
// recherche d'un service de paiement
ServiceReference[] refs=context.getServiceReferences
("com.bank.PaymentService","(bank=myBank)");
if(refs!=null && refs.length > 0) {
ref = refs[0];
// récupération du service
payService = (PaymentService) context.getService(ref);
// appel de la méthode
payService.pay();
}
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
this.printer.print("Stop Bundle ...");
// effacer le service du registre
reg.unregister();
if(ref != null) {
// liberation de l'instance
payService = null;
// libération du service
context.ungetService(ref);
}
}
}
L’utilisation de OSGi offre de nombreux avantages :
Implémentation Open source :
L’utilisation de OSGi au niveau des serveurs (serveurs d’application, bus ...) est une tendance forte à l’heure actuelle. Cependant, OSGi commence tout juste à faire son apparition au niveau des applications via l’arrivée de Spring Dynamic Module ou encore d’un plugin OSGi pour Struts 2. La réalisation d’applications autour d’un noyau OSGi apporte un réel gain aussi bien en terme de conception (faible couplage et forte cohérence des modules grâce aux services) qu’en terme de robustesse et qualité de service (possibilité d’intervenir à chaud). De plus, le noyau OSGi étant léger et nécessitant peu de ressources aura très peu d’impact sur les performances de l’application (empreinte mémoire, utilisation CPU). Les applications étant de plus en plus architecturées en couches, composants et services ; l’utilisation d’OSGi devrait se démocratiser au niveau d’applicatifs ayant de fortes contraintes de qualité de service et de robustesse.
Des réflections sont actuellement en cours pour rendre disponible la technologie OSGi sous d’autres plateformes :
Spring Source (l’entreprise derrière springframework) vient d’annoncer la sortie d’un serveur d’application non JEE mais fortement basé sur OSGI : SpringSource Application Platform