RMI - Plateforme e-learning Moodle de l`INSA de Rouen
Transcription
RMI - Plateforme e-learning Moodle de l`INSA de Rouen
INSA - ASI InfoRep : RMI Informatique Répartie Remote Method Invocation (RMI) Alexandre Pauchet INSA Rouen - Département ASI BO.B.RC.18, [email protected] 1/73 INSA - ASI InfoRep : RMI 2/73 Plan 1 2 3 Introduction 6 Le DGC 7 Objets activables 8 Interopérabilité : RMI sur IIOP Exemple : HelloWorld Gestion des exceptions 4 Passage d’objet Serializable 5 Les Callbacks INSA - ASI InfoRep : RMI Introduction(1/13) Histoire Les années 70, architecture Mainframe (1 tier) 3/73 INSA - ASI InfoRep : RMI Introduction 4/73 (2/13) Histoire Les années 80, architecture 2 tiers Re qu ète sS QL Requètes SQL QL sS ète qu Re Base de Données INSA - ASI InfoRep : RMI Introduction 5/73 (3/13) Histoire Fin des années 80, architecture 3 tiers (RPC) RP C Primergy Requètes SQL RP C Base de Données INSA - ASI InfoRep : RMI Introduction 6/73 (4/13) Histoire Les années 90, architecture 3 tiers (Objets) RM I/ CO RB Primergy Requètes SQL objet A objet A RB RM I/ CO objet objet Base de Données INSA - ASI InfoRep : RMI Introduction 7/73 (5/13) Rappels sur les objets Programmation Orientée Objet Encapsulation : état (attributs) + fonctionnalités (méthodes) Modularité : regroupement en classes (abstraction) Réutilisabilité Composition/agrégation Extensibilité OBJET Interface Méthodes États attributs Implantation corps des méthodes INSA - ASI InfoRep : RMI Introduction 8/73 (6/13) Objectif : transposition du mécanisme des RPC 1 Client 10 2 4 7 9 Processus client Invocation d'une méthode Emballage des arguments Transport de l'invocation Déballage des arguments Invocation de l'objet réel 6 Processus serveur 3 1 2 3 4 5 5 Souche serveur Souche cliente 8 Réseau 6 7 8 9 10 Retour de l'invocation locale Emballage des résultats Transport des résultats Déballage des résultats Retour de l'invocation distante INSA - ASI InfoRep : RMI Introduction (7/13) Description Protocole et outil d’invocation de méthodes à distance proposés par Sun depuis 1996 À partir du JDK 1.1, RMI fait partie intégrante de Java : Un ensemble de classes dans les packages : java.rmi java.rmi.server java.rmi.registry java.rmi.dgc java.rmi.activation Trois “exécutables” : rmic (jdk <1.5 et RMI sur IIOP pour la compatibilité avec Corba) rmid rmiregistry Protocole de transport utilisé : JRMP 9/73 INSA - ASI InfoRep : RMI Introduction 10/73 (8/13) Caractéristiques générales Produit gratuit Mono-langage mais multi-plateformes Orienté-objet Invocation de méthodes synchrones Passage de paramètres des invocations distantes : Type simple : passage par valeur Instance d’une classe qui implémente Serializable : passage par valeur Instance d’une classe qui implémente Remote et référencée comme objet distribué (voir suite du cours) : c’est un stub qui est envoyé Sinon une erreur est produite Service d’annuaire (rmiregistry) Port par défaut : 1099 INSA - ASI InfoRep : RMI Introduction 11/73 (9/13) Principe Client Stub Réseau Skeleton Serveur Service d'annuaire Stub (souche cliente) : talon (+ module de transport) client Skeleton (souche serveur) : talon (+ module de transport) serveur INSA - ASI InfoRep : RMI Introduction 12/73 (10/13) Cycle de développement 1 2 3 4 5 Développer et compiler l’interface de l’objet distant Développer et compiler une implémentation de cette interface Générer si nécessaire (jdk<1.5 ou RMI sur IIOP), à l’aide de rmic, le stub et le skeleton (stub serveur) Développer et compiler le serveur d’objet, qui : crée l’objet (crée une instance de l’implémentation) le référence Développer et compiler le client, qui : récupère un représentant de l’objet distant auprès de l’annuaire invoque une méthode Remarques À partir de la version 1.2 de RMI, le skeleton n’est plus visible À partir du jdk 1.5 : rmic n’est plus indispensable Pour supporter l’interopérabilité (communication d’un bus ORB avec un bus RMI), rmic reste indispensable INSA - ASI InfoRep : RMI Introduction 13/73 (11/13) Architecture Serveur RMI Client RMI Client RMI [ ] [ ] [ ] [ ] Interface [ [ ] rmiregistry Stub ] Skeleton Implémentation JVM INSA - ASI InfoRep : RMI Introduction 14/73 (12/13) Exécution Accès aux données Service de nommage (rmiregistry) : l’interface doit être accessible via le classpath ou le codebase Serveur : l’interface et l’implémentation doivent être accessibles via le classpath ou le codebase Client : l’interface doit être accessible via le classpath ou le codebase codebase java -Djava.rmi.server.codebase="http://..." java -Djava.rmi.server.codebase="file:/..." + chemin absolu INSA - ASI Introduction InfoRep : RMI 15/73 (13/13) Le service de nommage Le service de nommage est un objet RMI ⇒ rmiregistry est un serveur Registry.java package java . rmi . registry ; p u b l i c i n t e r f a c e Registry e x t e n d s java . rmi . Remote { p u b l i c s t a t i c f i n a l i n t REGISTRY_PORT = 1099; p u b l i c java . rmi . Remote lookup ( String name ) throws java . rmi . RemoteException , java . rmi . NotBoundException , java . rmi . AccessException ; p u b l i c v o i d bind ( String name , java . rmi . Remote obj ) throws java . rmi . RemoteException , java . rmi . AlreadyBoundException , java . rmi . AccessException ; p u b l i c v o i d rebind ( String name , java . rmi . Remote obj ) throws java . rmi . RemoteException , java . rmi . AccessException ; p u b l i c v o i d unbind ( String name ) throws java . rmi . RemoteException , java . rmi . NotBoundException , java . rmi . AccessException ; p u b l i c String [] list () throws java . rmi . RemoteException , java . rmi . AccessException ; } INSA - ASI InfoRep : RMI Exemple : HelloWorld (1/7) Description Étapes à réaliser 1 2 3 4 Développer Développer Développer Développer l’interface Hello.java une implémentation de l’interface : HelloImpl.java le serveur un client Exécution 1 2 3 Lancer le service de nommage Lancer le serveur Lancer le(s) client(s) 16/73 INSA - ASI InfoRep : RMI Exemple : HelloWorld (2/7) L’interface Hello Contraintes L’interface doit étendre l’interface java.rmi.Remote Chaque méthode doit pouvoir lever une exception du type java.rmi.RemoteException Hello.java package HelloWorldRMI ; import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c String sayHello ( String nom ) throws RemoteException ; } 17/73 INSA - ASI InfoRep : RMI Exemple : HelloWorld (3/7) Implémentation HelloImpl Contraintes La classe doit implémenter l’interface et donc implémenter java.rmi.Remote HelloImpl.java package HelloWorldRMI ; p u b l i c c l a s s HelloImpl implements Hello { p u b l i c String sayHello ( String nom ) { System . out . println ( " Request from " + nom ) ; r e t u r n " Bonjour " + nom + " ! " ; } } 18/73 INSA - ASI InfoRep : RMI Exemple : HelloWorld 19/73 (4/7) Stub Objet RMI Tout objet distribué doit l’être sous la forme d’un Skeleton ; il sera récupéré sous la forme d’un Stub chez le client Utilisation de UnicastRemoteObject.exportObject(IMPL,PORT) pour obtenir le Skeleton correspondant à une implémentation Service de nommage Le service de nommage est un stub offrant plusieurs services : bind(), rebind(), unbind(), list(), lookup() Il peut être récupéré par un appel à la méthode statique : Registry LocateRegistry.getRegistry([machine], [port]); Le port par défaut est 1099 Pour des raisons de sécurité, les méthodes bind(), sont accessibles que depuis la même machine rebind() et unbind() ne INSA - ASI InfoRep : RMI Exemple : HelloWorld (5/7) Le serveur Serveur.java import import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; java . util . Arrays ; HelloWorldRMI .*; p u b l i c c l a s s Serveur { p u b l i c s t a t i c v o i d main ( String args []) { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { Hello skeleton = ( Hello ) U n ic a s t R e m o t e O b j e c t . exportObject (new HelloImpl () , 0) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " Hello " ) ) registry . bind ( " Hello " , skeleton ) ; else registry . rebind ( " Hello " , skeleton ) ; System . out . println ( " Service Hello lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( e ) ; } } } 20/73 INSA - ASI Exemple : HelloWorld InfoRep : RMI (6/7) Le client Client.java import java . rmi . registry . LocateRegistry ; import java . rmi . registry . Registry ; import HelloWorldRMI . Hello ; p u b l i c c l a s s Client { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello obj = ( Hello ) registry . lookup ( " Hello " ) ; String message = obj . sayHello ( args [ args . length -1]) ; System . out . println ( message ) ; } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } 21/73 INSA - ASI InfoRep : RMI Exemple : HelloWorld 22/73 (7/7) Exécution distante Exécution 1 2 3 Lancer le serveur de nommage : rmiregistry [port] L’interface doit être accessible au serveur de nommage via le classpath ou le codebase Serveur : l’interface et l’implémentation doivent être accessibles via le classpath ou le codebase Client : accès à l’interface via le classpath ou le codebase codebase java -Djava.rmi.server.codebase=http://... java -Djava.rmi.server.codebase=file:/... + chemin absolu INSA - ASI InfoRep : RMI Gestion des exceptions (1/5) Exceptions distribuées La gestion des exceptions se fait de manière transparente Les exceptions existantes sont levées et transmises identiquement à un traitement local La création d’exceptions “spécifiques" se fait identiquement à une création locale Remarque Toute exception créée doit être accessible au serveur, au client et au rmiregistry (via le classpath ou le codebase). 23/73 INSA - ASI Gestion des exceptions InfoRep : RMI (2/5) ChaineVide et Hello Hello.java package HelloWorldRMI ; import java . rmi . Remote ; import java . rmi . RemoteException ; import java . io . Serializable ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c String sayHello ( String nom ) throws RemoteException , ChaineVide ; p u b l i c v o i d divisionParZero () throws RemoteException ; } ChaineVide.java package HelloWorldRMI ; p u b l i c c l a s s ChaineVide e x t e n d s Exception { p u b l i c ChaineVide () { s u p e r ( " String vide interdit ! " ) ; } } 24/73 INSA - ASI Gestion des exceptions InfoRep : RMI (3/5) Hello et HelloImpl HelloImpl.java package HelloWorldRMI ; import HelloWorldRMI . Hello ; import HelloWorldRMI . ChaineVide ; p u b l i c c l a s s HelloImpl implements Hello { p u b l i c String sayHello ( String nom ) throws ChaineVide { i f ( nom . length () ==0) throw new ChaineVide () ; System . out . println ( " Request from " + nom ) ; r e t u r n " Bonjour " + nom + " ! " ; } p u b l i c v o i d divisionParZero () { i n t tmp = 1/0; } } 25/73 INSA - ASI InfoRep : RMI Gestion des exceptions (4/5) Le serveur Serveur.java import import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; java . util . Arrays ; HelloWorldRMI .*; p u b l i c c l a s s Serveur { p u b l i c s t a t i c v o i d main ( String args []) { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { Hello skeleton = ( Hello ) U n ic a s t R e m o t e O b j e c t . exportObject (new HelloImpl () , 0) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " HelloExceptions " ) ) registry . bind ( " HelloExceptions " , skeleton ) ; else registry . rebind ( " HelloExceptions " , skeleton ) ; System . out . println ( " Service HelloExceptions lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( e ) ; } } } 26/73 INSA - ASI Gestion des exceptions InfoRep : RMI (5/5) Le client Client.java import java . rmi . registry . LocateRegistry ; import java . rmi . registry . Registry ; import HelloWorldRMI . Hello ; p u b l i c c l a s s Client { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello obj = ( Hello ) registry . lookup ( " HelloExceptions " ) ; i f ( args [ args . length -1]. equals ( " division " ) ) obj . divisionParZero () ; else System . out . println ( obj . sayHello ( args [ args . length -1]) ) ; } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } 27/73 INSA - ASI InfoRep : RMI Passage d’objet Serializable 28/73 (1/5) Principe Le passage d’un objet Serializable se fait de manière transparente Identiquement à un passage de type de base Il s’agit d’un passage par valeur pour un objet Remarque Tout objet non Serializable ne pourra pas faire l’objet d’un passage de paramètre en RMI À l’exécution, le rmiregistry (et évidemment le serveur et le client) doit avoir accès à la classe à sérialiser via le classpath ou le codebase INSA - ASI InfoRep : RMI Passage d’objet Serializable (2/5) Hello et HelloImpl Hello.java package H e l l o W o r l d S e r i a l i z a b l e ; import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c String sayHello ( Guy aGuy ) throws RemoteException ; } HelloImpl.java package H e l l o W o r l d S e r i a l i z a b l e ; import java . io . Serializable ; p u b l i c c l a s s HelloImpl implements Hello { p u b l i c String sayHello ( Guy aGuy ) { System . out . println ( " Request from a guy : " + aGuy . getName () ) ; r e t u r n " Bonjour " + aGuy . getName () + " ! " ; } } 29/73 INSA - ASI InfoRep : RMI Passage d’objet Serializable Guy Guy.java package H e l l o W o r l d S e r i a l i z a b l e ; import java . io . Serializable ; p u b l i c c l a s s Guy implements Serializable { p r i v a t e String name ; p u b l i c Guy ( String name ) { t h i s . name = name ; } p u b l i c String getName () { r e t u r n t h i s . name ; } } (3/5) 30/73 INSA - ASI InfoRep : RMI Passage d’objet Serializable (4/5) Le serveur Serveur.java import import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; java . util . Arrays ; H e l l o W o r l d S e r i a l i z a b l e .*; p u b l i c c l a s s Serveur { p u b l i c s t a t i c v o i d main ( String args []) { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { Hello skeleton = ( Hello ) U n ic a s t R e m o t e O b j e c t . exportObject (new HelloImpl () , 0) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " He llo Se ria liz abl e " ) ) registry . bind ( " Hel loS eri ali zab le " , skeleton ) ; else registry . rebind ( " He llo Se ria liz abl e " , skeleton ) ; System . out . println ( " Service H ell oSe ria liz ab le lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( e ) ; } } } 31/73 INSA - ASI InfoRep : RMI Passage d’objet Serializable (5/5) Le client Client.java import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; H e l l o W o r l d S e r i a l i z a b l e .*; p u b l i c c l a s s Client { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; Guy aGuy = new Guy ( args [ args . length -1]) ; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello obj = ( Hello ) registry . lookup ( " He llo Ser ial iz abl e " ) ; System . out . println ( obj . sayHello ( aGuy ) ) ; } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } 32/73 INSA - ASI InfoRep : RMI Les Callbacks 33/73 (1/6) Description Définition (rappel) Un callback (appel en retour) est le fait qu’un serveur (resp. un client) exécute une méthode côté client (resp. côté serveur) sur un objet distant transmis par le client (resp. par le serveur). Client Programme Objet (Stub) Serveur Objet Stub Service Objet Le client, lors de son appel de méthode distante passe en paramètre une référence sur l’objet (un stub) qu’il propose au serveur. Ce dernier peut alors invoquer une méthode sur cet objet Utilisation des méthodes statiques exportObject() et unexportObject() de UnicastRemoteObject pour créer un stub. INSA - ASI Les Callbacks InfoRep : RMI (2/6) Hello et HelloImpl Hello.java package H e l l oW o rl d Ca l lb a ck ; import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c String s a y H e l l o A n d C h a n g e N a m e ( Guy aGuy ) throws RemoteException ; } HelloImpl.java package H e l l oW o rl d Ca l lb a ck ; import java . rmi . RemoteException ; p u b l i c c l a s s HelloImpl implements Hello { p u b l i c String s a y H e l l o A n d C h a n g e N a m e ( Guy aGuy ) throws RemoteException { String name = aGuy . getName () ; System . out . println ( " Request from a guy : " + name ) ; aGuy . setName ( " Bob Leponge " ) ; r e t u r n " Bonjour " + name ; } } 34/73 INSA - ASI Les Callbacks InfoRep : RMI (3/6) Guy Guy.java package H e l l oW o rl d Ca l lb a ck ; import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Guy e x t e n d s Remote { p u b l i c String getName () throws RemoteException ; p u b l i c v o i d setName ( String name ) throws RemoteException ; } GuyImpl.java package H e l l oW o rl d Ca l lb a ck ; p u b l i c c l a s s GuyImpl implements Guy { p r i v a t e String name ; p u b l i c GuyImpl ( String name ) { t h i s . name = name ; } p u b l i c String getName () { r e t u r n t h i s . name ; } p u b l i c v o i d setName ( String name ) { t h i s . name = name ; } } 35/73 INSA - ASI InfoRep : RMI Les Callbacks (4/6) Le serveur Server.java import import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; java . util . Arrays ; H e l l o W o rl d Ca l lb a ck .*; p u b l i c c l a s s Serveur { p u b l i c s t a t i c v o i d main ( String args []) { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { Hello stub = ( Hello ) U n ic a s t R e m o t e O b j e c t . exportObject (new HelloImpl () , 0) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " HelloCallback " ) ) registry . bind ( " HelloCallback " , stub ) ; else registry . rebind ( " HelloCallback " , stub ) ; System . out . println ( " Service HelloCallback lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( e ) ; } } } 36/73 INSA - ASI InfoRep : RMI Les Callbacks (5/6) Le client Client.java import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; H e l l o W o rl d Ca l lb a ck .*; p u b l i c c l a s s Client { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; Guy stubGuy , aGuy = new GuyImpl ( args [ args . length -1]) ; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello obj = ( Hello ) registry . lookup ( " HelloCallback " ) ; stubGuy = ( Guy ) U n i c a st R e m o t e O b j e c t . exportObject ( aGuy ,0) ; System . out . println ( obj . s a y H e l l o A n d C h a n g e N a m e ( stubGuy ) ) ; U n i c a s t R em o t e O b j e c t . unexportObject ( aGuy , t r u e ) ; System . out . println ( " Nouveau nom : " + aGuy . getName () ) ; } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } 37/73 INSA - ASI InfoRep : RMI Les Callbacks 38/73 (6/6) Synthèse pour un objet passé en paramètre Serveur Client rmiregistry Objet Serializable Interface et Implémentation Interface et Implémentation Interface Stub Client → Serveur Interface Interface et Implémentation Interface Stub Serveur → Client Interface et Implémentation Interface Interface INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) 39/73 (1/7) Description RMI possède un DGC basé sur le concept de bail : Quand un client créé une référence locale (unmarshall) sur un objet RMI, il invoque la méthode dirty() du DGC, qui lui octroie un bail. Ce bail doit être renouvelé régulièrement (appels à dirty()) avant expiration du bail. Lorsque le client en termine avec sa référence locale, il fait appel à la méthode clean() du DGC Si le client ne renouvelle pas d’appel vers l’objet distant avant l’expiration du bail (défaut : 10 mn, cf. java.rmi.dgc.leaseValue), le DGC suppose que l’objet n’est plus référencé Le DGC est complètement transparent pour l’utilisateur Si le client invoque une méthode sur un objet ramassé par le DGC, une exception java.rmi.ConnectException est levée Si le serveur implémente l’interface Unreferenced, unreferenced() est invoquée lorsqu’il n’y a plus de référence INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) 40/73 (2/7) Hello et HelloImpl Hello.java import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c Msg getMsg () throws RemoteException ; } HelloImpl.java import java . rmi . Remote ; import java . rmi . RemoteException ; import java . rmi . server . U n i c a st R e m o t e O b j e c t ; p u b l i c c l a s s HelloImpl implements Hello { p u b l i c Msg getMsg () throws RemoteException { r e t u r n ( Msg ) U n i c a s t R em o t e O b j e c t . exportObject (new MsgImpl () ,0) ; } } INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) Msg Msg.java import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Msg e x t e n d s Remote { p u b l i c String getMessage () throws RemoteException ; } 41/73 (3/7) INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) 42/73 (4/7) MsgImpl MsgImpl.java import java . rmi . Remote ; import java . rmi . RemoteException ; import java . rmi . server . Unreferenced ; p u b l i c c l a s s MsgImpl implements Msg , Unreferenced { p r i v a t e s t a t i c i n t counter ; p r i v a t e i n t id ; p u b l i c MsgImpl () { s u p e r () ; t h i s . id = ++ MsgImpl . counter ; System . out . println ( " Message created : " + MsgImpl . counter ) ; } p u b l i c v o i d unreferenced () { System . out . println ( " Method unreferenced () called by " + t h i s . id ) ; } p u b l i c v o i d finalize () { System . out . println ( " Method finalize () called by " + t h i s . id ) ; } p u b l i c String getMessage () throws RemoteException { r e t u r n " Message : " + t h i s . id ; } } INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) 43/73 (5/7) Le serveur Server.java import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; java . util . Arrays ; p u b l i c c l a s s Server { p u b l i c s t a t i c v o i d main ( String args []) { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { Hello stub = ( Hello ) Un i c a s t R e m o t e O b j ec t . exportObject (new HelloImpl () , 0) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " HelloDGC " ) ) registry . bind ( " HelloDGC " , stub ) ; else registry . rebind ( " HelloDGC " , stub ) ; System . out . println ( " Service HelloDGC lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( e ) ; } } } INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) 44/73 (6/7) Le client Client.java import java . rmi . registry . LocateRegistry ; import java . rmi . registry . Registry ; import java . rmi . server . U n i c a st R e m o t e O b j e c t ; p u b l i c c l a s s Client { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; Msg msg = n u l l ; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello stub = ( Hello ) registry . lookup ( " HelloDGC " ) ; f o r ( i n t i = 0; i < 100; i ++) { msg = stub . getMsg () ; System . out . println ( msg . getMessage () ) ; } } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } INSA - ASI InfoRep : RMI Le garbage collector distribué (DGC) 45/73 (7/7) Résultat java -Djava.rmi.dgc.leaseValue=5000 Server Service HelloDGC lie au registre Message created:1 Message created:2 ... Message created:100 Method unreferenced() called by 42 Method unreferenced() called by 56 ... Method unreferenced() called by 9 Method finalize() called by 7 Method unreferenced() called by 1 Method unreferenced() called by 23 Method finalize() called by 21 ... Method unreferenced() called by 46 Method finalize() called by 19 ... Method finalize() called by 51 INSA - ASI InfoRep : RMI Objets activables 46/73 (1/9) Problématique Problématique Le nombre d’objets distribués par JVM est limité Dans des conditions réelles d’utilisation, plusieurs milliers d’objets peuvent être distribués simultanément À un instant donné, seule une partie des objets distribués est utilisée ⇒ lancer des JVM (proposant des objets distribués) à la demande C’est le rôle des objets activables Outil/Package Un package java.rmi.activation Un démon rmid qui active les objets à la demande INSA - ASI InfoRep : RMI Objets activables 47/73 (2/9) Description Paramètres à fournir Paramètres de la JVM associée à un ensemble d’objets distribués ? ⇒ Rôle de ActivationGroupDesc Identification d’une JVM associée à un ensemble d’objets distribués ? ⇒ Rôle de ActivationGroupID Informations associées à chaque objet distribué ? ⇒ Rôle de ActivationDesc Classe des objets distribués Les classes des objets distribués sont sous-classe de Activatable, ou passé en paramètre de la méthode statique exportObject() d’Activatable INSA - ASI InfoRep : RMI Objets activables (3/9) Cycle de développement 1 2 Créer l’interface Créer une implémentation de l’objet étend Activatable possède le constructeur obligatoire XX(ActivationID id, MarshalledObject data) 3 Créer le serveur : Il crée les groupes d’activation Il crée les objets et les associe au groupe d’activation Il enregistre l’objet auprès du registre 4 Créer un client “standard” 5 Lancer le registre “standard” : rmiregistry 6 Lancer le système d’activation : rmid 7 Lancer le serveur 8 Lancer le client 48/73 INSA - ASI InfoRep : RMI Objets activables (4/9) Focus sur le serveur Étapes principales : 1 Création de la description du groupe (ActivationGroupDesc) : 2 Obtention d’un identifiant de groupe (ActivationGroupID) Création de la description de l’objet activable (ActivationDesc) Propriétés + Paramètres de la JVM 3 ID + Classe + Localisation + Paramètre(s) aux constructeurs 4 5 Enregistrement auprès du rmid Enregistrement auprès du rmiregistry 49/73 INSA - ASI Objets activables InfoRep : RMI (5/9) L’exemple HelloWord activable Hello.java import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c String sayHello ( String name ) throws RemoteException ; } HelloImpl.java import java . rmi .*; import java . rmi . activation .*; import java . io . Serializable ; p u b l i c c l a s s HelloImpl e x t e n d s Activatable implements Hello { p u b l i c HelloImpl ( ActivationID id , MarshalledObject data ) throws RemoteException { s u p e r ( id , 0) ; } p u b l i c String sayHello ( String nom ) { r e t u r n " Hello " + nom + " ! " ; } } 50/73 INSA - ASI InfoRep : RMI Objets activables (6/9) L’exemple HelloWord activable Server.java import import import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . R MI Se c ur i ty M an a ge r ; java . rmi . activation .*; java . util . Properties ; java . util . Arrays ; p u b l i c c l a s s Server { p u b l i c s t a t i c v o i d main ( String args []) throws Exception { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { System . s e tS e cu r it yM a na g er (new R MI S ec u ri t yM a na g er () ) ; Properties props = new Properties () ; A c t i v a t io n G r o u p D e s c my_group_desc = new A c t i v a t i on G r o u p D e s c ( props , n u l l ) ; A c t iv ati onG ro upI D my_group_id = ActivationGroup . getSystem () . registerGroup ( my_group_desc ) ; A ct ivationGroup . createGroup ( my_group_id , my_group_desc , 0) ; Act ivationDesc objectdesc = new ActivationDesc ( my_group_id , " HelloImpl " , " " , n u l l ); ... 51/73 INSA - ASI InfoRep : RMI Objets activables (7/9) L’exemple HelloWord activable Server.java ... Hello stub = ( Hello ) Activatable . register ( objectdesc ) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " HelloActivatable " ) ) registry . bind ( " HelloActivatable " , stub ) ; else registry . rebind ( " HelloActivatable " , stub ) ; System . out . println ( " HelloActivatable active et lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( " Exception " + e ) ; } } } 52/73 INSA - ASI Objets activables InfoRep : RMI (8/9) L’exemple HelloWord activable Client.java import java . rmi . registry . LocateRegistry ; import java . rmi . registry . Registry ; p u b l i c c l a s s Client { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello stub = ( Hello ) registry . lookup ( " HelloActivatable " ) ; System . out . println ( stub . sayHello ( args [ args . length -1]) ) ; } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } 53/73 INSA - ASI InfoRep : RMI Objets activables 54/73 (9/9) L’exemple HelloWord activable helloworld.policy grant { // permission java . net . SocketPermission "*:1024 -65535" ," listen , connect , accept , resolve "; // permission java . net . SocketPermission "*:80" , " connect "; permission java . security . AllPermission ; /* on autorise tout */ }; L’exécution : rmiregistry rmid -J-Dsun.rmi.activation.execPolicy=default -J-Djava.security.policy=helloword.policy java -Djava.security.policy=helloworld.policy Server java Client NOM INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP 55/73 (1/17) Corba, ORB, IIOP Common Object Request Broker Architecture : CORBA interface de l'objet Référence de l'objet Application cliente Code d'implantation référence + opération + arguments en entrée ORB Objet CORBA activation Implantation de l'objet exception ou résultat + arguments en sortie Application serveur ORB : bus Corba IIOP (Internet Inter-Orb Protocol) : protocole Corba sur TCP/IP INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP 56/73 (2/17) JRMP (RMI) et IIOP (Corba) Interface Implémentation IDL orbit-idl-2 idlj rmic -iiop Stub RMI Bus RMI JRMP Skeleton RMI Tie Corba Bus RMI ORB Stub Corba IIOP ORB INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (3/17) Objet distribué Hello.java package Hel loWorldIIOP ; import java . rmi . Remote ; import java . rmi . RemoteException ; p u b l i c i n t e r f a c e Hello e x t e n d s Remote { p u b l i c String sayHello ( String nom ) throws RemoteException ; } HelloImpl.java package Hel loWorldIIOP ; import javax . rmi . P o r t a b l e R e m o t e O b j e c t ; p u b l i c c l a s s HelloImpl e x t e n d s P o r t a b l e R e m o t e O b j e c t implements Hello { p u b l i c HelloImpl () throws java . rmi . RemoteException { s u p e r () ; // invoke rmi linking and remote object initialization } p u b l i c String sayHello ( String nom ) { System . out . println ( " Requete en provenance de " + nom ) ; r e t u r n " Bonjour " + nom + " ! " ; } } 57/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (4/17) Serveur RMI ServeurJRMP.java import import import import import java . rmi . registry . LocateRegistry ; java . rmi . registry . Registry ; java . rmi . server . U n i c a st R e m o t e O b j e c t ; java . util . Arrays ; Hell oWorldIIOP .*; p u b l i c c l a s s ServeurJRMP { p u b l i c s t a t i c v o i d main ( String args []) { i n t port = 1099; i f ( args . length ==1) port = Integer . parseInt ( args [0]) ; try { Hello skeleton = ( Hello ) U n ic a s t R e m o t e O b j e c t . exportObject (new HelloImpl () , 0) ; Registry registry = LocateRegistry . getRegistry ( port ) ; i f (! Arrays . asList ( registry . list () ) . contains ( " Hello - JRMP " ) ) registry . bind ( " Hello - JRMP " , skeleton ) ; else registry . rebind ( " Hello - JRMP " , skeleton ) ; System . out . println ( " Service Hello - JRMP lie au registre " ) ; } c a t c h ( Exception e ) { System . out . println ( e ) ; } } } 58/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (5/17) Client RMI ClientJRMP.java import java . rmi . registry . LocateRegistry ; import java . rmi . registry . Registry ; import Hell oWorldIIOP . Hello ; p u b l i c c l a s s ClientJRMP { p u b l i c s t a t i c v o i d main ( String args []) { String machine = " localhost " ; i n t port = 1099; i f ( args . length ==3) { machine = args [0]; port = Integer . parseInt ( args [1]) ; } e l s e i f ( args . length ==2) machine = args [0]; try { Registry registry = LocateRegistry . getRegistry ( machine , port ) ; Hello obj = ( Hello ) registry . lookup ( " Hello - JRMP " ) ; String message = obj . sayHello ( args [ args . length -1]) ; System . out . println ( message ) ; } c a t c h ( Exception e ) { System . out . println ( " Client exception : " + e ) ; } } } 59/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (6/17) Serveur Corba (Java) ServeurIIOP.java import import import import import javax . naming . InitialContext ; javax . naming . Context ; javax . rmi . P o r t a b l e R e m o t e O b j e c t ; Hell oWorldIIOP . Hello ; Hell oWorldIIOP . HelloImpl ; p u b l i c c l a s s ServeurIIOP { p u b l i c s t a t i c v o i d main ( String [] args ) { try { Hello stub = new HelloImpl () ; Context i n i t i a l N a m i n g C o n t e x t = new InitialContext () ; i n i t i a l N a m i n g C o n t e x t . rebind ( " HelloWorld - IIOP " , stub ) ; System . out . println ( " HelloWorld - IIOP enregistre . " ) ; } c a t c h ( Exception e ) { System . out . println ( " Probleme : " + e ) ; e . p rintStackTrace () ; } } } 60/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (7/17) Client Corba (Java) ClientIIOP.java import import import import import import import import import java . rmi . RemoteException ; java . net . M a l f o r m e d U R L E x c e p t i o n ; java . rmi . Not Bou ndE xce pt i on ; javax . rmi .*; java . util . Vector ; javax . naming . NamingException ; javax . naming . InitialContext ; javax . naming . Context ; Hell oWorldIIOP . Hello ; p u b l i c c l a s s ClientIIOP { p u b l i c s t a t i c v o i d main ( String args []) { Context context ; Object reference ; Hello stub ; try { context = new InitialContext () ; reference = context . lookup ( " HelloWorld - IIOP " ) ; stub = ( Hello ) P o r t a b l e R e m o t e O b j e c t . narrow ( reference , Hello . c l a s s ) ; System . out . println ( stub . sayHello ( args [ args . length -1]) ) ; } c a t c h ( Exception e ) { System . err . println ( " Exception " + e + " Caught " ) ; e . p rintStackTrace () ; return ; } } } 61/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (8/17) Contrat IDL IDL : Interface Definition Language Contrat IDL : description de la coopération entre les fournisseurs et les utilisateurs de services Masquage des problèmes liés à l’interopérabilité Séparation interface/implantation des objets Masquage de l’hétérogénéité des objets Masquage de la localisation des objets Utilisé pour générer les talons, les squelettes et pour définir les interfaces du référentiel d’interface Il supporte l’héritage et l’héritage multiple Indépendant de tout langage de programmation/compilateur ⇒ langage pivot entre applications Correspondance IDL/langage est fournie pour : C, C++, Java, Smalltalk, Ada, Cobol, etc. 62/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (9/17) Structure d’un fichier IDL 3 éléments principaux module : un espace de définitions interface : un regroupement de services (un objet Corba) méthode : un service Exemple module Hell oWorldIIOP { i n t e r f a c e Hello { string sayHello ( in string name ) ; }; }; 63/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP 64/73 (10/17) Règles de projection : types simples IDL short unsigned short long unsigned long long long unsigned long long float double long double boolean octet char wchar string wstring fixed C++ CORBA::Short CORBA::UShort CORBA::Long CORBA::ULong CORBA::LongLong CORBA::ULongLong CORBA::Float CORBA::Double CORBA::LongDouble CORBA::Boolean CORBA::Octet CORBA::Char CORBA::WChar char* et CORBA::String char* et CORBA::WString template CORBA::Fixed Java short short int int long long float double pas encore défini boolean byte char char String String java.math.BigDecimal INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP 65/73 (11/17) Distribution utilisée Distribution fournie avec Gnome : Orbit2 Avantages : Fournie de fait avec Gnome : OpenSource Très rapide Utilisable depuis beaucoup de langages (C, C++, perl, python, etc.) Possède un POA Outils Compilateur de fichiers IDL : orbit-idl-2 Aide à la compilation et à l’édition de liens : orbit2-config Serveur de nommage : orbit-name-server-2 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (12/17) orbit-idl-2 Usage : orbit - idl -2 [ OPTION ...] < IDL files > Help Options : -? , -- help -- help - all -- help - libIDL -- help - cpp Application Options : -v , -- version -l , -- lang = LANG -d , -- debug = LEVEL -- idlwarnlevel = LEVEL -- showcpperrors -- nostubs -- noskels -- nocommon -- noheaders -- noidata -i , -- imodule -- add - imodule -- skeleton - impl -- backenddir = DIR -- onlytop -- pidl -- nodefskels -- deps = FILENAME Makefile -- h e a d e r g u a rd pre fix = PREFIX avoid conflicts . -- output - dir = DIR exist . Show Show Show Show help options all help options libIDL options preprocessor options Output compiler version and serial Output language ( d e f a u l t is C ) Debug level (0 to 4) IDL warning level (0 to 4 , d e f a u l t is 2) Show CPP errors Don ’t output stubs Don ’t output skels Don ’t output common Don ’t output headers Don ’t generate Interface type data Output only an imodule file Output an imodule file Output skeleton implementation Override IDL backend library directory Inhibit includes Treat as Pseudo IDL Don ’t output defs f o r skels in header Generate dependency info suitable f o r inclusion in Prefix f o r # ifdef header guards . Sometimes useful to Where to put generated files . This directory must 66/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (13/17) orbit2-config Usage : orbit2 - config [ OPTION ][ OPTION ]... TARGET Known values f o r OPTION are : -- prefix = DIR change ORBit prefix [ d e f a u l t / usr ] -- exec - prefix = DIR change ORBit executable prefix [ d e f a u l t / usr ] -- libs print library linking information -- cflags print pre - processor and compiler flags -- help display t h i s help and exit -- version output version information -- use - service = SRVC the service SRVC will be used Known values f o r SRVC are : name module CosNaming , interfaces LNameComponent , LName Known values f o r TARGET are : client ( calls pkg - config ) server ( calls pkg - config ) Exemple orbit2 - config -- cflags server orbit2 - config -- libs -- use - service = name server 67/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (14/17) Génération des fichiers HelloWorld.idl module Hell oWorldIIOP { i n t e r f a c e Hello { string sayHello ( in string name ) ; }; }; Fichiers générés Automatiquement (orbit-idl-2 –noskels Hello.idl) : Hello.h Hello-common.c Hello-stubs.c 68/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (15/17) Client Corba (C) Client.c # include # include # include # include < stdio .h > " Hello . h " < ORBitservices / CosNaming .h > < ORBitservices / CosNaming_impl .h > i n t main ( i n t argc , c h a r * argv []) { C O R B A _ E n v i ron men t env ; H e l l o W o r l d I I O P _ H e l l o corbaHelloObject ; C o s N a m i n g _ N a m i n g C o n t e x t nam eSe rvi ceO bje ct ; CORBA_ORB orb = NULL ; CORBA_char * temp ; C o s N a m i n g _ N a m e C o m p o n e n t namePath [1] = { " HelloWorld - IIOP " , " " }; Cos Naming _Name name = {1 , 1 , namePath , CORBA_FALSE }; C O R B A _ e x c e p t i o n _ i n i t (& env ) ; orb = COR BA_ORB_init (& argc , argv , " orbit - local - orb " , & env ) ; na m e S e r v i c e Ob jec t = C O R B A _ O R B _ r e s o l v e _ i n i t i a l _ r e f e r e n c e s ( orb , " NameService " , & env ) ; c o r b a H e l l o Object = C o s N a m i n g _ N a m i n g C o n t e x t _ r e s o l v e ( nameServiceObject , & name , & env ) ; temp = H e l l o W o r l d I I O P _ H e l l o _ s a y H e l l o ( corbaHelloObject , argv [ argc -1] , & env ) ; printf ( " % s \ n " , temp ) ; CORBA_free ( temp ) ; C O R B A _ O b j e c t _ r e l e a s e ( corbaHelloObject , & env ) ; C OR B A _ O R B _ sh u td o wn ( orb , CORBA_FALSE , & env ) ; r e t u r n 0; } 69/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP (16/17) Compilation compile.sh javac He lloWorldIIOP /* . java rmic - iiop HelloWorldIIOP . HelloImpl cp He lloWor ldIIOP /*. class Serveurs - Java / HelloWorldIIOP / cp He lloWor ldIIOP / Hello . class Clients - Java / HelloWorldIIOP / cp He lloWor ldIIOP / _Hello_Stub . class Clients - Java / HelloWorldIIOP / cd Serveurs - Java javac *. java cd ../ Clients - Java javac *. java cd ../ Client - C orbit - idl -2 -- noskels Hello . idl gcc -c Hello - common . c ‘ orbit2 - config -- cflags client ‘ gcc -c Hello - stubs . c ‘ orbit2 - config -- cflags client ‘ gcc -c Client . c ‘ orbit2 - config -- cflags client ‘ gcc -o client Hello - common . o Hello - stubs . o Client . o ‘ orbit2 - config -- use - service = name -- libs client ‘ cd .. 70/73 INSA - ASI InfoRep : RMI Interopérabilité : RMI sur IIOP 71/73 (17/17) Lancement Lancement sur JRMP (RMI) Service de nommage : rmiregistry Serveur : java ServeurJRMP Client : java ClientJRMP PARAM Lancement sur IIOP (Corba) Service de nommage : orbit-name-server-2 –ORBIIOPIPSock=1050 –ORBIIOPIPName=localhost –ORBIIOPIPv4=1 –ORBCorbaloc=1 –key=NameService Serveur (java) : java ServeurJRMP Client Java : java -classpath . -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=corbaloc:iiop:1.2@localhost:1050/NameServic ClientIIOP PARAM Client C : client -ORBInitRef NameService=corbaloc:iiop:1.2@localhost:1050/NameService PARAM INSA - ASI InfoRep : RMI 72/73 Conclusion Synthèse RMI est un puissant mécanisme de distribution d’objets Quelques points qui n’ont pas été vus dans ce cours : “Customisation” des sockets (par exemple pour crypter/compresser la communication) HTTP tunneling pour faire des invocations de méthodes rmi à travers un firewall http://www.geocities.com/dmh2000/ApacheTomcatRMI.htm Les classes d’amorçage INSA - ASI InfoRep : RMI 73/73 Références Programmation J2EE, Conteneurs J2EE, servlets, JSP et EJB : S. Allamaraju, K. Avedal, R.Browett, J. Diamond, J. Griffin, M. Holden, A. Hoskinson, R. Johson, T. Karsjens, L. Kim, A. Longshaw, T. Myers, A. Nakimovsky, D. O’Connor, S. Tyagi, G. Van Damme, G. Van Huizen, M. Wilcox, S. Zeiger Eyrolles - ISBN : 2-212-09260-1 Java RMI : W. Grosso O’Reilly - ISBN : 1-56592-452-5 Fundamentals of RMI JGuru http://developer.java.sun.com/developer/onlineTraining/rmi/