Master 2 TIW - Intergiciels et Services
Middlewares d'objets distribués - RMI
Objectifs pédagogiques
Comprendre et mettre en œuvre les principes fondamentaux de la communication entre objets dans des infrastructures distribuées.
Ressources
Pour la deuxième partie (implémentation de votre TP conteneur en RMI), vous pouvez vous inspirer du tutoriel sur RMI d'Oracle pour Java 8.
Mise en route
Lancement du client
Pour commencer, vous allez démarrer sur une application de type "Hello World" toute simple dont vous récupérerez le client et le serveur (dans lequel se trouve l'interface distante hello.Hello) sur le projet https://forge.univ-lyon1.fr/LIONEL.MEDINI/TP_RMI_TIW1_2017_base.
Dans un premier temps, vous allez générer un jar contenant l'interface du serveur et la passer au client. Vous la trouverez dans le répertoire Projet_serveur/hello.
- Placez-vous à la racine du projet serveur, et lancez les commandes javac hello/*.java et jar cvf hello.jar hello\*.class
- copiez le jar généré à la racine de votre projet client
Ensuite, vous allez réaliser un client RMI pour interface :
- Compilez les sources du client en ligne de commande avec javac.
Rappel : vous devrez faire cela depuis le répertoire où vous avez décompressé le package et utiliser des slash entre nom de package et nom de fichiers java.
- Le fichier client.policy doit être dans le répertoire au dessus de votre package client (Projet_client)
- Lancez le client (le serveur doit déjà tourner sur une machine dont l'adresse IP vous a été indiquée) et vérifiez qu'il est capable d'interroger ce serveur.
La syntaxe est la suivante :
java -cp .\hello.jar;. -Djava.rmi.server.codebase=file:./ -Djava.security.policy=client.policy client.Client 192.168.1.38,
où :
- l'argument classpath permet au client d'accéder à l'interface (Java) du serveur
- l'argument codebase permet d'accéder au répertoire de base du code à exécuter (ici, le client)
- l'argument policy permet d'accéder au fichier des propriétés liées à la sécurité (côté client)
- le dernier argument est passé au Main et est l'adresse IP de la machine où tourne le serveur de noms JNDI.
TP du 19/10/2016 : remplacez l'adresse IP de l'annuaire JNDI par la suivante : 134.214.88.178. Récupérez l'interface ici et collez-la à la racine de votre répertoire client.
Lancement du serveur
Allez ensuite dans le répertoire serveur du projet.
- De la même façon, compilez en ligne de commande et assurez-vous que le fichier serveur.policy est bien localisé dans le répertoire au-dessus du package serveur (Projet_serveur).
- Faites ensuite tourner le serveur avec la commande suivante :
java -cp .\hello.jar;. -Djava.rmi.server.codebase=file:./hello.jar
-Djava.rmi.server.hostname=127.0.0.1
-Djava.security.policy=server.policy serveur.Serveur,
où le codebase est le répertoire dans lequel est situé le package Java que vous avez compilé (ici : Projet_serveur) et l'option hostname permet d'indiquer au serveur de votre application l'adresse IP de la machine hébergeant le serveur JNDI que le stub doit interroger pour faire le bind (port par défaut : 1099).
Important:
- l'annuaire JNDI rmiregistry doit être lancé depuis le répertoire de votre projet serveur
- il doit impérativement y avoir un slash à la fin de l'argument de l'option -Djava.rmi.server.codebase
De la même manière, testez le client pour qu'il appelle le serveur sur votre machine locale.
Sécurisation
Utilisez les informations situées ici pour faire en sorte que seuls les fichiers situés dans vos répertoires client et serveur soient accessibles par le serveur JNDI.
Modification de l'interface
Enfin, modifiez le servant (l'interface Hello et sa classe d'implémentation) pour que la méthode sayHello prenne en entrée deux paramètres (un nom et un entier), et qu'elle dise autant de fois bonjour que l'entier le lui indique.
Utilisation dans Eclipse
Il peut arriver qu'un client ou un serveur tourne correctement dans Eclipse. Pour cela, une méthode qui a fonctionné est de créer le projet et la structure des packages à la main et de glisser-déposer les classes et interfaces dans l'explorateur de projet. Une fois que le code Java est correctement intégré dans le projet, il faut créer une Run Configuration :
- Onglet "Main" : sélectionner le projet et cliquer ensuite sur "Search" pour sélectionner la classe contenant le Main. Si Eclipse ne vous propose rien, essayez l'une des 3 solutions suivantes : redémarrez Eclipse / recréez un nouveau projet / abandonnez.
- Si vous avez réussi à sélectionner votre classe Main, passez à l'onglet "Arguments" :
- le champ "Program arguments" correspond aux arguments passés au Main (i.e. l'adresse IP du serveur JNDI pour le client)
- le champ "VM arguments" correspond à ceux passés à l'exécutable Java (i.e. les options qui commencent par "-D").
Une fois la configuration créée et appliquée, testez-la. Si Eclipse est incapable de trouver votre classe Main, essayez l'une des 3 solutions ci-dessus... Remarque : vous n'aurez pas tout perdu, Eclipse est au moins capable de compiler votre code Java.
N'oubliez pas que de toutes façons, il faut compiler et packager les interfaces du servant avec jar.
Conception : reprise du TP conteneur
Reprenez une version fonctionnelle de votre application d'agenda, décomposée en 4 parties (Main, Annuaire, Serveur, Client). Par exemple, celle issue de la question 0, mais si vous avez la version de la question 2.2 (uniformisation, cela vous simplifiera la tâche).
Dans votre projet Repertoire du TP 2 :
- supprimez le main de l'application
- faites deux projets séparés pour le serveur et le client (ne tenez plus compte de votre annuaire)
- si vous ne l'avez pas, faites en sorte d'extraire une interface commune aux quatre objets agendas
- dans le serveur, modifiez le code source pour qu'il récupère une référence sur le serveur de noms et qu'il y enregistre quatre objets, représentant les composants qui implémentent les méthodes add, remove, list et init,
- modifiez le source du client pour qu'il envoie ses requêtes au serveur de noms,
- faites tourner séparément client et serveur, après avoir lancé le serveur de noms.