Esercizio5:  Server attivabili parte I


1)Create in javarmi una directory activation ed al suo interno un package echo.

Al suo interno mettere i tre seguenti file:

a) l'interfaccia remota RemoteEcho.java:

package echo;

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

public interface RemoteEcho extends Remote
{
    Object echo(Object object) throws RemoteException;
}

b) Il server attivabile ActivatableEchoServer.java:

package echo;

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


public class ActivatableEchoServer
       extends  Activatable
       implements RemoteEcho,
                  Unreferenced
{
 public ActivatableEchoServer(ActivationID id,MarshalledObject data)
  throws RemoteException
 {
  super(id,2003);
  System.out.println("Constructed "+this);
 }
 
 protected void finalize() throws Throwable
 {
  System.out.println("finalize "+this);
  super.finalize();
 }
 
 public Object echo(Object object) { return object; }
 
 public void unreferenced()
 {
  try
  {
   boolean ok = inactive(getID());
   System.out.println(" Sono dentro il metodo unreferenced di ActivatableEchoServer");
   System.out.println(" L'oggetto {"+this+"} e' inattivo? "+ok);
                 System.out.close();
   // Get myself collected
   System.gc();
   System.runFinalization();
   System.out.println("L'oggetto attivabile e' stato garbage collected. PASSO ECHIUDO!");
  }
  catch (Exception e)
  {
   System.out.println("unreferenced: "+e);
                 System.out.close();
  }
 }
}


b) E la procedura di Setup seguente Setup.java:
package echo;

import java.io.*;
import java.net.*;
import java.rmi.*;
import java.rmi.activation.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.Properties;



/**
 * Setup RMI servers to be Activatable.
 *
 * @author Esmond Pitt
 * @version $Revision: 2 $
 */
public final class Setup
{ static Remote remote;
  public Setup(String codebase) throws ActivationException,
                                       UnknownGroupException,
                                       RemoteException,
                                       MalformedURLException
 {
  super();
  System.out.println("Sto eseguendo i comandi all'interno del costruttore di Setup");
  try
  {
   Properties properties = new Properties();
   properties.put("java.security.policy",System.getProperty("java.security.policy"));
   System.out.println("Le Properties sono state settate tramite: "+properties);
   System.out.println("Il codebase da dove verra' caricata la classe dell'oggetto attivabile e': "+codebase);
   // 3. Adesso creiamo un'istanza di tipo ActivationGroup
   // Usando il costruttore per ActivationDesc creiamo un descrittore di gruppo
   // Usando l'implementazione di gruppo per default.
   ActivationGroupDesc.CommandEnvironment ace = null;
   ActivationGroupDesc groupDesc = new ActivationGroupDesc(properties,ace);
   System.out.println("Abbiamo costruito l' ActivationGroupDescriptor: "+groupDesc);
   // registriamo il gruppo ed otteniamo il suo ID
   ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(groupDesc);
   System.out.println("Il gruppo e' stato registrato con groupID= "+agi);
   MarshalledObject data = null;
   ActivationDesc activationDesc = new ActivationDesc
    (
     agi,       // groupID
     ActivatableEchoServer.class.getName(), // nome della classe attivabile
     codebase,
     data
    );
   System.out.println("E' stato costruito l' ActivationDescriptor: "+activationDesc);
   // 5. Declare an instance of my remote interface - not really,
   // attraverso il metodo Activatable.register si registra l'oggetto attivabile e si
   // ottiene come risultato, da RMID,  una referenza remota (cioe' uno
   // stub) all'oggetto attivabile.
   remote = (Remote)Activatable.register(activationDesc);
   System.out.println("Ho registrato nel sistema di attivazione l'oggetto attivabile che puo' essere acceduto attraverso lo stub: "+"{"+remote+"}");
   // 6. Si lega lo stub ad un nome nel registro RMI
   System.out.println("Faccio il binding dello stub {"+remote+"} a cui diamo il nome {"+RemoteEcho.class.getName()+"} nel registro RMI: ");
   Naming.rebind("rmi://localhost:1098/"+RemoteEcho.class.getName(),remote);
  }
  finally
  { System.out.println("Sto uscendo dal costruttore di Setup.");
  }
 }
 
 public void test() throws RemoteException, NotBoundException, MalformedURLException
 {
  System.out.println("Faccio la lookup dell'oggetto il cui nome e' {"+RemoteEcho.class.getName()+"} nel registro RMI");
  RemoteEcho echo =
  (RemoteEcho)Naming.lookup("rmi://localhost:1098/"+RemoteEcho.class.getName());
  System.out.println("L'ho trovato! La lookup mi ha ritornato: {"+echo+"}");
  System.out.println("Invoco allora il suo metodo remoto echo.");
  System.out.println("Tale invocazione causera' l'attivazione del gruppo e dell'oggetto attivabile alla porta convenuta (la 2003)");
  System.out.println(echo.echo("SONO IL RISULTATO DELL'INVOCAZIONE DEL METODO echo DELL'OGGETTO REMOTO"));
  System.out.println(echo.echo("Il metodo test e' terminato!!!"));
//  System.out.println("Trying directly via register() result");
//  RemoteEcho echo = (RemoteEcho)remote;
//  System.out.println(echo.echo("o che bon eccho"));
 }

