[Java] - Remote et Observable

- Remote et Observable [Java] - Programmation

Marsh Posté le 14-02-2002 à 17:41:32    

Les habitués de Java doivent connaître le problème : pas d'héritage multiple en Java. Bien. Voilà mon problème je veux créer une classe Jeu qui hérite de Remote et de Observable. Jusqu'à présent j'ai pondu un petit source, mais plus j'avance et moins l'issue m'apparait certaine... Bref je pense que ce que suis en train de faire de va pas marcher. Alors, j'aimerais savoir si l'un d'entre vous s'est déjà frotté aux patterns Observable/Observer dans sa vie de programmeur et si il y a une manière standard de procéder, parce que là j'ai vraiment l'impression d'avancer dans une jungle qui s'épaissit au fur et à mesure que je mets des lignes de code.


---------------
Le site de ma maman
Reply

Marsh Posté le 14-02-2002 à 17:41:32   

Reply

Marsh Posté le 14-02-2002 à 18:01:56    

Il suffit qu'observable soit une interface et tu pourras l'hériter sans problème. Je ne comprends pas vraiment le probleme et je crois d'ailleurs que tu n'as pas compris le pattern observeur / observé.
 
Bon tu as un serveur c'est la classe Serveur
 
tu as des clients c'est la classe Client
 
Si je me souviens bien tu voudrais bien que lorsqu'un client se connecte, il recoive une nouvelle liste de clients (juste)?
 
bon alors on fait comme ca
 

Code :
  1. public interface ClientCallback {
  2.    public clientLists(Client[] clients);
  3. }


 
Voici l'interface que ton client doit implémenter quelque part (un objet quelconque).
 
Voici le code de ton Objet distant SERVEUR permettant de te connecter.

