Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2593 connectés 

  FORUM HardWare.fr
  Programmation
  Java

  [débutant] RMI et réutilisation de code

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[débutant] RMI et réutilisation de code

n°685558
Taz
bisounours-codeur
Posté le 27-03-2004 à 13:01:04  profilanswer
 

j'ai un TP sur RMI à faire avec l'exemple pompé et repompé du dictionnaire distribué (une collection de mot côté serveur).
 
Je me dis : je vais y aller doucement, faire un truc qui marche sans client serveur. je fais un classe classique Dictionary, et une petite interface en ligne de commande Cmd (d'ailleurs regarder moi cette verbosité, on est loin de python Cmd, enfin bon, c'est ça ni delegate, ni pointeur de fonction, hum hum)
Voilà, ça marche comme je veux en local : il me reste plus qu'à enrober tout ça pour l'exporter.
 
et là je bloque. déjà, je vois qu'il faut que je fasse une interface à mon Dictionary pour déclarer que tout est succeptible de lancer RemoteException. ok.
 
maintenant mon RDictionaryServer : là je bloque un peu. pas d'héritage multiple, donc comme ça doit "extends UnicastRemoteObject implements RDictionary" je me retrouve à faire de la composition : c'est un peu pénible, mais simple à faire. ok
 
mon RegisterIt : ras
 
mon RDictionaryClient ... ça commence facile, jusqu'au moment ou je veux utiliser mon code existent, à savoir mon Interface Cmd ... ben évidemment ça marche plus, j'ai pas pu hériter de Dictionary... là je bloque, je suis pas allé plus loin.
 
http://dejean.benoit.free.fr/code/rmi_rdict.tar.bz2 (rdict_old)
 
comment je peux faire pour réutiliser mon code, et en général, comment faire ?


Message édité par Taz le 27-03-2004 à 21:41:35
mood
Publicité
Posté le 27-03-2004 à 13:01:04  profilanswer
 

n°685597
kotw
Posté le 27-03-2004 à 14:28:14  profilanswer
 

Salut,
pour ta qst, je n'ai pas bien compris ton problème ...
 
Par contre, pour ton RDictionaryServer, je te conseillerais plutot de faire comme ça :
 
créer une classe de type :
1. RDictionaryImpl extends java.rmi.server.UnicastRemoteObject implements RDictionary qui fasse les traitemets.
 
2. une classe RDictionaryServer du genre :
import java.rmi.Naming;
 
public class RDictionaryServer
{
  public RDictionaryServer()
  {
    try
    {
      RDictionary = new RDictionaryImpl();
      Naming.rebind("rmi://localhost:1099/RDictionaryService", c);
    } catch (Exception e) {
      System.out.println(e);
    }
  }
 
  public static void main (String args[]) {
    new RDictionaryServer();
  }
}

n°685600
Taz
bisounours-codeur
Posté le 27-03-2004 à 14:46:25  profilanswer
 

ma question est simple : entre toutes ces interfaces et super-classes, je peux pas réutiliser mon code.
 
quant à ton conseil, il ne change rien au problème.
 
j'ai un client et du code qui jusqu'à présent manipule des Dictionary, je n'arrive pas par RMI à lui faire utiliser des  Dictionary distants.

n°685605
leonhard
Posté le 27-03-2004 à 15:23:16  profilanswer
 

citation=685600,1][nom]Taz a écrit[/nom]ma question est simple : entre toutes ces interfaces et super-classes, je peux pas réutiliser mon code.
 
quant à ton conseil, il ne change rien au problème.
 
j'ai un client et du code qui jusqu'à présent manipule des Dictionary, je n'arrive pas par RMI à lui faire utiliser des  Dictionary distants.
[/citation]
 
t'es pas obligé de faire hériter ta classe d'objet remote d'UnicastRemoteObject (URO).. il faut juste que tu fasses le boulot à la main...
 
