Chapitre 9 Dans ce chapitre nous abordons le mécanisme RMI (Remote Method Invocation) permettant le développe ment des systèmes répartis. Nous expliquerons comment les classes d un serveur peuvent être appelées par le client. Avec le mécanisme RMI, des méthodes d objets qui ne fonctionnent pas sur la même machine virtuelle peuvent être appelées. Après initialisation, l appel est réalisé comme celui d une méthode locale. JVM JVM Remote methode() RemoteObject methode() RMI est construit sur la base de plusieurs couches fonctionnelles. Chaque couche a un rôle bien précis permettant une communication parfaite entre client et serveur. Le serveur doit être connu comme objet RMI avant que le client ne puisse y accéder. En absence de cette contrainte, n importe quel client serait en mesure d appeler n importe quelle méthode du serveur. Pour pouvoir utiliser le mécanisme RMI, le serveur a besoin d une interface dérivée de l interface Remote. Les classes Stub et Skeleton sont créées pour assurer en interne la communication entre client et serveur. client serveur Stub RMI - couche de référence RMI - couche de transport Skeleton TCP/IP La classe Stub met à disposition la même interface sur l objet coté serveur et transfère un appel à l objet serveur. Elle doit être placée sur le client ou chargée en cours d exécution par RMIClassLoader. La classe Skeleton prend en charge les appels de Stub du coté serveur, les transfère à l objet serveur et renvoie la réponse à la classe Stub. Dans l ensemble, les deux classes, Stub et Skeleton, forment une couche fonctionnelle permettant d établir une référence commune de communication. Le Stub et le Skeleton sont générés automatiquement par l utilitaire rmic fournit dans la distribution Java RMI. Dans la même couche est intégré le service de noms appelé Registry. Quand un client effectue la demande d un objet distant, il doit regarder dans le service de noms (registry). Ce service retourne une
référence à l objet distant et informe le serveur qu un client demande son service. Le client charge le Stub correspondant à sa demande et il est prêt à invoquer la méthode distante. Un objet distant est doit être préparé pour une évocation du client distant. Cette opération est achevée en deux étapes: préparation d une interface décrivant les méthodes de l objet; implémentation de cette interface. La classe Stub met à disposition la même interface sur l objet coté serveur et transfère un appel à l objet serveur. Elle doit être placée sur le client ou chargée en cours d exécution par RMIClassLoader. La classe Skeleton prend en charge les appels de Stub du coté serveur, les transfère à l objet serveur et renvoie la réponse à la classe Stub. Dans l ensemble, les deux classes, Stub et Skeleton, forment une couche fonctionnelle permettant d établir une référence commune de communication. Le Stub et le Skeleton sont générés automatiquement par l utilitaire rmic fournit dans la distribution Java RMI. Dans la même couche est intégré le service de noms appelé Registry. Quand un client effectue la demande d un objet distant, il doit regarder dans le service de noms (registry). Ce service retourne une référence à l objet distant et informe le serveur qu un client demande son service. Le client charge le Stub correspondant à sa demande et il est prêt à invoquer la méthode distante. Client rmi://server/name Internet référence Serveur Naming Registry nom RemoteObject Un objet distant est doit être préparé pour une évocation du client distant. Cette opération est achevée en deux étapes: préparation d une interface décrivant les méthodes de l objet; implémentation de cette interface. En Java, les objets distants RMI héritent de la classe java.rmi.remoteobject. A partir de cette classe, est dérivée la classe java.rmi.unicastremoteobject. Tout objet qui accède par RMI doit être dérivé de cette classe. import java.rmi.server.*; public class MonServeurRMI extends RemoteObject implements RemoteSevice { public MonServeurRMI throws RemoteException { // constructeur super(); public Object mamethode(string valeur) { return resultat;
Pour créer les classes Stub et Skeleton, un tel objet doit également définir une interface pour l accès dérivée de java.rmi.remote. Seules les méthodes spécifiées dans cette interface peuvent être évoquées à distance. RemoteException est une super classe constituée de toutes les exceptions qui peuvent arriver pendant l exécution d une méthode distante. Toutes les méthodes distantes doivent pouvoir lever cette exception. Les clients peuvent évoquer seulement les objets/méthodes répertoriés dans un registre (Registry) de noms. Les objets distants s enregistrent dans le Registry par l intermédiaire de la classe java.rmi.naming. La classe Stub met à disposition la même interface sur l objet coté serveur et transfère un appel à l objet serveur. Elle doit être placée sur le client ou chargée en cours d exécution par RMIClassLoader. La classe Skeleton prend en charge les appels de Stub du coté serveur, les transfère à l objet serveur et renvoie la réponse à la classe Stub. Dans l ensemble, les deux classes, Stub et Skeleton, forment une couche fonctionnelle permettant d établir une référence commune de communication. Le Stub et le Skeleton sont générés automatiquement par l utilitaire rmic fournit dans la distribution Java RMI. Dans la même couche est intégré le service de noms appelé Registry. Quand un client effectue la demande d un objet distant, il doit regarder dans le service de noms (registry). Ce service retourne une référence à l objet distant et informe le serveur qu un client demande son service. Le client charge le Stub correspondant à sa demande et il est prêt à invoquer la méthode distante. Un objet distant est doit être préparé pour une évocation du client distant. Cette opération est achevée en deux étapes: préparation d une interface décrivant les méthodes de l objet; implémentation de cette interface. try { MonServeurRMI serveur = new MonServeurRMI(); Naming.rebind( MonServerRMI,serveur); java.rmi.remote java.rmi.remoteobject serverinterface java.rmi.unicastremoteobject implements extends server catch(exception e) { System.err.println(e); Un enregistrement effectif nécessite que le serveur rmiregistry soit lancé sur le poste serveur.
Un exemple L exemple suivant est une solution client serveur dans laquelle le client appelle le serveur pour y exécuter une méthode permettant de lire la date locale. Le résultat de cette lecture est affiché dans la partie client. Pour réaliser cette opération il nous faut trois classes: TimeClient.java - pour appeler la méthode externe, RemoteTime.java - l interface de cette méthode appelée en externe par le client et implémentée par le serveur, TimeServer.java - la classe du serveur RMI qui met la méthode à la disposition du client. L implantation de cette application peut être décomposée en six étapes: Ecrire une interface pour l objet distant. Cette interface représente les méthodes, via lesquelles un objet distant peut être accédé. Cette interface doit être connue du côté client et du côté serveur. Ecrire une implémentation de cette interface côté serveur. Cette classe servira à créer sur la machine serveur, un objet distant respectant cette interface; objet qui pourra être sollicité à distance par le client. Générer les classes du Stub et du Skeleton à partir de la classe implantant l interface. Exporter (exposer) l objet distant dans un serveur d objets, qui lui transmettra les appels distants de la méthode via son Skeleton. Faire connaître, c est-à-dire enregistrer avec un nom, l objet exposé dans un serveur de noms. Dans ce serveur, les applications clientes pourront récupérer un stub de cet objet. Evoquer à distance, depuis la machine cliente, les méthodes de l objet, déclarées par l interface, en utilisant un stub de l objet exposé. Définition de l interface L interface RemoteTime est dérivée de l interface Remote et définit l ensemble de méthodes qui pourront être appelées en externe par le client. public interface RemoteTime extends Remote { public Date getdate() throws RemoteException; // methode distante Définir une implementation (côté serveur) Ci-dessous, une implémentation de cette interface à installer et à exporter sur la machine serveur pour accepter les appels de méthodes distantes provenant du client. import java.rmi.server.*; public class TimeServerRMI extends RemoteObject implements RemoteTime { public TimeServerRMI throws RemoteException { // constructeur super();
public Date getdate() { return new Date(); public static void main (String[] args) { System.out.println( server getstarted ); try { TimeServerRMI time = new TimeServerRMI(); Naming.rebind( TimeServerRMI,time); catch(exception e) { System.err.println(e); import java.rmi.server.*; public class TimeServerRMI extends RemoteObject implements RemoteTime { public TimeServerRMI throws RemoteException { // constructeur super(); Définir la classe cliente La classe du client doit intégrer le package java.rmi.*. Dans la méthode main() nous créons un objet RemoteTime à appeler sur la machine serveur (ici localhost). public class TimeClientRMI { public static void main ( String[] args ) { try { RemoteTime remotetime = (RemoteTime) Naming.lookup("rmi://localhost/TimeServerRMI"); Date serverdate = remotetime.getdate(); // appel de methode distante System.out.println("Server : " + serverdate); catch (Exception e) { System.out.println("\nErreur\n" + e); Compilation L élaboration de cet exemple nécessite plusieurs phases de compilation. Côté serveur:
serveur:javac RemoteTime.java serveur: javac TimeServerRMI.java // compilation de l interface // compilation de la classe serveur server:rmic TimeServerRMI // creation de : TimeServerRMI_Stub.class et TimeServerRMI_Skel.class server: start /b rmiregistry server: java TimeServerRMI // enregistrement du serveur // lancement du serveur et côté client: client: javac RemoteTime.java client: javac TimeClientRMI.java client: java TimeClientRMI // compilation de l interface // compilation de la classe client // lancement du client Résumé Le mécanisme RMI permet d effectuer les appels de méthodes distantes. Les fonctions RMI cachent la complexité de la mise en oeuvre des applications client/serveur. RMI fournit l ensemble des fonctionnalités nécessaires à la préparation des objets distants suite à une demande provenant du client. Cette préparation concerne l enregistrement des méthodes distantes et la création des interfaces (Stub et Skeleton) permettant d effectuer le transfert d information.