Code :
  1. public class Serveur implements blablab (ce que tu veux) {
  2.    public void connect(ClientCallback callBackInterface, // autres infos comme par exemple le nom du client, etc.) {
  3.     // la tu ajoutes l'interface de callback dans ta liste de callback et ensuite pour tous les éléments de cette liste de callback tu appelles clientLists(TaListeDeClientMiseAJour);
  4. }


 
où est le problème?


---------------
What is popular is not always right, what is right is not always popular :D
Reply

Marsh Posté le 14-02-2002 à 18:04:13    

je savais pas que le java ressemblait autant au C que ça !!!
 
@++ et désolé de déranger


---------------
Visitez mon site : http://www.jujubarbare.linux-fan.com
Reply

Marsh Posté le 14-02-2002 à 18:06:55    

juju_le_barbare a écrit a écrit :

je savais pas que le java ressemblait autant au C que ça !!!
 
@++ et désolé de déranger  




 
tu n'as vu que des déclarations de méthodes c'est un peu juste pour comparer :D


---------------
What is popular is not always right, what is right is not always popular :D
Reply

Marsh Posté le 14-02-2002 à 18:09:58    

darklord22 a écrit a écrit :

 
 
tu n'as vu que des déclarations de méthodes c'est un peu juste pour comparer :D  




 
J'ai déjà vu des sources java. C'est seulement maintenant que la question métaphysique s'est imposée à moi ... Le java ressemble-t-il donc tellement que ça au C ???


---------------
Visitez mon site : http://www.jujubarbare.linux-fan.com
Reply

Marsh Posté le 14-02-2002 à 18:27:52    

juju_le_barbare a écrit a écrit :

 
Le java ressemble-t-il donc tellement que ça au C ???  



non


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 14-02-2002 à 18:31:32    

cherytree > je t'avais tout bien expliqué dans le post d'avant :(
 
je comprend pas ton problème d'héritage multiple ... tu n'as besoin d'hériter que de Remote.
Ne te sers surtour pas des classes java.util.Observable et java.util.Observer, ca ne sert à rien !
 
et puis ce pattern est pas complexe : c'est super logique. De toute façon y a pas beaucoup d'autres moyen que ca pour régler ce genre de problème.
 
Le principe c'est juste qu'un objet stocke une liste d'objet qu'il va prévenir lorsqu'il se passe quelque chose.
 
présente un peu les objets que tu compte mettre en place qu'on puisse mieux t'aiguiller !


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 14-02-2002 à 18:33:57    

darklord22 > Comme tu l'as justement deviné je suis toujours sur mon problème de liste de Clients. Comment dire... J'ai un peu spécifié mon appli (un jeu de tennis-pong au choix) il me semble judicieux d'avoir un objet Game (ou jeu, peu importe) qui contiendra l'état du jeu : en pause, en attente de connection, partie terminée... et le score courant. Je veux comme toujours que chaque réactualisation du score ou de l'état du jeu déclenche la mise à jour de ces valeurs dans les clients. Donc je me disais qu'en mettant l'objet en Remote et en Observable, et en déclarant les clients (ou un objet des clients) Observer, j'aurai mes réactualisations...
 
Bien. Ceci étant, je n'ai jamais fait d'héritage multiple. Donc j'ai passé l'après-midi à chercher des choses sur le net (bon sang déjà 6h !) et devant mon compilo, et je me perds, je peine à spécifier mes besoins ; qui doit avoir la main sur quoi. Et de plus j'affronte les 2 problèmes en même temps : héritage multiple et callback.


---------------
Le site de ma maman
Reply

Marsh Posté le 14-02-2002 à 18:38:17    

Cherrytree a écrit a écrit :

Et de plus j'affronte les 2 problèmes en même temps : héritage multiple et callback.  




call back ??? :??:
j'ai l'impression que tu te pose des problèmes pour rien !
bon je vais essayer de me remettre à RMI pour te montrer un exemple de ce pattern qui marche ...


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 14-02-2002 à 18:41:42    

benou > Je pensais que c'était bon ça Observer/Observable. Je jète alors ?
:( :cry: Désolé les gars, j'ai pensé bien faire en cherchant ce truc sur le pattern Observer/Observable (il me semble que c'est benou qui l'a écrit quelque part) et ça m'a pris toute l'attention. Du coup j'ai cherché par tous les moyens à interfacer les deux, perdant de vue les bons conseils que vous m'aviez prodigué, et échouant lamentablement dans mon entreprise.
 
Mais je vais me ressaisir et arrêter de repousser le moment où je vais devoir mettre en place. J'y mettrais le temps qu'il faudra. :jap: :p


---------------
Le site de ma maman
Reply

Marsh Posté le 14-02-2002 à 18:41:42   

Reply

Marsh Posté le 14-02-2002 à 18:42:59    

benou a écrit a écrit :

 
call back ??? :??:
j'ai l'impression que tu te pose des problèmes pour rien !
bon je vais essayer de me remettre à RMI pour te montrer un exemple de ce pattern qui marche ...  




 
Je ne veux pas que tu perdes ton temps. Vous m'en avez déjà consacré tant. :jap:


---------------
Le site de ma maman
Reply

Marsh Posté le 14-02-2002 à 18:51:39    

Voilà mon travail de l'après-midi. J'ai fait ce que j'ai pu avec ce que j'avais sous la main (internet et des bouquins, quoi) je me suis grassement inspiré d'un exemple d'un site web qui montrait une manière de faire de l'héritage multiple et du Remote. Pour l'instant c'est sensé gérer un Vector de Gamers (module de connexion chez client).
 
La méthode update de Gamer est délibérément vide. C'est juste une méthode qui sert à appeler le client pour voir s'il est encore là. C'est pour ça qu'elle throws RemoteException.
 
//Constants.java
public interface Constants {
    int WAIT = 0;
    int START = 1;
    int PAUSE = 2;
    int RESUME = 3;
    int STOP = 4;
}
 
//Gamer.java
import java.rmi.*;
 
public interface Gamer extends Remote {
    public void update() throws RemoteException;
}
 
//Game.java
import java.rmi.*;
 
public interface Game extends Remote {
    public void addGamer(Gamer g) throws RemoteException;
    public void removeGamer(Gamer g) throws RemoteException;
    public void removeAllGamers() throws RemoteException;
}
 
//BasicGame.java
import java.rmi.*;
import java.util.*;
 
public class BasicGame implements Constants, Game {
     
    protected Vector gamers = new Vector();
     
    protected int state = WAIT;
     
    public void addGamer(Gamer g) {
        gamers.addElement(g);
    }
     
    public void removeGamer(Gamer g) {
        gamers.removeElement(g);
    }
     
    public void removeAllGamers() {
        gamers.removeAllElements();
    }
     
    public void notifyGamers() {
        Vector deadGamers = null;
        Enumeration enum = gamers.elements();
        while (enum.hasMoreElements()) {
            Gamer g = (Gamer) enum.nextElement();
            try {
                g.update();
            }
            catch (ConnectException e) {
                if (deadGamers == null)
                    deadGamers = new Vector();
                deadGamers.addElement(g);
            }
            catch (NoSuchObjectException e){
                if (deadGamers == null)
                    deadGamers = new Vector();
                deadGamers.addElement(g);
            }
            catch (RemoteException e) {
            }
        }
        if (deadGamers != null) {
            enum = deadGamers.elements();
            while (enum.hasMoreElements()) {
                Gamer g = (Gamer) enum.nextElement();
                removeGamer(g);
            }
        }
    }
}
 
//TheGame.java
import java.rmi.*;
import java.util.*;
 
public class TheGame extends Observable implements Constants, Game {
     
    BasicGame game = new BasicGame();
     
    public void addGamer(Gamer g) throws RemoteException {
        game.addGamer(g);
    }
     
    public void removeGamer(Gamer g) throws RemoteException {
        game.removeGamer(g);
    }
     
    public void removeAllGamers() throws RemoteException {
        game.removeAllGamers();
    }
}
 
Voilà. A noter que l'entier "state" qui peut prendre les valeurs spécifiées dans Constants n'est pas implémenté. Au moment d'écrire le code pour state, l'état du jeu (pause, reprise...), je n'ai pas su où le mettre.

 

[jfdsdjhfuetppo]--Message édité par Cherrytree--[/jfdsdjhfuetppo]


---------------
Le site de ma maman
Reply

Marsh Posté le 14-02-2002 à 18:57:11    

Cherrytree a écrit a écrit :

benou > Je pensais que c'était bon ça Observer/Observable. Je jète alors ?




ben c'est le design patern que tu dois utiliser, mais ca ne sert à rien de vouloir réutiliser les classes Java qui implémente ce pattern : c'est tellement simple que tu peux le faire tout ceul ...
je t'avais parlé de ces classes juste pour te montrer un exemple ... désolé, je pensais pas que tu le prendrais à la lettre  
 
je reposte un truc que j'avais écrit dans l'autre post parce qu'il y a vraiment tout dedans  :  

Citation :

Résumons. Tu veux que tes clients recçoivent la liste des autres joueurs connectés au serveur, et que celles-ci se mette à jour lorsqu'un nouveau joueur se connecte.
 
Dans ce problème, l'objet Observé est le serveur, qui contient la liste des clients. Les clients sont les observeurs : ils observent une modification du serveur (un nouveau joueur se connecte).
 
Pour être au courant des évenements du serveur, les clients vont devoir s'abonner au serveur. Il faut donc qu'il y ait une méthode d'abonnement sur ton objet serveur, et que le serveur gère une liste des clients abonnés. :
 
 
 
import java.util.*;
 
public class Serveur {
 protected Collection clientsAbonnes = new ArrayList();
 ...  
 public abonner(Client client) {
    clientsAbonnes.add(client);
 }
 ...
}
 
remarque : pour faire propre il faudrait aussi gérer les désabonnement, mais bon ...    
 
On va dire que ton Client possède une méthode qui lui permet de remettre  jour la liste des joueur connectés :
 
 
public class Client {
  ...
  public void mettreAJourListeJoueurs(String[] joueurs) {
      ...
  }
  ...
}
 
 
ce qu'il suffit ensuite de faire c'est que lorsque le Serveur reçoit une nouvelle connection d'un de tes clients, il met à jour sa liste interne de joueurs puis la diffuse à tous les clients abonnés.
 
 
 
  ...
  Iterator it = clientsAbonnes.iterator();
  while (it.hasNext()) {
     ((Client)it.next()).mettreAJourListeJoueurs(listeInterneDeJoueurs);
  }
  ...


 
il me vient à l'idée que tu sais peut-être pas ce qu'est un design pattern ...
c'est une façon de régler des problème habituels. En programation, on est souvent amener à rencontrer les mêmes problèmes, et donc à utiliser les mêmes solutions.
 
Des gens on "normalisé" ou plutot identifier ces solutions. Ce sont les design-patern. En fait c'est juste un nom qu'on met sur une façon de programmer quelque chose. Comme ca, quand on dit à quelqu'un ou dans une doc qu'on a utilisé tel design-pattern, tout le monde comprend de quel façon on a résolu le problème : ca aide pour lire le code.
Ca permet de se coser entre programmeur, koi ... :)
 
En pratique, on utilise tous les jours des tas de design patterns sans s'en rendre compte ... (ex : le design pattern proxy)


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 14-02-2002 à 18:58:52    

Cherrytree a écrit a écrit :

 
Je ne veux pas que tu perdes ton temps. Vous m'en avez déjà consacré tant. :jap:  




bha t'inquiète pas : si je te le propose c'est que j'ai le temps (pauvre célibataire que je suis un 14 février :().
et puis ca me fera une bonne révision sur le RMI (j'en ai bien besoin !!!)
 
edit : je fais ca ce soir ....

 

[jfdsdjhfuetppo]--Message édité par benou--[/jfdsdjhfuetppo]


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 14-02-2002 à 19:18:20    

Merci beaucoup benou, tu es un ami.


---------------
Le site de ma maman
Reply

Marsh Posté le 14-02-2002 à 23:46:29    

ayé !
ca compile, ca execute, ca marche ! :)
 
attention voila les sources :  
 
Client.java

Citation :


package jeu;
 
import java.rmi.*;
import java.util.*;
 
public interface Client extends Remote {
    // ici, il faut définir toutes les méthodes que le serveur doit pouvoir appeler
 
    public String getName () throws RemoteException;
    public void informerListeClients(Collection clients) throws RemoteException;
}


 
ClientImple.java

Citation :


package jeu;
 
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
 
public class ClientImpl  
    extends UnicastRemoteObject  
    implements Client {
 
    protected String name;
    protected Serveur serveur;
 
    // constructeur obligatoire
    public ClientImpl(String name) throws RemoteException {
 this.name = name;  
    }  
 
    public String getName () throws RemoteException {
 return name;
    }
 
    public void informerListeClients(Collection clients) throws RemoteException {
 Iterator it = clients.iterator();
 System.out.println("liste des clients connectés : " );
 while (it.hasNext()) {
     System.out.println(" - " + it.next());
 }  
    }
 
 
    protected void connecter() throws Exception {
 try {
     serveur = (Serveur) Naming.lookup("//localhost/Serveur" );
 } catch(Exception e) {
     System.err.println("Impossible de trouver le serveur" );
     throw e;
 }
 try {
     serveur.connecter(this);
 } catch(RemoteException e) {
     System.err.println("Impossible de se connecter au serveur" );
     throw e;
 }
 
    }
 
    protected void deConnecter() throws RemoteException {
 try {
     serveur.deConnecter(this);
 } catch(RemoteException e) {
     System.err.println("Impossible de se déconnecter du serveur" );
     throw e;
 }
    }
 
 
    public static void main(String[] args) throws Exception {
 if ((args.length==0) || (args[0].equals("-?" ))) {
     System.err.println("usage : \n java jeu.ClientImpl nomDuClient\n" );      
 }
 String name = args[0];
 ClientImpl client = new ClientImpl(name);
 
 client.connecter();
 System.out.println("client " + name + " connecté\n" );
 
 System.out.println("<< Appuyez sur Entrée pour déconnecter le client >>" );
 System.in.read();
 
 client.deConnecter();
 System.out.println("client " + name + " déconnecté\n" );
 
 System.exit(0);
    }
     
}


 
Serveur.java

Citation :


package jeu;
 
import java.rmi.*;
 
public interface Serveur extends Remote {
    // ici, il faut définir toutes les méthodes que les clients doivent pouvoir appeler
 
    public void connecter(Client c) throws RemoteException;
    public void deConnecter(Client c) throws RemoteException;
}


 
ServeurImpl.java

Citation :


package jeu;
 
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
 
public class ServeurImpl  
    extends UnicastRemoteObject  
    implements Serveur {
 
    protected Collection clients;
    protected Collection nomsClients;
 
    // constructeur obligatoire
    public ServeurImpl() throws RemoteException {
 clients = new ArrayList();
 nomsClients = new ArrayList();
    }  
 
    public void connecter(Client c) throws RemoteException {
 String nom = c.getName();
 clients.add(c);
 nomsClients.add(nom);
 System.out.println(nom + " est connecté" );
 diffuserListeClients();
    }
 
    public void deConnecter(Client c) throws RemoteException {
 String nom = c.getName();
 clients.remove(c);
 nomsClients.remove(nom);
 System.out.println(nom + " s'est déconnecté" );
 diffuserListeClients();
    }
 
    protected void diffuserListeClients() {  
 try {
     Iterator it = clients.iterator();
     while (it.hasNext()) {
  ((Client) it.next()).informerListeClients(nomsClients);
     }  
 } catch (RemoteException  e) {
     System.err.println("Erreur RMI lors de la diffusion de la liste des clients connectés : " + e);
     e.printStackTrace(System.err);
 }  
    }
 
    public static void main(String[] args) throws Exception {
 //System.setSecurityManager(new RMISecurityManager());
 
 // lance le registre sur le port (1099 par defaut)
 LocateRegistry.createRegistry(1099);
 
 // créé et enregistre le serveur dans le registre
 Serveur serveur = new ServeurImpl();
 Naming.bind("//localhost/Serveur", serveur);
 System.out.println("Serveur en attante ..." );
    }
     
}


 
voila. Il faut mettre tout ca dans un rep jeu (puisque ces classes appartiennent u package jeu).. On va dire que ce sera e:\sources\java\jeu. ensuite, tu compiles les classes.
 
Il faut ensuite générer les stub et les skel. Pour ca il faut se mettre dans le rep e:\sources\java et lancer les deux commandes suivantes :  

Citation :


rmic jeu.ServeurImpl
rmic jeu.ClientImpl


 
ensuite y a plus qu'à tout lancer : Ouvre plusieurs shell dos et dans chacune tu execute une des commandes suivante :  

Citation :


java jeu.ServeurImpl
java jeu.ClientImpl toto
java jeu.ClientImpl titi
java jeu.ClientImpl tutu


 
et voila ! en principe à chaque connection - deconnection, tu devrais voir la liste des joueurs dans chacun des clients.
 
Remarque :  
1) tu n'as pas besoin de lancer la registry : elle est lancée avec le serveur.
2) dans thinking in java, ils disaient de mettre la ligne System.setSecurityManager(new RMISecurityManager()); dans le main, mais ca me générait une exceptino à l'execution. Ca avait rapport avec la config de sécurité (fichier de config de java à modifier). Si je ne met pas cette ligne, je n'ai plus de problème => je vais pas m'embetter pour rien non plus ! ;)
3) j'avais oublié la merde que c'était pour voir les erreurs : quand une méthode du seveur appelée par un client déclenche une exception sur le serveur, ce n'est pas le serveur qui plante mais le client. Et ca fais une exception bien peu strange... http://forum.hardware.fr/icones/icon16.gif Et parfois ca t'affiche "null" comme seul message d'exception. Super pour débuguer ! ;)
4) c'est quand même sympa RMI ...


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 14-02-2002 à 23:50:04    