1) Tu crées une interface décrivant l'objet remote avec juste les méthodes que tu veux voir disponibles à distance...  
2) Tu crée ta classe d'objet remote sans hériter d'URO... mais tu peux alors utiliser l'héritage unique pour ta propre arborescence.
3) Dans le code qui va créer réellement l'objet remote (càd souvent le code du serveur) tu  dois simplement faire  

Code :
  1. <interface type> var = new <remote object class>(...);
  2. <interface type> stub = (<interface type> )UnicastRemoteObject.exportObject(var);
  3. Naming.rebind(<service name>, stub);


ou <interface type> est le nom de ton interface, <remote object class> est le nom de la classe réalisant l'interface et <service name> est le nom que tu as choisit pour ton service
et normalement ça devrait marcher comme tu l'espère


Message édité par leonhard le 27-03-2004 à 15:23:59
n°685607
kotw
Posté le 27-03-2004 à 15:25:59  profilanswer
 

Taz a écrit :

ma question est simple : entre toutes ces interfaces et super-classes, je peux pas réutiliser mon code.
 
quant à ton conseil, il ne change rien au problème.
 
j'ai un client et du code qui jusqu'à présent manipule des Dictionary, je n'arrive pas par RMI à lui faire utiliser des  Dictionary distants.


 
Je n'ai pas dit cela allait résoudre ton pb, c t juste un conseil de conception au niveau de tes classes. D'ailleurs, je t'avais dit que n'avais pas bien compris ton problème ... tu parles d'Interface Cmd alors que c une classe, tu veux hériter de Dictionary, alors que tu n'en as absolument pas besoin ...

n°685611
Taz
bisounours-codeur
Posté le 27-03-2004 à 15:35:10  profilanswer
 

kotw a écrit :

tu parles d'Interface Cmd alors que c une classe, tu veux hériter de Dictionary, alors que tu n'en as absolument pas besoin ...  

je parlais d'IHM :o
je veux juste que mon appli client puisse récupérer un sous type de Dictionary pour pouvoir utiliser du code existant.
 
donc si je te suis, je garde mon <interface> RDictionary. donc à part faire une sous-interface Remote et une classe implémentant cette sous-interface composé d'un Dictionary, ça devrait passer.  
 
question : si tu veux exporter une classe complète, tu fais comment ? parce que faire une interface pour juste rajouter les déclarations d'exception et une classe d'implémentation qui ne fait strictement rien si ce n'est enrober pour que ça colle au niveau des prototypes ...

n°685613
Taz
bisounours-codeur
Posté le 27-03-2004 à 15:40:26  profilanswer
 

genre

Code :
  1. import java.rmi.*;
  2. import java.rmi.server.*;
  3. public class RemoteDictionaryImpl implements RemoteDictionary
  4. {
  5.     // et voilà, boom, pas d'héritage multiple
  6.     private Dictionary rdict;
  7.     public RemoteDictionaryServer() throws RemoteException
  8.     {
  9. super();
  10. this.rdict = new Dictionary();
  11.     }
  12.     public boolean hasWord(String w) throws RemoteException
  13.     {
  14. return this.rdict.hasWord(w);
  15.     }
  16.     public void addWord(String w) throws RemoteException
  17.     {
  18. this.rdict.addWord(w);
  19.     }
  20.     public void delWord(String w) throws RemoteException
  21.     {
  22. this.rdict.delWord(w);
  23.     }
  24.     public int count() throws RemoteException
  25.     {
  26. return this.rdict.count();
  27.     }
  28.     public String[] allWords() throws RemoteException
  29.     {
  30. return this.rdict.allWords();
  31.     }
  32. }

c'est pas ce que ça m'amuse mais bon ;)

n°685616
kotw
Posté le 27-03-2004 à 15:56:04  profilanswer
 

