Vous êtes sur la page 1sur 5

M2 RSD 

: Construction d’applications réparties


TP N° 1 : Java RMI 2020/2021

Exercice 1 :

Dans ce qui suit, nous allons considérer les codes suivants (modification légère par rapport au TD 1) :

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ObjetSInterface extends Remote {
public String miroir (String a) throws RemoteException;
}

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ObjetCInterface extends Remote {
public int mul(int a, int b) throws RemoteException;
}
TTT est une nouvelle interface par rapport au TD 1.

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface TTT extends Remote {
public int add (int a, int b) throws RemoteException;
}

ObjetS implémente une seule interface contenant une seule méthode (miroir).

import java.rmi.*;
import java.rmi.server.*;
public class ObjetS extends UnicastRemoteObject implements ObjetSInterface{
public ObjetS() throws RemoteException {}
public String miroir (String a) throws RemoteException {
String r="";
for (int i=a.length() ;i>0 ;i--) r=a.charAt(a.length()-i)+r;
return r;
}
}
ObjetC implémente 2 interfaces (une méthode par interface), add et mul respectivement.
import java.rmi.*;
import java.rmi.server.*;
public class ObjetC extends UnicastRemoteObject implements ObjetCInterface, TTT {
public ObjetC() throws RemoteException {}
public int mul (int a, int b) throws RemoteException {
return (a*b);
}
public int add(int a, int b) throws RemoteException {
return (a+b);
}
}

import java.rmi.*;
import java.rmi.registry.LocateRegistry;
public class ServeurSC {
public static void main(String[] args){
try {LocateRegistry.createRegistry(1099);
} catch (RemoteException e1) {
System.err.println("rmiregistry est déjà lancé sur ce port");
System.exit(1);
}
try {
ObjetS objets= new ObjetS();
System.out.println(objets);
Naming.rebind("Miroir", objets);
ObjetC objetc = new ObjetC();
System.out.println(objetc);
Naming.rebind("Multi", objetc);
System.out.println("Le serveur est pret");
}
catch (Exception e) {
System.err.println("Erreur: " + e.getMessage());
}
}
}

import java.rmi.*;
class ClientSC{
public static void main (String [] argv){
try {
ObjetSInterface s= (ObjetSInterface) Naming.lookup ("Miroir"); // une seule interface
System.out.println (s);
System.out.println (s.miroir("RSDJAVARMI"));
// dans ce qui suit, caster avec la première interface pour appeler mul
ObjetCInterface a=(ObjetCInterface) Naming.lookup("Multi");
System.out.println (a);
System.out.println (a.mul(5,6));
TTT b = (TTT)a; // caster avec la deuxième interface pour appeler add
System.out.println (b);
System.out.println (b.add(5,6)); }
catch (Exception e) {System.err.println("Erreur: " + e.getMessage());
}
}
}
1. Dans ObjetS(), mettez la ligne : public ObjetS() throws RemoteException{} en commentaire. C’est
quoi le problème ?
2. Reprenez votre code et retirez throws RemoteException{} de la déclaration du constructeur. C’est
quoi le problème ?
3. Reprenez votre code et lancez ServeurSC plusieurs fois. Examinez le numéro de port de chaque
objet, comment se fait le choix de ce port ?
4. En examinant la documentation de la classe UnicastRemoteObject.
https://docs.oracle.com/javase/8/docs/api/java/rmi/server/UnicastRemoteObject.html
Installez ObjetS sur le port 1000 et ObjetC sur le port 2000 (utilisez le constructeur de la classe
UnicastRemoteObject ).
5. Exécutez à nouveau ServeurSC pour vérifier.
6. Peut-on installer les deux objets sur le port 1099 ? Faites un test.
7. Installez les deux objets sur le port 0. Comment se fait le choix du port dans ce cas ?
8. Comparez les infos de chaque objet distant avec son stub respectivement. Quel est le lien ?
9. Supposons que l’affichage de l’un des stub donne ce qui suit :
Proxy[ObjetSInterface,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:
[192.168.1.6:56640](remote),objID:[-1a9a6e54:16e13d14270:-7fff, -1740617560762366171]]]]]
Quel est le rôle de objID ? Voir le lien
https://docs.oracle.com/javase/7/docs/api/java/rmi/server/ObjID.html.
10. Quel est le rôle de [192.168.1.6:56640] ?
11. Dans ClientSC, affichez les noms enregistrés (les clés) dans l’annuaire qui est installé coté serveur.

Exercice 2 :

Dans cet exercice, nous allons utiliser une autre manière afin d’exporter un objet dans le serveur.
Cette manière est obligatoire si la classe représentant l’objet distant est déjà une classe fille d’une
autre classe mère.
Ex. dans l’exercice 1, supposons que ObjetS est déclaré comme suit :
public class ObjetS extends A (A est une classe quelconque qui peut être aussi prédéfinie comme
JApplet ou autres).
Dans ce cas, on ne peut pas faire ce qui suit :
public class ObjetS extends A, UnicastRemoteObject implements ObjetSInterface  pas d’héritage
multiple en JAVA.
Comment procéder dans ce cas pour exporter un objet lié à une classe mère dans le serveur ?
Dans la documentation de la classe UnicastRemoteObject :
https://docs.oracle.com/javase/8/docs/api/java/rmi/server/UnicastRemoteObject.html, examiner les différentes
signatures de la méthode exportObject.
Dans ce qui suit, nous allons utiliser la signature suivante :
public static Remote exportObject(Remote obj, int port) throws RemoteException