:cry: :cry: le forum il m'a niqué toute ma belle indentation !!!!


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 15-02-2002 à 00:06:07    

Je n'ai encore lu ton code mais, je m'apprête à la faire immédiatement.
 
Cela fait bien longtemps que je n'ai rencontré quelqu'un d'aussi charitable. En vérité, je ne sais pas quoi dire pour t'exprimer ma gratitude. C'est... Enfin merci beaucoup.
 
Merci aussi à darklord22, qui est un ami aussi (je te dois un repas, il me semble !)
 
Bien, je tâcherai de ne pas trop vous ennuyer à nouveau avec ça. De toutes les manières avec un code prêt à l'emploi, je me demande même si j'aurais encore besoin d'aide. Encore merci pour tout Monsieur benou.


---------------
Le site de ma maman
Reply

Marsh Posté le 15-02-2002 à 00:29:25    

Bon, j'ai testé. Le programme marche et en prime j'ai appris comment lancer la registry avec le serveur (ça c'est bien cool). Ton code est vraiment impec'. C'est super.
 
J'ai une question à te poser cependant : quelle a été ta motivation pour accomplir ce travail ? Raviver tes connaissances ? Plaisir esthétique ? Humanisme ? Amour de la programmation ?
 
J'ai mon compte pour ce soir. Je vais regarder les sources une nouvelle fois avant de dormir, rêver... et me reconnecter demain pour chatter comme une bête.
 
Vive le monde :)
 