1. Tu gardes ta classe RDictionary
2. tu jettes ta classe Dictionary : tu créés à la place une classe RDictionaryImplementation qui hérite de UnicastRemoteObject et qui implemente RDictionary.
3. Dans ton RDictionaryServer, tu créés un objet de type :
RDictionary dict = new RDictionaryImplementation();
Naming.rebind("rmi://localhost:1099/RDictionaryService", dict); (tu enregistres cet objet de serveur au niveau du service)
4. Coté client, pour accéder à ce service de manière distante, tu fais :
RDictionary dico = (RDictionary )
          Naming.lookup(
              "rmi://localhost/RDictionaryService" );
 
après, "dico" pourra etre utilisé dans ta classe Cmd !

n°685617
R3g
fonctionnaire certifié ITIL
Posté le 27-03-2004 à 16:00:47  profilanswer
 

kotw a écrit :

1. Tu gardes ta classe RDictionary
2. tu jettes ta classe Dictionary : tu créés à la place une classe RDictionaryImplementation qui hérite de UnicastRemoteObject et qui implemente RDictionary.
3. Dans ton RDictionaryServer, tu créés un objet de type :
RDictionary dict = new RDictionaryImplementation();
Naming.rebind("rmi://localhost:1099/RDictionaryService", dict); (tu enregistres cet objet de serveur au niveau du service)
4. Coté client, pour accéder à ce service de manière distante, tu fais :
RDictionary dico = (RDictionary )
          Naming.lookup(
              "rmi://localhost/RDictionaryService" );
 
après, "dico" pourra etre utilisé dans ta classe Cmd !

C'est trop facile ça. La base du cahier des charges c'est de réutiliser Dictionnary et Cmd...
Ceci dit j'ai jamais fais de RMI donc je peux pas aider...


---------------
Au royaume des sourds, les borgnes sont sourds.
n°685619
kotw
Posté le 27-03-2004 à 16:06:00  profilanswer
 

R3g a écrit :

C'est trop facile ça. La base du cahier des charges c'est de réutiliser Dictionnary et Cmd...
Ceci dit j'ai jamais fais de RMI donc je peux pas aider...


 
Dis moi, à quoi elle sert cette classe Dictionary ? Je n'arrive pas à voir son utilité ...
 
Edit : qd on fait des invocations de méthodes distantes, les variables d'objets sont des interfaces et non des objets !!


Message édité par kotw le 27-03-2004 à 16:07:42
mood
Publicité
Posté le 27-03-2004 à 16:06:00  profilanswer
 

n°685622
kotw
Posté le 27-03-2004 à 16:11:03  profilanswer
 

Si le but est de "réutiliser" Dictionary, c'est dans la classe RDictionaryImplementation qu'il faudra utiliser les méthodes de Dictionary. Mais il faut avoir à l'esprit que ce sont des objets de type interface auxquels on accède aux méthodes ...

n°685669
Taz
bisounours-codeur
Posté le 27-03-2004 à 19:01:32  profilanswer
 

kotw a écrit :

Si le but est de "réutiliser" Dictionary, c'est dans la classe RDictionaryImplementation qu'il faudra utiliser les méthodes de Dictionary. Mais il faut avoir à l'esprit que ce sont des objets de type interface auxquels on accède aux méthodes ...

mais c'est exactement ce que j'ai posté. et le problème c'est justement ça : avec 2/3 méthodes ça passe, maintenant, si tu veux exporter un truc complet genre java.util.List, pas la peine d'y penser. ton edit confirme le problème. les interfaces, c'est bien, mais quand tu as tu code existant... Donc déjà, ça répond à une de mes questions, à savoir que c'est fastidieux à mettre en place.
 
par contre ça me dit pas comment récupérer un Dictionary sur le client. le problème c'est que ma classe Cmd bosse avec des Dictionary ...
 
je te remercie de ton aide. maintenant que le problème est posé, à savoir réutiliser du code, est-ce que tu vois un moyen de récupérer un Dictionary et pas un RDictionary coté client ?

n°685679
kotw
Posté le 27-03-2004 à 19:23:51  profilanswer
 

