Compte-rendu soirée OSGi par Clément Escoffier
Clément Escoffier (Twitter, LinkedIn), architecte chez Akquinet et PMD sur le projet Apache Felix, est venu nous présenter OSGi mardi dernier.
Il a commencé par expliquer rapidement ce qu’est OSGi et à qui ce framework est destiné. Pour résumer ses propos, OSGi est une spécification d’un framework qui a pour but de concevoir et d’exécuter des applications hautement dynamiques. Ce qui a pour conséquence de les modulariser fortement. Ceci permet d’alléger la maintenance et l’exploitation de systèmes relativement complexes (plus d’un millions de lignes de code d’après clément).
Dans la suite de sa présentation, Clément a passé en revue les différentes couches qui composent le framework :
- La couche Module : qui implémente les concepts de base d’OSGi (bundle, résolution de dépendances, …)
- La couche Lifecylce : qui définit le cycle de vie des différentes entités du framework à commencer par les bundle présents sur une plateforme et le tout totalement à chaud (sans redémarrage de la machine virtuelle)
- La couche Service : qui fournit et permet de définir des service de haut niveau se basant sur les couches précédentes. C’est cette couche qui permet la haute dynamicité des applications.
Selon Clément, OSGi prend tout son sens avec la couche service. S’arrêter dans la conception de son application à l’une des deux autres couches, c’est de ne pas profiter de ce qui fait la force du framework, l’utiliser uniquement afin de modulariser son application est une grossière erreur et ouvre la porte à de fortes déceptions et potentiellement à de gros problèmes.
La couche Module
Clément nous a décrit le concept de bundle qu’il présente comme une sorte de jar étendu. En effet, le format jar n’est pas réellement bouleversé pour créer un bundle à deux différences majeures : le fichier MANIFEST contient plus d’informations (description des dépendances entre bundles, de visibilité du code interne) et la possibilité de ne publier qu’une sous partie du bundle vers l’extérieur (export) rendant ainsi invisible aux yeux des autres bundles le code non spécifié comme exporté.
Précisions importantes : il est obligatoire de préciser dans un bundle l’ensemble des dépendances (import) dont il dépend et OSGi se base sur les packages pour son système d’import/export de code entre bundles, ainsi il est impossible de n’exporter qu’une seule classe d’un package Java donné (il faudra organiser son code en fonction).
La couche Lifecycle
C’est durant cette partie que l’on a commencé à voir du code (du vrai !), en effet, la spécification définit des API d’administration à implémenter par les plateforme OSGi permettant de gérer le cycle de vie des bundles (chargement/déchargement/démarrage/arrêt/mise à jour).
Le framework permet aussi de définir des Activator qui sont utilisés par le bundle pour s’initialiser lors des phases de démarrage ou encore des BundleListener qui écoutent l’arrivée d’évènements précis liés au cycle de vie d’un bundle dans le système OSGi. Puisqu’il est possible d’ajouter/retirer/activer ou désactiver des bundles à chaud il devient nécessaire de pouvoir réagir dans les autres bundles à ces évènements.
Ce sont ces mécanismes évènementiels du cycle de vie d’un bundle qui permettent de créer via OSGi une extensibilité dynamique. Clément nous a d’ailleurs présenté un pattern de conception OSGi permettant de gérer clairement ces évènements : l’Extender Pattern
La couche Service
D’après Clément, les développeurs OSGi doivent se focaliser sur cette couche et déléguer les précédentes aux plateformes sur lesquelles ils feront tourner leur applications. OSGi permet de déclarer des services qui sont publiés dans un Service Registry, les consommateurs de service pourront requêter cet annuaire pour récupérer le service et se lier à lui de manière directe (pas de proxy, pas d’intermédiaire quelconque comme dans Spring par exemple : simple, efficace).
La création et la publication de services OSGi implique généralement un découplage de l’interface de l’implémentation permettant de masquer aux bundles consommateurs la complexité de réalisation et les contraintes techniques (réseau, base de données, …). Les bundles publient des services via le BundleContext et le font généralement par le biais des Activator dont on a parlé juste au-dessus.
Et après ? On y passe comment ?
Jusqu’à ce point, OSGi paraît tout beau, tout gentil mais attention ! Ce n’est pas pour rien que de gros projet on fait machine arrière (Mule ESB par exemple). En effet, le passage à OSGi nécessite de prendre en compte ce qu’habituellement on laisse faire à nos plateformes : classloading avancé, synchronisation et gestion des accès concurrents, et le packaging.
Heureusement, Clément souligne qu’il existe déjà plusieurs moyens de se faciliter la tâches, les IDEs, les outils de builds et de packaging (plugins eclipse et maven, …) . Il a plus particulièrement insisté sur iPOJO qui permet de simplifier la création de services OSGi en manipulant des annotations Java (le XML c’est sale !) sur de simples POJO (ou interfaces). Cet outil, qu’il a utilisé dans ses démonstrations, propose aussi une console d’administration web qui permet de parcourir l’état de la plateforme OSGi (bundles présents, services avec leur état, …).
Pour conclure, on retiendra qu’OSGi est puissant, pas encore utilisé à sa juste valeur (par exemple, l’IDE Eclipse qui l’utilise partout n’exploite pas la couche Service) et possède de nombreux outils qui réduisent grandement la complexité inhérent à la nature d’OSGi. Cependant, on retiendra aussi que celui-ci se destine essentiellement à des applications nécessitant de la modularité et de la dynamicité et que ces besoins doivent être clairement identifiés avant d’engager un – coûteux – passage à OSGi. C’est aussi pour ces raisons que des IDE et des serveurs d’applications JEE ont choisi OSGi comme socle.
Merci Clément.