OVH Cloud OVH Cloud

RMI et JBuilderX

12 réponses
Avatar
Albert Kunzunsky
Bonjour,

Je me lance dans une application distribuée, et pour comprendre les
mécanismes du RMI, j'ai copié l'exemple d'un bouquin. Un truc tout
simple avec un objet renvoyant une chaine de caractères.

Voici les quelques problèmes auquelles je suis confrontés.

- Si je lance le registre RMI par JBuilder, l'application serveur
plante avec une exception d'authorisation.

- Si je lance le registre RMI et l'application serveur sous une fenêtre
DOS, l'application serveur plante avec une exception d'authorisation.

- Si je lance le registre RMI sous une fenêtre DOS, l'application
serveur et l'application cliente dans JBuilder, l'application serveur et
l'application cliente fonctionnent correctement, a condition que
l'ensemble des classes soient dans le même dossier.

- Mais si l'ensemble des classes serveur sont dans un dossier et
l'application cliente dans une autre, l'application serveur fonctionne,
mais lorsque je lance l'application cliente elle lance l'exception:

java.rmi.UnmarshallException: error unmarshalling return; nested
exception is:
java.lang.ClassNotFoundException: rmiserver.ProductImpl_Stub
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknow Source)
etc...


Pouvez-vous s'il vous plait m'expliquer pourquoi j'ai ces différentes
erreurs, qu'es-ce que je n'ai pas fait correctement, et qu'es ce qu'il
faut que je fasse pour que ça fonctionne.

Merci beaucoup.

10 réponses

1 2
Avatar
Rémi COCULA
Tu devrais jeter un coup d'oeil sur
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/codebase.html

Le serveur RMI doit spécifier l'emplacement des classes téléchargeables à
l'aide de la propriété codebase.


"Albert Kunzunsky" a écrit dans le message de
news: 41ad8247$0$28718$
Bonjour,

Je me lance dans une application distribuée, et pour comprendre les
mécanismes du RMI, j'ai copié l'exemple d'un bouquin. Un truc tout
simple avec un objet renvoyant une chaine de caractères.

Voici les quelques problèmes auquelles je suis confrontés.

- Si je lance le registre RMI par JBuilder, l'application serveur
plante avec une exception d'authorisation.

- Si je lance le registre RMI et l'application serveur sous une fenêtre
DOS, l'application serveur plante avec une exception d'authorisation.

- Si je lance le registre RMI sous une fenêtre DOS, l'application
serveur et l'application cliente dans JBuilder, l'application serveur et
l'application cliente fonctionnent correctement, a condition que
l'ensemble des classes soient dans le même dossier.

- Mais si l'ensemble des classes serveur sont dans un dossier et
l'application cliente dans une autre, l'application serveur fonctionne,
mais lorsque je lance l'application cliente elle lance l'exception:

java.rmi.UnmarshallException: error unmarshalling return; nested
exception is:
java.lang.ClassNotFoundException: rmiserver.ProductImpl_Stub
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknow Source)
etc...


Pouvez-vous s'il vous plait m'expliquer pourquoi j'ai ces différentes
erreurs, qu'es-ce que je n'ai pas fait correctement, et qu'es ce qu'il
faut que je fasse pour que ça fonctionne.

Merci beaucoup.


Avatar
Vincent Cantin
Il y a une option dans les menus de JBuilder pour qu'il lance RMI,
probablement avec les bons parametres.

Vincent

PS: Maintenant, il y a JBuilder2005.
Avatar
Vincent Cantin
oops, j'ai mal lu ton post, desole.
... decidement, aujourd'hui je ne fais que des bourdes.
Avatar
Albert Kunzunsky
Tu devrais jeter un coup d'oeil sur
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/codebase.html

Le serveur RMI doit spécifier l'emplacement des classes téléchargeables à
l'aide de la propriété codebase.

Avant toutes choses merci beaucoup.