Le problème, c'est qu'en RMI, ton client ne peut récupérer que des objets de type interface et non des objets instances d'une classe (comme c'est le cas dans ta classe Cmd). Il y a une énorme différence entre programmer en RMI et programmer "classiquement" : "classiquement" tu peux utiliser ou pas des interfaces, en RMI c'est obligatoire ! Dans ta classe Cmd, si tu veux absolument trouver un moyen de faire :
Dictionary dit = new Dictionary(); // en utilisant RMI bon courage !
 
Maintenant, dans ta classe Cmd, il faut que tu fasses comme dans ta classe RDictionaryClient :
RDictionary dict = (RDictionary) Naming.lookup (..);
 
PS : je te rappelle que RMI = invocation distante de Méthodes et non pas d'objets ...

n°685681
Taz
bisounours-codeur
Posté le 27-03-2004 à 19:30:21  profilanswer
 

oui mais bon, on a quand même plus la notion d'objets qu'en RPC.
 
je sais bien que je peux résoudre mon problème en créant faisant un Dictionary qui a implémente Remote et non pas dans l'autre sens. à çe moment là, pour sur, ça fonctionne très bien.
 
est-ce que je peux conclure que RMI c'est bien, sauf que la réutilisabilité stricte (c'est à dire la possibilité de réutiliser du code déjà écrit et fonctionnel sans le modifier), elle tend vers zéro ?

n°685683
kotw
Posté le 27-03-2004 à 19:39:35  profilanswer
 

Ben, tout dépend quand même du code existant !
AMHA, si tu prends l'habitude de programmer en utilisant au maximum les interfaces, les possibilités de réutilisabilité ne tendent pas vers zéro.

n°685684
Taz
bisounours-codeur
Posté le 27-03-2004 à 19:45:14  profilanswer
 

euh comment ça ? comment je peux faire sans foutre une seule ligne de RMI dans mon code Cmd et Dictionary ?

n°685688
kotw
Posté le 27-03-2004 à 19:56:00  profilanswer
 

Lol je n'ai pas dit que tu pouvais le faire directement dans ton cas particulier, mais en règle générale ...
 
Maintenant, dans ton cas, honnetement, c'est si pénalisant d'écire dans Cmd : RDictionary dict = (RDictionary) ...
et d'écrire une classe du genre :  
RDictionaryImplementation extends UnicastRemoteObject implements RDictionary qui fasse exactement la meme chose que ta classe Dictionary ?

n°685689
Taz
bisounours-codeur
Posté le 27-03-2004 à 19:59:21  profilanswer
 

donc, je dois bien comprendre que pour travailler avec RMI:
- soit créer une interface basée sur Remote et dériver tôt ou tard de UnicastRemoteObject
- soit créer une interface basée sur Remote et utiliser UnicastRemoteObject.exportObject
 
bref au moment ou tu codes, il faut penser à faire cette sous-interface de Remote et tout travailler avec. correct ?

n°685705
kotw
Posté le 27-03-2004 à 20:17:58  profilanswer
 

AMHA, le plus simple est :
- créer une interface qui hérite de java.rmi.Remote qui contient les signatures des méthodes
- créer une classe d'implémentation qui hérite d'UnicastRemoteObject et qui implémente ton interface. Cette classe peut effectivement hériter d'une autre classe et utiliser UnicastRemoteObject.exportObject.
 
Edit :
- soit créer une interface basée sur Remote et dériver tôt ou tard de UnicastRemoteObject  --> créer simplement une interface qui hérite de Remote.
- soit créer une interface basée sur Remote et utiliser UnicastRemoteObject.exportObject -- > créer une classe(et non pas une interface !) qui hérite d'UnicastRemoteObject et qui implémente ton interface.
 
J'espère que c'est un peu plus clair pour toi, parce-que j'ai l'impression que tu confonds parfois interface et classe ...


Message édité par kotw le 27-03-2004 à 20:24:24
n°685714
Taz
bisounours-codeur
Posté le 27-03-2004 à 20:25:55  profilanswer
 

c'est un peu exactement ce que j'ai dit :D
 
non, je ne fais pas de confusion, seulement tu interprètes mal à chaque fois que je fais de l'implicite.
 
