le stub démarshalise les données provenant du squelette et les transmet à l'objet
faisant l'appel de méthode à distance
Pour créer une application avec RMI il suffit de procéder comme suit :
- définir la classe distante. Celle-ci doit dériver de java.rmi.server.UnicastRemoteObject (utilisant elle-même les classes Socket et SocketServer, permettant la communication par protocole TCP)
- définir l'interface pour la classe distante. Celle-ci doit implémenter
l'interface java.rmi.Remote et déclarer les méthodes publiques globales
de l'objet, c'est-à-dire les méthodes partageables. De plus ces méthodes doivent
pouvoir lancer une exception de type java.rmi.RemoteException.
- créer les classes pour le stub et le squelette grâce à
la commande rmic
- Lancer le registre RMI et lancer l'application serveur, c'est-à-dire instancier
l'objet distant. Celui-ci lors de l'instanciation créera un lien avec le registre
- Créer un programme client capable d'accèder à aux méthodes
d'un objet sur le serveur grâce à la méthode Naming.lookup()
- Compiler l'application cliente
- Instancier le client
La première chose à faire consiste à identifier
les méthodes de l'objet qui seront accessibles à distance
(on parle d'interface), celles-ci devant être publiques et retourner
un type primaire ou bien un objet sérialisable. De plus ces méthodes
doivent pouvoir lever l'exception java.rmi.RemoteException.
Voici l'interface d'un objet possèdant une seule méthode retournant
une chaˆne de caractères (objet String) :
import java.rmi.* ;
public interface CCMInterface extends Remote {
public String CCMDistant(String valeur) throws RemoteException ;
}
Il s'agit désormais de définir la classe implémentant
l'interface définie précédemment. cette classe une fois
instanciée sera l'objet distant.
La classe distante doit donc
- implémenter l'interface définie antérieurement
- hériter de java.rmi.server.UnicastRemoteObject afin de pouvoir communiquer (elle doit donc importer java.rmi.server.*)
public class CCM extends UnicastRemoteObject implements CCMInterface { }
- posséder un constructeur sans arguments et pouvant renvoyer une exception de type RemoteException
public CCM() throws RemoteException {
super();
}
- implémenter les méthodes définies dans l'interface, pouvant renvoyer une exception de type RemoteException
public String CCMDistant(String valeur) throws RemoteException {
// Operations a effectuer...
}
- Enregistrer l'objet distant dans le registre RMI. Pour cela une solution consiste à
l'enregistrer dans la méthode main() de l'objet, en effectuant les opérations suivantes:
- déclarer un gestionnaire de sécurité :
System.setSecurityManager(new RMISecurityManager());
- Instancier l'objet distant grâce à son constructeur par défaut :
ServeurRMIInterface sRI = new ServeurRMI();
- Lier l'objet au registre RMI grâce à l'interface java.rmi.Naming.
Naming.rebind("//NomDuServeur/Objet",sRI);
Voici un exemple montrant l'implémentation de l'objet CCM :
import java.rmi.*;
import java.rmi.server.*;
import CCMInterface;
public class CCM extends UnicastRemoteObject implements ServeurRMIInterface {
public CCM() throws RemoteException {
super();
}
public String CCMDistant(String valeur) throws RemoteException {
return "Ca marche !!";
}
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
ServeurRMIInterface sRI = new ServeurRMI();
Naming.rebind("//NomDuServeur/CCMDistant",sRI);
}
catch (Exception e) {
// Gerer l'exception
System.out.println("Erreur lors du Bind:"+e.toString);
}
}
}
L'étape suivante consiste à créer le stub et le squelette.
Le JDK fournit l'outil rmic permettant de générer le squelette et
la souche à partir de la classe de l'objet distant. La syntaxe de rmic
est très simple :
rmic classObjetDistant
dans notre cas :
rmic CCM
L'implémentation du client doit se faire de telle façon que l'application
obtienne une référence vers l'objet distant. Le reste des opérations
(marshalling, récupération du stub, ...) est fait de manière transparente.
Le client doit donc obtenir le stub auprès du registre RMI. Pour cela il
s'agit d'utiliser la méthode lookup() de l'objet javax.rmi.Naming premettant
de récupérer le stub en lui passant en paramètre le nom du serveur
et de l'objet "partagé" sous la forme :
//serveur/objet
D'autre part, la méthode lookup() de l'objet Naming renvoie un objet, il faut
ainsi convertir la référence générée en le type de l'interface
de l'objet distant (qu'il faut importer dans la classe cliente) :
InterfaceDistante ID = (InterfaceDistante)Naming.lookup("//serveur/objet")
Il est ensuite possible d'accèder localement aux méthodes de l'objet distant par
l'intermédiaire de son interface :
Type resultat = (Type)ID.methodeDistante(parametre);
Voici un exemple de client pouvant accèder à la méthode partagée
de l'objet distant implémenté précédemment :
import java.rmi.*
import CCMInterface;
public class CCMClient {
public static void main(String[] args) {
try {
CCMInterface CCMI = (CCMInterface)Naming.lookup("//serveur/objet");
String Valeur = CCMI.getValeur();
}
catch(Exception e) {
// Gerer les exceptions
System.out.println("Erreur lors du lookup:"+e.toString);
}
}
}
InterfaceDistante ID = (InterfaceDistante)Naming.lookup("//serveur/objet")
Le registre RMI permet au client d'obtenir les références vers les objets distants.
La syntaxe pour lancer rmiregistry est tout simplement :
rmiregistry
ou
start rmiregistry
Le processus tourne alors sur le port par défaut (1099) à l'écoute des requêtes du client.
Il est également possible de spécifier un autre port (les ports de 1 à
1023 sont réservés, il faut donc choisir un port entre 1024 et 65535). La syntaxe de
rmiregistry est :
start rmiregistry numero_de_port
Java par nature propose une sécurité renforcé ne lui permettant
pas de communiquer avec des éléments extérieurs à la Java
Virtual Machine. Ainsi le JDK1.1 empêcher la communication hors de la JVM
(baptisée ironiquement "bac à sable). Le Java2 SDK propose un
système permettant de définir des autorisations personnalisées
grâce à un fichier appelé fichier de stratégie
(en anglais policy file). Ce fichier (dont l'extension est .policy
contient des lignes accordant des permissions sur les classes. Ainsi pour permettre
à des classes de communiquer avec des éléments extérieurs
il faut définir un fichier de stratégie contenant les lignes suivantes :
grant {
permission java.net.SocketPermission "*:1024-65535","connect,accept,listen";
permission java.net.SocketPermission "*:80","connect";
}
Pour définir un accès restreint, il suffit de remplacer l'astérisque
par le nom de domaine des ordinateurs autorisés à se connecter :
grant {
permission java.net.SocketPermission ".commentcamarche.net:1024-65535","connect,accept,listen";
permission java.net.SocketPermission ".commentcamarche.net:80","connect";
}
Une fois le client implémenté, il suffit de le compiler :
Puis de l'exécuter :
L'étape suivante consiste à compiler le serveur :
javac CCM.java
Puis suit l'exécution du serveur. Toutefois cette étape
est critique pour plusieurs raisons :
- Le stub doit être accessible, c'est-à-dire qu'il doit être
dans le CLASSPATH ou bien chargeable par HTTP ou par URL locale grâce à
un paramètre en ligne de commande :
java [...] -Djava.rmi.server.codebase=URL
- Le serveur doit être associé à un fichier de stratégie
(portant l'extension .policy) indiquant les ressources pouvant accèder à
l'objet distant, puis spécifié sur la ligne de commande :
java [...] -Djava.security.policy=emplacement
Ainsi l'exécution de l'objet se fera par une ligne de commande de la forme :
java
-Djava.security.policy=./monfichier.policy
-Djava.rmi.server.codebase=file:/c:\jdk1.2.2\lib\
CCM
en supposant que le stub se situe dans le répertoire c:\jdk1.2.2\lib\
et que le fichier de stratégie se trouve dans le même répertoire que les
classes. Si le stub est placé sur un serveur HTTP, la ligne de commande pourra être :
java
-Djava.security.policy=./monfichier.policy
-Djava.rmi.server.codebase=http://www.commentcamarche.net/stub/
CCM
© Copyright 2001 Jean-François Pillou
Ce document issu de CommentCaMarche.net est soumis à la licence GNU FDL.Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement.