Le Paris JUG nous a proposé une présentation d’OSGI ce mois-ci, organisée par Cyrille Le Clerc et Nicolas Griso de Xebia. Après une présentation sur l’histoire d’OSGI, nous avons vu les différents champs d’applications, avec en point de mire la question posée sur le blog de xebia : « est-ce vraiment une plus value pour les développements ? »
La présentation commence par une introduction à l’histoire de l’Alliance OSGI, constituée d’acteurs du monde des télécoms, de l’embarqué et des middlewares. OSGI existe depuis 1999, la dernière version de la spécification de ce framework est la release 4.1 (aka JSR-291) sortie en mai 2007. Je retiens qu’avant tout, OSGI a été spécifié pour des problèmes d’applications embarquées dans des téléphones, de l’équipement automobile (BMW) et finalement, le tout me fait penser que c’est assez loin de mon informatique de « gestion » comme dit Cyrille.
OSGI est entre autre constitué d’une spécification d’un framework. Ce framework répond à deux soucis en Java : la modularité afin d’exposer un contrat versionné de classe et le contrôle d’un service entre plusieurs applications. Nicolas explique qu’en Java, le mécanisme actuel basé sur les JAR n’est pas adapté. Un JAR n’a pas de consistance au runtime, toutes les classes se retrouvent chargées dans le Classpath de l’application. Il existe bien un mécanisme peu connu (protected / public) dans le Manifest.mf mais qui reste peu utilisé et inadapté. Il n’y a pas de protections des dépendances en Java à l’exécution. La première classe trouvée est chargée par le ClassLoader, ce qui entraine parfois des ClassNotFound Exception ou des NoClassDefFoundException (quizz : expliquez la différence). C’est un point faible de Java.
ClassLoader mon pote de 10 ans
Le classloader respecte une hierarchie. Il faut savoir que là où BEA Weblogic ou JBoss utilise un class-loader « children first » où une classe de votre WAR sera chargée avant la classe du serveur d’application, IBM Websphere fait l’inverse : une classe du serveur d’application se retrouve chargée avant la version de votre WAR. Ennuyant non ? J’en ai fait l’expérience en 2007.
Cela donne des choses assez amusantes comme l’explique Cyrille avec JBoss. Celui-ci package une version 3.2.4 d’hibernate alors que vous voudriez peut-être utiliser la version 3.3. Il explique aussi qu’avec Tomcat il est impossible à priori de faire tourner à la fois du Spring 2.0 et du Spring 2.5 au sein du même WAR. Bref le souci : la gestion des versions des dépendances dans une application peut vite tourner au cauchemar et Java n’offre rien (pour l’instant).
JCP et OSGI sont sur un bateau
Nicolas et Cyrille abordent ensuite l’historique entre OSGI d’une part et le Java Community Process (JCP) d’autre part. OSGI est une alliance fermée dont le droit d’entrée de 20 000 $ (je crois) permet de filtrer les happy-fews. JCP est gratuit pour le commun des mortels (ce qui m’a valu une petite peluche Duke d’ailleurs pour avoir bien répondu). Il faut voir qu’historiquement, OSGI Alliance répond à un besoin bien différent de celui du JCP, piloté par SUN. Cependant OSGI et JCP travaillent main dans la main, puisqu’OSGI est spécifié sous la forme de la JSR 291. Bref je vous passe les détails mais ils se sont rabibochés et ils vont nous faire un petit.
Du code, du code, du code
Cyrille ouvre le capot de la belle afin de commencer à nous montrer en live ce que donne OSGI. Avant cela, Nicolas explique le fonctionnement d’OSGI d’un point de vue technique. Un JAR classique devient « osgi-fié » à partir du moment où son MANIFEST.MF s’est fait en quelque sorte visité par OSGI. Je m’explique. Un certain nombre de mots-clés sont ajoutés dans le fichier Manifest.MF afin de définir les dépendances, ce qu’expose le module et les bundles nécessaires à l’execution. Ce système très simple permet d’ajouter des règles de version afin que votre module OSGI n’utilise qu’une certaine version d’une API. Imaginez une sorte de balise « dependencyManagment » à la Maven, au coeur du Manifest.mf. Voici un exemple pour illustrer ce charabia :
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: HelloService Plug-in
Bundle-SymbolicName: com.javaworld.sample.HelloService
Bundle-Version: 1.0.0
Bundle-Vendor: JAVAWORLD
Bundle-Localization: plugin
Export-Package: com.javaworld.sample.service
Import-Package: org.osgi.framework;version="1.3.0"
Ici j’ai un bundle « HelloService » qui importe en dépendance le framework OSGI dans sa version 1.3.
(à noter qu’une ligne du fichier Manifest.mf ne doit pas dépasser 72 caractères). Comme on le constate le mécanisme est simple et rustique. Ceci s’explique par le fait qu’OSGI fonctionne sans soucis avec Java 1.1 et J2ME. C’est prévu pour de l’embarqué au départ.
Au niveau du code Cyrille montre ensuite le code d’un service OSGI afin de nous présenter avant la pause le concept d’Activator et de ServiceRegistration. Je vous donne un peu de code car je n’ai pas les slides de Xebia, mais je vous invite à surveiller plutôt sur le site du Paris JUG les slides afin de vous faire votre propre idée du code.
Sur cet exemple j’implémente l’interface BundleActivator afin d’être à l’écoute et d’enregistrer mon service de test dans OSGI :
public class HelloServiceActivator implements BundleActivator { ServiceRegistration helloServiceRegistration; public void start(BundleContext context) throws Exception { HelloService helloService = new HelloServiceImpl(); helloServiceRegistration =context.registerService(HelloService.class.getName(), helloService, null); } public void stop(BundleContext context) throws Exception { helloServiceRegistration.unregister(); } }
Voyons comment ensuite importer mon service afin de m’en servir :
public class Activator implements BundleActivator { ServiceReference helloServiceReference; public void start(BundleContext context) throws Exception { System.out.println("Salut le touilleur "); helloServiceReference= context.getServiceReference(HelloService.class.getName()); HelloService helloService =(HelloService)context.getService(helloServiceReference); System.out.println(helloService.sayHello()); } public void stop(BundleContext context) throws Exception { System.out.println("ByeBye le touilleur !"); context.ungetService(helloServiceReference); } }
La clé de voute qui semble un peu bizarre c’est ce ServiceReference qui n’est ni plus ni moins un pointeur vers notre service. Le context nous sert de transport. Avouez que ce code tout simple nous semble un peu « old-school » à l’époque d’IoC et compagnie non ? et les annotations ?
A cela Nicolas apporte une explication importante : OSGI c’est au départ pour de l’embarqué, et donc pour une version de Java plus simple que Java 5 avec annotations et compagnie. D’ailleurs OSGI pose un certain nombre de soucis avec la programmation orientée AOP car ces mécanismes ne sont pas de bons collaborateurs pour OSGI. Il faudrait creuser pour en savoir plus.
Je vous donne mon impression : ça sent la naphtaline. Et je crois bien que c’est le message que Nicolas et Cyrille font passer. Une partie de la salle a peut-être mal compris l’exercice qui se déroule ce soir : on explique OSGI, on entre dans le détail, mais on vous laisse vous faire votre propre opinion. J’ai beaucoup aimé.
Cyrille qui pourrait vendre un brushing à un chauve propose à un moment une idée pour expliquer OSGI qui m’a bien plus : OSGI est un pare-feu (firewall) visant à d’abord isoler les classloaders, puis à apporter une couche de contrôle simple à une application. Quelque part, c’est une forme d’injection de dépendance avec un moteur de versionning dont finalement tout repose sur Manifest.mf. Si vous me suivez bien vous voyez un peu où je veux en venir : là où Spring fait de l’injection de dépendance pour vous brancher votre application, on s’attend à ce qu’OSGI fasse la même chose mais au niveau des Class, une sorte de Spring mais pour le ClassLoader… Or ce n’est pas franchement le cas.
Nicolas présente ensuite le système de configuration basé sur du XML après la présentation des Declaratives Services. Bien que plus facile à maintenir, c’est peut-être du côté de Spring DM finalement que l’on aura un système sympathique à utiliser. Et encore une fois je pense en effet que les génies de Spring vont nous pondre un système qui répondra à nos besoins.
Spring, spring, spring, la peinture fraîche
Spring DM avec la RFC 124 écrite par SpringSource propose un système intelligent de configuration qui n’est encore qu’à l’état de Draft au sein de l’Alliance OSGI. En même temps il n’y a pas d’alternatives (aussi intelligentes). Nicolas explique que Spring apporte une simplification d’OSGI grâce à un namespace qui permet de piloter les services OSGI très facilement au sein de la configuration XML de Spring. Et en effet, c’est vraiment ce qu’il manque pour séduire le tout venant. Attention ce n’est pas encore terminé comme l’explique Cyrille. Bref ça sent la napthaline et la peinture fraiche
Pause glouglou
A peine le temps de discuter avec quelques têtes connues que nous repartons pour la deuxième partie, que je vais faire courte. La démonstration propose de voir comment un service résoud une dépendance, comment un service s’expose à travers une Servlet, comment utiliser log4j et entre autre, passer un fichier log4j.properties au bundle de Log4j. Enfin la démonstration s’est terminée par le changement à chaud d’un bundle. C’était convaincant et simple. L’assistance a peut-être pensé que Cyrille et Nicolas allaient tenter de les convertir mais je pense pas que c’était le cas. J’ai pensé qu’ils ont montré du code en l’état, en laissant chacun se forger une opinion. Et évidemment que cela laisse perplexe. Que penser de la gymnastique pour remplacer à chaud une partie de l’application ? Cyrille le dit honnêtement : « en application de gestion moi je n’ai jamais eu ce cas d’usage ».
Le seul truc marrant que je trouve à dire à mon voisin pendant que cyrille arrête, relance, arrête son service :
« ….et je coupe le son….. et je remets le son… et je coupe le son… et je remets le son… »
Est-ce que penser que l’on arrête une partie de l’application avec OSGI ce n’est pas faire du Philippe Katerine ?
OSGI dans le monde JEE
Nicolas apporte ensuite une explication à l’utilité d’OSGI et je pense que c’était le plus intéressant. OSGI se retrouve de facto dans les serveurs d’application comme Websphere 6.1 et Weblogic 10 (en partie). L’explication est assez simple : OSGI permet aux éditeurs de middleware de gérer et d’isoler les JAR du serveur d’application par rapport à ceux de l’application, et aussi de faire cohabiter sans soucis les EJB 2.1 et les EJB3 sans que le ClassLoader ne vienne perturber le tout. D’autre part la gestion du cycle de vie permet à Websphere par exemple de piloter l’orchestration de services facilement.
L’ESB Apache ServiceMix 4 est basé sur Spring DM et apporte des fonctions de monitoring et d’exploitation. Les équipes de production vont être contentes. Glassfish bascule sur Apache Felix, une des implémentations Open-source d’OSGI comme l’explique Alexis MP qui était présent.
Pour terminer les bonnes pratiques pour OSGI :
- Préferer Import-Package à Require-Bundle
- Utiliser des plages de version dans le manifest afin de ne pas trop restreindre les versions (gag)
- Séparer les apis des implémentations afin de faciliter la maintenance
- Penser orienté objet
- Gérer le cycle des dépendances
Dans les antipatterns j’ai noté :
- Utilisation des ClassForName au lieu de passer par une Factory
- Utilisation des librairies non osgi-fiées
A ce propos un gros point bizarre,pouri, c’est les librairies osgi-fiées. Il s’agit d’un JAR dont le Manifest.mf a été trituré afin de devenir compatible avec OSGI. Or comme il n’y a pas de normes, chacun y va de sa version faite maison. Spring propose un repository, mais ils ne pourront pas obliger les gens d’Apache ServiceMix de repackager leurs Jar en module OSGI. D’où des millions de question dans ma tête dont la première est : ce n’est pas un risque de gros gros b…l ?
La conclusion
Sur le contenu : OSGI est un socle robuste et éprouvé qui répond à des problématiques complexes que la plateforme Java n’adresse pas pour l’instant. Il manque de maturité dans le monde JEE et il est en pleine évolution, en partie grâce à SpringSource. C’est donc un acteur à surveiller du coin de l’oeil et il aurait été dommage de ne pas utiliser certains de ses principes. Maintenant s’agissant d’un framework « historique », certaines de ses implémentations sont un peu dépassées.
Sur la forme je vais vous donner mon avis : pour une fois on a eu une présentation au caviar de Xebia qui a réussi à montrer à la fois les points intéressants d’OSGI mais aussi le côté qui « coince un peu » : à la fois le vieux et le trop jeune. Naphtaline et peinture fraîche pour ceux qui suivent.
Et là, c’était un exercice pas forcément facile au Paris JUG devant une assemblée qui attendait peut-être une présentation « OSGI ça déchire et je vais vous convertir mes frères ». C’était bien plus fin que cela. Enfin moi c’est ce que j’ai compris.
Merci à Nicolas et Cyrille, de Xebia.
Actualités du Paris JUG :
A l’occasion de l’anniversaire du JUG en février prochain, Antonio recherche des speakers pour faire des quickies de 15mn. Etant donné que je devrai en faire une à Devoxx en décembre prochain, je pense que je vais proposer un sujet à Antonio rapidement.
JetBrains, l’éditeur de l’excellent IDEA IntelliJ, offre des licences gratuites pour les participants du JUG.
Eyrolles offre des livres et le Paris JUG vous propose de participer à des lectures de livres afin de publier des articles.
Enfin j’ai entendu l’appel d’Antonio pour bloger sur le blog du Paris JUG. Là il est 00h41 et je pense que je vais fermer la boutique pour ce soir. Je vais réfléchir encore un peu avant de proposer ma candidature.
Enfin en décembre prochain ne manquez pas la conférence Devoxx (ex Javapolis) qui aura lieu à Anvers (2h de paris en TGV) et qui se déroule sur 3 jours. Florent (de jaxio) m’a boosté afin que je fasse une présentation à Devoxx. J’ai donc postulé et proposé de faire une présentation sur la mise en place d’un ESB dans une plate forme de traitement de flux financiers. Ensuite il faut que je sois accepté, ce qui n’est pas encore acquis.
Pour terminer quelques photos. Cliquez sur les photos pour les afficher en grand :
Merci beaucoup pour le rapport très instructif.
Pour les ClassLoader Jboss l’affirmation « JBoss utilise un class-loader “children first” où une classe de votre WAR sera chargée avant la classe du serveur d’application » n’est pas pas tout à fait exacte.
Sans modifier la configuration par défaut et sans instruction spécifique dans le descripteur de déploiement JBoss utilise un ClassLoader unifié (en fait un unique dépôt de classes auquel sont rattachés les divers ClassLoader). Ceci a comme conséquence que les classes des divers packages ne sont pas isolées et la première chargée l’emporte. C’est bien documenté sur le Wiki JBoss mais un peu déroutant par rapport aux autres serveurs d’application. Par contre, les classes d’un WAR peuvent bien entendu être isolées via une instruction dans le DD ou la conf du serveur, et dans ce cas effectivement on est dans un mode « Children-First » .
C’est la même chose sur WebLogic il me semble, c’est du « parent first ».
Pour pouvoir utiliser les librairies embarquées dans le WEB-INF/lib il faut le spécifier dans le descripteur propriétaire weblogic.xml du WAR (tag prefer-webinf-classes) ou dans le weblogic-application.xml de l’EAR.
Merci pour ce très bon compte-rendu.
J’aimerais également apporter une légère correction vis-à-vis de WebLogic (qui est la même que celle de Luc pour JBoss) : le schéma de class loading par défaut n’est pas le child-delegation-first. Ce modèle est disponible sur configuration uniquement et, depuis les dernières versions, il est déconseillé, au profit du mécanisme de FilteringClassLoader qui gère plus efficacement et proprement ces conflits.
Autre petite précision, qui m’a été donnée par Bill Shannon, le terme « Java EE » doit être préféré à « JEE ».
http://www.java.com/en/about/brand/naming.jsp
Bonne continuation !
Trés bon article pour ceux qui n’y était pas.
Pour en revenir à IOC dans un environnement OSGI, il y a plusieurs solutions qui s’offrent à nous. Spring DM est une des solutions. Le couple Guice – Peaberry en est une autre.
Vous pouvez lire l’article que j’ai écrit sur Javalobby http://java.dzone.com/articles/osgi-and-injection
Excellente revue. Beau boulot.
J’ai également fait mon retour sur la soirée.
OSGI : oui mais non
http://www.tomsquest.com/blog/osgi-oui-mais-non/
Tom
Oui, très bonne présentation, honnête, technique, fouillée. L’impression de faire du neuf avec du vieux était assez forte. Mais pourquoi pas.
J’ai aussi beaucoup apprécié le fait de demander à haute voix : en a-t on vraiment besoin (dans l’informatique de gestion)?
Pour faire fonctionner OSGi et l’AOP qui, il est vrai, n’étaient pas prévu pour fonctionner ensemble au départ Martin Lippert a développé un palliatif : Equinox Aspects
Merci pour la qualité de votre compte rendu.
Comme vous l’avez rappelé, nous avons essayé de sortir des discours angéliques pour voir l’apport d’OSGI aux différents acteurs du développement « d’informatique de gestion ».
Si nous avons trouvé des avantages différentiants pour les éditeurs de middlewares, en revanche, OSGi nous a semblé manquer de stabilité et de maturité pour convaincre des équipes de développement d’application de gestion qui utilisent aujourd’hui Spring ou les EJB 3.
La RFC 124 – A Component Model for OSGi, en reprenant Spring DM, peut apporter les éléments de productivité qui pénalisent aujourd’hui OSGi face à nos techniques d’injection de dépendances. Encore faut-il que cette RFC soit intégrée à la version finale d’OSGi R4.2 …
Les slides sont disponibles sur le site du Paris JUG à l’url http://parisjug.org/xwiki/bin/view/Meeting/20081014 .
Cyrille Le Clerc (Xebia)