RMI

publicité
Lods
RMI
RMI (Remote Method Invocation) est une API fournissant une approche de haut niveau de la
programmation distribuée. On peut ainsi invoquer des méthodes d'un objet distant (résidant
sur un serveur) de la même manière que l'on appelle les méthodes d'un objet local. Cette API
est présente dans le JDK standard depuis la version 1.1 et a été améliorée dans la version 1.2.
Développé pour permettre l’appel de méthodes entre objets Java s’exécutant dans des VM
différentes.
Si cette API est simple à mettre en oeuvre pour le développeur, elle implique que le serveur
(dans lequel résident les objets distribués) et les clients soient écrits en Java. Cette situation
est cependant maintenant assez commune pour que la mise en oeuvre de RMI soit
envisageable. Si ce n'est pas le cas, on préférera se tourner vers une solution qui puisse être
implémentée dans d'autres langages, comme CORBA.
Stub et Skeleton
Stub
==> Client  applet et l’interface
Skeleton
==> Serveur  driver InterClient pour se connecter à la B.D. et l’interface et
son implémentation
Connaissance Java :
Pour concevoir une application RMI, il faut connaître les principaux mécanismes,
instanciation et utilisation des objets. Pour qu’un objet puisse être utilisé en RMI, il faut qu’il
soit sérialisable, c’est-à-dire implémenter l’interface java.io.Serializable. Dans les cas
complexes, on doit coder les méthodes readObjects et writeObject, pour permettre un
transport plus approprié.
Interface :
Dans un premier temps on doit savoir la ou les méthodes que l’on veut distribuées. Comme le
client doit aussi connaître ces méthodes pour pouvoir les appeler, on crée une interface qui va
être partagée entre le client et le serveur. Ce dernier implémentant cette interface.
Exemple :
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface JCustomer extends Remote
{
public String getCustomerName(String customerID) throws RemoteException;
}
Lods
Le serveur met à disposition des clients la méthode leur permettant la recherche du nom
Note : Objet Integer et non int ->int n’est pas un objet et donc pas sérialisable !!!!
La méthode rebind permet de faire connaître le serveur au système d’enregistrement et de
sécurité
Stub et Skeleton
Pour que le client puisse utiliser l’objet distribué, il faut créer un petit bout de code permettant
le lien entre l’interface et l’objet distant.
Lorsque le serveur crée un objet distribué, il ne fait pas vraiment de connexion direct avec ses
clients, il utilise un autre serveur qui lui est sécurisé (enfin presque)
Pour que le serveur puisse effectuer le lien entre l’objet distribué et l’enregistreur de serveur,
il faut une classe, c’est le rôle de la classe …_Skel.class
Le transport des appels est géré par RMI à travers un couple de programmes jouant le rôle
d’adaptateurs -> Stub / Skeleton.
En fait lorsqu’un client effectue un appel à l’objet distant, il réalise un appel classique dans le
code du stub, ce dernier intégrant tout le code nécessaire au transport de l’appel vers le
serveur.
Le Skeleton, quant à lui, définit l’infrastructure nécessaire à la prise en charge des appels côté
serveur.
Stub et Skeleton : réalisent les appels sur la couche réseau et se chargent de l’empaquetage et
du dépaquetage des paramètres des méthodes (marshalling et démarshalling)
Avant de pouvoir effectuer un appel de méthode sur un objet RMI, le client devra obtenir une
référence initiale. Vous obtiendrez généralement cette référence à travers l’annuaire RMI
L’attachement d’un client à un objet RMI s’effectuera à l’aide d’une adresse au format
suivant :
Rmi://NomServeur/NomDeLObjetRmi
La sérialisation :
RMI utilise la sérialisation afin de transporter les références d’objets entre clients et serveurs.
La sérialisation est un mécanisme Java permettant la persistance des objets. Un objet est
sérialisé lorsque son état est sauvegardé vers un dispositif de stockage quelconque et
désérialisé par une opération de relecture de l’objet dans un flux et construction de l’instance
mémoire correspondante.  java.io.Serializable
Page 686
Lods
[Mes prises de notes
Middleware -> P. 680 -> tolérance panne -> équilibrage machine
RMI -> 100 % JAVA -> différent avec CORBA utilise plusieurs langages
RMI utilise directement les sockets
Objet serveur
|
interface
|
objets client
Lire le tutorial sur streamable dataSet]
RMI ou Remote Method Invocation permet de créer des applications java-à-java distribuées,
dans lesquelles les méthodes des objets java distants peuvent être appelées depuis des
machines virtuelles java et sur différents hôtes. Un programme java peut effectuer un appel
sur un objet distant lorsqu’il obtient la référence de l’objet distant, soit en recherchant l’objet
distant dans le service d’annuaire d’amorce fourni par RMI, soit n recevant la référence sous
forme d’argument ou de valeur de retour.
RMI utilise la sérialisation d’objets pour le marshalling et le dé-marshalling des paramètres, il
ne tronque pas les types, et supporte un véritable polymorphisme orienté objet.
Dans le langage de programmation Java un objet distant est une instance d’une classe
qui implémente une interface distante. Votre interface distante déclarera chacune des
méthodes que vous souhaitez appeler à distance. Les interfaces distantes ont les
caractéristiques suivantes :
-
L’interface distante doit être déclarée publique -> sinon les clients provoque
une erreur lorsqu’ils tentent de charger un objet distant implémentant
l’interface distante.
-
L’interface distante étend l’interface java.rmi.Remote
-
Chaque méthode dit déclarer java.rmi.RemoteException (ou une superclasse de
RemoteException) dans sa clause throws, en plus des exceptions propres à
l’application
-
Le type de données de tout objet distant transmis sous forme d’argument ou de
valeurs de retour doit être déclaré en tant que type interface distante et non en
tant que classe d’implémentation.
Comme l’invocation des méthodes distantes peut échouer de manière très différente de
l’invocation des méthodes locales, les méthodes distantes signalent les échecs de
communication en déclenchant une exception java.rmi.RemoteException
Au minimum, la classe d’implémentation d’un objet distant doit :
-
Implémenter une interface distante
Définir le constructeur de l’objet distant
Lods
-
Fournir des implémentations pour les méthodes pouvant être appelées à
distance.
Dans ce contexte, une classe « serveur » est une classe ayant une méthode main qui crée une
instance de l’implémentation de l’objet distant , et qui lie cette instance à un nom dans le
registre RMI.
-
créer et installer un gestionnaire de sécurité
Créer une ou plusieurs instances d’un objet distant
Recenser l’objet distant
Implémenter une interface distante :
Dans le langage Java, lorsqu’une classe déclare qu’elle implémente une interface, un contrat
est passé entre la classe et le compilateur. Parc e contrat, la classe garantit qu’elle fournira le
corps des méthodes, ou définition, pour chacune des signatures des méthodes déclarées dans
l’interface qu’elle implémente. Les méthode d’interface sont implicitement public et abstract,
ainsi si la classe d’implémentation ne remplit pas son contrat, elle devient par définition une
classe abstraite et le compilateur signalera ce point si la classe n’a pas été déclarée abstract.
Lorsqu’un objet RMI publie une interface, il définit les signatures d’un ensemble de méthodes
et seules ces méthodes sont accessibles par le client.
La classe d’implémentation déclare la ou les interfaces distantes qu’elle implémente
public class HelloImpl extends UnicastRemoteObject
implements Hello {
Le constructeur d’une classe distante procure les mêmes fonctionnalités que le constructeur
d’une classe non distante : il initialise les variables de chaque nouvelle instance de la classe et
renvoie une instance de la classe au programme ayant appelé le constructeur.
En outre, votre instante d’objet distant a besoin d’être « exportée ».
Exporter un objet distant le rend capable d’accepter les demandes entrantes des
méthodes distantes en écoutant s’il existe des appels entrant pour l’objet distant sur un
port anonyme. Lorsque vous étendez java.rmi.UnicastReloteObject ou
java.rmi.activation.Activable, votre classe sera automatiquement exportée à la création.
public HelloImpl(String s) throws RemoteException {
super(); }
Lods
comme l’exportation de l’objet peut déclencher une excepttion
java.rmi.RemoteException, vous devez définir un constructeur qui déclenche une
RemoteException, même s’il ne fait rien d’autre.
EN RESUME : La classe d’implémentation d’un objet distant doit :
-
Implémenter une interface distante
Exporter l’objet afin qu’il puisse accepter les appels entrants aux méthodes
distantes
Déclarer son ou ses constructeurs pour, au moins, déclencher une
java.rmi.RemoteException
 L’appel de la méthode super() ; invoque un constructeur sans argument de
java.rmi.unicastRemoteObject, qui exporte l’objet distant.
Fournir une implémentation pour chaque méthode distante
L’implémentation de classe d’un objet distant contient le code qui implémente chaque
méthode spécifiée dans l’interface distante.
Les objets distants sont transmis par référence. La référence à un objet distant est en fait une
référence à un Stub, qui est un Proxy côté client pour l’objet distant
La méthode main du serveur doit d’abord créer et installer un gestionnaire de sécurité : le
RMISecurityManager :
If (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
Un gestionnaire de sécurité doit être exécuté pour garantir que les classes chargées
n’effectuent pas d’opérations non autorisées. Si aucun gestionnaire de sécurité n’est spécifié
aucun chargement de classe par les clients et serveurs RMI n’est autorisé
Créer une ou plusieurs instances d’un objet distant
La méthode main du serveur doit créer une ou plusieurs instances de l’implémentation de
l’objet distant qui fournit le service.
HelloImpl obj = new HelloImpl() ;
Lods
Le constructeur exporte l’objet distant, ce qui signifie qu’une fois crée, l’objet distant est prêt
à accepter les appels entrants.
Recensement de l’objet distant
Pour qu’un appelant (un client, un pair ou une applet) soit en mesure d’appeler une méthode
sur un objet distant, il doit d’abord obtenir la référence de l’objet distant.
RMI fournit un registre d’objet distant qui vous permet de lier un nom de type url sous la
forme //host/nom_d’objet à l’objet distant, où nom_d’objet est un nom de chaîne.
Le registre RMI est un simple serveur de noms côté serveur qui permet aux clients distants
d’obtenir la référence à un objet distant.
Par exemple : le code suivant lie le nom « HelloServer » à une référence de l’objet distant
Naming.rebind(« //localhost/HelloServer »,obj) ;
Le premier paramètre est une java.lang.String de format URL, représentant l’emplacement et
le nom de l’objet distant
Le second paramètre est la référence à l’implémentation de l’objet sur laquelle les méthodes
distantes seront appelées
Le runtime de RMI remplace une référence au stub de l’objet distant par la référence de
l’objet distant spécifié par l’argument obj.
Obtient la référence à l’implémentation de l’objet distant (« HelloServer ») depuis le registre
RMI de l’hôte serveur. Comme la méthode Naming.rebind, la méthode Naming.lookup utilise
une java.lang.string au format URL.
Naming.lookup prend en charge les tâches suivantes :
-
construit une instance du stub registre (pour contacter le registre du serveur) en
utilisant le nom d’hôte et le numéro de port fournis en arguments de
Naming.lookup
-
Utilise le stub registre pour appeler la méthode lookup sur le registre, en
utilisant le composant nom de l’URL (« HelloServer »)
o Le registre renvoie l’instance HelloImpl_Stub liée à ce nom
o Reçoit l’instance du stub de l’implémentation de l’objet distant (HelloImpl)
et charge la classe stub -> CLASSPATH
-
Naming.lookup renvoie le stub à son appelant (HelloApplet)
Lods
L’applet invoque la méthode sayHello distante sur l’objet distant du serveur.
-
RMI sérialise et renvoie la chaîne « Hello World »
RMI désérialise la chaîne et la stocke dans une variable appelée message
La chaîne URL construite passée en paramètre à la méthode Naming.lookup doit inclure le
nom d’hôte du serveur. Sinon c’est le client qui est utilisé par défaut et provoque des
problèmes avec le gestionnaire de sécurité.
Création du fichier policy.txt
Compilation des fichiers sources .java -> pour créer des fichiers .class ainsi que des stubs et
des squelettes.
Un stub est le Proxy côté client d’un objet distant, qui fait suivre les appels RMI au répartiteur
(squelette) côté serveur, qui fait suivre à son tour l’appel à l’implémentation de l’objet distant.
Applications RMI sont souvent compris en 2 programmes séparés -> serveur / client. Un
serveur qui crée les objets distants et qui les rends accessibles par référence et attend que les
clients invoquent les méthodes de ses objets distants.
Un client -> obtient référence objet distant du serveur ou plusieurs et invoque les méthodes
 utilisé le rmiregistry pour obtenir les références aux objets distants
Le serveur -> main -> crée instance objet distant -> implémente l’interface -> crée le
gestionnaire de sécurité et fini avec un petit Naming.bin (« … »,obj)  référence ->
référence d’un objet distant est un stub dans le côté client  avant qu’un client puisse
invoquer une méthode sur un objet distant, il doit d’abord obtenir une référence à cette objet
distant -> RMIRegistry -> serveur de nom -> permet au client de recevoir une référence à
l’objet distant.
Constructeur -> super() ; -> aller dans le truc unicast -> écoute des appels des clients ///
Le client utilise la méthode Naming.lookup -> pour chercher l’objet distant avec la référence
dans le registre de l’hôte distant  vers le RMIRegistry -> récupérer la référence et pouvoir
faire des appels sur le serveur
Lods
Résolution de L’exercice  Inspiré du cours ->
http://flenu.ise-mons.be/jbuilder6/pdf/database.pdf
Téléchargement