Les services Service : entité informatique définie par un ensemble de descripteurs de service enregistrés dans un annuaire de service La plateforme dynamique à services OSGi™ Descripteur : ensemble de propriétés définissant l’accès à l’entité Exp : une interface Java ou IDL pour un fournisseur (interface offerte) ou une interface Java ou IDL pour un client (interface requise) Gaël Thomas [email protected] Contrat : ensemble des descripteurs mis en relation Exp : deux interfaces égales (ifce fournisseur = ifce du client) + propriétés de QoS En général : contrat = mis en relation d’un client et d’un founrisseur (Basé sur un cours de Dider Donsez) Annuaire : associe des entités avec des descripteurs de service Université Pierre et Marie Curie Master Informatique 2007/2008 Exp : service associant des serveurs et des interfaces, recherche d’un serveur à partir de son interface service de nommage (associe un nom aux serveurs) Gaël Thomas Les services OSGi 2 Les services Trois intervenants : Intérêt des services Fournisseur de service Seul le descripteur est nécessaire pour trouver un fournisseur Imprimante, amazone.com Pas de dépendance vis à vis d’un nom indépendant Descripteur définit l’interface, les meta-données, les assertions etc… Client du service Utilisateur final, application à base de services, moteur d’orchestration Annuaire de services (Service Registry) Mécanisme de recherche intuitif UDDI, pages jaunes, registry OSGi Exemple : "Trouve moi une imprimante couleur à l’étage" Interface d’imprimante { void print(PostScript file) } Gaël Thomas Un annuaire de service contient des associations entre descripteurs et instances de fournisseur Propriétés : couleur = vrai étage = mon-étage OSGi 3 Gaël Thomas OSGi 4 Les services Les services Architecture orientée service Architecture orientée service dynamique Exemples : Web Services, OSGi™, Jini… Perte du serveur détection de la perte d’un service + reliaison (presque) transparente Exemple : OSGi, Jini… Annuaire de services 2 – Recherche Loc + props Annuaire de services 1 – Enregistrement Disparition du service Loc + props Loc + props 3 – Résultat et sélection Utilisateur de Service 5 – Utilisation Fournisseur de service Utilisateur de Service 4 – Liaison Gaël Thomas OSGi 5 Gaël Thomas Les services Fournisseur de service Fournisseur de service OSGi 6 Les services Séparation supplémentaire entre modules logiciels : Un utilisateur conçoit son application en fonction d’un service offert et non d’une implémentation précise du service Architecture orientée service dynamique Perte du serveur détection de la perte d’un service + reliaison (presque) transparente Exemple : OSGi, Jini… Par exemple : j’utilise un service météo au lieu de Météo France Annuaire de services La liaison avec une implémentation de service est effectuée Lors de la conception (programmation classique) Mais l’application reste indépendante de l’implémentation Lors de la compilation Pendant l’exécution Loc + props Utilisateur de Service Les services augmentent Re-liaison dynamique L’indépendance entre modules logiciels La flexibilité dynamique Fournisseur de service Gaël Thomas OSGi 7 Gaël Thomas OSGi 8 Les services Qu’est ce qu’OSGi™ Plateforme à service Hypothèse forte L’interface d’un service n’évolue jamais En revanche, la description peut évoluer (assertions, meta-données…) Centralisé (une seule VM) Orienté au départ vers les Gateway Dynamique Liaison (de base) uniquement par appel de méthode Consortium indépendante Fondée en mars 1999 Soutenue par de nombreux acteurs (IT, téléphonie, Eclipse, Apache) Releases 22/11/1999 : SUN transfert le JSR008 du JCP à OSGi 1.0 : mai 2000 (189 pages) 2.0 : octobre 2001 (238 pages) 3.0 : mars 2003 (602 pages) 4.0 : octobre 2005 (1000 pages!) Remarque : Open Services Gateway Initiative est obsolète Gaël Thomas OSGi 9 Gaël Thomas Qu’est ce qu’OSGi™ OSGi 10 Motivation d’OSGi™ Programmation orientée service en Java Cible des systèmes à mémoire restreinte Mise à jour dynamique d’application sans interruption Trois principales implantations de la spécification Felix (Apache) Eclipse-equinox (IBM) Installation, mise à jour, lancement, arrêt, retrait Moteur à pluggin d’eclipse Knopflerfish Résolution des dépendances de version de code Chargement/déchargement de code en Java Gaël Thomas OSGi 11 Gaël Thomas OSGi 12 Sommaire Bundle Unité fonctionnelle fondamentale de OSGi™ Motivations Bundle, services et packages Cycle de vie Manifest, Activator et BundleContext Enregistrement et recherche de services Gestion d’événements Offre des services Se lie (utilise) des services Un bundle est l’unité de déploiement d’OSGi™ Bundle Machine Virtuelle Java Bundle Bundle Chargement Plateforme OSGi™ Gaël Thomas OSGi 13 Gaël Thomas Notion de contrat de service OSGi 14 Notion de contrat de service Un service implémente (offre) un interface Java Un service possède des meta données C’est l’interface Java que doit implémenter la classe Java du service Représenté par la partie XML-Schema en Web Services Table de hash associant String à Object Permet le filtrage, l’évolution dynamique du contrat Représenté par le nom de la classe de l’interface Plusieurs services peuvent implanter la même interface simultanément Exemple de descripteur : Interface implantée : org.osgi.Printer Propriétée : color=true, proto=ftp, (dpi>=300 && dpi<=600) L’interface se trouve dans un bundle pour pouvoir être déployé et chargé dynamiquement dans OSGi™ Pas de notion d’assertions en OSGi Gaël Thomas OSGi 15 Gaël Thomas OSGi 16 Dépendance de services, dépendances de packages Dépendance de services, dépendances de packages Une interface de service => déployée dans un bundle Une interface Java est un binaire! Il ne faut pas embarquer le binaire contrat dans les fournisseurs ou les utilisateurs Sujet à incohérences Lourd en mémoire Bundle qui n’offre pas de service! Il existe donc une seconde dépendance entre bundles : la dépendance de packages La plateforme OSGi™ résout automatiquement les dépendances de packages Gaël Thomas OSGi 17 Gaël Thomas Structure d’un bundle OSGi 18 L’interface de service typique Notion d’activateur : code exécuté au chargement Ressources Services Fournis Packages Exportés Services Requis 0010 0010 1001 … 0010 0010 1001 … 0010 0010 1001 … Manifest …. Packages Importés 0010 0010 1001 … 0010 0010 1001 … Exporte le package de l’interface 0010 0010 1001 … Manifest …. Exemple : osgi.printer Description du Bundle Activateur (classe Java) Objets métiers (classes ou jar Java) Enregistre les services fournis Implémentent les services Cherche les services requis Gaël Thomas OSGi 19 Pas d’activateur Gaël Thomas OSGi 20 Le fournisseur de service typique L’utilisateur de service typique Ressources Ressources Le Service fourni Le Service requis Exemple : osgi.printer.Printer Exemple : osgi.printer.Printer 0010 0010 1001 … 0010 0010 1001 … 0010 0010 1001 … Manifest …. Exemple : osgi.printer Activateur : instancie le service, l’enregistre dans le repository Gaël Thomas 0010 0010 1001 … 0010 0010 1001 … Le Package de l’interface OSGi 21 toto.MonImplemdePrinter Service d’impression Le Package de l’interface Exemple : osgi.printer Gaël Thomas OSGi 22 Sommaire Un fournisseur de service est une instance d’une classe implantant l’interface d’un service Un client du service manipule directement la référence Java du service osgi.printer.Printer Manifest …. Activateur : cherche le service dans le repository à partir du nom de son interface Représentation en mémoire des services Utilisé par le client du service 0010 0010 1001 … Bundle interface Motivations Bundle, services et packages Cycle de vie Manifest, Activator et BundleContext Enregistrement et recherche de services Gestion d’événements Bundle fournisseur Est une instance de Instancié et enregistré dans le repository par l’activateur Gaël Thomas OSGi 23 Gaël Thomas OSGi 24 Cycle de vie Cycle de vie Le bundle a été correctement téléchargé (pas chargé dans OSGi™) Update, refresh Resolve Installed Install start Resolved Active Uninstalled Gaël Thomas Active Stop, update, refresh Uninstalled 25 Gaël Thomas Update, refresh Install Le bundle a été chargé dans OSGi et Resolve start Les packages sont résolus Active OSGi Resolve L’activateur a été terminé avec succés start Il a, par exemple, enregistré les services fournis Resolved Stop, update, refresh Uninstalled Gaël Thomas Install Starting Update refresh Installed Update refresh Starting Uninstall 26 Cycle de vie Update, refresh Resolved Stopping OSGi Cycle de vie Installed start Uninstall Stopping OSGi Resolve Resolved Stop, update, refresh Uninstall Starting Update refresh Install Starting Update refresh Installed Update, refresh Active Stop, update, refresh Uninstall Stopping Uninstalled 27 Gaël Thomas OSGi Stopping 28 Cycle de vie Cycle de vie B2 : bundle du service X. X est dans le repository. X requiert Y B3 : bundle interface exporte les interfaces X et Y Actif X B1 : requiert service X, offre Y, importe les interfaces X et Y Installation code chargé dans OSGi™ Actif Installé Y Y Actif X X Actif Y ??? ??? B2 X,Y B3 B1 Activateur Activateur X,Y Activateur B2 X,Y 29 Gaël Thomas Actif X Starting : appel de l’activateur. Activateur cherche un service de type Y Actif Starting Y Y Actif X X ??? B2 X,Y Activateur X,Y Activateur Actif Y ??? B1 30 Cycle de vie Résolution : OSGi™ trouve le bundle qui exporte les interfaces X et Y X Activateur OSGi Cycle de vie Résolu X,Y Plateforme OSGi™ OSGi Y X,Y Activateur Plateforme OSGi™ Gaël Thomas B3 B3 B1 Activateur Activateur X,Y B2 B3 X,Y X,Y Activateur X,Y Activateur Cherche un service de type Y Plateforme OSGi™ Gaël Thomas OSGi Plateforme OSGi™ 31 Gaël Thomas OSGi 32 Cycle de vie Cycle de vie OSGi™ renvoie une référence vers l’instance du service X de B2 Activateur : alloue une instance d’un service ayant l’interface X, puis enregistre le service Y dans le repository OSGi™ Liaison Starting Y Actif X X Actif Starting Y Y Actif X X Actif Y ??? B1 ??? B2 X,Y X,Y Activateur B3 B1 Activateur Activateur X,Y Activateur B2 X,Y Renvoie une référence vers l’instance X 33 Gaël Thomas OSGi Actif X B2 cherche un service de type Y Actif Starting Y Y Actif X X ??? B2 X,Y Activateur X,Y B3 B1 Activateur Activateur X,Y Activateur B3 X,Y Activateur X,Y Activateur Cherche un service de type Y Plateforme OSGi™ OSGi B2 X,Y Génère un événement « arrivée d’un service » Gaël Thomas Actif Y ??? B1 34 Cycle de vie OSGi™ génère un événement d’arrivée de service pour le bundle B2 X Activateur Plateforme OSGi™ Cycle de vie Starting X,Y Alloue et enregistre le service Y comme disponible, de type B OSGi Y X,Y Activateur Plateforme OSGi™ Gaël Thomas B3 Plateforme OSGi™ 35 Gaël Thomas OSGi 36 Cycle de vie Cycle de vie OSGi™ renvoie la référence vers l’instance de Y Starting Actif Y X X B1 Actif Actif Y Y B2 X,Y X,Y Activateur Fin de l’enregistrement de Y fin de l’activateur de B1 B1 passe dans l’état actif Activateur Actif X B3 B1 Activateur Activateur X,Y X Actif Y B2 B3 X,Y X,Y Activateur X,Y Activateur Renvoie une référence vers l’instance Y de B1 Plateforme OSGi™ Gaël Thomas OSGi Plateforme OSGi™ 37 Gaël Thomas Développement OSGi 38 Développement OSGi Développement d’un bundle : Rôle de l’activateur Le descripteur de déploiement Fichier manifest.mf Les fichiers binaires (classes) Méthode start() : appelée lors du passage à l’état starting • Chercher les services requis nécessaire au démarrage du bundle • Instancier les services offerts par le bundle • Enregistrer les services offerts par la bundle • Activateur • Classes fournisseurs • Classes clientes Méthode stop() : appelée lors du passage à l’état stopping • Relâcher les références vers les services utilisés • Supprimer les services offerts par le bundle Développement d’une applications Des bundles interface Des bundles de services (clients et serveurs) Gaël Thomas OSGi OSGi Bundle interface : en général pas d’activateur Juste des interfaces et des exceptions 39 Gaël Thomas OSGi 40 Développement OSGi Développement OSGi Écriture de l’interface Description d’un bundle Descripteur de déploiement Fichier manifest.mf dans META-INF : nom du bundle Bundle-Name Import-Package : packages importés (au chargement) Export-Package : packages exportés Bundle-Activator Bundle-ClassPath Bundle-Name: HelloWorld Bundle-Description: The HelloWorld Contract Bundle-Version: 1.0.0 Bundle-Vendor: Gael Thomas Bundle-ContactAddress: [email protected] Bundle-Copyright: Library GNU Public License Export-Package: lip6.services.HelloWorld : classe de l’activateur : un bundle peut contenir des sous-fichiers jar Bundle-UpdateLocation : url pour màj bundle Dynamic-Import-Package : package importés à l’exécution Gaël Thomas OSGi 41 Gaël Thomas Développement OSGi OSGi 42 Développement OSGi Écriture de l’interface Écriture du fournisseur Descripteur de déploiement L’interface du service package lip6.services; Bundle-Name: HelloWorldImpl Bundle-Description: An implementation of HelloWorld Bundle-Version: 1.0.0 Bundle-Vendor: Gael Thomas Bundle-ContactAddress: [email protected] Bundle-Copyright: Library GNU Public License Bundle-Activator: lip6.helloimpl.Activator Import-Package: lip6.services.helloworld, org.osgi.framework public interface HelloWorld { public static hello(); } Gaël Thomas OSGi 43 Gaël Thomas OSGi 44 Développement OSGi Développement OSGi Écriture du fournisseur Écriture du fournisseur Le fournisseur de service L’activateur : enregistre un service Donne des propriétés (<string clé, Object val>) au service package lip6.helloimpl; public class Activator implements BundleActivator { private ServiceRegistration reg; package lip6.helloimpl; public class HelloWorldImpl implements HelloWorld { public void hello() { System.out.println("Bonjour, monde!!!"); } } Gaël Thomas OSGi public void start(BundleContext ctx) throws BundleException { HelloWorld impl = new HelloWorldImpl(); Dictionary props = new Hashtable(); props.put("language", "français"); reg = ctx.registerService(HelloWorld.class.getName(), impl, props); /* type: HelloWorld, props: language=français */ } /* suite transparent suivant */ 45 Gaël Thomas Développement OSGi 46 Développement OSGi Écriture du fournisseur Écriture du consommateurs L’activateur : désenregistre les services Descripteur de déploiement … public void stop(BundleContext ctx) throws BundleException { if(reg != null) reg.unregister(); } } Gaël Thomas OSGi OSGi 47 Bundle-Name: HelloWorldClient Bundle-Description: A clientof HelloWorld Bundle-Version: 1.0.0 Bundle-Vendor: Gael Thomas Bundle-ContactAddress: [email protected] Bundle-Copyright: Library GNU Public License Bundle-Activator: lip6.client.Activator Import-Package: lip6.services.helloworld, org.osgi.framework Gaël Thomas OSGi 48 Développement OSGi Développement OSGi Écriture du Consommateur Propriétés et filtres de recherche L’activateur : cherche un service Expressions LDAP classiques Opérateurs de compositions : &, |, !… Opérateurs de regroupement : () Opérateurs d’égalité, inégalité : =, <, >… • Donne l’interface cherchée • Un filtre LDAP optionnel pour les propriétés • Renvoie un ensemble de services trouvés package lip6.client; Clé spéciale objectClass : l’interface du service (String) public class Activator implements BundleActivator { public void start(BundleContext ctx) throws BundleException { ServiceReference[] refs = context.getServiceReferences(HelloWorld.class.getName(), "language=*"); HelloWorld hw = context.getService(refs[0 ]); hw.hello(); context.ungetService(refs[0 ]); } } Gaël Thomas OSGi 49 Exemple getServiceReference(HelloWorld.class.getName(), "|(language=fr)(cpt<18)"); Tous les services de type HelloWorld ayant language=fr et cpt<18 getServiceReferences(null, "&(objectClass=*)(language=français)); Tous les services (tous type) dans le langage est le français Gaël Thomas OSGi et la programmation dynamique OSGi 50 Conclusion sur OSGi Possibilité d’attacher des gestionnaires d’événements à OSGi : modèle de plateforme à service locale en Java Arrivée ou départ de bundle (BundleListener) Arrivée ou départ de services (ServiceListener) Très performant Pas de mandataire entre serveur et client Uniquement local Exemple : être informée de l’arrivée d’un service HelloWorld De nombreux travaux existent autour de la répartition et de la génération à la volée de mandataire pour invocation distante public class Ecoute extends ServiceListener { public void serviceChanged(ServiceEvent ev) { ServiceReference ref = event.getServiceReference(); String objectClasses[] = (String[])ref.getProperty("objectClass"); if(objectClasses[0].equals(HelloWorld.class.getName()) { switch(ev.getType()) { case MODIFIED: /* props ont changées */ case REGISTERED: /* arrivée d’un fournisseur */ case UNREGISTERING: /* départ d’un fournisseur */ } } } } /* dans Activator : context.addServiceListener(new Ecoute()); */ Gaël Thomas OSGi Uniquement en Java pour Java Contribue à obtenir de bonnes performances! Technologie en pleine expansion Programmation dynamique difficile à prendre en main… Déchargement de classe difficile (voir cours chargeur de classes) Encore peu d’outils d'ingénierie logiciel 51 Gaël Thomas OSGi 52