merci

n°685720
kotw
Posté le 27-03-2004 à 20:42:11  profilanswer
 

En fait, je fais autre chose à côté ...
et c'est vrai qu'il m'arrive dans ces cas là de pas bien comprendre :-)

n°685729
Taz
bisounours-codeur
Posté le 27-03-2004 à 21:33:08  profilanswer
 

voilà j'ai donc fait mon TP comme ça.
http://dejean.benoit.free.fr/code/rmi_rdict.tar.bz2


Message édité par Taz le 27-03-2004 à 21:41:03
n°685734
kotw
Posté le 27-03-2004 à 21:53:57  profilanswer
 

Si ça marche chez toi, c'est le principal ... :-)  
Après, y a tjrs des remarques sur la façon de faire... que je ne dirais pas parce-que j'ai pas envie de me prendre pour un expert alors que je n'en suis pas ...

n°685737
Taz
bisounours-codeur
Posté le 27-03-2004 à 22:00:15  profilanswer
 

ben là j'ai fait une sous-interface RemoteDictionary de java.rmi.Remote. j'ai gardé ma classe Dictionary. J'ai créé une classe RemoteDictionaryImplementation qui concrétise RemoteDictionary en utilisant Dictionary. Et puis comme ça me paraissait trop simple, j'ai mélangé, c'est à dire que RemoteDictionaryImplementation ne dérive pas de java.rmi.server.UnicastRemoteObject, par contre je crée moi même le stub avec  java.rmi.server.UnicastRemoteObject.exportObject :D

n°685739
kotw
Posté le 27-03-2004 à 22:18:20  profilanswer
 

AMHA,
1. ta classe RegisterIt devrait s'appeler RemoteDictionaryServer avec une méthode  
main (String[] args]
{
  new RemoteDictionaryServer();
}
et, dans le constructeur de RemoteDictionaryServer, tu mets le code actuel de ta mtd main de RegisterIt.
 
2. ton client devrait pas appeler run directement mais pourrait être appelé en ligne de commande.
Imagines que ton service se trouve sur une autre machine, tu pourras appeler ton client en passant en paramètre l'adresse exacte de la machine --> dans ton client, tu ferais un Naming.lookup(args[0]) par ex plutot que d'écrire en dur le nom du service ...
 
etc... :-)

n°685740
Taz
bisounours-codeur
Posté le 27-03-2004 à 22:46:27  profilanswer
 

1) mouef, c'est une autre technique
 
2) ouaip

n°685784
nraynaud
lol
Posté le 28-03-2004 à 01:06:18  profilanswer
 

Taz > j'ai la flemme de ragarder en détail (j'ai juste cru capter que tu veux réutiliser du code sans te taper 15 délégations à la mano), mais je te file ça : http://java.sun.com/j2se/1.4.2/doc [...] Proxy.html
 
Qui est probablement en rapport avec la choucroute.
 
J'ai un exemple d'utilisation là (classe "CollectionProxy" ) de délégation sur la classe Collection:
http://rien.a.dire.free.fr/concour [...] nning.html


---------------
trainoo.com, c'est fini
n°685792
Taz
bisounours-codeur
Posté le 28-03-2004 à 01:13:32  profilanswer
 

oui et non. c'est vrai que c'est pas mal, pour résoudre le problème de la fastidieuse délégation. je vais apprendre à jouer avec. edit: mais d'ailleurs, je ne suis pas sur de pouvoir m'en sortir, puisque ce qui m'obligeait à la délagation était le changement de prototype, à savoir le type d'exception suceptible d'être lancé ( <rien> -> RemoteException ). et j'ai pas encore découvert si je pouvais le régler facilement.
 
mais le principal problème n'était pas là et la solution s'est éloignée de ce que j'avais prévu (en fait j'ai tout réécrit sauf une classe et là effectivement, j'ai délégué)


Message édité par Taz le 28-03-2004 à 01:19:16
n°687232
machinbidu​le1974
Do you feel lucky, punk ?
Posté le 30-03-2004 à 12:19:50  profilanswer
 