Soit les classes suivantes:

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface SSN extends Remote {
public String getSSN(String name) throws RemoteException;
}
import java.rmi.*;
import java.util.*;
import javax.swing.JApplet;
public class SSNImpl extends JApplet implements SSN {
private Map rep; // rep est un attribut dans l’objet
public SSNImpl() throws RemoteException{
rep = new HashMap();
rep.put("Anes","111-11-1111");
rep.put("Badr", "222-22-2222");
rep.put("Youcef", "333-33-3333");
rep.put("Saleh", "444-44-4444"); }
public String getSSN(String name) throws RemoteException {
if (rep.containsKey(name)) return (String)rep.get(name);
else return null;
}
}
Pour Map, voir : https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
Pour HashMap, voir :https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html
Explication : notre objet contient un attribut ressemblant à une table de hachage dont les clés sont des
personnes (String) et les valeurs sont leurs numéros de sécurité sociale respectivement (String).

import java.rmi.server.*;
import java.rmi.registry.*;
import java.rmi.registry.LocateRegistry;
public class SSNServer {
public static void main(String args[]) {
try {
SSNImpl objet = new SSNImpl();
SSN objetexport =(SSN) UnicastRemoteObject.exportObject(objet, 5000);
System.out.println(objetexport);
Registry registry=LocateRegistry.createRegistry(4444);
System.out.println(registry);
registry.rebind("SSN", objetexport);
System.out.println("Le serveur est prêt ...");
} catch (Exception e) {System.out.println("Exception: " + e.getMessage());}
}
}

import java.rmi.registry.*;
import java.rmi.registry.LocateRegistry;
public class SSNClient {
public static void main(String args[]) {
try {
Registry registry = LocateRegistry.getRegistry(3333); // récupérer la référence de l'annuaire
SSN stub = (SSN) registry.lookup("SSN"); // utiliser la référence de l'annuaire au lieu de Naming
String RA = stub.getSSN("Saleh"); // appel de la méthode à distance
System.out.println("SSN de Saleh : " + RA);
String RB = stub.getSSN("Youcef"); // appel de la méthode à distance
System.out.println("SSN de Youcef : " + RB);
String RD = stub.getSSN("Badr"); // appel de la méthode à distance
System.out.println("SSN de Badr : " + RD);
} catch (Exception e) {System.out.println("exception: " +e.getMessage());
}
}
}
1. Lancez le serveur et le client, ça ne marche pas. Vérifiez le numéro de port coté client et lancez une
nouvelle exécution.

2. Dans la classe SSNImpl, remplacez public class SSNImpl extends JApplet implements SSN par
public class SSNImpl extends UnicastRemoteObject implements SSN. Mettez en commentaire
import javax.swing.JApplet; et ajouter import java.rmi.server.UnicastRemoteObject; Lancez le
serveur. C’est quoi le problème ? Expliquez l’exécution : Exception: object already exported.
Remarque : l’annuaire contient une seule clé (SSN), cette dernière pointe vers l’objet contenant
l’attribut rep et c’est ce dernier qui contient le HashMap comme indiquer dans la figure suivante.

3. Reprendre la signature suivante pour SSNImpl : public class SSNImpl implements SSN.
Ajoutez la méthode public void REMPLACER(String name) throws RemoteException à la
classe SSNImpl. Cette méthode remplace le numéro de sécurité sociale d’une personne indiquée ici
par name par son ancien numéro concaténé avec "-DZ".
Exemple : L’appel suivant stub.REMPLACER("Anes"); dans le client doit remplacer 111-11-1111
par 111-11-1111-DZ dans le serveur. Ici, le client ne s’attend pas à recevoir une réponse de la part
du serveur, il veut juste exécuter une méthode dans le serveur (méthode de type void).

4. Ajoutez la méthode public String AfficherTout() throws RemoteException; à la classe SSNImpl.


Cette méthode affiche les numéros de sécurité sociale de toutes les personnes.
Exemple : System.out.println (stub.AfficherTout()); dans le client affiche [222-22-2222, 111-11-
1111-DZ, 333-33-3333, 444-44-4444] suite à l’exécution dans le serveur de la méthode
AfficherTout().
Bien évidement votre interface finale sera comme suit :
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface SSN extends Remote {
public String getSSN(String name) throws RemoteException;
public void REMPLACER(String name) throws RemoteException;
public String AfficherTout() throws RemoteException;
}

Indication : voir les méthodes de https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html pour


les deux dernières questions.

5. Faites une modification sur le code précédent afin de mettre en place un service d’annuaire
téléphonique permettant d’enregistrer des noms et des numéros de téléphone sous la forme de
chaines de caractères en se basant sur une HashMap.

Vous aimerez peut-être aussi