 // Main program
 public static void main(String args[])
 {
  System.out.println("Sto iniziando il programma main di Setup.");
  String codebase;
  if (args.length > 0)
   codebase = args[0];
  else
  {
   codebase = System.getProperty("java.rmi.server.codebase");
   if (codebase == null)
    codebase = "http://localhost/";
  }
  try
  {
   // NB different from tutorial which does it on the command line - why?
   System.setProperty("java.rmi.server.codebase",codebase);
   // Install a SecurityManager
   System.setSecurityManager(new RMISecurityManager());
   System.out.println("Creo un nuovo oggetto di tipo Setup invocando il suo costruttore.");
   Setup setup = new Setup(codebase);
   System.out.println("Adesso sono ritornato nel main del programma di Setup ed invoco il metodo test che fara' una lookup per ottenere (lo stub al)l'oggetto attivabile contenuto nel registro RMI");
   setup.test();
   System.out.println("Sono nuovamente nel main del programma di Setup!!!");
  }
  catch (Throwable t)
  {
   t.printStackTrace();
  }
  finally
  {
   System.gc();
   System.out.println("Ho fatto la garbage collection dal main del programma di Setup!!!");
   System.runFinalization();
   System.out.println("Ho lanciato il metodo System.runFinalization()dal main del programma di Setup!!!");
   // 7. Quit
   System.out.println("Stiamo per lanciare il comando System.exit(0) dal main del programma di Setup per uscire dalla JVM.");
   System.exit(0);

  }
 }
}


b) infine aggiungere il solito file di policy.

2)  dopodiche' compilare il codice in echo col comando javac *.java

3)  Fare la compilazione rmic

4) Copiare le classi in una directory comune ~/common/echo/

5)  lanciare il sistema di attivazione dalla directory activation con:

rmid -J-Djava.rmi.server.codebase=file://$HOME/common/ -J-Djava.security.policy=file://$HOME/javarmi/activation/echo/policy &

(se non funziona sostituire la variabile $HOME col proprio homepath)

6)  Lanciare da activation il seguente comando:

 java -Djava.rmi.server.codebase=file:///home/massimo/common/ -Djava.security.policy=file:///home/massimo/javarmi/activation/echo/policy echo.Setup

se tutto funziona vi spunta una videata del tipo:

Sto iniziando il programma main di Setup.
Creo un nuovo oggetto di tipo Setup invocando il suo costruttore.
Sto eseguendo i comandi all'interno del costruttore di Setup
Le Properties sono state settate tramite: {java.security.policy=file:///home/massimo/javarmi/activation/echo/policy}
Il codebase da dove verra' caricata la classe dell'oggetto attivabile e': file:///home/massimo/common/
Abbiamo costruito l' ActivationGroupDescriptor: java.rmi.activation.ActivationGroupDesc@0
Il gruppo e' stato registrato con groupID= java.rmi.activation.ActivationGroupID@92bc01de
E' stato costruito l' ActivationDescriptor: java.rmi.activation.ActivationDesc@4ccd9600
Ho registrato nel sistema di attivazione l'oggetto attivabile che puo' essere acceduto attraverso lo stub: {echo.ActivatableEchoServer_Stub[RemoteStub [ref: null]]}
Faccio il binding dello stub {echo.ActivatableEchoServer_Stub[RemoteStub [ref: null]]} a cui diamo il nome {echo.RemoteEcho} nel registro RMI:
Sto uscendo dal costruttore di Setup.
Adesso sono ritornato nel main del programma di Setup ed invoco il metodo test che fara' una lookup per ottenere (lo stub al)l'oggetto attivabile contenuto nel registro RMI
Faccio la lookup dell'oggetto il cui nome e' {echo.RemoteEcho} nel registro RMI
L'ho trovato! La lookup mi ha ritornato: {echo.ActivatableEchoServer_Stub[RemoteStub [ref: null]]}
Invoco allora il suo metodo remoto echo.
Tale invocazione causera' l'attivazione del gruppo e dell'oggetto attivabile alla porta convenuta (la 2003)
Wed Jun 04 14:23:38 CEST 2003:ExecGroup-1:out:Constructed echo.ActivatableEchoServer[RemoteStub [ref: [endpoint:[127.0.0.1:2003](local),objID:[1]]]]
SONO IL RISULTATO DELL'INVOCAZIONE DEL METODO echo DELL'OGGETTO REMOTO
Il metodo test e' terminato!!!
Sono nuovamente nel main del programma di Setup!!!
Ho fatto la garbage collection dal main del programma di Setup!!!
Ho lanciato il metodo System.runFinalization()dal main del programma di Setup!!!
Stiamo per lanciare il comando System.exit(0) dal main del programma di Setup per uscire dalla JVM.
[massimo@localhost activation]$ Wed Jun 04 14:23:38 CEST 2003:ExecGroup-1:out: Sono dentro il metodo unreferenced di ActivatableEchoServer
Wed Jun 04 14:23:38 CEST 2003:ExecGroup-1:out: L'oggetto {echo.ActivatableEchoServer[RemoteStub [ref: [endpoint:[127.0.0.1:2003](local),objID:[1]]]]} e' inattivo? true


7) STUDIATE ESATTAMENTE PASSO PASSO COSA AVVIENE E PERCHE'.