Vous êtes sur la page 1sur 6

Formation java Pr M.

LETHRECH SupMTI

TD RMI

Objectifs : Réalisation d’un exemple de communication réseau via RMI.

Rappel :
L'implémentation avec RMI d'une application comprenant un objet distant se décompose en
cinq étapes :
1. Ecrire une interface pour l'objet distant. Cette interface représente l'ensemble de
méthodes, via lesquelles un objet distant pourra être manipulé.
2. Ecrire une implémentation de cette interface du cote serveur. Cette classe servira à
créer une instance (l'objet distant) respectant cette interface qui pourra être accédée à
distance depuis la machine cliente. Cette implémentation expose, c'est-à-dire rend
accessible l'objet distant dans un serveur d'objets, qui lui transmettra les appels distants de
méthodes via son squelette.
3. Générer, à partir de la classe implémentant l'interface, les classes souches (du talon et
du squelette) de l'objet distant.
4. Publier l'existence de cet objet exposé dans un serveur de noms, c'est-à-dire associer
cet objet a un nom, a partir duquel des applications distantes clientes pourront récupérer
un talon de cet objet (une instance de la classe du talon généré à l'étape 3).
5. Appeler à distance des méthodes de l'objet distant depuis la machine cliente, déclarées
par l'interface, en utilisant le talon de l'objet exposé.

Architecture de Java RMI

1
Formation java Pr M. LETHRECH SupMTI

Exercice 1 : Hello, en version distribuée


Développement d’une application classique de type Hello, mais en version distribuée.
L'intérêt est de réaliser une application distribuée qui permet au client d'envoyer une chaîne de
caractères au serveur, qui à son tour l'affichera, précédée du message « Hello ».

Etape 1 : Objet distant : définir son interface


La première étape consiste à définir l'interface par laquelle les applications clientes auront
accès aux services offerts par l'objet distant.

public interface Hello extends java.rmi.Remote {


String sayHello(String param) throws java.rmi.RemoteException;
}

Cette interface expose une seule méthode « sayHello » et prend en paramètre un String.

Etape 2 : Implémentation de l'objet distant


L'interface définit uniquement les services accessibles sur l'objet distant, mais ne définit pas le
comportement de ces services. C'est à l'implémentation de l'objet distant de spécifier ce
comportement.

L'objet distant doit être rendu accessible par le réseau pour que, par exemple, une application
cliente puisse lui transmettre un appel de méthode à distance via un talon. Cette opération,
appelée exposition, peut être réalisée grâce à l'héritage de classes. La classe utilisée est
java.rmi.server.UnicastRemoteObject.

L'appel au constructeur de la super-classe, UnicastRemoteObject, entraînera alors


implicitement et automatiquement l'exposition de l'objet.

public class HelloImpl extends java.rmi.server.UnicastRemoteObject implements Hello {

private final static String CURRENT_HOSTNAME = getHostName();

public HelloImpl() throws java.rmi.RemoteException {


}

public String sayHello(String param) {


return "Hello "+ param+" from : " + CURRENT_HOSTNAME + "!";
}

protected static String getHostName() {


try {
return java.net.InetAddress.getLocalHost().getHostName();
} catch (java.net.UnknownHostException e) {
return "Unknown";
}
}
}

La classe UnicastRemoteObject permet d'exposer des objets du cote serveur afin de les rendre
accessibles, a distance, aux applications clientes. Elle encapsule, de façon transparente pour le
développeur, la prise en charge des objets auprès d'un serveur d'objets. Ce serveur d'objets,
exécuté dans un processus léger, attend les appels de méthodes des clients et les aiguille vers
les instances concernées via leur squelette.

2
Formation java Pr M. LETHRECH SupMTI

Etape 3 : Serveur, créer et publier l'objet distant


Le serveur est chargé essentiellement de créer et publier l'objet distant pour que les clients
puissent l'accéder.

Création de l’objet
Un objet distant est crée comme tout autre objet d'une application, instance de la classe
d'implémentation. L'exception RemoteException doit être traitée au cas où une erreur se
produit lors de l'instanciation.

Publier un objet distant


Pour faire connaître le nouvel objet exposé, ce dernier peut alors être publié dans un serveur
de noms (un objet distant à son tour). Le serveur de noms maintient une table d'associations
entre des noms et des talons. Les objets situés sur la même machine que le serveur de noms
peuvent publier des talons auprès de ce serveur de noms. Ces talons seront ensuite récupères,
localement ou a distance, a partir de leur nom.
La classe « java.rmi.Naming » encapsule l'accès aux objets serveurs de noms.
Pour cette classe, un nom est une URL, au format « //machine:port/nom ». Les champs
machine et port permettent de repérer l'objet serveur de noms, attaché à une adresse Internet et
un port TCP particulier. Ces derniers peuvent être omis, dans ce cas la machine locale
(localhost) et le port par défaut (1099) seront utilisés.

Les méthodes de la classe Naming sont toutes statiques on va utiliser la méthode suivante :
- rebind(url, objet) : une alternative de la méthode bind, permet d'associer un talon a un nom
même si ce dernier est utilise ;

public class HelloServer {

private final static String CURRENT_HOSTNAME = getHostName();


private final static String REGISTRY_ENTRY_ID = "ObjDistant";

public static void main(String args[]) {

try {
HelloImpl helloImpl = null;
helloImpl = new HelloImpl();
// Bind this object instance to the name "HelloServer"
java.rmi.Naming.rebind(REGISTRY_ENTRY_ID, helloImpl);
System.out.println(":) HelloServer bound in registry at the url ");
System.out.println(" rmi://"+CURRENT_HOSTNAME+"/"+REGISTRY_ENTRY_ID);
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
} catch (java.rmi.RemoteException e) {
System.out.println("!!! --> There is no RMI Registry running on that host : Cannot
bind the HelloServer");
e.printStackTrace();
}
}

protected static String getHostName() {


try {
return java.net.InetAddress.getLocalHost().getHostName();
} catch (java.net.UnknownHostException e) {
return "Unknown";
}
}
}

3
Formation java Pr M. LETHRECH SupMTI

Etape 4 : Client : utiliser l'objet à distance


Pour utiliser l'objet a distance, nous construisons une application cliente. Celle-ci commence
par récupérer un objet (talon) correspondant à l'objet distant, via le serveur de noms qui se
trouve sur la machine serveur. Pour cela, la méthode statique lookup de la classe
java.rmi.Naming est utilisée. Cette méthode retourne un objet de la classe java.rmi.Remote
qu'il faut transtyper à l'interface de l'objet distant utilisé.

Les instructions minimales de l'application cliente sont les suivantes :


- la récupération de la référence de l'objet distant (son talon) par l'interrogation du serveur de
noms, en connaissant le nom de l'objet publié. L'URL donne (en argument dans la ligne de
commande) doit contenir l'adresse de la machine sur laquelle tourne le serveur de noms (sous
forme d'adresse IP ou de nom de machine, complété éventuellement par le numéro de port, si
un autre que le port par défaut est utilisé). L'objet récupéré est de type Remote, qui sera
transtypé vers le type de l'objet distant, en l'occurrence Hello. Le client manipule uniquement
des objets distants ayant le type de l'interface, jamais le type de l'implémentation, car le client
ne connaît pas l'implémentation des services.
- l'appel de méthode à distance, sur l'objet distant récupéré.

public class HelloClient {

public static void main(String[] args) {


if (args.length != 1) {
System.out.println("You must pass the URL of the remote HelloServer such as
rmi://maroc.ma/HelloServer");
System.exit(1);
}

try {
Hello remoteHelloServer = null;
// get a remote reference (a stub) on the remote server
remoteHelloServer = (Hello) java.rmi.Naming.lookup(args[0]);
if (remoteHelloServer == null) return;
System.out.println(remoteHelloServer.sayHello("Mohammed"));
} catch (java.rmi.NotBoundException e) {
System.out.println("!!! --> HelloServer not bound at the given URL");
e.printStackTrace();
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
}
}
}

Etape 5 : Déploiement d'applications RMI

Compilation
javac Hello.java HelloImpl.java HelloServer.java HelloClient.java
Ou en utilisant *.java

Les souches : le talon et le squelette


Les classes talon et squelette sont générées grâce à la commande rmic. Cette commande prend
en argument un nom de classe.

rmic HelloImpl

(La racine de l’implémentation doit figurée dans le CLASSPATH)

4
Formation java Pr M. LETHRECH SupMTI

A partir de la version 1.2 de Java, le squelette n'est plus exigé. Pourtant, il peut être généré
pour des questions de compatibilité. A partir de la version 5 de Java, le talon n'est plus
nécessaire, il est généré dynamiquement.

Etape 6 : Exécution d'une application distribuée RMI

Lancement du serveur de noms


Lancement du serveur de noms La commande rmiregistry lance un serveur de noms destiné a
RMI; celui-ci doit être démarré sur la même machine que le programme effectuant la
publication (l'application serveur).

Lancement de l'application serveur


L'application serveur réalisant la création et la publication de l'objet distant peut être lancée
une fois le serveur de noms en exécution.

java HelloServer

Résultat :
:) HelloServer bound in registry at the url
rmi://pc/ObjDistant

La méthode d'exposition d'objet distant a pour effet de créer et démarrer le serveur d'objets
dans un processus léger concurrent. Ce serveur d'objets est automatiquement placé en attente
d'appels à distance de méthodes. Pour cette raison, l'exécution du serveur ne rend pas la main,
même après l'affichage des messages (le serveur d'objets reste en attente)

Lancement de l'application cliente


Génération de la classe stub (le talon) à partir de la classe d’implémentation de l’objet distant
: >rmic HelloImpl
Résultat : génération du fichier HelloImpl_Stub.class
L'application cliente s'exécute généralement sur une machine distincte de la machine serveur.
Dans notre exemple, le client nécessite connaître l'adresse de la machine sur laquelle le
serveur de noms tourne (ou l'objet distant est publié).
L'adresse sera définie par le nom de la machine suivi de : et du numéro du port de lancement
du serveur de noms.
Le lancement du client pour l'exemple proposé est :
java HelloClient rmi://pc/ObjDistant

Résultat : Hello Mohammed from : pc!

Exercice 2
Utiliser l’exercice précédant pour envoyer un paramètre de type Message.
La classe Message contient deux attributs : date de type Calandar et text de type String
Les paramètres doivent être sérialisés.
Le serveur affiche le text du Message et retourne un accusé de réception qui sera affiché au
niveau du client.
Adapter l’objet distant, le client et le serveur pour utiliser la classe Message comme
paramètre.
Ci-dessous un exemple de la classe Message :

5
Formation java Pr M. LETHRECH SupMTI

public class Message implements java.io.Serializable {

private String message;

public String getMessage() {


return message;
}

public void setMessage(String message) {


this.message = message;
}
}

Vous aimerez peut-être aussi