Tu as confirmé ce dont je me doutais: c'est mon codebase qui déconne.

J'avais écrit:
-Djava.rmi.server.codebase="file:/d:/TestRMI/RMIServer/classes/"
C'est pour celà que ça fonctionne lorsque les classes serveur et
clientes sont dans le même répertoire: c'est une adresse locale.

Par contre je n'arrive pas à l'écrire correctement, je n'ai pas trouvé
la doc trés explicite sur le sujet. Si tu pouvais m'aider...

Je te donne les différents paramètres.

Nom de machine: ServeurHttp (elle fait également office de serveur web,
mais le dossier TestRMI ne se trouve pas dans l'arborescence du service
web).

chemin des classes serveur, interface, objet distribué, stub et
skeleton: d:/TestRMI/RMIServer/classes/rmiserver/

rmiserveur étant le nom du package.

D'avance merci beaucoup.

Avatar
Rémi COCULA
Le codebase doit être une URL valide.
Si c'est un URL http tu dois forcément avoir un alias dans ton serveur web
qui pointe vers le répertoire où se trouve les classes téléchargeables.

"Albert Kunzunsky" a écrit dans le message de
news: 41af0f12$0$30451$
Tu devrais jeter un coup d'oeil sur
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/codebase.html

Le serveur RMI doit spécifier l'emplacement des classes téléchargeables
à


l'aide de la propriété codebase.

Avant toutes choses merci beaucoup.


Tu as confirmé ce dont je me doutais: c'est mon codebase qui déconne.

J'avais écrit:
-Djava.rmi.server.codebase="file:/d:/TestRMI/RMIServer/classes/"
C'est pour celà que ça fonctionne lorsque les classes serveur et
clientes sont dans le même répertoire: c'est une adresse locale.

Par contre je n'arrive pas à l'écrire correctement, je n'ai pas trouvé
la doc trés explicite sur le sujet. Si tu pouvais m'aider...

Je te donne les différents paramètres.

Nom de machine: ServeurHttp (elle fait également office de serveur web,
mais le dossier TestRMI ne se trouve pas dans l'arborescence du service
web).

chemin des classes serveur, interface, objet distribué, stub et
skeleton: d:/TestRMI/RMIServer/classes/rmiserver/

rmiserveur étant le nom du package.

D'avance merci beaucoup.



Avatar
Albert Kunzunsky
Bien, j'ai bien progressé depuis ton dernier message. Effectivement, avec un
alias dans le serveur web ça marche beaucoup mieux. Même si j'ai pas mal
tourné en rond parce que tous les bouquins codent l'URL dans le codebase
avec:
....codebase=http://alias/
alors qu'il faut écrire:
...codebase=http:/alias/
Il n'y a qu'un seul / apres http:

Donc grace à ton aide, j'ai réussi à faire fonctionner la classe server.
Mais j'ai toujours des problèmes coté client.

Quand je lance ma classe client par
D:TestRMIRMIClientclasses>java -Dsecurity.policy=file:D:/TestRMI/RMIClien
t/client.policy rmiclient.ProductClient

sous JBuilder il me lève une exception:
java.rmi.NotBoundException

et sous DOS il me lève une exception:
java.security.AccesControlException: acces denied
(java.net.SocketPermission 127.0.0.1:1099 connect, resolve)

et tous les deux à la ligne Naming.lookup(....)

D'avance merci pour tes lumières. J'espère qu'après ça, j'arriverai à faire
"tourner" l'ensemble.


"Rémi COCULA" a écrit dans le message news:
41af7d2c$0$11767$
Le codebase doit être une URL valide.
Si c'est un URL http tu dois forcément avoir un alias dans ton serveur web
qui pointe vers le répertoire où se trouve les classes téléchargeables.

"Albert Kunzunsky" a écrit dans le message
de

news: 41af0f12$0$30451$
Tu devrais jeter un coup d'oeil sur
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/codebase.html

