Introduction Java Naming and Directory Interface (JNDI) Java Standard Edition Java Naming and Directory Interface API de connexion à des services d’annuaires et de résolution de noms RMI Registry (RMI), CosNaming (Corba), LDAP, NIS, File System, DNS… !!Uniformise l’accès à ces annuaires dans une seule API !!Utilisation simultanée et transparente de ces annuaires Gaël Thomas [email protected] Service de résolution de noms Associe des noms à des entités + recherche à partir du nom Université Pierre et Marie Curie Master Informatique M2 – Spécialité SAR Service d’annuaire Associe des attributs et des noms aux entités + recherche à partir des deux 2008-2009 Introduction Exemple de service de résolution de noms : RMIRegistry !!API définie en Java !!Associe des noms plats à des objets RMI Rappel : objet RMI = objet Serveur, implémente l’interface Remote Serveur WEB Service de transport : IIOP, RMI ou autre Cache 2008-2009 Conteneur EJB Master SAR - M2 MDOC - Introduction Lancer le service de résolution de noms : Service BD : JDBC Conteneur WEB Service Transaction: JTA/JTX Service Nommage : JNDI JEE Conteneur EJB 2 Exemples d’annuaire Client léger : navigateur Web HTTP Client lourd Master SAR - M2 MDOC - Introduction !!shell$ rmiregistry & Se connecter au service de résolution de noms en Java !!Registry LocateRegistry.getRegistry(String host, int port); Base De Donnée 3 2008-2009 Master SAR - M2 MDOC - Introduction 4 Exemples d’annuaire Exemples d’annuaire Exemple de service de résolution de noms : le système de fichiers Exemple de service de résolution de noms : RMIRegistry !! API définie par le système d’exploitation !! Associe des noms hiérarchiques à des objets fichiers Notion de répertoire : Utiliser le RMI Registry !!void bind(String name, Remote obj); !!void rebind(String name, Remote obj); !!String[] list(); !!Remote lookup(String name); •! Entité contenant des noms •! Un répertoire possède un nom dans un autre répertoire Utiliser le système de fichier sous linux !! ls (list), rm (remove), touch/redirection (bind), mv (move) / etc passwd 2008-2009 Master SAR - M2 MDOC - Introduction 5 2008-2009 Exemples d’annuaire uid=anne 2008-2009 !!Recherche à l’aide de filtre Exemples : •! (user=Bob) : cherche Bob •! (&(user=B*)(objectclass=Person)) : cherche une personne dont le nom commence par B •! (&(age>22)(age<33)(objectclass=Person)) : cherche les personne dont l’âge est compris entre 22 et 33 dn: dc=inria, dc=fr uid=igor 6 •! scope=sub : dans tout le sous-arbre •! scope=one : uniquement parmi les fils •! scope=base : uniquement sur notre propre nœud (utile pour consulter les autres attributs d’un nœud) dn: dc=fr ou=people Master SAR - M2 MDOC - Introduction !!Recherche : dans un sous-arbre (à partir d’un DN) !!Scope : définit la profondeur de la recherche Un nœud est identifié par son DN (Distinguished Name) constitué de la liste (inverse) des RDN jusqu’à la racine ou=computer ls Exemple de service d’annuaire : LDAP !! Associe des propriétés (clé=valeur) à des entités !! Chaque entité possède une classe (Person etc..) définie dans un schéma !! Structure hiérarchique, appelée DIT (Directory Information Tree) !! Chaque nœud de l’arbre est une entité qui possède une propriété appelée RDN (Relative Distinguished Name) unique pour la classe dc=inria conf.d Exemples d’annuaire Exemple de service d’annuaire : LDAP dc=fr bin dn: ou=people, dc=inria, dc=fr Un annuaire LDAP est une BD hiérarchique dn: uid=igor, ou=people, dc=inria, dc=fr Master SAR - M2 MDOC - Introduction 7 2008-2009 Master SAR - M2 MDOC - Introduction 8 Architecture de JNDI Architecture de JNDI Architecture de JNDI JNDI API : api d’utilisation de services de nommage javax.naming.*, javax.naming.directory.*, javax.naming.ldap.*, javax.naming.event.* Naming Manager : correspondance entre l’API JNDI et les fournisseurs de services JNDI SPI : api interne des fournisseurs de services javax.naming.spi.* 2008-2009 Master SAR - M2 MDOC - Introduction 9 2008-2009 Master SAR - M2 MDOC - Introduction Architecture de JNDI Architecture de JNDI JNDI : système hiérarchique de résolution de noms et annuaire Hiérarchie de contexte !!API d’accès à des annuaires avec des fournisseurs d’annuaires !!API d’accès à des services de résolution de noms sinon (API d’accès à un annuaire hérite de l’API de résolution de noms) !!Un contexte est un répertoire de noms (répertoire dans les fs, NamingContext Corba, nom de domaine DNS…) !!Contient des associations <nom, objet> !!Peut contenir des sous-contextes (association <nom, Context>) !!N’existe que si le fournisseur de service l’offre (pas le cas de RMIRegistry) Différences principales entre les deux API !!Annuaire : recherche par nom ou par filtre !!Service résolution nom : recherche par nom uniquement InitialContext !!Contexte racine dans JNDI !!Obligatoire pour toute recherche !!Construit avec new InitialContext() ou new InitialContext(Hashtable env) Possibilité de passer des paramètres au contexte initial via Étude dans le suite : le service de résolution de nom uniquement !!API pour les annuaires : voir la JavaDoc javax.naming.directory !!Notions correspondent à celles de LDAP 2008-2009 Master SAR - M2 MDOC - Introduction 10 •! Propriété (jndi.properties) •! Table de hash env 11 2008-2009 Master SAR - M2 MDOC - Introduction 12 Utilisation de JNDI Utilisation de JNDI Les deux paramètres de base du contexte initial Extrait de l’API de Context !!INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial" Classe du fournisseur de service du contexte initial !!void bind(String name, Object obj): associe l’objet obj au nom name (Attention : cette classe doit être dans le CLASSPATH) (chemin complet, tous les contexte intermédiaires doivent exister) !!PROVIDER_URL = "java.naming.provider.url » Paramètres passé au fournisseur, en général URL du service !!NamingEnumeration<Binding> listBinding(String name): renvoie la liste des associations possédant le nom name (1 niveau) !!Object lookup(String name): Renvoie l’objet ayant pour nom name (dans le sous-arbre) !!void rebind(String name, Object obj): Ré-associe l’objet obj au nom name !!void unbind(String name): Détruit l’association ayant pour nom name !!Context createSubcontext(String name): Crée un sous-contexte ayant pour nom name (préférable à bind) Exemple Properties props = Properties(); props.put(INITIAL_CONTEXT_FACTORY, "com.sun.jndi.registry.RegistryContextFactory"); props.put(PROVIDER_URL, "rmi://localhost:1099"); Context ic = new InitialContext(props); 2008-2009 Master SAR - M2 MDOC - Introduction 13 2008-2009 Utilisation de JNDI Master SAR - M2 MDOC - Introduction 14 L’usine à objet Exemple avec le service de résolution de noms RMI Problème avec les Stateful Bean: A chaque client son Bean! public interface Hello { void sayHello(); } public HelloImpl implements Hello { … implem … } ! ! ic.lookup("Test@Remote") renvoie un nouveau Bean à chaque appel Côté serveur Context ic = new InitialContext(props); Remote obj = new HelloImpl(); UnicastRemoteObject.exportObject(obj, 0); ic.rebind("mon-serveur", obj); Solution : enregistrer des javax.naming.Reference ! ! Interception de la recherche Côté client Context ic = new InitialContext(props); Hello server = (Hello)ic.lookup("mon-serveur"); server.sayHello(); 2008-2009 Master SAR - M2 MDOC - Introduction 15 2008-2009 Master SAR - M2 MDOC - Introduction 16 L’usine à objet L’usine à objet Exemple : l’usine MaFactory Exemple : l’enregistrement public MaFactory extends ObjectFactory { public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) { String cname = name.get(0); // nom de l’objet Class cl = Class.forName(name); // charge la classe return cl.newInstance(); } } interface Cinema {} public CinemaImpl implements Cinema {} 2008-2009 Master SAR - M2 MDOC - Introduction // (class de l’objet, class de l’usine, classpath de l’usine) Reference ref = new Reference( Cinema.class.getName(), MaFactory.class.getName(), null); ic.bind("CinemaImpl", ref); 17 2008-2009 L’usine à objet 18 URL JNDI Exemple : la recherche ContextInitial : associé à un unique fournisseur ic.lookup("CinemaBean"); lookup Master SAR - M2 MDOC - Introduction Valeur retournée Problème : Utiliser simultanément plusieurs fournisseurs de nommages new CinemaBean getObjectInstance "CinemaBean" rmiregistry ref car instance de MyFactory Solution : Les URL JNDI Reference !!Définissent des protocoles !!Associe des protocoles avec des fournisseurs "rmi://localhost:1099/mon-serveur", "iiop://susanoo.lip6.fr/un-autre-serveur" 2008-2009 Master SAR - M2 MDOC - Introduction 19 2008-2009 Master SAR - M2 MDOC - Introduction 20 URL JNDI URL JNDI URL RMI : accès direct à un service de résolution de noms Exemple : InitialContext ic = new InitialContext(); URL = schema:partie-specific-au-protocole Hello sever = (Hello)ic.lookup("rmi://localhost:1099/mon-server"); !!Le fournisseur correspondant au schéma est automatiquement chargé !!Évite de donner explicitement une classe au contexte initiale // ! équivalent à // (new com.sun.jndi.url.rmi.rmiURLContextFactory()) // .getInitialContext(props) // .lookup("mon-server"); // avec props "contient" localhost et 1099 Construction de la classe correspondant au schema package_prefix.schema.schemaURLContextFactory package_prefix = com.sun.jndi.url par défaut Remarque : ici, le contexte initial ic n’a pas de drivers (SPI) associé 2008-2009 Master SAR - M2 MDOC - Introduction 21 2008-2009 URL JNDI Master SAR - M2 MDOC - Introduction 22 URL JNDI Définition de nouvelles URL JNDI Exemple : !!Paramètre du contexte initial (propriété) !!Context.URL_PKG_PREFIX = "java.naming.factory.url.pkgs » Exemple : InitialContext ic = new InitialContext(props); ic.lookup("java:comp/env/ejb/Cinema"); // charge com.bubble.java.javaURLContextFactory // délègue la recherche de comp/env/ejb/Cinema à // cette usine à fournisseur d’annuaire props.put(URL_PKG_PREFIX, "org.wiz:com.bubble"); Cherche les usines à fournisseur d’annuaire en essayant de charger les classes org.wiz.schema.schemaURLContextFactory puis com.bubble.schema.schemaURLContextFactory puis com.sun.jndi.url.schema.schemaURLContextFactory 2008-2009 Master SAR - M2 MDOC - Introduction 23 2008-2009 Master SAR - M2 MDOC - Introduction 24 JNDI dans Java Enterprise Edition JNDI et Java Enterprise Edition Nommage local Deux espaces de nommage pour chaque composant (Web ou EJB) Nommage local !!Espace de nommage global (new InitialContext()) Service de nommage classique, service peut être distant !!Espace de nommage local sous le schéma d’URL java: Convention : les noms importés sont dans java:comp/env Réécriture des noms, service forcément local Principe : !!Un composant utilise les noms locaux !!Le descripteur de déploiement importe les noms globaux ! Le code est indépendant des noms globaux 2008-2009 Master SAR - M2 MDOC - Introduction Nommage global EJB Test Client Lourd Référence comp/ env/ Cinema Utilisation directe Test@Remote Lien Lien Cinema@Remote comp/ env/ Cinema Référence MaServlet 25 2008-2009 JNDI dans Java Enterprise Edition comp/ env/ Test Lien Nommage local JNDI dans Java Enterprise Edition EJB Cinema Master SAR - M2 MDOC - Introduction 26 JNDI dans Java Enterprise Edition Principe du nommage avec les annotations : Exemple 1 en utilisant les paramètres par défaut : !!name : le nom local !!mappedName : le nom global (donc, à éviter! Sauf pour clients lourds…) !!Fichier TestBean.java Exemple 1 : @Stateful(name= "Test", mappedName="Test@Remote") @Remote(Test.class) Par défaut, public class TestBean implements Test { name=nom de l’interface @EJB(name="Cinema") de l’entité en question (sans le package) Cinema cinema; les deux name peuvent } êtres omis @Stateful(mappedName="Test@Remote") public class TestBean implements Test { @EJB Cinema cinema; } !!Fichier CinemaBean.java @Stateless public class CinemaBean implements Cinema {…} Tous les noms locaux des beans sont exportés dans l’unité de déploiement (ici, Cinema est packagé dans le même Bean que Test) 2008-2009 Master SAR - M2 MDOC - Introduction 27 2008-2009 Master SAR - M2 MDOC - Introduction 28 JNDI dans Java Enterprise Edition JNDI dans Java Enterprise Edition Exemple 2 : EJB : importation de noms externes et modification des liaisons @Resource(name="rigolo", mappedName="topic_rigolo") Topic topic; @Resource(name="factory", mappedName="JTCF") TopicConnectionFactory factory; Ajouter un fichier ejb-jar.xml Les noms dans le services globales sont donc !! "topic_rigolo" pour le topic !!"JTCF" pour l’usine Intérêt du nom local : Pour modifier le lien entre nom global et nom local dans le fichier de déploiement 2008-2009 Master SAR - M2 MDOC - Introduction 29 <ejb-jar> <enterprise-beans> <session> <ejb-name>AutreBean</ejb-name> <!-- insérer ici les importations </session> </enterprise-beans> </ejb-jar> 2008-2009 JNDI dans Java Enterprise Edition --> Master SAR - M2 MDOC - Introduction JNDI dans Java Enterprise Edition Importation d’un EJB Test dans un EJB AutreBean Importation d’une ressource dans un EJB AutreBean <ejb-name>AutreBean</ejb-name> paramètre name de @EJB <ejb-ref> <ejb-ref-name>Test</ejb-ref-name> <remote>mdoc.ejbsample.Test</remote> <mapped-name>Test@Remote</mapped-name> nom global du Bean Test <injection-target> <injection-target-class> mdoc.AutreBean</injection-target-class> <injection-target-name> champs @EJB de AutreBean champsEJB</injection-target-name> </injection-target> </ejb-ref> <ejb-name>AutreBean</ejb-name> paramètre name de @Resource <resource-ref> <res-ref-name>monitor</res-ref-name> <mapped-name>monitoring_topic</mapped-name> <injection-target> nom global du topic <injection-target-class> mdoc.AutreBean</injection-target-class> <injection-target-name> champs @Resource de AutreBean topic</injection-target-name> </injection-target> </resource-ref> class AutreBean { @EJB(name="Test") champsEJB; } class AutreBean { @Resource(name="monitor") topic; } 2008-2009 Master SAR - M2 MDOC - Introduction 30 31 2008-2009 Master SAR - M2 MDOC - Introduction 32 JNDI dans Java Enterprise Edition JNDI dans Java Enterprise Edition Web : importation de noms externes et modification des liaisons Web : importation de noms externes et modification des liaisons 1 - Enrichir le fichier web.xml 2 - Définir le fichier jonas-web.xml correspond à java:comp/env/Test dans le composant Web <ejb-ref> <ejb-ref-name>Test</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home></home> <remote>mdoc.ejbsample.Test</remote> </ejb-ref> correspond à java:comp/env/monitor <jonas-web-app> <jonas-ejb-ref> Nom local <ejb-ref-name>Test</ejb-ref-name> <jndi-name>Test@Remote</jndi-name> Nom global </jonas-ejb-ref> Nom local <jonas-resource> <res-ref-name>monitor</res-ref-name> <jndi-name>monitoring_topic</jndi-name> </jonas-resource> Nom global </jonas-web-app> dans le composant Web <resource-ref> <res-ref-name>monitor</res-ref-name> <res-type>javax.jmx.Topic</res-type> <res-auth>Container</res-auth> </resource-ref> 2008-2009 Master SAR - M2 MDOC - Introduction 33 2008-2009 JNDI dans Java Enterprise Edition Master SAR - M2 MDOC - Introduction 34 JNDI dans Java Enterprise Edition Web : importation de noms externes et modification des liaisons Nommage et répartition !!Version centralisée : deux conteneurs centralisés sur deux machines Utilisation : void doGet(HttpServletRequest i, HttpServletResponse o) { Test test = (Test)(new InitialContext()). lookup("java:comp/env/Test"); Topic topic = (Topic)(new InitialContext()). lookup("java:comp/env/monitor"); } Service de nommage 1 sur Machine 1 Service de nommage 2 sur Machine 2 Conteneur 1 sur Machine1 class MaServlet extends HttpServlet { @EJB(name="Test") Test test; @Resource(name="monitor") Topic topic; } Master SAR - M2 MDOC - Introduction Conteneur 2 sur Machine2 !!Version distribuée : un service de nommage commun sur une autre machine Ou 2008-2009 Conteneur 1 sur Machine1 Conteneur 2 sur Machine2 Service de nommage sur Machine 3 35 2008-2009 Master SAR - M2 MDOC - Introduction 36 JNDI dans Java Enterprise Edition Conclusion Nommage et répartition JNDI : masque l’hétérogénéité des services d’annuaires !!Version tolérante aux fautes et/ou répartition de charge Conteneur 1 sur M1 Conteneur 2 sur M2 Proxy de répartition sur M1 Proxy de répartition sur M2 !!Une API pour de multiples services !!Mais : possibilité limitées par le service •! Pas d’arbre avec JNDI si service RMIRegistry •! Pas de lookup("*t*") avec RMIRegistry Notion d’URL JNDI : accès simultané à plusieurs services d’annuaire !!Mais ne masque pas la localisation du service d’annuaire !!Mais ne masque pas le type du service d’annuaire Tolérance aux pannes Service de nommage répliqué 1 sur M3 JNDI dans JEE Service de nommage répliqué 2 sur M4 !!Le conteneur à composant prend en charge l’accès aux service de nommage !!Masquage des noms réels via le schéma d’URL java: + fichier déploiement !!Construction avancée distribuée pour tolérance aux pannes/répartition charge synchronisation 2008-2009 Master SAR - M2 MDOC - Introduction 37 2008-2009 Master SAR - M2 MDOC - Introduction 38