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!!!!