La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

RMI Remote Method Invocation Didier DONSEZ Université Joseph Fourier (Grenoble 1) IMA – LSR/ADELE Hafid Bourzoufi.

Présentations similaires


Présentation au sujet: "RMI Remote Method Invocation Didier DONSEZ Université Joseph Fourier (Grenoble 1) IMA – LSR/ADELE Hafid Bourzoufi."— Transcription de la présentation:

1 RMI Remote Method Invocation Didier DONSEZ Université Joseph Fourier (Grenoble 1) IMA – LSR/ADELE Hafid Bourzoufi Université de Valenciennes - ISTV

2 RMI - H. Bourzoufi, D. Donsez, Sommaire nRappel et Limites des RPC (Remote Procedure Call) nPrincipe des RMI nEtapes de développement et d exécution nParamètres des méthodes nObjet Activable nPersonnalisation de la couche de transport nRamasse-Miette distribuée nAutour des RMI CORBA, IIOP, EJB

3 RMI - H. Bourzoufi, D. Donsez, Rappel des RPC nRPC (Remote Procedure Call) modèle client/serveur appel de procédures à distances entre un client et un serveur le client appelle une procédure le serveur exécute la procédure et renvoie le résultat Outil rpcgen génère la souche d invocation et le squelette du serveur (en C, C++, Fortran, …) la souche et le squelette ouvre un socket et encode/décode les paramètres Couche de présentation XDR (eXchange Data Representation) format pivot de représentation des données de types primitifs et structurés (tableau de longueur variable, structures) quelque soit l architecture (Little Endian/Big Endian, IEEE, …) le langage (ordre ligne/colonne dans les tableaux C et les tableaux Fortran) ou le système (ASCII, IBM ECDCII,...)

4 RMI - H. Bourzoufi, D. Donsez, Limites des RPC nLimitations paramêtres et valeur de retour sont des types primitifs programmation procédurale dépendance à la localisation du serveur pas d objet pas de « référence distante » nEvolutions CORBA Multilangage, multi-plateforme (architecture+OS), MuliVendeurs Java RMI mono-langage : Java, multiplateforme : de JVM à JVM DCOM / Object RPC /.NET Remoting multi-langages, plateforme Win32 principalement, il existe des implémentations (non MicroSoft) pour Unix, Propriétaire.NET Remoting multi-langages (CLR), plateforme Win32 principalement Normalisé à lECMA et à lISO SOAP (Simple Access Object Protocol) multi-langages, multi-plateforme Réponse et requête en XML (DTD SOAP), Transport sur HTTP, IETF

