RMI le langage java
Remote
Method
Invocation
(RMI)
XII-1 JMF
RMI le langage java
Introduction
RMI est un ensemble de classes permettant
de manipuler des objets sur des machines
distantes (objets distants) de manière
similaire aux objets sur la machine locale
(objet locaux).
RMI apparaît avec Java 1.1 et est
complètement intégré dans Java 1.1 donc est
gratuit (≠ CORBA)
C'est un bon pas vers CORBA. C'est du
CORBA allégé avec ses avantages (c'est plus
simple) et ses inconvénients (tout doit être
Java coté client comme coté serveur).
Si on veut être hétérogène coté client et coté
serveur, il faut utiliser CORBA.
C'est un peu du "RPC orienté objet". Un objet
local demande une fonctionnalité à un objet
distant. Il y a donc une machine virtuelle
Java des 2 cotés.
Ces manipulations sont "relativement"
transparente. Pour cela RMI propose :
- un ramasse-miettes distribué.
- la gestion des représentants locaux
d'objets distants et leur activation.
- la liaison avec les couches transport et
l'ouverture de sockets appropriés.
- la syntaxe d'invocation, d'utilisation d'un
objet distant est la même qu'un objet local.
XII-2 JMF
RMI le langage java
RMI en pratique
fonctionne dans les applications Java 1.1 et
dans appletviewer.
pas dans IE 3.0.
Dans netscape 3.0 la classe
[Link] doit être
présente dans le répertoire repéré par
CODEBASE) et l'URL doit être htpp:// (et non
[Link]
client RMI serveur RMI
1 4 3 2
Souche (Stub) Skeleton
Remote Reference Remote Reference
Layer (RRL) Layer (RRL)
couche Transport couche Transport
la couche souche contient des représentants
locaux de références d'objets distants. Une
invocation d'une fonctionnalité sur cet objet
distant est traité par la couche RRL
(ouverture de socket, passage des
arguments, marshalling, ...). Les objets
distants sont repérés par des références
gérées par la couche skeleton.
XII-3 JMF
RMI le langage java
Programmation avec RMI
Pour créer une application RMI, suivre les
étapes suivantes.
1°) définir les interfaces pour les classes
distantes.
2°) Créer et compiler les implémentations
de ces classes.
3°) Créer les classes pour la souche et le
skeleton à l'aide de la commande rmic.
4°) Créer et compiler une application
serveur.
5°) lancer le rmiregister et lancer
l'application serveur.
6°) Créer et compiler un programme client
qui accède à des objets distants du serveur.
7°) lancer ce client.
Un exemple classique :
serveur bancaire
Un gestionnaire de comptes bancaires est
capable de gérer plusieurs comptes. Il sera
placé sur une machine distante, interrogé et
manipulé par des clients.
exemple inspiré de [JDH] chapitre 12.
XII-4 JMF
RMI le langage java
1°) définir les interfaces
pour les classes
distantes.
Les classes placées à distance sont
spécifiées par des interfaces qui doivent
implémenter [Link] et dont les
méthodes lèvent une
[Link] exception. On
définit alors 2 interfaces CreditCard et
CreditManager.
package credit;
import credit.*;
import [Link].*;
public interface CreditCard extends Remote {
/** retourne le credit sur ce compte */
public float getCreditLine() throws
RemoteException;
/** permet de faire un achat de amount francs.
Leve une exception si la somme est supérieure
au credit bancaire.*/
public void makePurchase(float amount, int
signature) throws RemoteException,
InvalidSignatureException,
CreditLineExceededException;
/** positionne la signature de ce compte
bancaire. */
public void setSignature(int pin) throws
RemoteException;
}
XII-5 JMF
RMI le langage java
1°) définir les interfaces
pour les classes distantes
(suite)
package credit;
import credit.*;
import [Link].*;
public interface CreditManager extends
[Link] {
/** recherche le compte bancaire d'une
personne. S'il n'en a pas en crée un et le
retourne.*/
public CreditCard findCreditAccount(String
Customer) throws DuplicateAccountException,
RemoteException;
/** crée un nouveau compte bancaire pour la
personne newCustomer */
public CreditCard newCreditAccount(String
newCustomer) throws RemoteException;
}
XII-6 JMF
RMI le langage java
2°) Créer et compiler les
implémentations de ces
classes.
Il s'agit d'écrire 2 classes qui implémentent
les interfaces ci dessus. En général ces
classes ont pour nom nomInterfaceImpl.
Ces classes doivent dériver de
[Link].
package credit;
import [Link].*;
import [Link].*;
import [Link];
public class CreditCardImpl
extends UnicastRemoteObject
implements CreditCard, Serializable
{
private float creditLine = 5000f;
private int signature = 0;
private String accountName;
public CreditCardImpl(String customer)
throws RemoteException,
DuplicateAccountException {
accountName = customer;
}
public float getCreditLine() throws
RemoteException {
return creditLine;
}
XII-7 JMF
RMI le langage java
public void setSignature(int pin) throws
RemoteException {
signature = pin;
}
/** effectue un achat en s'assurant :
- de la bonne signature
- que l'achat est inférieure au credit.*/
public void makePurchase(float amount, int
signature)
throws RemoteException,
InvalidSignatureException,
CreditLineExceededException {
if (signature != [Link]) {
throw new InvalidSignatureException();
}
if (amount > creditLine) {
throw new
CreditLineExceededException();
} else {
creditLine -= amount;
}
}
}
XII-8 JMF
RMI le langage java
2°) Créer et compiler les
implémentations de ces
classes (suite)
package credit;
import [Link].*;
import [Link].*;
import [Link];
public class CreditManagerImpl extends
UnicastRemoteObject implements
CreditManager {
private static transient Hashtable accounts =
new Hashtable();
/** Le constructeur par défaut qui ne fait rien
d'autre qu'appeler super() */
public CreditManagerImpl() throws
RemoteException { }
/** Crée un nouveau compte. Entre autre ajoute
le nouveau client dans la hashtable accounts */
public CreditCard newCreditAccount(String
customerName) throws RemoteException {
CreditCardImpl newCard = null;
try {
newCard = new
CreditCardImpl(customerName);
} catch (DuplicateAccountException e) {
return null;
}
[Link](customerName, newCard);
return newCard;
}
XII-9 JMF
RMI le langage java
/** recherche un compte bancaire pour le client
customer. S'il n'en trouve pas, retourne en crée
un et le retourne */
public CreditCard findCreditAccount(String
customer) throws DuplicateAccountException,
RemoteException {
CreditCardImpl account =
(CreditCardImpl)[Link](customer);
if (account != null) {
return account;
}
account = new CreditCardImpl(customer);
[Link](customer, account);
return account;
}
}
Pour compiler utiliser les commandes :
javac -d . [Link]
javac -d . [Link]
javac -d . [Link]
javac -d . [Link]
Ces commandes vont créer les fichiers
.class et les déposer dans ./credit.
XII-10 JMF
RMI le langage java
3°) Créer les classes pour
la souche et le skeleton
(commande rmic)
Il faut maintenant créer la souche et le
skeleton pour accéder aux classes ci dessus.
Java donne un outil rmic qui utilisent les
fichiers .class.
la syntaxe de rmic est
rmic [options]
[Link]..nomBaseByteCo
de1
[Link]..nomBaseByteCo
de2 ...
On a donc ici :
rmic -d . [Link]
[Link]
ce qui crée 4 classes dans le répertoire
credit : CreditCardImpl_Skel.class,
CreditCardImpl_Stub.class,
CreditManagerImpl_Skel.class,
CreditManagerImpl_Stub.class.
XII-11 JMF
RMI le langage java
4°) Créer et compiler une
application serveur
C'est le programme qui sera à l'écoute des
demandes des clients. Ce programme crée un
objet CreditManagerImpl qui attend alors
les requêtes.
package credit;
import [Link].*;
import [Link].*;
public class CardBank {
public static void main (String args[]) {
// Cree et installe un security manager.
[Link](new
RMISecurityManager());
try {
// Cree un gestionnaire bancaire
[Link]("CardBank:
gestionnaire bancaire cree");
CreditManagerImpl cmi = new
CreditManagerImpl();
// enregistre ce gestionnaire bancaire
// dans le registre des objets disponibles.
[Link]("CardBank: bind le
gestionnaire");
[Link]("cardManager", cmi);
} catch (Exception e) {
[Link]();
[Link]([Link]());
}
}
}
XII-12 JMF
RMI le langage java
4°) Créer et compiler une
application serveur
(suite)
Il faut pour un serveur d'objet installé un
SecurityManager spécifique. Celui-ci est
donné par Java et on l'installe par :
[Link](new RMISecurityManager());
Pour rendre l'objet gestionnaire bancaire
disponible, il faut l'enregistrer dans le
"RMIregistry" (voir ci dessous). On lui
donne pour cela un nom et on l'enregistre
par la méthode statique
[Link]("cardManager", cmi);
Par la suite cet objet serveur bancaire sera
accessible par les autres machines en
indiquant la machine sur laquelle est
exécuté ce serveur et son nom (cf. ci
dessous).
Le premier argument de [Link]()
doit être :
rmi://nomServeurRMI:port/nom.
Par défaut nomServeurRMI est la machine
locale qui contient le serveur RMI et port
est 1099.
Cet "URL rmi" sera utilisé par les clients
pour interroger le serveur grâce à l'appel
[Link]().
On compile ce serveur par :
javac -d . [Link]
XII-13 JMF
RMI le langage java
5°) lancer le rmiregister
et lancer l'application
serveur
Il faut d'abord lancer le rmiregister puis le
serveur.
% rmiregister &
% java [Link]
Ce qui rend maintenant le serveur
disponible pour de futur clients.
Les sorties du serveur sont :
CardBank: gestionnaire bancaire cree
CardBank: bind le gestionnaire
XII-14 JMF
RMI le langage java
6°) Créer et compiler un
programme client qui
accède au serveur
Le programme doit être lancé par :
% java ClientBancaire serveurRMI
nomClient
package credit;
import [Link].*;
public class ClientBancaire{
public static void main(String args[]) {
CreditManager cm = null;
CreditCard account = null;
// verifie la ligne de commande
if ([Link] < 2) {
[Link]("Usage : ");
[Link]("java ClientBancaire
<server> <account name>");
[Link] (1);
}
// Cree et installe un security manager.
[Link](new
RMISecurityManager());
XII-15 JMF
RMI le langage java
// recupere une reference sur le
// gestionnaire bancaire distant.
try {
String url = new String ("rmi://" + args[0] +
"/cardManager");
[Link] ("ClientBancaire
recherche le gestionnaire bancaire a l' url = " +
url);
cm = (CreditManager)[Link](url);
} catch (Exception e) {
[Link]("Erreur a l'acces du
gestionnaire bancaire" + e);
}
// recupere le compte bancaire (distant)
// du client.
try {
account = [Link](args[1]);
[Link] ("recherche du compte
de " + args[1]);
} catch (Exception e) {
[Link]("Erreur a la recherche
du compte de " + args[1]);
}
XII-16 JMF
RMI le langage java
// effectue des transactions.
try {
[Link]("credit disponible : "
+ [Link]());
[Link]("Changement de
signature");
[Link](1234);
[Link]("un achat de 100 F");
[Link](100.00f, 1234);
[Link]("credit disponible : " +
[Link]());
[Link]("second achat de 160 F");
[Link](160.00f, 1234);
[Link]("credit disponible : "+
[Link]());
} catch (Exception e) {
[Link]("Erreur dans les
transactions pour " + args[1]);
}
[Link](0);
}
}
remarque :
le code ci dessus manipule les objets
distants comme s'ils étaient locaux.
Après avoir installé un security manager
RMI, le client recherche le serveur bancaire
distant par [Link](url) où url est
une "URL rmi" de la forme
rmi://machineDuServeurRMI:port/nomGest
ionnaireBancaire
Pour tester ce programme sur une seule
machine utiliser localhost comme
machineDuServeurRMI.
[Link]() retourne une référence
Remote qu'il faut nécessairement caster.
XII-17 JMF
RMI le langage java
7°) lancer ce client
par
% java ClientBancaire serveurRMI
nomClient
Bibliographie
[JDH] Java 1.1 developer's Handbook Philip
Heller, Simon Roberts ed Sybex.
Java client-serveur Cédric Nicolas et al.
collection fi-system ed Eyrolles
Remote Method Invocation Specification à :
[Link]
.1/docs/guide/rmi/spec/[Link]
XII-18 JMF