nraynaud a écrit :

Taz > j'ai la flemme de ragarder en détail (j'ai juste cru capter que tu veux réutiliser du code sans te taper 15 délégations à la mano), mais je te file ça : http://java.sun.com/j2se/1.4.2/doc [...] Proxy.html
 
Qui est probablement en rapport avec la choucroute.
 
J'ai un exemple d'utilisation là (classe "CollectionProxy" ) de délégation sur la classe Collection:
http://rien.a.dire.free.fr/concour [...] nning.html


 
Dans quel cas, la génération dynamique d'un objet Proxy peut-être utile ? Est-ce-que tu as un exemple d'utilisation de cette classe ?

n°687285
Taz
bisounours-codeur
Posté le 30-03-2004 à 13:08:29  profilanswer
 

ben l'exemple de nraynaud est superbe je trouve

n°687301
machinbidu​le1974
Do you feel lucky, punk ?
Posté le 30-03-2004 à 13:29:06  profilanswer
 

ben son code doit être trop pointu pour moi car je panne que dalle à ce que c'est censé faire  :sweat:


Message édité par machinbidule1974 le 30-03-2004 à 13:29:36
n°687538
nraynaud
lol
Posté le 30-03-2004 à 16:30:14  profilanswer
 

machinbidule1974 a écrit :

ben son code doit être trop pointu pour moi car je panne que dalle à ce que c'est censé faire  :sweat:  

je fais un proxy de collection.
Les méthodes qui m'intéressent je les prends ; les autre je les file à l'objet réel (collection dans ce cas).
 
Tout appel de méthode sur le proxy fini dans le invoke() avec les paramètres qui vont bien.

Code :
  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2.   try {
  3. /* la méthode contains() m'intéresse, je la traite moi-même */
  4.    if (method.equals(containsMethod))
  5.     if (args[0] == null)
  6.      return Boolean.FALSE;
  7.     else
  8.      return unwrappingInvoke(collection, method, args);
  9. /* la méthode containsAll() m'aintéresse, je traite moi-même */
  10.    if (method.equals(containsAllMethod))
  11.     return containsAll((Collection)args[0]);
  12.   } catch (OverlapsException e) {
  13.    return Boolean.FALSE;
  14.   }
  15. /* les autres méthodes, c'est le vrai objet (collection) qui se démerdera avec */
  16.   return unwrappingInvoke(collection, method, args);
  17.  }
  18. /* une petite feinte au niveau des exceptions expliquée ici : http://forum.hardware.fr/forum2.ph [...] 0&subcat=0
  19. */
  20.  private Object unwrappingInvoke(Object object, Method method, Object[] args)
  21.   throws Throwable {
  22.   try {
  23.    return method.invoke(object, args);
  24.   } catch (InvocationTargetException e) {
  25.    throw e.getCause();
  26.   }
  27.  }


 
 
 
Taz > attention cependant que ce code est buggé dans sa partie comportementale (et j'ai la flemme de le corriger). Il y a des cas dans lequels prendre un sous-arbre ne renvoie pas le bon réultat.


Message édité par nraynaud le 30-03-2004 à 16:31:09

---------------
trainoo.com, c'est fini
n°687543
Taz
bisounours-codeur
Posté le 30-03-2004 à 16:32:13  profilanswer
 

ok. toutes façons, a priori, je ne peux pas l'utiliser, j'ai résolu mon programme en réécrivant tout

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Java

  [débutant] RMI et réutilisation de code

 

Sujets relatifs
Débutant et calculCode java !!!
aide debutantExplication de code
Comptage de lignes de code C ou Java sous WindowsBrowser de code C
Générer du code HTML "à la volée" avec le langage ASP.NET ?Quel vérificateur de code genre lint ( free)
Un bout de code relatif à plusieurs pages dans un fichier à part[Debutant] envoyer une bitmap d'un serveur vers un client
Plus de sujets relatifs à : [débutant] RMI et réutilisation de code


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR