Newsgroup: it.comp.java
Titolo: RMIClassLoader e Bootstrap Client

Ciao ragazzi,
stavo esercitandomi con RMI e in particolare con il caricamento del client
prelevandolo dalla macchina server.
Ecco alcune indicazionisul mio ambiente di sviluppo:
Le mie classi sono in un package netinventions.rmitest e il classpath è così
configurato
C:\j2sdk1.4.1_01\sorgenti
All'interno del package ci sono le classi:
1. L'interfaccia dell'oggetto remoto
2. L'implementazione dell'oggetto remoto
3. La classe del Server
4. La classe LoadClient (la classe che risedierà sul client, la quale
caricherà il client vero e proprio)
5. Le classi stub e skeleton
6. i files policy e policyclient che per semplicità sono uguali e così
relaizzati:
grant{
 // Permetti tutto per ora
 permission java.security.AllPermission;
};
Il test lo eseguo su una singola macchina che fa da server e da client (in
questo momento ho a disposizione solo un computer :-))
Avviato l'rmiregistry con start rmiregistry
Faccio partire il Server con java -Djava.security.policy=policy
netinventions.rmitest.Server
A questo punto il server parte regolarmente e procedo all'avvio del
LoadClient nel seguente modo:
 java -Djava.security.policy=policyclient netinventions.rmitest.LoadClient
file://c:\j2sdk1.4.1_01\sorgenti\netinventions\rmitest pegaso
(pegaso è il nome del computer del server che in questo caso coincidono sia
per il server che per il client)
Ma a questo punto ottengo il seguente errore:
Exception: Client
java.lang.ClassNotFoundException: Client
        at java.net.URLClassLoader$1.run(URLClassLoader.java:198)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:186)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:217)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:427)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:159)
        at
java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:631)
        at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:169)
        at netinventions.rmitest.LoadClient.main(LoadClient.java:11)
Ho provato anche nel seguente modo, ma ottengo il seguente errore:
C:\Documents and Settings\user>java -Djava.security.policy=policyclient
netinventions.rmitest.LoadClient file://c:\j2sdk1.4.1_01\sorgenti\ pegaso
Exception: access denied (java.io.FilePermission \j2sdk1.4.1_01\sorgenti
read)
java.security.AccessControlException: access denied (java.io.FilePermission
\j2sdk1.4.1_01\sorgenti read)
        at
java.security.AccessControlContext.checkPermission(AccessControlContext.java
:270)
        at
java.security.AccessController.checkPermission(AccessController.java:401)
        at
java.lang.SecurityManager.checkPermission(SecurityManager.java:542)
        at java.lang.SecurityManager.checkRead(SecurityManager.java:887)
        at java.io.File.exists(File.java:677)
        at sun.net.www.protocol.file.Handler.openConnection(Handler.java:62)
        at java.net.URL.openConnection(URL.java:943)
        at
sun.rmi.server.LoaderHandler.addPermissionsForURLs(LoaderHandler.java:1013)
        at
sun.rmi.server.LoaderHandler.getLoaderAccessControlContext(LoaderHandler.jav
a:982)
        at sun.rmi.server.LoaderHandler.lookupLoader(LoaderHandler.java:853)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:378)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:159)
        at
java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:631)
        at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:169)
        at netinventions.rmitest.LoadClient.main(LoadClient.java:11)
Come mai? Vi ringrazio.
Mr.Deckard?

 client prelevandolo dalla macchina server.
Cerca "rmi codebase" sui vecchi post.
-- 
Fighting for peace is like fucking for virginity
ObjectZone - 
http://space.tin.it/computer/csadun


Ti ringrazio, ma scusami non sono venuto a capo di molto, mi spiego meglio:
quando io lancio il comando
java -Djava.security.policy=policyclient netinventions.rmitest.LoadClient
file://c:\j2sdk1.4.1_01\sorgenti\netinventions\rmitest pegaso
In realta passo alla Classe LoadClient due parametri:
uno è file://c:\............
l'altro pegaso (il nome del macchina server)
Il primo parametro viene passato a questa riga della classe LoadClient:
Class cl = RMIClassLoader.loadClass(new java.net.URL(args[0]), "Client");
Il parametro file://....  è rappresentato dal args[0].
Come si vede viene passato più esattamente a java.net.URL(), mi domando
allora è sbagliato il formato con dell'url che io passo??
Chiedo ancora grazie e scusa, ma sono un po' confuso
Grazie infinite
Mr. Deckard

 l'altro pegaso (il nome del macchina server)
Hai scordato una barra:
file:///c:/...
Gaetano

Ciao a tutti,
qualche giorno fa avevo già scritto sull'argomento e avevo ricevuto anche
qualche indicazione, trascorsi alcuni giorni, non essendo riuscito a
risolvere il problema, mi permetto di riscrivere sullo stesso tema,
scusatemi!
Su di un noto libro ho trovato un piccolo esercizio di programmazione
distribuita (RMI) nel quale si mostra come poter caricare anche il client
dal server (senza doverlo installare sulla macchina client), ovvero come
effettuare il bootstrap dell'applicazione client.
Tutto funziona, eccetto il bootsrap.
Prima di illustrarvi il problema vi espongo le condizioni di lavoro:
- Il test è effettuato su di una singola macchina che funge, dunque, da
server che da client (il nome della macchina è pegaso).
- Le classi e i file sorgenti sono conenuti nel seguente PATH
c:\j2sdk1.4.1_01\sorgenti\netinventions\rmitest
- Le classi appartengono al package netinventions.rmitest
- La CLASSPATH è c:\j2sdk1.4.1_01\sorgenti
Di seguito riporto il codice delle classi e delle interfaccie del semplice
test:
Interfaccia del servizio:




Interfaccia del servizio:
package netinventions.rmitest;
import java.rmi.*;
public interface Pinco extends Remote{
 abstract public int getValue() throws RemoteException;
}
Implementazione dell'interfaccia
package netinventions.rmitest;
import java.net.*;
import java.rmi.*;
import java.rmi.server.*;
public class PincoImpl extends UnicastRemoteObject implements Pinco{
 private int value = 0;
 public PincoImpl(String objName) throws RemoteException{
  //Costruttore di UnicastRemoteObject
  super();
  try{
   Naming.rebind(objName, this); // In questo caso il compito di registrare
l'oggetto stesso è affidato a esso stesso invece che al server
  }
  catch(MalformedURLException mue){
   mue.printStackTrace();
  }
 }
 public int getValue() throws RemoteException{
  return ++value;
 }
}
Classe Server:
package netinventions.rmitest;
import java.rmi.*;
public class Server{
 public static void main(String[] args){
  System.setSecurityManager(new RMISecurityManager());
  try{
   PincoImpl pi = new PincoImpl("PINCO");
  }
  catch(RemoteException re){
   re.printStackTrace();
  }
 }
}
Classe Client:
package netinventions.rmitest;
import java.rmi.*;
import java.net.*;
public class Client{
 public void run(String host){
  try{
   Pinco pinco = (Pinco)Naming.lookup("rmi://"+host+"/PIPPO");
   for(int i=0;i<10;i++)
    System.out.println("--->>> "+pinco.getValue());
  }
  catch(MalformedURLException mue){
   mue.printStackTrace();
  }
  catch(NotBoundException nbe){
   nbe.printStackTrace();
  }
  catch(java.rmi.UnknownHostException uhe){
   uhe.printStackTrace();
  }
  catch(RemoteException re){
   re.printStackTrace();
  }
 }
}
Classe LoadClient:
package netinventions.rmitest;
import java.rmi.RMISecurityManager;
import java.rmi.server.RMIClassLoader;
import java.net.*;
public class LoadClient{
 public static void main(String[] args){
  System.setSecurityManager(new RMISecurityManager());
  try{
                        URL url = new
URL("file:///c:/j2sdk1.4.1_01/sorgenti");
   Class cl = RMIClassLoader.loadClass(url, "netinvention.rmitest.Client");
   Client client = (Client)cl.newInstance();
   client.run("pegaso");
  }
  catch(Exception e){
   System.out.println("Exception: "+e.getMessage());
   e.printStackTrace();
  }
 }
}
Inoltre preparo i seguenti file di policy
File policy:
grant{
 // Permetti tutto per ora
 permission java.security.AllPermission;
 permission java.net.SocketPermission "*:1024-65535", "accept,
connect,listen";   //Ho provato anche senza questa riga
};
File policyclient
grant{
 // Permetti tutto per ora
 permission java.security.AllPermission;
};
A questo punto procedo alla compilazione dell'interfaccia, della sua
implementazione e delle classi Client, Server e LoadClient e alla
generazione dello stub e dello skeleton.
Fino a questo punti tutto OK.
Addesso avvio l'rmiregisty con uno start rmiregistry
avviato l'rmiregistry, avvio il Server nel seguente modo:
java -Djava.security.policy=policy netinventions.rmitest.Server
Il Server parte correttamente.
Ora viene la volta di avviare la classe LoadClient e la richiamo nel
seguente modo:
java -Djava.security.policy=policyclient.txt
netinventions.rmitest.LoadClient
Ma a questo punto ottengo il seguente errore:
Exception: access to class loader denied
java.lang.ClassNotFoundException: access to class loader denied
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:421)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:159)
        at
java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:631)
        at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:169)
        at netinventions.rmitest.LoadClient.main(LoadClient.java:14)
Caused by: java.security.AccessControlException: access denied
(java.io.FilePermission \c:\j2sdk1.4.1_01\- read)
        at
java.security.AccessControlContext.checkPermission(AccessControlContext.java
:270)
        at
java.security.AccessController.checkPermission(AccessController.java:401)
        at
java.lang.SecurityManager.checkPermission(SecurityManager.java:542)
        at
sun.rmi.server.LoaderHandler$Loader.checkPermissions(LoaderHandler.java:1128
)
        at
sun.rmi.server.LoaderHandler$Loader.access$000(LoaderHandler.java:1082)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:385)
        ... 4 more
Come mai?
Scusatemi per il messaggio troppo lungo, ma non riesco proprio a trovare
dove sia l'errore, dal momento che ho dato tutti i permessi.
Mi domando è corretta l'URL del path a cui prelevare il Clienti, ovvero  URL
url = new URL("file:///c:/j2sdk1.4.1_01/sorgenti");
vi ringrazio infinitamente.
Mr. Dekcard!

Il tuo codice gira perfettamente, devi solo correggere tre sviste:
- quando riporti il listato del file di policy del client chiami il file 
'policyclient', mentre quando avvii LoadClient lo chiami 
'policyclient.txt'; controlla di non avere errori su questo punto; sul 
server puoi evitare di usare un security manager, e dunque un file di 
policy;
- in LoadClient hai dimenticato la 's' di netinventions nel nome della 
classe (netinventions.rmitest.Client);
- l'oggetto remoto viene registrato come PINCO, ma fai il lookup con PIPPO.
Ciao,
Alberto
---
do...@mclink.it
---
JavaClass - Formazione Java e XML
java...@javaclass.it
http://www.javaclass.it


Grazie mille Alberto,
osservazioni più che precise.... l'ora a cui ho postato la dice lunga sulla
mia capiacità in quel momento di trovare errore.
Barvissimo, e grazie mille.
Mr. Deckard