Râââhhhh dodo !


---------------
Le site de ma maman
Reply

Marsh Posté le 15-02-2002 à 00:58:06    

Cherrytree a écrit a écrit :

Merci aussi à darklord22, qui est un ami aussi (je te dois un repas, il me semble !)




 
absolument !
 
 :hello:


---------------
What is popular is not always right, what is right is not always popular :D
Reply

Marsh Posté le 15-02-2002 à 08:43:40    

Cherrytree a écrit a écrit :

J'ai une question à te poser cependant : quelle a été ta motivation pour accomplir ce travail ? Raviver tes connaissances ? Plaisir esthétique ? Humanisme ? Amour de la programmation ?




bha un peu tout ca, et puis ca fait plaisir de rendre service à quelqu'un de vraiment sympa ... :)
 
je dois avoir une ame de prof qui sommeille en moi : j'aime bien transmettre ce que je sais....


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 15-02-2002 à 08:52:35    

Salut tout le monde !
 

benou a écrit a écrit :

 
je dois avoir une ame de prof qui sommeille en moi : j'aime bien transmettre ce que je sais....  




 
Pareil, c'est pour ça que quand mon Pong sera fini, je mettrai les sources sur un site web pour que les autres en profite. A moins que la portion de code que tu m'as proposé soit copyrightée naturellement :D


---------------
Le site de ma maman
Reply

Marsh Posté le 15-02-2002 à 10:30:46    

Cherrytree a écrit a écrit :

 A moins que la portion de code que tu m'as proposé soit copyrightée naturellement :D  




ouais !!! je veux des royalties !!! :D :lol:


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 15-02-2002 à 12:12:51    

Bon récapitulons je dois un dîner de con à darklord22 (c'est pas lui le con, hein :jap:) et des royalties à benou... Qui a dit que Java c'était gratuit déjà ?


---------------
Le site de ma maman
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed