Esercizio 6: Registri RMI attraverso JNDI.
L'esercizio consiste nel programmare un client ed un server remoto. Il
server fornisce un
oggetto remoto RemoteEcho come quello gia' visto in precedenza. La
differenza consiste
nel fatto che l'oggetto viene registrato su un registro RMI attraverso
JNDI. E similmente il
client accede all'oggetto utilizzando l'API di JNDI. Comiciamo a
descrivere le operazione che
deve fare il server.
1) Il server deve creare all'interno della directory javarmi una
directory jndi che fungera' da
package. All'interno di tale package mettteremo i seguenti
sorgenti:
a) L'interfaccia remota RemoteEcho.java constituita da:
package jndi;
import java.rmi.*;
public interface RemoteEcho extends Remote {
public Object echo(Object object) throws
RemoteException;
}
b) L'implentazione del server remoto RemoteEchoServer.java
costituito da:
package jndi;
import java.rmi.*;
import java.rmi.server.*;
public class RemoteEchoServer extends UnicastRemoteObject implements
RemoteEcho {
public RemoteEchoServer throws RemoteException;
public Object echo(Object
object) { return object; }
}
c) Un programma BindJNDI.java che si occupa di creare
un'istanza dell'oggetto remoto e
di legare tale istanza nel registro RMI; infine si visualizza il
contenuto del registro.
package jndi;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import javax.naming.*;
// Fa il Bind di un server RMI via JNDI.
// USIAMO com.sun.jndi.cosnaming.CNCtxFactory ( per CORBA IIOP
CosNaming),
// USIAMO com.sun.jndi.rmi.registry.RegistryContextFactory (per RMI
Registry).
public class BindJNDI {
public static void main(String[] args) {
try {
Properties props = new Properties();
System.out.println("Settiamo la proprieta'
java.naming.factory.initial.");
props.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.rmi.registry.RegistryContextFactory");
System.out.println("La proprieta'
java.naming.provider.url dove allocare il registro RMI e' settata col
valore " + System.getProperty("java.naming.provider.url"));
Context cxt = new InitialContext(props);
System.out.println("Viene creata un'istanza
dell'oggetto remoto. Si ricordi che un oggetto UnicastRemoteObject viene
esportato alla creazione.");
RemoteEcho server = new RemoteEchoServer();
System.out.println("Facciamo il binding
dell'oggetto " + RemoteEcho.class.getName() +" nel registro RMI.");
cxt.rebind(RemoteEcho.class.getName(),server);
System.out.println("Fatto il binding
dell'oggetto");
System.out.println("Stampiamo il contenuto
del registro RMI.");
NamingEnumeration list = cxt.list(""); // list or
listBindings
int j = 1;
while (list.hasMore()) {
NameClassPair item =
(NameClassPair)list.next();// NameClassPair or Binding
System.out.println(j+".\t"+item);
j++;
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
2) Compiliamo i sorgenti in jndi col comando javac *.java
3) eseguiamo la compilazione rmic digitando dalla direcotry javarmi:
rmic -d ~/public_html/common/
jndi.RemoteEchoServer.
4) Lanciate (correttamente) il registro RMI con rmiregistry 4567 &.
6) Ritornate nella directory javarmi e lanciate il programma di bind
facendo attenzione a settare il comando
con i valori del vostro host.
java -classpath
:/home/..../public_html/common/
-Djava.rmi.server.codebase=file:///home/....../public_html/common/
-Djava.naming.provider.url=rmi://profs.sci.univr.it:4567
jndi.BindJNDI
Notate che il valore java.naming.initial.factory e' fornito da
programma mentre il valore java.naming.provider.url
viene fornito da linea di comando. Ovviamente si puo' scegliere
una o l'altra opzione.
se tutto va bene vi apparira una schermata del tipo:
Viene settata la proprieta'
java.naming.factory.initial.
La proprieta'
java.naming.provider.url dove allocare il registro RMI e' settata col
valore rmi://profs.sci.univr.it:4567
Viene creata un'istanza dell'oggetto
remoto. Si ricordi che un oggetto UnicastRemoteObject viene esportato
alla creazione.
Facciamo il binding dell'oggetto
jndi.RemoteEcho nel registro RMI.
Fatto il binding dell'oggetto remoto.
Stampiamo il contenuto del registro
RMI.
1.
jndi.RemoteEcho: java.lang.Object
7) Passiamo al client. Anche lui deve creare una direcotry jndi
sotto javarmi. in tale directory oltre
all'interfaccia remota RemoteEcho.java vista prima, ed al solito
file di policy, mettiamo il codice
del client RemoteEchoClient.java:
package jndi;
import java.io.IOException;
import java.rmi.*;
import java.util.*;
import javax.naming.*;
import javax.rmi.*;
public class RemoteEchoClient {
public static void main(String[] args) {
try {
System.setSecurityManager(new
RMISecurityManager());
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
// L'URL la diamo da programma.
p.put(Context.PROVIDER_URL,args[0]);
InitialContext context = new
InitialContext(p);
RemoteEcho echo =
(RemoteEcho)context.lookup(RemoteEcho.class.getName());
System.out.println(echo.echo("Io
sono l'oggetto remoto con naming JNDI!!!!"));
}
catch (Exception e){
e.printStackTrace();
}
}
}
8) Compiliamo il codice del client facendo javac *.java.
9) A questo punto siamo pronti a lanciare il client andando in javarmi.
Ricordiamoci che dobbiamo usare
il file di policy poiche il client carichera' del codice dinamicamente
(lo stub). Chiaramente rimpiazzate
remotehost con la macchina dove gira il server.
java -Djava.security.policy=jndi/policy jndi.RemoteEchoClient
rmi://remotehost:4567
Notate che da linea di comando passiamo la macchina su cuio e' in
esecuzione il server. in questo esempio profs.sci.univr.it (voi
sostiutitelo con la macchina opportuna).
Se tutto va bene vi apparira' la scritta dovuta all'invocazione del
metodo remoto echo:
Io sono l'oggetto remoto con naming
JNDI!!!!