TP Applications Distribuées : mise en oeuvre en RMI



HARMONISATION

Mireille Blay-Fornarino
Annick Fron
Anne-Marie Pinna-Dery

Septembre 2008

Le but de ce TP est de mieux appréhender  la problématique de passage par valeur/ par référence.
Nous nous appuyons sur RMI pour mettre en oeuvre ces concepts.

Installation

Pour ce TP utilisez le JDK 1.6.
Vous pouvez utiliser eclipse avec le JDK 1.6 Il suffit de modifier éventuellement le paramètre de la JVM :

Menu Window/Preferences
Onglet Java/Installed JRES
et bouton "Add" pour ajouter une nouvelle version de Java

Liens utiles

Exercice pour débutant


Exercice pour débutantSi vous êtes vraiment débutant en Java et RMI, faire le TP suivant : Getting started with RMI  http://java.sun.com/javase/6/docs/technotes/guides/rmi/hello/hello-world.html
 

Exercice Préparatoire

Cet exercice a pour objectif de poser sur un exemple simple les concepts de fabrique et d'objets distants.
Définir une application telle que :

  1. Décider de votre architecture en prenant soin de séparer les codes d'implémentation des interfaces, le code du serveur, ...
  2. Implémenter votre application
  3. Tester la.
Si vous rencontrez des problèmes pour implémenter cette application, vous pouvez, après avoir évidemment essayé de l'implémenter seul, vous inspirez des codes suivants.

A la fin de cet exercice, vous devez savoir :
 - Décider d'une architecture distribuée : quelles sont les entités qui doivent être enregistrées auprès d'un serveur de nom, comment rendre une entité accessible à distance, quel est le rôle de la fabrique, quelle est la durée de vie d'une entité distribuée, ...

Une partie de cartes

Sur la base de l'exercice préparatoire précédent, fabriquez une partie de cartes : la bataille.
L'objectif est d'introduire la notion d'objets sérialisés.

A présent les joueurs ne choisissent plus un nombre au hasard mais une carte parmi un ensemble de cartes dont ils disposent :
- celui qui a la plus forte carte ramasse les cartes de tous les autres,
- si un joueur n'a plus de carte, il pioche et  si la pioche est vide, il ne joue plus.
- Pour simplifier, nous considérons que le gagnant est celui qui a toutes les cartes.

Vous pouvez reprendre pour vous aider le code d'un jeu de bataille écrit en non-distribué, vous n'avez plus qu'à le "distribuer" !

Tu me fends le coeur !

Notre objectif est de  pouvoir lancer le serveur de jeu  et chacun des joueurs sur des machines différentes.
Pour les utilisateurs d'eclipse, ceci se traduit par des projets différents, pour les autres par des répertoires différents.
Pour le tester, il y a deux modes :

 

1) Conception de l'application

Faites un schéma UML de l'application : Diagramme de classes et scénario.
Ce diagramme doit vous aider à comprendre le code existant.

a) Déterminez d'abord la nature de chacune des classes d'implémentation pour pouvoir la distribuer :

b) Posez vous les questions suivantes :

2) Plan de déploiement

Déterminez ensuite combien vous allez utiliser de rmiregistry, ainsi que leur localisation sur les différentes machines et le nombre d'objets à y stocker, ainsi que leur nommage.
Déterminez quelles classes doivent être déployées sur chaque répertoire : pour le serveur de jeu et pour chacun des joueurs.

3) Implémentation

Implémentez alors les classes supplémentaires ou modifiez les classes existantes, et écrivez une courte notice de jeu permettant à un joueur de se connecter et de jouer.

Notes :

4) Chasse aux tricheurs

A présent, on fait la chasse aux tricheurs. Est-il possible de vérifier avant chaque tour de jeu qu'on n'a pas plus de quatre
as dans le jeu ? Serait-il possible à un joueur de créer une carte à l'insu du serveur de jeu ?

5) Liste partagée

Un joueur peut-il s'inscrire en cours de partie ? Quelles sont les conséquences ?

6) Variables statiques

Si dans la classe Carte, vous initialisez les constantes statiques par code et non dans la déclaration,
ces valeurs seront-elles transmises aux joueurs ?

7) Pioche

Comment faire pour qu' à présent chaque fois qu'un joueur n'a plus de carte il puisse piocher une carte
a) en passant par le jeu
b) en accédant directement à la pioche

8) Carte NULL : amélioration du code

Que pensez-vous des comparaisons avec une CARTE_NULL ?
a) pourquoi .equals ne peut pas fonctionner à distance?
b) comment pourriez-vous pallier cet inconvénient et rendre le code plus propre?

9) Synchronisation des joueurs

A quoi sert la classe : TesterBatailleServeur (à renommer!!!!)
pourquoi introduire une attente dans le lanceur du jeu de bataille ?
Quel probleme voyez-vous à lancer en même temps plusieurs fois TesterBatailleServeur

10) Si vous peinez trop
Vous pouvez vous reporter aux éléments de corrections suivants


Erreurs fréquentes

  java.rmi.ServerException: RemoteException
occurred in server ...
java.rmi.UnmarshalException: error
unmarshalling ...
java.lang.ClassNotFoundException:

Le stub est bien accessible au serveur MAIS PAS AU rmiregistry
 se traduit par
java.net.ConnectException

se traduit par :
HelloImpl.java:20: unreported exception java.rmi.RemoteException in default constructor
public class HelloImpl extends UnicastRemoteObject implements Hello {
       ^
se traduit par :
java.rmi.server.ExportException: Port already in use: 1099
On peut lancer un autre registry mais sur un autre port.

S'il n'hérite pas de UnicastRemoteObject, il n'est pas Remote donc on lui demande d'être Serializable ...
Trouble: java.rmi.MarshalException: error marshalling arguments; nested 
exception is:
         java.io.NotSerializableException: CalculatorImpl

Elements de correction

Fichier descriptif
Code de la bataille Distribuée
Code ServeurDeBataille
CodeServeurDeJoueur

Version avec répertoires séparés
entites
jeu
joueur
serveur de jeu
serveur de joueur