Sistema di naming JNDI. 


              import java.rmi.Naming;
              MyRemote oggetto = (MyRemote)Naming.lookup("rmi://profs.sci.univr.it:2345/ServerRemoto);


              import javax.naming.*;
              Properties pr = new Properties();
              pr.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
              pr.put(Context.PROVIDER_URL,"rmi://profs.sci.univr.it:4567");
              InitialContext ctx = new InitialContext(pr);
              MyRemoto oggetto = (MyRemote)ctx.lookup(rmi://profs.sci.univr.it:4567/ServerRemoto);


         

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' vista in precedenza. La differenza consiste nel fatto che l'oggetto viene registrato nel 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.*;
/** Third Echo example; remote method invocation    */
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.*;

/** Third Echo example; remote method invocation    */

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 visulaizza 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("Viene settata la proprieta' java.naming.factory.initial.");
   props.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.rmi.registry.RegistryContextFactory");
   // L'URL del registro la immettiamo da linea di comando
   //props.put(Context.PROVIDER_URL,args[0]);
   // System.out.println("La proprieta' java.naming.provider.url la diamo da linea di comando.");
   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 h = new RemoteEchoServer();
   System.out.println("Facciamo la binding dell'oggetto " + RemoteEcho.class.getName() +" nel registro RMI.");
   cxt.rebind(RemoteEcho.class.getName(),h);
   System.out.println("Fatta la binding dell'oggetto " + RemoteEcho.class.getName()+ "  nel registro RMI.");
    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 da javarmi rmic -d ~/public_html/myclasses/  jndi.RemoteEchoServer. Qui sto supponendo che all'interno di public_html voi abbiate una directory myclasses, al cui intermo verra' creato (automaticamente) il package jndi con dentro gli stub.

4) Copiate la classe dell'interfaccia remota RemoteEcho.class nell'area comune, cioe' in ~/public_html/myclasses/jndi/.  Tale operazione e' necessaria perche' il sistema
     JNDI ha bisogno di caricare dinamicamente anche la classe dell'interfaccia remota.

5) Andate nella home directory e digitate unset CLASSPATH e poi lanciate il registro RMI con rmiregistry 4567 &. (ricordate E' IMPORTANTE che il registro sia lanciato in una directory che non possa vedere gli stub -- anche se chiusi dentro il package).

6) Ritornate nella directory javarmi e lanciate il programma di bind. Rimpiazzate (i) $HOME con la vostra home, (ii) cambiate il codebase usando la vostra homepage; (iii) cambiate il provider.url con le informazioni relative alla macchina e la porta su cui e' stato lanciato il registro RMI.  Esempio

java -classpath $HOME/javarmi/:$HOME/public_html/myclasses/    
         -Djava.rmi.server.codebase=http://arena..../myclasses/
         -Djava.naming.provider.url=rmi://delta45:4567 jndi.BindJNDI

Notate come il mentre il valore java.naming.initial.factory sia fornito da programma, 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 la binding dell'oggettojndi.RemoteEcho nel registro RMI.
Fatta la binding dell'oggetto remoto nel registro RMI.
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 codecie del client RemoteEchoClient.java:

package jndi;
import java.io.IOException;
import java.rmi.*;
import java.util.*;
import javax.naming.*;
import javax.rmi.*;

/**
 * JNDI client of javarmi.mytests.jndi.RemoteEcho.
 * Same as javarmi.mytests.quicktour.echo3.client.RemoteEchoClient,
 * except that it uses JNDI with the RMI Registry plugin,
 * instead of directly calling the Registry (by RemoteEchoFactory).
 */
public class RemoteEchoClient
{
 public static void main(String[] args)
 {
  try
  {
   System.setSecurityManager(new SecurityManager());
   Properties p = new Properties();
   p.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.rmi.registry.RegistryContextFactory");
   // Qui l'URL la diamo da programma.
   p.put(Context.PROVIDER_URL,"rmi://"+args[0]+":4567");
   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) Compililiamo 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 profs.sci.univr.it con la macchina dove gira il server.

java -Djava.security.policy=jndi/policy jndi.RemoteEchoClient profs.sci.univr.it

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