Le serveur RMI doit spécifier l'emplacement des classes
téléchargeables



à
l'aide de la propriété codebase.

Avant toutes choses merci beaucoup.


Tu as confirmé ce dont je me doutais: c'est mon codebase qui déconne.

J'avais écrit:
-Djava.rmi.server.codebase="file:/d:/TestRMI/RMIServer/classes/"
C'est pour celà que ça fonctionne lorsque les classes serveur et
clientes sont dans le même répertoire: c'est une adresse locale.

Par contre je n'arrive pas à l'écrire correctement, je n'ai pas trouvé
la doc trés explicite sur le sujet. Si tu pouvais m'aider...

Je te donne les différents paramètres.

Nom de machine: ServeurHttp (elle fait également office de serveur web,
mais le dossier TestRMI ne se trouve pas dans l'arborescence du service
web).

chemin des classes serveur, interface, objet distribué, stub et
skeleton: d:/TestRMI/RMIServer/classes/rmiserver/

rmiserveur étant le nom du package.

D'avance merci beaucoup.







Avatar
Sébastien
Albert Kunzunsky wrote:
Bien, j'ai bien progressé depuis ton dernier message. Effectivement, avec un
alias dans le serveur web ça marche beaucoup mieux. Même si j'ai pas mal
tourné en rond parce que tous les bouquins codent l'URL dans le codebase
avec:
....codebase=http://alias/
alors qu'il faut écrire:
...codebase=http:/alias/
Il n'y a qu'un seul / apres http:


non non, la première doit marcher aussi. Tu dois préciser des urls valides dans le codebase, du
genre http://monserveur.mondomaine/chemin/malib.jar. Tu peux en mettre plusieurs en les séparant par
des espaces


Donc grace à ton aide, j'ai réussi à faire fonctionner la classe server.
Mais j'ai toujours des problèmes coté client.

Quand je lance ma classe client par
D:TestRMIRMIClientclasses>java -Dsecurity.policy=file:D:/TestRMI/RMIClien
t/client.policy rmiclient.ProductClient

sous JBuilder il me lève une exception:
java.rmi.NotBoundException


tu n'as pas du faire un Registry.(re)bind() de l'objet côté serveur


et sous DOS il me lève une exception:
java.security.AccesControlException: acces denied
(java.net.SocketPermission 127.0.0.1:1099 connect, resolve)

et tous les deux à la ligne Naming.lookup(....)


tu n'as pas les droits pour faire le lookup. Es-tu sûr de ton fichier policy ?

Sébastien

Avatar
Albert Kunzunsky
Merci pour ta réponse.

Je vais préciser un peu questions.

Pour mon problème d'URL dans le codebase, j'ai revérifié, et je confirme, si
je marque http://.... au lancement de la classe serveur il me lève
l'exception la ligne Naming.rebind(.......):

java.rmi.ServerException: RemoteException occurred in server thread; nested
exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested
exception is:
java.lang.ClassNotFoundException: rmiserver.ProductImpl_Stub
etc...

Alors que si je ne mets qu'un /, la classe se déroule normalement.

Sinon, pour mon problème de classe client, je te donne les principales
sources, tu me dira ce que tu en pense.

Coté serveur:

La classe ProductImpl (l'objet distribué)

package rmiserver;

import java.rmi.*;
import java.rmi.server.*;

public class ProductImpl extends UnicastRemoteObject implements Product
{

private String descr;

public ProductImpl(String d) throws RemoteException
{
descr = d;
}

public String getDescription() throws RemoteException
{
return "Je suis " + descr + " .";
}

}

La classe ProductServer (qui lance l'application serveur)

package rmiserver;

import java.rmi.*;
import java.rmi.server.*;

public class ProductServer
{
public static void main(String args[])
{
try
{

System.out.println("Construction et implémentation du serveur...");
ProductImpl p1 = new ProductImpl("Objet 1");
ProductImpl p2 = new ProductImpl("Objet 2");

System.out.println("Liaison des implémentations du serveur à la base
de registre...");
Naming.rebind("ob1", p1);
Naming.rebind("ob2", p2);

System.out.println("Attente des invocations des clients...");
}
catch(Exception e)
{
e.printStackTrace();
}
}
public ProductServer()
{

}
}

Coté client.

La classe ProductClient (l'application distante)

package rmiclient;

import java.rmi.*;

public class ProductClient
{
public static void main(String[] args)
{
System.setProperty("java.security.policy", "client.policy");
System.setSecurityManager(new RMISecurityManager());
String url = "rmi:/Http-1j901-1/";

try
{
Product c1 = (Product) Naming.lookup(url + "ob1");
Product c2 = (Product) Naming.lookup(url + "ob2");
System.out.println(c1.getDescription());
System.out.println(c2.getDescription());
}
catch(Exception e)
{
// System.out.println(e.toString());
e.printStackTrace();
}
}

public ProductClient()
{
}

}

Et pour finir le fichier .policy

grant
{
permission java.net.SocketPermission "*:1024-65535", "connect";
};

Tu vois, c'est vraiment l'application de base pour comprendre les mécanismes
RMI.
C'est un copier/coller à partir d'un bouquin Java. Donc a prioris le code
n'est pas en cause.

Les classes serveurs sont dans: d:/TestRMI/RMIServer/classes/rmiserver/
L'alias du serveur web pointe sur: d:/TestRMI/RMIServer/classes/
Les classes clientes sont dans d:/TestRMI/RMIClient/classes/rmiclient/

Il y a quand même des réactions bizzares. Par exemple pourquoi lorsque je
lance l'application depuis JBuilder ou depuis DOS, l'esception levée n'est
pas la même.
C'est pourtant la même classe...

Bon, si tu peux me filler un coup de main pour comprendre l'ensemble... Je
te remercie d'avance.


"Sébastien" a écrit dans le message news:
41b489a2$0$9055$
Albert Kunzunsky wrote:
Bien, j'ai bien progressé depuis ton dernier message. Effectivement,
avec un


alias dans le serveur web ça marche beaucoup mieux. Même si j'ai pas mal
tourné en rond parce que tous les bouquins codent l'URL dans le codebase
avec:
....codebase=http://alias/
alors qu'il faut écrire:
...codebase=http:/alias/
Il n'y a qu'un seul / apres http:


non non, la première doit marcher aussi. Tu dois préciser des urls valides
dans le codebase, du

genre http://monserveur.mondomaine/chemin/malib.jar. Tu peux en mettre
plusieurs en les séparant par

des espaces


Donc grace à ton aide, j'ai réussi à faire fonctionner la classe server.
Mais j'ai toujours des problèmes coté client.

Quand je lance ma classe client par

D:TestRMIRMIClientclasses>java -Dsecurity.policy=file:D:/TestRMI/RMIClien


t/client.policy rmiclient.ProductClient

sous JBuilder il me lève une exception:
java.rmi.NotBoundException


tu n'as pas du faire un Registry.(re)bind() de l'objet côté serveur


et sous DOS il me lève une exception:
java.security.AccesControlException: acces denied
(java.net.SocketPermission 127.0.0.1:1099 connect, resolve)

et tous les deux à la ligne Naming.lookup(....)


tu n'as pas les droits pour faire le lookup. Es-tu sûr de ton fichier
policy ?


Sébastien



Avatar
Sébastien
Albert Kunzunsky wrote:
La classe ProductServer (qui lance l'application serveur)

package rmiserver;

import java.rmi.*;
import java.rmi.server.*;

public class ProductServer
{
public static void main(String args[])
{
try
{

System.out.println("Construction et implémentation du serveur...");
ProductImpl p1 = new ProductImpl("Objet 1");
ProductImpl p2 = new ProductImpl("Objet 2");

System.out.println("Liaison des implémentations du serveur à la base
de registre...");
Naming.rebind("ob1", p1);
Naming.rebind("ob2", p2);

System.out.println("Attente des invocations des clients...");
}
catch(Exception e)
{
e.printStackTrace();
}
}
public ProductServer()
{

}
}


sur quel port crées-tu la registry ?

{
public static void main(String[] args)
{
System.setProperty("java.security.policy", "client.policy");
System.setSecurityManager(new RMISecurityManager());
String url = "rmi:/Http-1j901-1/";

try
{
Product c1 = (Product) Naming.lookup(url + "ob1");
Product c2 = (Product) Naming.lookup(url + "ob2");
System.out.println(c1.getDescription());
System.out.println(c2.getDescription());
}
catch(Exception e)
{
// System.out.println(e.toString());
e.printStackTrace();
}
}


j'insiste : ton url pour faire le lookup doit être de la forme : rmi://host:port/name


Et pour finir le fichier .policy

grant
{
permission java.net.SocketPermission "*:1024-65535", "connect";
};



pour ne pas t'embêter avec les permissions pour l'instant, utilise

permission java.security.AllPermission;

Tu vois, c'est vraiment l'application de base pour comprendre les mécanismes
RMI.
C'est un copier/coller à partir d'un bouquin Java. Donc a prioris le code
n'est pas en cause.

Les classes serveurs sont dans: d:/TestRMI/RMIServer/classes/rmiserver/
L'alias du serveur web pointe sur: d:/TestRMI/RMIServer/classes/
Les classes clientes sont dans d:/TestRMI/RMIClient/classes/rmiclient/

Il y a quand même des réactions bizzares. Par exemple pourquoi lorsque je
lance l'application depuis JBuilder ou depuis DOS, l'esception levée n'est
pas la même.
C'est pourtant la même classe...

Bon, si tu peux me filler un coup de main pour comprendre l'ensemble... Je
te remercie d'avance.



en ce qui concerne ton code base, il te faut une URL http comme je te l'ai décrite dans mon mail
précédent. Assure-toi qu'elle fonctionne en l'ouvrant dans un navigateur.

Autre chose : as-tu configuré JBuilder pour qu'il génère un stub ?

Sébastien.

Avatar
Albert Kunzunsky
Avant toute chose, merci beaucoup de me répondre.

1. Je ne spécifie pas de port quand je crée la registry. Et donc normalement
il utilise le port par défaut donc le 1099.

2. Mon url pour le lookup est rmi:/rmi/ob1 (je me suis trompé dans la ligne
de code que je t'ai donné précédemment; c'était un de mes essai)

- si je mets rmi://..... il me dit unknow host
- si je mets rmi:/..... il me lève NotBoundException (toujours ces
problèmes d'un seul /), mais à la deuxième ligne il me dit que c'est sur le
ProductImpl_Skeleton

- j'ai essayé avec rmi:/rmi:1099/obj1 mais ça fait la même chose.

3. Jbuilder à bien crée les classes Stub et Skeleton.

4. Quand je lance la classe serveur, elle se lance correctement (Affichage
du message:"Attente des invocation des clients")
Donc les rebind fonctionnent, et les références aux objets 1 et 2 sont
bien dans la registry.

5. L'interface Product (de l'objet ProductImpl) coté serveur est dans le
package rmiserver, alors que coté client elle est dans le package rmiclient.
Es-ce que ça a une influance????

6. Pour terminer, j'ai essayé avec: permission java.security.AllPermission;
ça n'a rien changé.

Je te serai trés reconnaissant si tu arrive à éclairer ma lanterne. Parce
que ça commence à m'agacer de rester bloqué pour ce qui est certainement
une connerie qui est devant mon nez et que je n'arrive pas à voir.
1 2