5 RMI - H. Bourzoufi, D. Donsez, Principes des RMI nRPC à la Java invoquer de façon simple des méthodes sur des objets distribués. nOutils pour la génération des stub/skeleton, l enregistrement par le nom, l activation Tous les détails ( connexion, transfert de données..) sont transparents pour le développeur grâce au stub/skeleton généré nMono-langage et Multiplateforme. Java : de JVM à JVM (les données et objets ont la même représentation qqs la JVM) nOrienté Objet Les RMIs utilisent le mécanisme standard de sérialisation de JAVA pour l envoi d objets. nDynamique Les classes des Stubs et des paramêtres peuvent être chargées dynamiquement via HTTP (http://) ou NFS (file:/) nSécurité un SecurityManager vérifie si certaines opérations sont autorisés par le serveur

6 RMI - H. Bourzoufi, D. Donsez, Structure des couches RMI (i) l architecture logique Client RMI (Application / Applet / Servlet) HelloClient,HelloApplet Souche ou Stub HelloImpl_Stub Couche de Référence java.rmi.Naming Couche de Transport java.net.Socket pour TCP Réseau (IP) Serveur RMI HelloServer, rmid Squelette ou Skeleton HelloImpl_Skel Couche de Référence java.rmi.Naming Couche de Transport java.net.SocketServer pour TCP Invocation de méthodes sayHello(...) Interface Distante Hello Implémentation Distante HelloImpl

7 RMI - H. Bourzoufi, D. Donsez, Structure des couches RMI (ii) nSouche ou Stub (sur le client) représentant local de lobjet distant qui implémente les méthodes exportées de l objet distant marshalise les arguments de la méthode distante et les envoie en un flot de données au serveur démarshalise la valeur ou l objet retournés par la méthode distante la classe xx_Stub peut être chargée dynamiquement par le client (Applet) nSquelette ou Skeleton (sur le serveur) démarshalise les paramètres des méthodes fait un appel à la méthode de lobjet local au serveur marshalise la valeur ou l objet renvoyé par la méthode

8 RMI - H. Bourzoufi, D. Donsez, Structure des couches RMI (ii) nCouche des références distantes traduit la référence locale au stub en une référence à lobjet distant elle est servie par un processus tier : rmiregistry nCouche de transport écoute les appels entrants établit et gère les connexions avec les sites distants java.rmi.UnicastRemoteObject utilise les classes Socket et SocketServer (TCP) cependant d autres classes peuvent être utilisées par la couche transport (Compression sur TCP, SSL sur TCP, UDP)

9 RMI - H. Bourzoufi, D. Donsez, hostreg La configuration rmiregistry hostcli Client HelloClient hostwww httpd hostser Serveur HelloServer Instance :.class : StubSkelImpl... http ou nfs Socket

10 RMI - H. Bourzoufi, D. Donsez, hostreg L enregistrement de l objet rmiregistry hostcli Client HelloClient hostwww httpd hostser Serveur HelloServer Instance :.class : StubSkelImpl "HelloObject" le serveur enregistre lobjet distant : il communique une instance de Stub 1- le serveur charge les classes Stub et Skel d après java.rmi.server.codebase http ou nfs Socket

11 RMI - H. Bourzoufi, D. Donsez, hostreg La récupération du Stub rmiregistry hostcli Client HelloClient hostwww httpd hostser Serveur HelloServer Instance :.class : StubSkelImpl "HelloObject" le client réclame le Stub associé à "HelloObject" 4- rmiregistry retourne le Stub 5- le client charge la classe Stub d après java.rmi.server.codebase http ou nfs Socket

12 RMI - H. Bourzoufi, D. Donsez, hostreg Invocation d une méthode rmiregistry hostcli Client HelloClient hostwww httpd hostser Serveur HelloServer Instance :.class : StubSkelImpl "HelloObject" le client invoque une méthode sur le Stub 7- le Stub « mashalle » les paramêtres de la méthode et les envoie au serveur 8- le Skel « demashalle » les paramètres de la méthode et invoque la méthode sur l objet retourne le résultat marshallé 9- le Stub « demashalle » le résultat de la méthode appel méthode Socket

13 RMI - H. Bourzoufi, D. Donsez, Création et manipulation d'objets distants n5 Packages java.rmi : pour accéder à des objets distants java.rmi.server : pour créer des objets distants java.rmi.registry : lié à la localisation et au nommage dobjets distants java.rmi.dgc : ramasse-miettes pour les objets distants java.rmi.activation : support pour l activation d objets distants. nEtapes du développement 1- Spécifier et écrire l'interface de l'objet distant. 2- Ecrire l'implémentation de cette interface. 3- Générer les Stub/Skeleton correspondants. (outil rmic) nEtapes de l exécution 4- Ecrire le serveur qui instancie l'objet implémentant l'interface, exporte son Stub puis attend les requêtes via le Skeleton. 5- Ecrire le client qui réclame l objet distant, importe le Stub et invoque une méthode de l'objet distant via le Stub.

14 RMI - H. Bourzoufi, D. Donsez, Spécifier l interface d'un objet distant nFormat l interface étend java.rmi.Remote les méthodes doivent pouvoir lever java.rmi.RemoteException nExemple package examples.hello; public interface Hello extends java.rmi.Remote{ public static final int EN=0;// English public static final int FR=1;// French public static final int ES=2;// Spanish String sayHello() throws java.rmi.RemoteException; String sayHello(String name) throws java.rmi.RemoteException; String sayHello(String name, int lang) throws java.rmi.RemoteException; }

15 RMI - H. Bourzoufi, D. Donsez, Implémentation de l objet distant La classe HelloImpl doit implémenter l interface distante Hello et étendre une des sous-classes de java.rmi.server.RemoteServer comme java.rmi.server.UnicastRemoteObject java.rmi.server.UnicastRemoteObject sous classe le plus souvent utilisée offre toutes les fonctionnalités des classes distantes appelle la classe squelette pour la (dé)marshalisation utilise TCP/IP pour la couche transport

16 RMI - H. Bourzoufi, D. Donsez, Implémentation de l objet distant package examples.hello; public class HelloImpl extends java.rmi.server.UnicastRemoteObject implements Hello { private int defaultlang; public HelloImpl(int defaultlang) throws java.rmi.RemoteException{ super(); this.defaultlang=defaultlang; } public String sayHello() { return sayHello(null, defaultlang); } public String sayHello(String name) { return sayHello(name, defaultlang); } public String sayHello(String name, int lang) { switch(lang) { case Hello.EN : break; case Hello.FR : break; case Hello.ES : break; default : lang=Hello.EN; } switch(lang) { case Hello.EN : return "Hello " +((name==null) ? "World" : name) + " !"; case Hello.FR : return "Bonjour " +((name==null) ? "tout le monde" : name) + " !"; case Hello.ES : return "Hola " +((name==null) ? "todo el mundo" : name) + " !"; default : return null; } } // method String sayHello(String name, int lang) } // class HelloImpl

17 RMI - H. Bourzoufi, D. Donsez, La génération des Stub et Skeleton L outil rmic génère la classe souche examples.hello.HelloImpl_Stub la classe squelette examples.hello.HelloImpl_Skel à partir de l implémentation examples.hello.HelloImpl nExemple (sous Win32) set CLASSPATH=%CLASSPATH%;./myclasses javac -d.\myclasses Hello.java javac -d.\myclasses HelloImpl.java rmic -keepgenerated -d./myclasses examples.hello.HelloImpl Remarque : -keepgenerated à conserve les sources des Stub et Skeleton

18 RMI - H. Bourzoufi, D. Donsez, Implémentation du serveur de l objet distant Crée un ou plusieurs objets distants (une ou plusieurs classes) Naming.bind() : les enregistre auprès du serveur de liaison rmiregistry nExemple package examples.hello; public class HelloServer { public static void main(String args[]) { // argument : l hôte/port du rmiregistry // Crée et Installe un Security Manager if (System.getSecurityManager() == null) { System.setSecurityManager(new java.rmi.RMISecurityManager()); } try { // instancie l objet HelloImpl obj = new HelloImpl(Hello.EN); // Enregistre l objet sous le nom "HelloObject" auprès de rmiregistry java.rmi.Naming.bind("//"+args[0]+"/HelloObject", obj); } catch (Exception e) { e.printStackTrace(); } } javac -d.\myclasses HelloServer.java

19 RMI - H. Bourzoufi, D. Donsez, Implémentation du serveur de l objet distant nRemarques L objet distant servi peut être d une sous classe de HelloImpl public class HelloESImpl extends HelloImpl { public HelloESImpl() throws java.rmi.RemoteException{ super(HelloES); } } // et dans HelloServer java.rmi.Naming.rebind("//"+args[0]+"/HelloObject", new HelloESImpl()); Le serveur peut crée et enregistré plusieurs objets appartenant à une ou plusieurs classes l enregistrement peut se faire auprès des plusieurs rmiregistry

20 RMI - H. Bourzoufi, D. Donsez, Implémentation du serveur de l objet distant nRemarques il faut prévoir une procédure d arrêt ( shutdown ) du serveur Demande d arrêt Unix : kill SIGQUIT Win32 : ?? Arrêt des objets UnicastRemoteObject public static void Naming.unbind(String name) public static boolean UnicastRemoteObject.unexportObject(Remote, boolean force) Dans les exemples et tutoriels, le serveur est constitué par la méthode main(String args[]) de l implémentation HelloImpl

21 RMI - H. Bourzoufi, D. Donsez, Implémentation d un client invoquant l objet distant Demande un stub auprès du serveur de liaison rmiregistry invoque des méthodes sur le stub chargé nExemple (Application) package examples.client; public class HelloClient { public static void main(String args[]) { String message = "blank"; try { // récupère le stub de l objet enregistré au nom de « HelloObject » Hello obj = (Hello) java.rmi.Naming.lookup("//" + args[0] + "/HelloObject"); // invocation des 3 méthodes message = obj.sayHello(); System.out.println(message); message = obj.sayHello(args[1]); System.err.println(message); System.err.println( obj.sayHello(args[1], Integer.parseInt(args[2]))); } catch (Exception e) { e.printStackTrace(); } } } javac -d.\myclasses HelloClient.java

22 RMI - H. Bourzoufi, D. Donsez, Implémentation d un client invoquant l objet distant nExemple (Applet) import java.rmi.Naming; public class HelloApplet extends java.applet.Applet{ String message = "blank"; public void init() { try { // récupère le stub de l objet enregistré au nom de « HelloObject » // Remarque : rmiregistry et le serveur Web doit être sur la même machine (même #IP) Hello obj = (Hello)Naming.lookup("//" + getCodeBase().getHost() + "/HelloObject"); // invocation d une des 3 méthodes message = obj.sayHello(); } catch (Exception e) { // sortie d erreur sur la console System.out.println(" HelloApplet exception: " + e.getMessage()); e.printStackTrace(); } public void paint(java.awt.Graphics g) { g.drawString(message, 25, 50); } } javac -d.\myclasses HelloApplet.java

23 RMI - H. Bourzoufi, D. Donsez, L exécution Coté Serveur Le serveur de liaison rmiregistry expose un objet distant serveur de liaisons (de noms) le port de liaison par défaut est le port TCP 1099 hostreg> rmiregistry ^C hostreg> rmiregistry 2001 ^C hostreg> rmiregistry 1099 cet objet fait la correspondance entre nom et instance de Stub enregistré par le(s) serveur(s) avec Naming.bind()

24 RMI - H. Bourzoufi, D. Donsez, L exécution Coté Serveur L accès au serveur de liaison nLa classe Naming encaspule le dialogue avec plusieurs objets serveur de liaison URL de liaison rmi://hostreg:2001/Hello/World rmi://:2001/Hello/World //:2001/Hello/World /Hello/World Méthodes Statiques bind(String url, Remote r), rebind(String url, Remote r), unbind(String url) enregistre/désenregistre un objet auprès du serveur Remote lookup(String url) retourne un stub String[] list() liste les noms enregistrés

25 RMI - H. Bourzoufi, D. Donsez, L exécution Coté Serveur L implantation du serveur de liaison nLes objets serveur de liaison réalise la correspondance nom avec stub Interface d un objet serveur de liaison sun.rmi.registry.Registry (extends java.rmi.Remote) Implémentation par défaut de l objet serveur de liaison sun.rmi.registry.RegistryImpl Méthodes non statiques bind(),rebind(),unbind(),lookup(),list() nLa classe LocateRegistry localise ou active un objet serveur de liaison Méthodes Statiques Registry createRegistry(int port) crée un objet serveur de liaison sur le port spécifié Registry getRegistry(int port) récupère l objet serveur de liaison qui a été crée

26 RMI - H. Bourzoufi, D. Donsez, L exécution Coté Serveur nLe serveur d objets distants le Stub doit être dans le CLASSPATH ou chargeable via FS ou HTTP hello.policy autorise l usage du accept et du connect sur les Sockets hostser> java -Djava.security.policy=./hello.policy -Djava.rmi.server.codebase=http://hostwww/hello/myclasses/ examples.hello.HelloServer hostreg:1099 Mais aussi -Djava.rmi.server.codebase=file://dev/hello/myclasses/Unix -Djava.rmi.server.codebase=file:/c:\dev\hello\myclasses/Win32./hello.policy grant { permission java.net.SocketPermission "*: ","connect,accept"; permission java.net.SocketPermission "*:80", "connect"; // permission java.security.AllPermission; /* ou autorise tout */ };

27 RMI - H. Bourzoufi, D. Donsez, L exécution Coté Client nL application le Stub doit être dans le CLASSPATH ou chargeable via FS ou HTTP hello.policy autorise l usage du connect sur les Sockets hostcli> java -Djava.security.policy=./client.policy -Djava.rmi.server.codebase=http://hostwww/hello/myclasses/ examples.client.HelloClient hostreg:1099./client.policy grant { permission java.net.SocketPermission "*: ","connect"; permission java.net.SocketPermission "*:80", "connect"; };

28 RMI - H. Bourzoufi, D. Donsez, L exécution Coté Client nL applet l élément HTML applet doit spécifier le codebase Hello World Hello World The message from the HelloServer is: seuls les sockets vers hostwww sont autorisés par la sandbox donc hostreg = hostser = hostwww hostcli> appletviewer

29 RMI - H. Bourzoufi, D. Donsez, Principales Exceptions nClient java.net.MalformedURLException java.rmi.RemoteException java.rmi.NotBoundException java.rmi.StubNotFoundException nServeur java.net.MalformedURLException java.rmi.RemoteException java.rmi.NotBoundException java.rmi.StubNotFoundException Under Construction En Construction

30 RMI - H. Bourzoufi, D. Donsez, Le passage de paramètres nLes paramêtres des méthodes invoquées sur un objet distant sont soit: une valeur de type Primitif La valeur est passée un objet d une classe qui implemente l interface Serialisable (ou l interface Externalizable ) l objet est sérialisé et envoyé à l objet distant : le paramétre est alors déserialisé pour l objet d istant l utilse un objet d une classe qui implémente l interface Remote c est l objet Stub qui est sérialisé et envoyé à l objet distant : quand l objet distant invoque un méthode sur le paramêtre, l invocation est distante. nUne exception est levée si un paramêtre ne rentre pas dans ces trois cas.

31 RMI - H. Bourzoufi, D. Donsez, Le passage de paramètres nUn exemple plus complexe package examples.order; public class OrderLine implements java.io.Serializable { // une classe sérialisable public String productname; public int quantity; } package examples.order; import java.util.Vector; // une classe sérialisable public interface Order extends java.rmi.Remote { // l interface distante public float price(String productname, int quantity) throws java.rmi.RemoteException; public float price(Vector orderlines) throws java.rmi.RemoteException; public float price(OrderLine[] orderlines) throws java.rmi.RemoteException; public Vector priceInDetail(Vector orderlines) throws java.rmi.RemoteException; public Vector priceInDetail(OrderLine[] orderlines) throws java.rmi.RemoteException; }

32 RMI - H. Bourzoufi, D. Donsez, Le passage de paramètres nUn exemple plus complexe package examples.order; public class OrderException extends Exception { // exception applicative ou java.rmi.RemoteException private String unknownproductname; public OrderException(String productname) { this.unknownproductname=productname; } public String toString() { return "Unknown Product Name : " + unknownproductname; } package examples.order; public interface Order extends java.rmi.Remote { // l interface distante public float price(String productname, int quantity) throws java.rmi.RemoteException, OrderException;... }

33 RMI - H. Bourzoufi, D. Donsez, Passage d un paramètre de classe inconnue du serveur La sous classe dun paramètre est inconnue du serveur le serveur charge la classe du sous-type inconnu à partir du java.rmi.server.codebase du client à défaut du CLASSPATH nVoir : jdk1.2.2/docs/guide/rmi/codebase.htm

34 RMI - H. Bourzoufi, D. Donsez, Passage d un paramètre de classe inconnue du serveur (i) hostcli Client HelloClient hostwww2 httpd hostser Serveur HelloServer Param.class : Impl 6- le client invoque une méthode avec un paramêtre inconnu du serveur 7- le Stub sérialise linstance du paramêtre et lenvoie au serveur 8- le serveur charge la classe d après java.rmi.server.codebase du client appel méthode Socket Instance :

35 RMI - H. Bourzoufi, D. Donsez, Passage d un paramètre de classe inconnue du serveur (ii) hostcli Client HelloClient hostwww2 httpd hostser Serveur HelloServer Param.class : Impl 9 - l objet est déserialisé 10- la méthode est invoquée 12- le Stub « démashalle » le résultat de la méthode appel méthode Socket Instance : 11- le Skel retourne le résultat marshallé

36 RMI - H. Bourzoufi, D. Donsez, Passage d un paramêtre de classe inconnue du serveur - Exemple package examples.bank; // l interface du 1er paramêtre de la méthode credit() public interface Account extends Serializable { float getBalance(); void setBalance(float amount); } // l interface de l objet distant public interface Bank implements Remote { void credit(Account acc, float amount); } // une sous-classe de Account inconnue du serveur public class CheckingAccount implements examples.bank.Account { private String name; private float balance; public CheckingAccount(String name, float initamount) { this.name=name; this.balance= initamount; } public float getBalance(return balance;) public void setBalance(float amount) { balance=amount; } } // un client examples.bank.Bank mybank = (Bank) java.rmi.Naming.lookup("//hostreg/MyBank"); examples.bank.Account accjohn = new CheckingAccount("john",1000.0); mybank.credit(accjohn,2000.0);

37 RMI - H. Bourzoufi, D. Donsez, Le passage de paramètres nLe passage en paramêtre d un Stub (cas 3) l objet Stub est du type de la déclaration l objet Stub est d un sous type inconnu le java.rmi.server.codebase du client est utilisé par le serveur à défaut du CLASSPATH pour charger la classe du sous-type nVoir : jdk1.2.2/docs/guide/rmi/codebase.htm

38 RMI - H. Bourzoufi, D. Donsez, Le passage de paramètres Exemple nLe passage en paramêtre d un Stub (cas 3) interface Account implements Remote { float getBalance(); void setBalance(float amount); } interface Bank implements Remote { void credit(Account acc, float amount); } Bank ban1 = (Bank) java.rmi.Naming.lookup("//regb/CA"); Account acc1 = (Account) java.rmi.Naming.lookup("//reg1/Account1"); ban1.debit(acc1,2000.0); Account acc2=new CheckingAccount("john",1000.0) java.rmi.Naming.rebind("//reg2/Account2",acc2); ban1.credit(acc2,2000.0);

39 RMI - H. Bourzoufi, D. Donsez, Passage d un Stub en paramêtre nMéthode 1 Le Stub est celui d un objet distant déjà servi nMéthode 2 : Objet Distant Temporaire But: L objet distant est local au client et n est utilisé que pour la durée d une ou plusieurs invocations distantes depuis le client Solution exporter l objet avec la méthode UnicastRemoteObject.exportObjet() l objet doit implémenter l interface Unreferenced pour être ramassé par le GC

40 RMI - H. Bourzoufi, D. Donsez, Objet Distant Temporaire Le client public class AsyncHelloClient { public static void main( String[] args) { Hello hello = (Hello) Naming. lookup("//hostreg/HelloObject"); Person person = new PersonImpl("Didier","Donsez"); UnicastRemoteObject.exportObject(person); String hellomessage = hello.sayHello(person, Hello.EN); person = null; // force le GC local et le GC reparti System.println.out(hellomessage);... }

41 RMI - H. Bourzoufi, D. Donsez, Objet Distant Temporaire Le serveur temporaire public interface Person extends Remote { String getFirstname() throws RemoteException; String getLastname() throws RemoteException; } public class PersonImpl implements Person, Unreferenced { private String lastname; private String firstname; PersonImpl(String lastname, String firstname) { this.lastname=lastname,this.firstname=firstname; } String getFirstname() throws RemoteException { return firstname; } String getLastname() throws RemoteException { return lastname; } void unreferenced() { ThreadGroup tg = Thread.currentThread().getThreadGroup(); tg. stop() }

42 RMI - H. Bourzoufi, D. Donsez, Objet Distant Temporaire L objet distant et son serveur public interface Hello extends Remote { String sayHello(Person person, int lang) throws RemoteException; String sayHello(String name, int lang) throws RemoteException; } public class HelloImpl extends java.rmi.server.UnicastRemoteObject implements Hello { String sayHello(Person person, int lang) throws RemoteException { String firstname= person.getFirstname();// invocation distante sur le Stub String lastname= person.getLastname();// invocation distante sur le Stub return sayHello(firstname + " " + lastname, lang); } … } public class HelloServer { public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new java.rmi.RMISecurityManager()); } try { HelloImpl obj = new HelloImpl(Hello.EN); java.rmi.Naming.rebind("//hostreg/HelloObject", obj); } catch (Exception e) { e.printStackTrace(); } } }

43 RMI - H. Bourzoufi, D. Donsez, Objet Distant Temporaire Déroulement de l exécution hostser JVM HelloServer hostcli JVM AsyncHelloClient main threadhello unicastobject thread attente d une invocation de méthode person thread(s) création de person export de person invocation de hello.sayHello(person,Hello.EN) exécution de hello.sayHello(person,Hello.EN) attente du résultat attente d une méthode exécution de person.getFirstname() invocation de person.getFirstname() exécution de person.getLastname() invocation de person.getLastname() réception et exécution de unreferenced() DGC réception du résultat attente d une invocation de méthode

44 RMI - H. Bourzoufi, D. Donsez, Le détail du Stub généré // Stub class generated by rmic, do not edit. // Contents subject to change without notice. package examples.hello; public final class HelloImpl_Stub extends java.rmi.server.RemoteStub implements examples.hello.Hello, java.rmi.Remote { private static final java.rmi.server.Operation[] operations = { new java.rmi.server.Operation("java.lang.String sayHello()"), new java.rmi.server.Operation("java.lang.String sayHello(java.lang.String)"), new java.rmi.server.Operation("java.lang.String sayHello(java.lang.String, int)") }; private static final long interfaceHash = L; private static final long serialVersionUID = 2; private static boolean useNewInvoke; private static java.lang.reflect.Method $method_sayHello_0; private static java.lang.reflect.Method $method_sayHello_1; private static java.lang.reflect.Method $method_sayHello_2; static { try { java.rmi.server.RemoteRef.class.getMethod("invoke", new java.lang.Class[] { java.rmi.Remote.class, java.lang.reflect.Method.class, java.lang.Object[].class, long.class }); useNewInvoke = true; $method_sayHello_0 = examples.hello.Hello.class.getMethod("sayHello", new java.lang.Class[] {}); $method_sayHello_1 = examples.hello.Hello.class.getMethod("sayHello", new java.lang.Class[] {java.lang.String.class}); $method_sayHello_2 = examples.hello.Hello.class.getMethod("sayHello", new java.lang.Class[] {java.lang.String.class, int.class}); } catch (java.lang.NoSuchMethodException e) { useNewInvoke = false; } // constructors public HelloImpl_Stub() { super(); } public HelloImpl_Stub(java.rmi.server.RemoteRef ref) { super(ref); } // methods from remote interfaces // implementation of sayHello() public java.lang.String sayHello() throws java.rmi.RemoteException { try { if (useNewInvoke) { Object $result = ref.invoke(this, $method_sayHello_0, null, L); return ((java.lang.String) $result); } else { java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash); ref.invoke(call); java.lang.String $result; try { java.io.ObjectInput in = call.getInputStream(); $result = (java.lang.String) in.readObject(); } catch (java.io.IOException e) { throw new java.rmi.UnmarshalException("error unmarshalling return", e); } catch (java.lang.ClassNotFoundException e) { throw new java.rmi.UnmarshalException("error unmarshalling return", e); } finally { ref.done(call); } return $result; } } catch (java.lang.RuntimeException e) { throw e; } catch (java.rmi.RemoteException e) { throw e; } catch (java.lang.Exception e) { throw new java.rmi.UnexpectedException("undeclared checked exception", e); } // implementation of sayHello(String) public java.lang.String sayHello(java.lang.String $param_String_1) throws java.rmi.RemoteException { try { if (useNewInvoke) { Object $result = ref.invoke(this, $method_sayHello_1, new java.lang.Object[] {$param_String_1}, L); return ((java.lang.String) $result); } else { java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash); try { java.io.ObjectOutput out = call.getOutputStream(); out.writeObject($param_String_1); } catch (java.io.IOException e) { throw new java.rmi.MarshalException("error marshalling arguments", e); } ref.invoke(call); java.lang.String $result; try { java.io.ObjectInput in = call.getInputStream(); $result = (java.lang.String) in.readObject(); } catch (java.io.IOException e) { throw new java.rmi.UnmarshalException("error unmarshalling return", e); } catch (java.lang.ClassNotFoundException e) { throw new java.rmi.UnmarshalException("error unmarshalling return", e); } finally { ref.done(call); } return $result; } } catch (java.lang.RuntimeException e) { throw e; } catch (java.rmi.RemoteException e) { throw e; } catch (java.lang.Exception e) { throw new java.rmi.UnexpectedException("undeclared checked exception", e); } // implementation of sayHello(String, int) public java.lang.String sayHello(java.lang.String $param_String_1, int $param_int_2) throws java.rmi.RemoteException { try { if (useNewInvoke) { Object $result = ref.invoke(this, $method_sayHello_2, new java.lang.Object[] {$param_String_1, new java.lang.Integer($param_int_2)}, L); return ((java.lang.String) $result); } else { java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 2, interfaceHash); try { java.io.ObjectOutput out = call.getOutputStream(); out.writeObject($param_String_1); out.writeInt($param_int_2); } catch (java.io.IOException e) { throw new java.rmi.MarshalException("error marshalling arguments", e); } ref.invoke(call); java.lang.String $result; try { java.io.ObjectInput in = call.getInputStream(); $result = (java.lang.String) in.readObject(); } catch (java.io.IOException e) { throw new java.rmi.UnmarshalException("error unmarshalling return", e); } catch (java.lang.ClassNotFoundException e) { throw new java.rmi.UnmarshalException("error unmarshalling return", e); } finally { ref.done(call); } return $result; } } catch (java.lang.RuntimeException e) { throw e; } catch (java.rmi.RemoteException e) { throw e; } catch (java.lang.Exception e) { throw new java.rmi.UnexpectedException("undeclared checked exception", e); } Under Construction En Construction

45 RMI - H. Bourzoufi, D. Donsez, Le détail du Skeleton généré // Skeleton class generated by rmic, do not edit. // Contents subject to change without notice. package examples.hello; public final class HelloImpl_Skel implements java.rmi.server.Skeleton { private static final java.rmi.server.Operation[] operations = { new java.rmi.server.Operation("java.lang.String sayHello()"), new java.rmi.server.Operation("java.lang.String sayHello(java.lang.String)"), new java.rmi.server.Operation("java.lang.String sayHello(java.lang.String, int)") }; private static final long interfaceHash = L; public java.rmi.server.Operation[] getOperations() { return (java.rmi.server.Operation[]) operations.clone(); } public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash) throws java.lang.Exception { if (opnum < 0) { if (hash == L) { opnum = 0; } else if (hash == L) { opnum = 1; } else if (hash == L) { opnum = 2; } else { throw new java.rmi.UnmarshalException("invalid method hash"); } } else { if (hash != interfaceHash) throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch"); } examples.hello.HelloImpl server = (examples.hello.HelloImpl) obj; switch (opnum) { case 0: // sayHello() { call.releaseInputStream(); java.lang.String $result = server.sayHello(); try { java.io.ObjectOutput out = call.getResultStream(true); out.writeObject($result); } catch (java.io.IOException e) { throw new java.rmi.MarshalException("error marshalling return", e); } break; } case 1: // sayHello(String) { java.lang.String $param_String_1; try { java.io.ObjectInput in = call.getInputStream(); $param_String_1 = (java.lang.String) in.readObject(); } catch (java.io.IOException e) { throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); } catch (java.lang.ClassNotFoundException e) { throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); } finally { call.releaseInputStream(); } java.lang.String $result = server.sayHello($param_String_1); try { java.io.ObjectOutput out = call.getResultStream(true); out.writeObject($result); } catch (java.io.IOException e) { throw new java.rmi.MarshalException("error marshalling return", e); } break; } case 2: // sayHello(String, int) { java.lang.String $param_String_1; int $param_int_2; try { java.io.ObjectInput in = call.getInputStream(); $param_String_1 = (java.lang.String) in.readObject(); $param_int_2 = in.readInt(); } catch (java.io.IOException e) { throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); } catch (java.lang.ClassNotFoundException e) { throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); } finally { call.releaseInputStream(); } java.lang.String $result = server.sayHello($param_String_1, $param_int_2); try { java.io.ObjectOutput out = call.getResultStream(true); out.writeObject($result); } catch (java.io.IOException e) { throw new java.rmi.MarshalException("error marshalling return", e); } break; } default: throw new java.rmi.UnmarshalException("invalid method number"); } Under Construction En Construction

46 RMI - H. Bourzoufi, D. Donsez, L activation d objets distants nRappel (JDK1.1) l objet distant est actif au démarrage du serveur RMI nMotivation principe du démon inetd d Unix Le démon rmid démarre une JVM qui sert l objet distant seulement au moment de l invocation d une méthode (à la demande) ou au reboot. nJDK1.2 introduit un nouveau package java.rmi.activation un objet activable doit dériver de la classe Activatable un démon RMI rmid qui active les objets à la demande ou au reboot de la machine nInfo : jdk1.2.2\docs\guide\rmi\activation.html nRemarque : lactivition est très utilisée par JINI !

47 RMI - H. Bourzoufi, D. Donsez, Créer une implémentation activable La classe doit étendre java.rmi.activation.Activable et implémenter l interface distante La classe doit déclarer un constructeur avec 2 arguments java.rmi.activation.ActivationID, java.rmi.MarshalledObject public class HelloActivatableImpl extends java.rmi.activation.Activatable implements Hello { private int defaultlang; public ActivatableImplementation(ActivationID id, MarshalledObject data) throws java.rmi.RemoteException { super(id, 0); this.defaultlang=((Integer)data.get()).intValue(); } // implémentation des méthodes public String sayHello() throws java.rmi.RemoteException { … }... }

48 RMI - H. Bourzoufi, D. Donsez, Créer le programme d enregistrement (Setup) nRôle passer l information nécessaire à l activation de l objet activable au démon rmid puis enregistrer l objet auprès de rmiregistry nDescripteur ActivationDesc : description des informations nécessaires à rmid nGroupes dobjets activables rmid active une JVM par groupe Les objets du même groupe partagent la même JVM ActivationGroup : représente un groupe d objets activables ActivationGroupDesc : description d un groupe ActivationGroupID : identifiant d un groupe

49 RMI - H. Bourzoufi, D. Donsez, Créer le programme d enregistrement Exemple (partie 1) import java.rmi.*; import java.rmi.activation.*; import java.util.Properties; public class SetupActivHello { public static void main(String[] args) throws Exception { System.setSecurityManager(new RMISecurityManager()); // création d un groupe d objets activables Properties props = new Properties(); props.put("java.security.policy", "./helloactiv.policy"); ActivationGroupDesc.CommandEnvironment ace = null; // descripteur du groupe ActivationGroupDesc agroupdesc = new ActivationGroupDesc(props, ace); // ActivationSystem asystem = ActivationGroup.getSystem(); ActivationGroupID agi = asystem.registerGroup(agroupdesc); // enregistrement du groupe ActivationGroup.createGroup(agi, agroupdesc, 0);

50 RMI - H. Bourzoufi, D. Donsez, Créer le programme d enregistrement Exemple (partie 2) // le descripteur doit contenir le codebase pour chercher les classes String classeslocation = "http:/hostwww/hello/myclasses/"; // le descripteur peut contenir un objet sérialisable pour l initialisation de l objet ; data peut être null MarshalledObject data = new MarshalledObject (new Integer(Home.ES)); // création d un descripteur pour l objet activable ActivationDesc adesc = new ActivationDesc (agi, "examples.hello.HelloActivatableImpl", classeslocation, data ); // enregistrement de l objet auprès du démon rmid : récupération d un stub Hello obj = (Hello)Activatable.register(adesc); // enregistrement du stub auprès du rmiregistry Naming.rebind("//hostreg/HelloActiv", obj); System.exit(0); }

51 RMI - H. Bourzoufi, D. Donsez, Personnaliser la couche Transport des RMI nRappel Par défaut, TCP est utilisé par la couche de transport RMISocketFactory (classes java.net.Socket et java.net.SocketServer ) cependant dans les cas de Firewall/proxies, elle invoque les méthodes en utilisant la méthode POST de HTTP. La propriété java.rmi.server.disableHttp=true désactive le tunneling HTTP nMotivation utiliser d autres classes (que Socket et SocketServer) basées sur TCP pour de la compression, du chiffrage, … Remarque : RMI over SSL utilise cette technique (voir l exemple) ou non (UDP) nInfo : jdk1.2.2\docs\guide\rmi\rmisocketfactory.doc.html

52 RMI - H. Bourzoufi, D. Donsez, Personnaliser la couche Transport des RMI nEtape 1 Écrire 2 sous classes de java.rmi.RMIClientSocketFactory, java.rmi. RMIServerSocketFactory qui utilisent 2 autres classes de transport que java.net.Socket java.net.SocketServer (voir cours Socket)

53 RMI - H. Bourzoufi, D. Donsez, Personnaliser la couche Transport des RMI package examples.rmisocfac; import java.io.*; import java.net.*; import java.rmi.server.*; public class CompressionClientSocketFactory implements RMIClientSocketFactory, Serializable { public Socket createSocket(String host, int port) throws IOException { return new CompressionSocket(host, port); } } public class CompressionServerSocketFactory implements RMIServerSocketFactory, Serializable { public ServerSocket createServerSocket(int port) throws IOException { return new CompressionServerSocket(port); } }

54 RMI - H. Bourzoufi, D. Donsez, Personnaliser la couche Transport des RMI nEtape 2 Spécifier les factories dans le constructeur de l objet distant qui hérite de la classe UnicastRemoteObject protected UnicastRemoteObject( int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) nExemple: public AccountImpl() throws RemoteException { super( 0, new CompressionClientSocketFactory(), new CompressionServerSocketFactory() ); … }

55 RMI - H. Bourzoufi, D. Donsez, RMI et SSL nCouche de transport custom SSLClientSocketFactory, SSLServerSocketFactory utilisent SSLSocket, SSLServerSocket (www.phaos.com) nvoir jdk1.2.2\docs\guide\rmi\SSLInfo.html jdk1.2.2\docs\guide\rmi\PhaosExample.html

56 RMI - H. Bourzoufi, D. Donsez, RMI over SSL RMIClientSocketFactory et RMIServerSocketFactory package examples.rmissl; import java.io.*; import java.net.*; import java.rmi.server.*; import crypsec.SSL.*; // importe des classes de SSL (www.phaos.com) public class SSLClientSocketFactory implements RMIClientSocketFactory, Serializable { public Socket createSocket(String host, int port) throws IOException { return ((Socket) new SSLSocket(host, port, new SSLParams())); } public class SSLServerSocketFactory implements RMIServerSocketFactory, Serializable { transient protected SSLParams params; public SSLServerSocketFactory() { this(new SSLParams()); } public SSLServerSocketFactory(SSLParams p) { params = p; } public ServerSocket createServerSocket(int port) throws IOException { return new SSLServerSocket(port); } }

57 RMI - H. Bourzoufi, D. Donsez, RMI over SSL l objet distant package examples.rmissl; import java.io.*; import java.net.*; import java.rmi.*; import java.rmi.server.*; public class SSLHelloImpl extends UnicastRemoteObject implements Hello { private int defaultlang ; public SSLHelloImpl(SSLServerSocketFactory ssf, int defaultlang) throws RemoteException { super(0, new SSLClientSocketFactory(), ssf); this.defaultlang = defaultlang ; } public String sayHello() throws RemoteException {... }... }

58 RMI - H. Bourzoufi, D. Donsez, RMI over SSL le serveur package examples.rmissl; import java.io.*; import java.net.*; import java.rmi.*; import java.rmi.server.*; public class SSLHelloServer { public static void main(String args[]) { try { // initialize server certificate SSLCertificate cert = new SSLCertificate(); cert.certificateList = new Vector(); cert.certificateList.addElement(new X509(new File("server-cert.der"))); cert.certificateList.addElement(new X509(new File("ca-cert.der"))); SSLParams params = new SSLParams(); // initialize SSL context object params.setServerCert(cert); params.setRequestClientCert(true); // require client authentication System.setSecurityManager(new RMISecurityManager()); // secure server socket factory to use in remote objects SSLServerSocketFactory ssf = new SSLServerSocketFactory(params); // create a secure rmiregistry Registry registry = LocateRegistry.createRegistry(1099,new SSLClientSocketFactory(), ssf); // create a remote object that will use a secure client/server socket pair SSLHelloImpl o = new SSLHelloImpl(ssf, Hello.FR); registry.rebind("/SSLHelloObject", o); } catch (Exception e) { System.err.println(e.getMessage()); e.printStackTrace(); } } }

59 RMI - H. Bourzoufi, D. Donsez, RMI over SSL le client package examples.rmissl; import java.io.*; import java.net.*; import java.rmi.*; import java.rmi.server.*; public class SSLHelloClient { public static void main(String args[]) { try { if (args.length "); System.exit(1); } System.setSecurityManager(new RMISecurityManager()); // Create a secure rmiregistry Registry registry = LocateRegistry. getRegistry(args[0], 1099, new SSLClientSocketFactory()); // Obtain a reference to the HelloObject Hello hello = (Hello) registry.lookup("/SSLHelloObject"); System.out.println("Message: " + hello.sayHello()); } catch (Exception e) { e.printStackTrace(); }

60 RMI - H. Bourzoufi, D. Donsez, Le glaneur de cellules distibué des RMI java.rmi.dgc nMotivation pour un GC réparti ramasser les objets distants qui ne sont plus référencés (i.e. plus de stub sur des clients) nPrincipe basé sur le comptage de références interagit avec les GCs locaux de toutes les JVM maintient des weaks references pour éviter le ramassage par le GC local nRemarque: en cas de partition du réseau, les objets peuvent être prématurément ramassés

61 RMI - H. Bourzoufi, D. Donsez, Le glaneur de cellules distibué des RMI java.rmi.dgc nInterface java.rmi.server.Unreferenced package java.rmi.server; public interface Unreferenced {public void unreferenced();} Un objet distant peut être notifié quand il n est plus référencé il doit implémenter l interface java.rmi.server.Unreferenced la méthode void unreferenced() est appelée par le DGC quand il n y a plus de référence.

62 RMI - H. Bourzoufi, D. Donsez, Le glaneur de cellules distibué des RMI java.rmi.dgc nEtapes du GC Lorsqu'un OD est passé en paramètre à un autre OD ® ref_count++ Lorsqu'un stub n'est plus référencé ® weak reference Lorsque le GC du client libère le stub, sa méthode finalize est appellée et informe le DGC ® ref_count­­ Lorsque le nombre de références d'un OD = 0 ® weak reference Le GC du serveur peut alors libérer l'OD Le client doit régulierement renouveller son bail au pres du DGC. Si référence à un OD libéré ® RemoteException Under Construction En Construction

63 RMI - H. Bourzoufi, D. Donsez, Détail d implantation nCoté serveur Une thread par appel d un client + la thread d écoute des nouveaux appels sur le socket L appel concurrent aux méthodes n est pas synchronisé La synchronisation est à la charge du développeur Un couple pour tous les objets par une JVM Under Construction En Construction

64 RMI - H. Bourzoufi, D. Donsez, RMI over IIOP nCouche de transport : IIOP (www.omg.org) Under Construction En Construction

65 RMI - H. Bourzoufi, D. Donsez, RMI et EJB Under Construction En Construction

66 RMI - H. Bourzoufi, D. Donsez, RMI et EJB nEncapsulation des RMI dans 2 interfaces EJBHome EJBObject nNommage avec JNDI Under Construction En Construction

67 RMI - H. Bourzoufi, D. Donsez, RMI et JINI nJINI mécanisme discovery-join-lookup Nommage tolérant aux pannes (redondance) Recherche par rapport à linterface du service à des attributs qualifiants (Entry) à des groupes Le client récupère la liste des objets distants (stub RMI) potentiellement actifs ou activables offrant ce service

68 RMI - H. Bourzoufi, D. Donsez, Ajout du J2SE 1.4 njava.rmi.server.RMIClassLoaderSpi Délégation du chargement dynamique des classes nSupport du POA (Portable Object Adapter) pour rmic rmic -iiop -poa …

69 RMI - H. Bourzoufi, D. Donsez, Comparaison RMI.NET Remoting CORBASOAP Plate-formesMulti Win32, FreeBSD, Linux Multi Langages de Programmation Java C#, VB, J#, … Multi Langages de Définition de Service JavaCLRIDLXML Réseau TCP, HTTP, IIOP customisable TCP,HTTP, IIOP GIOP, IIOP, Pluggable Transport Layer RPC,HTTP Intercepteurdepuis 1.4 Oui CallContext Oui Extension applicative dans le header Extra Chargement dynamique des classes Services Communs Services Sectoriels Marshalling Sérialisation Java SOAP QuiSUN MicroSoft/ECMA OMGW3C Nommage RMI, JNDI,JINI IP+NomCosNamingIP+Port, URL Formatteurs Binaire, SOAP Pas de Chargement dynamique des classes Représentation IIOP RPC Multi C, C++, … RPCGEN TCP, UDP Non SUN/OSF IP+Port

70 RMI - H. Bourzoufi, D. Donsez, Comparaison RMIRPCDCOMCORBASOAP Plate-formesMulti Win32Multi Langages de Programmation JavaC, C++, … C++, VB, VJ, OPascal, … Multi Langages de Définition de Service JavaRPCGENODLIDLXML Réseau TCP, HTTP, IIOP customisable TCP, UDPIP/IPX GIOP, IIOP, Pluggable Transport Layer RPC,HTTP TransactionNon MTSOTS, XA Extension applicative dans le header Extra Chargement dynamique des classes Services Communs Services Sectoriels Firewall Tunneling HTTP HTTP QuiSUNSUN/OSFMicroSoftOMGW3C Nommage RMI, JNDI,JINI IP+PortIP+NomNomIP+Port, URL

71 RMI - H. Bourzoufi, D. Donsez, Bibliographie nSpécification des RMI java.sun.com et jdk1.2.2/docs/guide/rmi/spec nGuide de la doc du JDK jdk1.2.2/docs/guide/rmi nTutorial Java Trail sur les RMI et sur JINI (Objet activables) Online Training ok/rmi.html nAutres Jeremie : une implémentation OpenSource des RMI

72 RMI - H. Bourzoufi, D. Donsez, Bibliographie nGilles Roussel, Étienne Duris, "Java et Internet, Concepts et programmation", Ed Vuibert, 01/2000, ISBN : le chapitre 11 détaille bien les RMI du JDK1.2 et notamment les objets activables nElliotte Rusty Harold, "Programmation Réseau avec Java", Ed O Reilly, 1997, ISBN date un peu nJava Distributed Computing, Ed Oreilly existe en français date un peu nRobert Orfali, Dan Harkey, Client/Server Programming with Java and Corba, 2ème édition, 1998, Ed Wiley, ISBN X. survol rapide comparaison intéressante avec les autres techniques (DCOM, CORBA, …)


Télécharger ppt "RMI Remote Method Invocation Didier DONSEZ Université Joseph Fourier (Grenoble 1) IMA – LSR/ADELE Hafid Bourzoufi."

Présentations similaires


Annonces Google