Esercizio 5: Server attivabili  (Leggete con attenzione il punto 11). 

In questa esercitazione lavoreremo con server attivabili. Il client ha una procedura
di bootstrap attraverso la quale carica dinamicamente da un codebase del server
due classi atttraverso cui invoca il metodo del server remoto. Cominciamo col
descrivere il codice da  installare sulla macchina server. Ricordate di sostituire
i miei dati con i vostri. Io ho assunto che il server giri su prof.sci.univr.it.
Voi dovete usare la vostra macchina.


1) Create una directory activation in javarmi. Nella directory javarmi/activation
create una sottodirectory datetime in cui mettere i seguenti codici:


1.a) L'interfaccia remota RemActDateTime.java che dichiara un metodo remoto che
 ritorna oggetti di tipo AcTrDate.

package datetime;
import java.rmi.*;
import java.rmi.activation.*;
import java.io.*;


public interface RemActDateTime extends Remote {
   public AcTrDate remAcTrDate()
              throws ActivationException, IOException, ClassNotFoundException;
}

Notate che il metodo remoto ritorna un oggetto di tipo AcTrDate.

1.b) AcTrDate.java: Un oggetto AcTrDate e' un oggetto di cui si possono invocare tre metodi

Questo oggetto serve per memorizzaro lo stato di attivazione di un server. Memorizzando il numero di
attivazione (ovvero quante volte e' stato attivato), il numero delle invocazione e l'ora presso
il server remoto.


package datetime;
import java.io.*;
import java.util.Date;

public class AcTrDate implements Serializable {
  int  activationNumber = 0;
  int  transactionNumber = 0;
  Date transactionDateTime;

   public AcTrDate(int an, int  tn, Date td){
     activationNumber    = an ;
     transactionNumber   = tn ;
     transactionDateTime = td ;
   }
   public int  getActNumber()     {return activationNumber;}
   public int  getTransNumber()   {return transactionNumber;}
   public Date getTransDateTime() {return transactionDateTime;}
}



1.c) L'implementazione dell'oggetto remoto RemActDateTimeServer.java e' riportata sotto.
Come noterete, dovete dedicare particolare cura sia al costruttore che al metodo remoto.
Notate che vie e' anche un metodo unreferenced, visto che il server implementa l'interfaccia
Unreferenced.


package datetime;
import java.io.*;
import java.rmi.*;
import java.rmi.activation.*;
import java.rmi.server.*;
import java.util.Date;

public class RemActDateTimeServer extends Activatable implements RemActDateTime, Unreferenced {
    public RemActDateTimeServer(ActivationID id,MarshalledObject atDate)
    throws ActivationException, IOException, ClassNotFoundException {
    super(id,0);
    System.out.println("");
    System.out.println(" Sono dentro il costruttore del server.");
    System.out.println(" E' stato invocato con successo il costruttore della superclasse Activatable, ");
    System.out.println(" passando come parametro l'ActivationID "+id+" del server. ");
    ActivationSystem actS = ActivationGroup.getSystem();
    System.out.println(" La referenza al sistema di attivazione e': "+actS);
    ActivationDesc   actD = actS.getActivationDesc(id);
    System.out.println(" Ho ricavato l' ActivationDescriptor "+actD+", associato al server attivabile grazie all'ActivationID= "+id);
    // Adesso creiamo un valore di defult per inizializzare il server.
    int an = 1; int tn = 0;
    if (atDate != null ) {
        AcTrDate fatDate = (AcTrDate)(atDate.get());
        an = fatDate.getActNumber()+1;
        tn = fatDate.getTransNumber();
    }
    AcTrDate natDate = new AcTrDate(an,tn,new Date());
    System.out.println(" Ho creato un oggetto " + natDate + " di tipo AcTrDate con cui inizializzare il server.");
    //Creiamo un nuovo ActivationDesc per il nostro server attivabile che contenga anche
    //Un valore di default.
    ActivationDesc nad = new ActivationDesc(actD.getGroupID(),actD.getClassName(),actD.getLocation(), new MarshalledObject(natDate));
    System.out.println(" Ho creato un nuovo ActivationDescriptor "+nad+" contenente il nuovo oggetto AcTrDate: "+natDate);
    actD = actS.setActivationDesc(id,nad);
    System.out.println(" Ho aggiornato l'ActivationDesc "+ actD+" del server, con l'informazione contenuta nell'ActivationDesc appena creato.");
    System.out.println(" Questa e' l'ultima istruzione del costruttore del server attivabile");
    }
 
    //Implementazione del metodo remoto.
    public AcTrDate remAcTrDate()
    throws ActivationException, IOException, ClassNotFoundException {
    System.out.println(" Sono dentro l'implementazione del metodo remoto remAcTrDate() del server attivabile");
    ActivationSystem actS = ActivationGroup.getSystem();
    System.out.println(" Ho ottenuto la seguente referenza al sistema di attivazione: "+actS);
    ActivationID id = getID();
    System.out.println(" Ho ottenuto il seguente ActivationID del server: "+id);
    ActivationDesc actD = actS.getActivationDesc(id);
    System.out.println(" Grazie a tale ActivationID ho ricavato l' ActivationDescriptor del server: "+actD);
    // Ricavo l'oggetto di tipo AcTrDate con cui il server e' correntemente settato.
    Object object = ((MarshalledObject)actD.getData()).get();
    AcTrDate fatDate = (AcTrDate)object;
    System.out.println("Dall'Activation Descriptor del server estraggo l'oggetto di tipo AcTrDate con cui il server e' correntemente settato: "+fatDate);
    int an = fatDate.getActNumber();
    int tn = fatDate.getTransNumber()+1;
    System.out.println("Creo un nuovo oggetto AcTrDate con il medesimo Activation Number, incremento il Transition Number, e prendo la data corrente");
    AcTrDate natDate = new AcTrDate(an,tn,new Date());
    System.out.println(" Ho creato il nuovo oggetto AcTrDate: "+natDate);
    ActivationDesc nad = new ActivationDesc(actD.getGroupID(),actD.getClassName(), actD.getLocation(), new MarshalledObject(natDate));
    System.out.println(" Ho creato un nuovo ActivationDescriptor "+nad+" contenente  il nuovo oggetto AcTrDate");
    actD = actS.setActivationDesc(id,nad);
    System.out.println(" Ho aggiornato l'ActivationDesc "+ actD+" del server, con l'informazione contenuta nell'ActivationDesc appena creato.");
    System.out.println(" Questa e' l'ultima istruzione del metodo remoto del server.");
    // Ok,  vanno riguardate con attenzione nella documentazione API.
    return natDate;
    }
 
    public void unreferenced() {
    try {
          System.out.println(" Sono dentro il metodo unreferenced del server remoto: " + this);
          boolean ok = inactive(getID());
          System.out.println(" Ho invocato il metodo inactive per disattivare il server attivabile");
          System.out.println(" Il server "+this+" e' inattivo? "+ok);
          // Get myself collected
          System.out.println(" Sto invocando il garbage collector dentro la JVM del server attivabile");
          System.gc();
          System.out.println(" Sto uscendo dal metodo unreferenced.");
      }
    catch (Exception e) {
        System.out.println("unreferenced: "+e);
        System.out.close();
    }
    }
}



1.d) Il programma Setup.java si occupa di fare il set-up del server remoto, ovvero:


package datetime;
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;


public final class Setup {
   
    private  static ActivationGroupID createActivationGroup()
      throws ActivationException, RemoteException {
      Properties properties = new Properties();
      properties.put("java.security.policy",System.getProperty("java.security.policy"));
      ActivationGroupDesc.CommandEnvironment config = null;
      ActivationGroupDesc groupDesc = new ActivationGroupDesc(properties,config);
      ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(groupDesc);
      return agi;
    }
   
    private static RemActDateTime createServer(ActivationGroupID groupID, String classname,
                                               String codebase, MarshalledObject data)
       throws ActivationException, RemoteException{
       ActivationDesc activationDesc = new ActivationDesc(groupID, RemActDateTimeServer.class.getName(), codebase,data);
       RemActDateTime stub_server = (RemActDateTime)Activatable.register(activationDesc);
       return stub_server;
       }

    private static void test() throws IOException, NotBoundException, MalformedURLException,
                                                     ActivationException, ClassNotFoundException {
        System.out.println("Sono dentro il metodo test() di Setup");
        System.out.println("Faccio una lookup sul registro RMI alla porta 1098 per ricavare lo stub al server attivabile "+RemActDateTime.class.getName());
        RemActDateTime atDateServ = (RemActDateTime)Naming.lookup("//localhost:1098/"+ RemActDateTime.class.getName());
        System.out.println("La lookup ha avuto successo ed ho ottenuto lo stub "+atDateServ);
        System.out.println("Si noti che poiche' lo stub non e' stato ancora utilizzato la sua RemoteRef e' a null.");
        System.out.println("Uso lo stub per invocare il metodo remoto remAcTrDate() del server attivabile");
        System.out.println("Poiche' e' la prima invocazione, cio' causera' il lancio della JVM del gruppo di attivazione relativo e successivamente il lancio del server.");
        System.out.println("Tale operazione prendera' qualche secondo");
        AcTrDate atDate = atDateServ.remAcTrDate();
        System.out.println("Visualizzo il risultato dell'invocazione: activation indica il numero di volte che e' stato attivato il server; transaction e' il numero           dell'invocazioni remote al server, infine viene fornita la data remota.");
        System.out.println("activation n. "+atDate.getActNumber()+", "+"transaction n. "+atDate.getTransNumber()+", "+"at remote date&time "+atDate.getTransDateTime());
        System.out.println("Visualizzo nuovamente lo stub al server dopo l'invocazione: "+atDateServ);
        System.out.println("Notate che adesso, dopo la prima invocazione, la RemoteRef non e' piu' a null");
        }


    public static void main(String args[]) {
       System.out.println("");
       System.out.println("Inizia la procedura main di Setup");
       String codebase;
       //Verifica che il codebase sia stato settato da linea di comando
       if (args.length > 0)
          codebase = args[0];
       else {
            codebase = System.getProperty("java.rmi.server.codebase");
            if (codebase == null)
                codebase = "file:///home/........ common/activation/";       //DA MODIFICARE CON I VOSTRI DATI
        // Sto assumendo di utilizzare un protocollo http se usate file cambiate di conseguenza.
       }
       System.out.println("Il codebase utilizzato durante l'attivazione e': "+codebase);
       try {
            //Ho settato il codebase che verra' usato nella creazione ed attivazione del server. 
            System.setProperty("java.rmi.server.codebase",codebase);
            System.setSecurityManager(new RMISecurityManager());
             System.out.println("Creo un gruppo di attivazione e lo registro col sistema di attivazione");
             ActivationGroupID agi = createActivationGroup();
             System.out.println("Il gruppo e' stato registrato, ed ha identificativo groupID= "+agi);
             MarshalledObject data = null;
             System.out.println("Iniziamo adesso la fase di registrazione del server attivabile utilizzando il groupID ");
             RemActDateTime stub_server = createServer(agi,RemActDateTimeServer.class.getName(),codebase,data);
             System.out.println("Ho registrato il server attivabile che adesso puo' essere acceduto attraverso lo stub: "+stub_server);
             System.out.println("Notate come la RemoteRef dello stub sia a null");
             System.out.println("Faccio il binding dello stub "+stub_server+", del server attivabile "+RemActDateTime.class.getName()+", nel registro RMI alla porta 1098 dove gia' si trova registrato il sistema di attivazione "+ ActivationGroup.getSystem());
             Naming.rebind("//localhost:1098/"+ RemActDateTime.class.getName(),stub_server);
             System.out.println("Adesso invoco il metodo test della classe Setup");
             test();
             System.out.println("E' terminato il metodo test della classe Setup");
             }
             catch (Throwable t){
                t.printStackTrace();
             }
   }
}



1.e) mettete  infine in javarmi il file di policy (inizialmente quello che fornisce tutti i diritti)
 visto che il sistema di attivazione effettua del caricamento dinamico di codice dall'area condivisa.


2) Compiliamo i sorgenti in datetime con javac *.java

3)  facciamo la compilazione rmic da activation digitando:

rmic -d ~/public_html/common/activation/ datetime.RemActDateTimeServer


4) Nota che l'implementazione del server, cioe' la classe RemActDateTimeServer.class, deve essere
caricata dinamicamente dal sistema di attivazione al momento dell'attivazione del server attivabile.
Per tale ragione spostiamo la sua classe, insieme alle classi RemActDateTime.class e AcTrDate.class,
nel codebase  ~/public_html/common/activation/datetime/. Nella directory javarmi/activation/datetime/
restera' quindi una sola classe, la Setup.class. L'unica che deve essere usata una volta sola quando si
lancia il Setup. Tale classe non verra' caricata dinamicamente.

5) Adesso in una finestra del server, lanciamo  il sistema rmid sostituendo codebase e indirizzo di
policy opportuni. Per comodita' lanciamo in una finestra differente del server.

 rmid -log ~/javarmi/activation/log-rmid/
          -J-Djava.rmi.server.codebase=file:///home..../common/activation/    
          -J-Djava.security.policy=/home/..../javarmi/policy &


L'attivazione di rmid vi creera' una directory su disco, li' dove avete indicato col parametro -log
Tale directory di log conterra' i file di log e conterra' le informazioni per riattivare i server
 attivabili registrati col sistema di attivazione. Poiche tale informazione e' persistente
(e' scritta su disco) i server attivabili sono persistenti e possono essere riattivati anche dopo
un reboot del server,  rilanciando il sistema di attivazione.

6) Lanciamo il programma di setup dalla directory activation in un altra finestra del server:

java   -classpath :/home.../public_html/common/activation/
         -Djava.rmi.server.codebase=file:///home/...../common/activation/
         -Djava.security.policy=/home/ .../javarmi/policy
          datetime.Setup


- Nella finestra in cui e' stato lanciato il codice di Setup vi apparira'  una videata di questo tipo:

Inizia la procedura main di Setup
Il codebase utilizzato durante l'attivazione e': file:///home/massimo/public_html/common/activation/
Creo un gruppo di attivazione e lo registro col sistema di attivazione
Il gruppo e' stato registrato, ed ha identificativo groupID= java.rmi.activation.ActivationGroupID@b6524b41
Iniziamo adesso la fase di registrazione del server attivabile utilizzando il groupID
Ho registrato il server attivabile che adesso puo' essere acceduto attraverso lo stub: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]
Notate come la RemoteRef dello stub sia a null
Faccio il binding dello stub datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]], del server attivabile datetime.RemActDateTime, nel registro RMI alla porta 1098 dove gia' si trova registrato il sistema di attivazione sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[127.0.0.1:1098](remote),objID:[0:0:0, 4]]]]
Adesso invoco il metodo test della classe Setup
Sono dentro il metodo test() di Setup
Faccio una lookup sul registro RMI alla porta 1098 per ricavare lo stub al server attivabile datetime.RemActDateTime
La lookup ha avuto successo ed ho ottenuto lo stub datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]
Si noti che poiche' lo stub non e' stato ancora utilizzato la sua RemoteRef e' a null.
Uso lo stub per invocare il metodo remoto remAcTrDate() del server attivabile
Poiche' e' la prima invocazione, cio' causera' il lancio della JVM del gruppo di attivazione relativo e successivamente il lancio del server.
Tale operazione prendera' qualche secondo
Visualizzo il risultato dell'invocazione: activation indica il numero di volte che e' stato attivato il server; transaction e' il numero dell'invocazioni remote al server, infine viene fornita la data remota.
activation n. 1, transaction n. 1, at remote date&time Mon May 24 11:24:51 CEST 2004
Visualizzo nuovamente lo stub al server dopo l'invocazione: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: sun.rmi.server.UnicastRef2@bfc93a]]
Notate che adesso, dopo la prima invocazione, la RemoteRef non e' piu' a null
E' terminato il metodo test della classe Setup
Mi accingo a fare la garbage collection dal main del programma di Setup.



Studiate attentamente queste righe di codice per capire esattamente cosa avviene e dove avviene.

7) Notate che nella finestra in cui e' stato lanciato il sistema di attivazione RMID,  nel momento stesso
in cui si invoca il metodo del server e quindi (poiche' e' inizialmente inattivo) lo si attiva, appare la s
chermata riportata sotto.  Tale schermata, mostra che, prima di eseguire il costruttore del server, viene
lanciato un gruppo d'attivazione. Dopodiche', poiche' il server era inattivo, vengono prima eseguite le
istruzioni all'interno del costruttore e solo dopo le istruzioni del metodo remoto invocato. Si noti che
il gruppo di attivazione ed il suo server vanno in esecuzione su una JVM differente da rmid.


Mon May 24 11:24:50 CEST 2004:ExecGroup-0:out:
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Sono dentro il costruttore del server.
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: E' stato invocato con successo il costruttore della superclasse Activatable,
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: passando come parametro l'ActivationID java.rmi.activation.ActivationID@b6524b43 del server.
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: La referenza al sistema di attivazione e': sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[127.0.0.1:1098](remote),objID:[0:0:0, 4]]]]
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho ricavato l' ActivationDescriptor java.rmi.activation.ActivationDesc@1af5200, associato al server attivabile grazie all'ActivationID= java.rmi.activation.ActivationID@b6524b43
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho creato un oggetto datetime.AcTrDate@7d5d2a di tipo AcTrDate con cui inizializzare il server.
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho creato un nuovo ActivationDescriptor java.rmi.activation.ActivationDesc@e6db4b3a contenente il nuovo oggetto AcTrDate: datetime.AcTrDate@7d5d2a
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho aggiornato l'ActivationDesc java.rmi.activation.ActivationDesc@1af5200 del server, con l'informazione contenuta nell'ActivationDesc appena creato.
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Questa e' l'ultima istruzione del costruttore del server attivabile
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Sono dentro l'implementazione del metodo remoto remAcTrDate() del server attivabile
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho ottenuto la seguente referenza al sistema di attivazione: sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[127.0.0.1:1098](remote),objID:[0:0:0, 4]]]]
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho ottenuto il seguente ActivationID del server: java.rmi.activation.ActivationID@b6524b43
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Grazie a tale ActivationID ho ricavato l' ActivationDescriptor del server: java.rmi.activation.ActivationDesc@e6db4b3a
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out:Dall'Activation Descriptor del server estraggo l'oggetto di tipo AcTrDate con cui il server e' correntemente settato: datetime.AcTrDate@a352a5
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out:Creo un nuovo oggetto AcTrDate con il medesimo Activation Number, incremento il Transition Number, e prendo la
data corrente
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho creato il nuovo oggetto AcTrDate: datetime.AcTrDate@86fe26
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho creato un nuovo ActivationDescriptor java.rmi.activation.ActivationDesc@b0586fb2 contenente  il nuovo oggetto AcTrDate
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Ho aggiornato l'ActivationDesc java.rmi.activation.ActivationDesc@e6db4b3a del server, con l'informazione contenuta nell'ActivationDesc appena creato.
Mon May 24 11:24:51 CEST 2004:ExecGroup-0:out: Questa e' l'ultima istruzione del metodo remoto del server.




Studiate questi passi uno alla volta e comprendete esattamente cosa succede e perche'.
 
7) Dopodiche' fate il seguente esperimento. Dalla macchina client invocate la ListRegistry, vista nella lezioni
 precedenti,  con parametro //delta...:1098, dove delta.... e' la macchina in cui e' stato creato il server attivabile.
Otterrete una videata di questo genere:

Contents of registry at rmi://profs.sci.univr.it:1098 (2 entries)
1.      name=rmi://profs.sci.univr.it:1098/java.rmi.activation.ActivationSystem
        remote=sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[157.27.252.10:1098](remote),objID:[0:0:0, 4]]]]
2.      name=rmi://profs.sci.univr.it:1098/datetime.RemActDateTime
        remote=datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]

Cioe' il registro contiene due elementi. Il primo e' il sistema di attivazione ed il secondo e' il server attivabile
datetime.RemActDateTime con referenza remota: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]].


8) Osservate che se spostate le classi dalla directory comune avrete problemi in fase di attivazione
del server poiche' il sistema di attivazione non riesce a trovare le classi per attivare il server. 
Le classi necessarie per lanciare il server non sono solo gli stub ma anche le classi dell'implementazione,
dell'interfaccia, e quelle su cui si basa l'interfaccia.


9) Passiamo a vedere il codice Client. Noi siamo interessati a caricamento dinamico del codice del client
dalla macchina server. Quindi mettiamo il codice del client sulla macchina del server. Piu precisamente,
sempre nella  directory javarmi/activation/datetime del server, mettiamo due sorgenti java:

a)  RemActDateTimeClient.java: che consiste nel codice client che si appoggia su una classe factory data di seguito.
package datetime;

package datetime;

import java.io.*;
import java.rmi.*;


public class RemActDateTimeClient implements Runnable {
    public void run() {
    try {
        System.out.println("Sto eseguendo il codice del Client, caricato dinamicamente dal codebase del server");
        System.out.println("Invoco il metodo getServ di RemActDateTimeFactory per ottenere la referenza remota al server attivabile");
        RemActDateTime atDateServ = RemActDateTimeFactory.getServ();
        System.out.println("La referenza remota ottenuta e': "+atDateServ);
        System.out.println("Adesso invoco il metodo remoto del server attivabile");
        System.out.println("Cio' causera'  l'attivazione del server, se al momento e' inattivo, e l'eventuale attivazione del gruppo di attivazione.");
        AcTrDate atDate = atDateServ.remAcTrDate();
        System.out.println("Ristampo nuovamente la referenza remota del server. Notate che la RemotRef adesso e' definita: "+atDateServ);
        System.out.println("Visualizzo il risultato dell'invocazione remota. Ovvero l'informazione racchiusa nell'oggetto AcTrDate.");
        System.out.println("Activation indica quante volte e' stato attivato il server, transaction conta le invocazione, ed infine diamo l'ora remota.");
        System.out.println("activation n. "+atDate.getActNumber()+", "+
                   "transaction n. "+atDate.getTransNumber() + ", " +
                   "at remote date&time "+atDate.getTransDateTime()
                   );
    }
    catch (Exception e)
        {
        e.printStackTrace();
        }
    }
}


b) RemActDateTimeFactory.java (sostituite i miei dati con i vostri).
Tale classe si occupa di recuperare la referenza remota da un file locale, se esiste,
oppure facendo una lookup sul registro RMI del server per poi memorizzare tale
referenza nel file locale per future invocazioni remote.


package datetime;
import java.io.*;
import java.rmi.*;
import java.net.*;


public class RemActDateTimeFactory {
 
 
    static final String reg = "//remotehost:1098/";    // DA MODIFICARE COL NOME DELLA MACCHINA DEL SERVER.
    // questa e' la locazione remota e la porta dove si trova il registro RMI
    // Sostuite profs con la macchina in cui avete il server attivabile.
    static final String saveProt="file://";
    static final String saveRef=System.getProperty("user.dir")+"/.RemAcTrDateTimeRef";
    //questo e' il file locale al client in cui memorizzo la referenza remota.
    //user.dir vuol dire la directory corrente. Percio' nella direcotry corrente
    // del cliente viene memorizzato la referenza nel file .RemAcTrDateTimeRef.
    static RemActDateTime persRef = null;

    public static RemActDateTime getServ()
         throws IOException, NotBoundException,
         ClassNotFoundException, java.net.MalformedURLException {
        System.out.println("Sono dentro il metodo getServ() di RemActDateTimeServer");
        if (persRef == null)
        try {
        InputStream in = new URL(saveProt+saveRef).openStream();
        System.out.println("Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile e' stato trovato.");
        System.out.println("Facciamo allora l'unmarshalling per ottenere la referenza dal file.");
        ObjectInputStream oin = new ObjectInputStream(in);
        Object object = ((MarshalledObject)oin.readObject()).get();
        persRef = (RemActDateTime)object;
        }
        catch (FileNotFoundException e) {
        System.out.println("Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile NON e' stato trovato.");
        System.out.println("Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile sara' creato in: "+saveRef);
        System.out.println("Facciamo allora una lookup sulla macchina remota per ottenere la referenza remota all'oggetto");
        persRef = (RemActDateTime)Naming.lookup(reg+RemActDateTime.class.getName());
        OutputStream out = new FileOutputStream(saveRef);
        ObjectOutputStream oout = new ObjectOutputStream(out);
        oout.writeObject(new MarshalledObject(persRef));
        oout.close();
        System.out.println("Dopodiche' ci preoccupiamo di salvare la referenza remota al server attivabile, nel file .RemAcTrDateTimeRef, della directory corrente per successive invocazioni.");
        }
    return persRef;
    }
}



10) Compilate presso il server, in javarmi/activation/datetime le classi client con le relative
interfacce remote:

        javac  RemActDateTime.java AcTrDate.java  RemActDateTimeClient.java  RemActDateTimeFactory.java

11) Dopodiche' spostate le classi generate in una seconda area comune del server (possibilmente diversa
da quella utilizzata prima).  Ad esempio,  ~/public_html/common/client/datetime/ , accertandovi di fornire
 i diritti di lettura ed esecuzione. Facciamo allora:

        mv RemActDateTime.class AcTrDate.class RemActDateTimeClient.class  
              RemActDateTimeFactory.class   ~/public_html/common/client/datetime/


IMPORTANTE: Nella classe ~/public_html/common/client/datetime/  e' necessario mettere anche una copia degli
stub che verranno caricati dinamicamente dal codice client quando effettua la lookup. Nota che abbiamo due copie degli
stub: una in ~/public_html/common/activation/datetime/per il sistema di attivazione che dovra' attivare i server, ed
una in ~/public_html/common/client/datetime/  per consentire al codice client di fare la lookup sul registro alla porta
1098 ed ottenere una referenza al server attivabile.

COMMENTO:  A pensarci bene, creare una copia degli stub nell'aria condivisa di accesso al client e' perfettamente
legittimo ed auspicabile. Nell'area ~/public_html/common/client/datetime/dobbiamo mettere tutto e sole le classi
che il client dovra' caricare dinamicamente. E tra queste, come di norma, ci sono anche le classi stub. Nessun trucco.
Per ovviare il problema di cast in fase di esecuzione del client ci potrebbero essere due soluzioni, entrambe poco
pulite:

i) Nel codice di URLClientBootstrap.java,  quando fissate il codebase mettete,  anche
.../public_html/common/activation/datetime/,
 ovvero qualcosa del genere:

static final String codebase = "file:///home/massimo/public_html/common/client/ file:///home/massimo/public_html/activation/client/"

tale soluzione non e' accetttabile perche' forniamo al codice di bootstrap del server un'informazione
sul fatto che esiste un'altra area condivisa presso il server di cui il client non dovrebbe venire a
conoscenza.

ii) Un altra soluzione sarebbe quella di fornire al codice URLClientBootstrap.java anche le classi
RemActDateTime.java e AcTrDate.java e compilarle presso il client. Ma anche questo e' superfluo
perche' non c'e' motivo per cui il client deve essere in possesso di tali classi visto che il caricamento
del codice e' dinamico.


12)  Andiamo adesso nella macchina Client. E mettiamo nella directory ~/javarmi/activation/datetime/
il seguente codice minimale per il caricamento dinamico delle classi clienti: URLClientBootstrap.java
(anche qui sostituire i mie dati con quelli vostri)

package datetime;
import java.io.*;
import java.net.*;
import java.rmi.server.*;

public class URLClientBootstrap{
    static final String codebase = "......................../common/client/";  //DA MODIFICARE CON I VOSTRI DATI
    //qui va messa l'area condivisa da cui caricare il client.
    static final String clientClass = "datetime.RemActDateTimeClient";
    public static void main(String[] args) throws Exception{
    System.setSecurityManager(new SecurityManager());
    Class cl = RMIClassLoader.loadClass(codebase,clientClass);
    Runnable client = (Runnable)cl.newInstance();
    client.run();
    }
}

13) Nella directory datetime del client aggiungiamo il file di policy (visto che vi e' il caricamento di codice dinamico).

14) Compiliamo il sorgente sopra indicato.

15)  Lanciamo il codice di bootstrap dalla macchina client, dalla directory activation con:

        java -Djava.security.policy=../policy datetime.URLClientBootstrap

16) La prima volta che lo lanciate vi apparira' una videata del tipo:

Sto eseguendo il codice del Client, caricato dinamicamente dal codebase del server
Invoco il metodo getServ di RemActDateTimeFactory per ottenere la referenza remota al server attivabile
Sono dentro il metodo getServ() di RemActDateTimeServer
Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile NON e' stato trovato.
Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile sara' creato in: /home/massimo/javarmi/activation/CLIENT/.RemAcTrDateTimeRef
Facciamo allora una lookup sulla macchina remota per ottenere la referenza remota all'oggetto
Dopodiche' ci preoccupiamo di salvare la referenza remota al server attivabile, nel file .RemAcTrDateTimeRef, della directory corrente per successive invocazioni.
La referenza remota ottenuta e': datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]
Adesso invoco il metodo remoto del server attivabile
Cio' causera'  l'attivazione del server, se al momento e' inattivo, e l'eventuale attivazione del gruppo di attivazione.
Ristampo nuovamente la referenza remota del server. Notate che la RemotRef adesso e' definita: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: sun.rmi.server.UnicastRef2@1121f6]]
Visualizzo il risultato dell'invocazione remota. Ovvero l'informazione racchiusa nell'oggetto AcTrDate.
Activation indica quante volte e' stato attivato il server, transaction conta le invocazione, ed infine diamo l'ora remota.
activation n. 1, transaction n. 2, at remote date&time Mon May 24 11:27:10 CEST 2004

-- Notate che il client cerca di vedere se ha gia' la referenza nel file .RemAcTrDateTimeRef
della directory corrente (la mia non e' necessariamente uguale alla vostra).  Poiche' e' la prima volta,
non trovera' tale file e' tentera' di fare una looup sul registro alla porta 1098 per ottenere lo stub al
server. Una volta ottenuta la referenza verra memorizzata nel file .RemAcTrDateTimeRef  per successivi
accessi.
-- L'ultima linea sta ad indicare che l'oggetto e' stato attivato una volta (dalla Setup) ed invocato due volte (una volta dal
metodo test della Setup ed un'altra adesso). Infine viene fornita l'ora di invocazione.

17) Nel frattempo nella finestra dove e' stato lanciato il sistema di attivazione viene notato che l'oggetto e' stato invocato.
 E poiche' l'oggetto era disattivo viene attivato insieme al suo gruppo di attivazione ed appare la seguente videata:
Per verificare che il server e' attivo basta digitare il comando ps dalla finestra di RMID per notare che c'e' un processo
java in esecuzione. Per l'appunto il server attivabile.

Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out: Sono dentro l'implementazione del metodo remoto remAcTrDate() del server attivabile
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out: Ho ottenuto la seguente referenza al sistema di attivazione: sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[127.0.0.1:1098](remote),objID:[0:0:0, 4]]]]
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out: Ho ottenuto il seguente ActivationID del server: java.rmi.activation.ActivationID@b6524b43
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out: Grazie a tale ActivationID ho ricavato l' ActivationDescriptor del server: java.rmi.activation.ActivationDesc@b0586fb2
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out:Dall'Activation Descriptor del server estraggo l'oggetto di tipo AcTrDate con cui il server e' correntemente settato: datetime.AcTrDate@34a7d8
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out:Creo un nuovo oggetto AcTrDate con il medesimo Activation Number, incremento il Transition Number, e prendo la
data corrente
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out: Ho creato il nuovo oggetto AcTrDate: datetime.AcTrDate@f78ef1
Mon May 24 11:27:10 CEST 2004:ExecGroup-0:out: Ho creato un nuovo ActivationDescriptor java.rmi.activation.ActivationDesc@7dd386b4 contenente  il nuovo oggetto AcTrDate
Mon May 24 11:27:11 CEST 2004:ExecGroup-0:out: Ho aggiornato l'ActivationDesc java.rmi.activation.ActivationDesc@b0586fb2 del server, con l'informazione contenuta nell'ActivationDesc appena creato.
Mon May 24 11:27:11 CEST 2004:ExecGroup-0:out: Questa e' l'ultima istruzione del metodo remoto del server.


IMPORTANTE:

Notate che poiche' il server e' gia' attivo, stavolta non viene eseguito il suo costruttore e quindi non
viene creato un nuovo gruppo di attivazione ma l'implemetazione del metodo avviene all'interno del
gruppo di attivazione in cui il server e' stato attivato.


18) Se lanciamo ancora il client ancora il client questi avra' una schermata leggermente differente:


Sto eseguendo il codice del Client, caricato dinamicamente dal codebase del server
Invoco il metodo getServ di RemActDateTimeFactory per ottenere la referenza remota al server attivabile
Sono dentro il metodo getServ() di RemActDateTimeServer
Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile e' stato trovato.
Facciamo allora l'unmarshalling per ottenere la referenza dal file.
La referenza remota ottenuta e': datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]
Adesso invoco il metodo remoto del server attivabile
Cio' causera'  l'attivazione del server, se al momento e' inattivo, e l'eventuale attivazione del gruppo di attivazione.
Ristampo nuovamente la referenza remota del server. Notate che la RemotRef adesso e' definita: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: sun.rmi.server.UnicastRef2@388993]]
Visualizzo il risultato dell'invocazione remota. Ovvero l'informazione racchiusa nell'oggetto AcTrDate.
Activation indica quante volte e' stato attivato il server, transaction conta le invocazione, ed infine diamo l'ora remota.
activation n. 1, transaction n. 3, at remote date&time Mon May 24 11:33:36 CEST 2004



-Infatti la prima volta il client ha  cercato nella vostra directory corrente (javarmi/activation/) il file
.RemAcTrDateTimeRef per ottenere la referenza remota all'oggetto attivabile. Tale file non esisteva
ancora e quindi e' stata fatta fatta la lookup nel registro RMI alla porta 1098 per ottenere la referenza
che e' poi e' stata memorizzata nel file suddetto (nella directory corrente) per le successive invocazioni.

- La seconda volta il client non ha bisogno di fare la lookup e ricava la referenza remota all'oggetto
attivabile dal suo file  locale .RemAcTrDateTimeRef dove l'ha memorizzato la prima volta.

- Inoltre l'ultima linea evidenzia che il server e' stato attivato due volte ed invocato 3 volte.
 Infatti l'ultima volta, essendo gia' attivo lo si e' invocato senza doverlo attivare prima.


19) Anche qui studiate attentamente il codice del client che viene caricato dinamicamente.


20) Per verificare la persistenza della referenza remota al server attivabile andate sul server,
sulla finestra di rmid e fate rmid -stop; vi apparira' una scritta: activation daemon shut down. 
Tale comando causa infatti lo shut-down del sistema di attivazione rmid ed anche lo shut-down
del registro RMI alla porta 1098,  come potete verificare rilanciando ListRegistry. Infatti se
rilanciate ListRegistry sul registro alla porta 1098 ritornera' un'eccezione perche' non trova
piu'  il registro.

Se adesso provate a rilanciare il Client a questo punto avrete un'eccezione perche'
lo stub non trova il sistema di attivazione con cui interagire.


22) Se pero' rilanciate il sistema di attivazione rmid, come fatto prima, allora potete subito dopo
rilanciare il clientm il quale, invocando il metodo remoto causera' l'attivazione del server remoto.
Come viene evidenziato nella finestra sul server dove e' stato lanciato rmid.  Notate che rilanciando
rmid rilanciate anche il registro RMI alla porta 1098 (se non diversamente specificato)
in cui pero' stavolta vi sara' registrato il solo sistema di attivazione (potete verificarlo con la
Listregistry).  Infatti il server lo avevamo espressamente registrato nella setup.

-Il client avra' la videata seguente in cui viene evidenziato che il server e' stato  attivato per la
seconda volta (ed invocato per la quarta volta)!

Sto eseguendo il codice del Client, caricato dinamicamente dal codebase del server
Invoco il metodo getServ di RemActDateTimeFactory per ottenere la referenza remota al server attivabile
Sono dentro il metodo getServ() di RemActDateTimeServer
Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile e' stato trovato.
Facciamo allora l'unmarshalling per ottenere la referenza dal file.
La referenza remota ottenuta e': datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]
Adesso invoco il metodo remoto del server attivabile
Cio' causera'  l'attivazione del server, se al momento e' inattivo, e l'eventuale attivazione del gruppo di attivazione.
Ristampo nuovamente la referenza remota del server. Notate che la RemotRef adesso e' definita: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: sun.rmi.server.UnicastRef2@388993]]
Visualizzo il risultato dell'invocazione remota. Ovvero l'informazione racchiusa nell'oggetto AcTrDate.
Activation indica quante volte e' stato attivato il server, transaction conta le invocazione, ed infine diamo l'ora remota.
activation n. 2, transaction n. 4, at remote date&time Mon May 24 11:35:50 CEST 2004


Poiche' sul registro RMI alla porta 1098 non vi e' piu' la referenza remota al server ne deriva che
il client funziona solo perche' prende la referenza remota all'oggetto dal file locale .RemAcTrDateTimeRef
dove l'aveva memorizzata precedentemente. Se pero' cancellaste il file .RemAcTrDateTimeRef, il client proverebbe
a fare la lookup sul registro RMI alla porta 1098 e fallirebbe perche' non vi troverebbe piu' la referenza remota
al server remoto attivabile.


23) Se non interagite con il server attivabile  per un 'po di tempo (5-10 minuti)  lui si disattivera' da solo,
a seguito dell'invocazione del metodo unreferenced da parte del sistema RMI,  e sulla finestra di RMID apparira'
 qualcosa del genere:


Mon May 24 11:50:49 CEST 2004:ExecGroup-0:out: Sono dentro il metodo unreferenced del server remoto: datetime.RemActDateTimeServer[RemoteStub [ref: [endpoint:[127.0.0.1:48163](local),objID:[1]]]]
Mon May 24 11:50:49 CEST 2004:ExecGroup-0:out: Ho invocato il metodo inactive per disattivare il server attivabile
Mon May 24 11:50:49 CEST 2004:ExecGroup-0:out: Il server datetime.RemActDateTimeServer[RemoteStub [ref: [endpoint:[127.0.0.1:48163](local),objID:[1]]]] e' inattivo? true
Mon May 24 11:50:49 CEST 2004:ExecGroup-0:out: Sto invocando il garbage collector dentro la JVM del server attivabile
Mon May 24 11:50:49 CEST 2004:ExecGroup-0:out: Sto uscendo dal metodo unreferenced.



24) Se dopo la disattivazione automatica un'ulteriore invocazione da parte del client causera'
Lo riattivazione del server con una videata di questo tipo sullo schermo del client, segnalando
che il server e' stato attivato per la terza volta:

Sto eseguendo il codice del Client, caricato dinamicamente dal codebase del server
Invoco il metodo getServ di RemActDateTimeFactory per ottenere la referenza remota al server attivabile
Sono dentro il metodo getServ() di RemActDateTimeServer
Il file .RemAcTrDateTimeRef dove memorizziamo la referenza all'oggetto attivabile e' stato trovato.
Facciamo allora l'unmarshalling per ottenere la referenza dal file.
La referenza remota ottenuta e': datetime.RemActDateTimeServer_Stub[RemoteStub [ref: null]]
Adesso invoco il metodo remoto del server attivabile
Cio' causera'  l'attivazione del server, se al momento e' inattivo, e l'eventuale attivazione del gruppo di attivazione.
Ristampo nuovamente la referenza remota del server. Notate che la RemotRef adesso e' definita: datetime.RemActDateTimeServer_Stub[RemoteStub [ref: sun.rmi.server.UnicastRef2@388993]]
Visualizzo il risultato dell'invocazione remota. Ovvero l'informazione racchiusa nell'oggetto AcTrDate.
Activation indica quante volte e' stato attivato il server, transaction conta le invocazione, ed infine diamo l'ora remota.
activation n. 3, transaction n. 5, at remote date&time Mon May 24 11:56:25 CEST 2004


25) Mentre sullo schermo del server dove e' stato lanciato rmid apparira' una videata che evidenzia il fatto che
il server viene riattivato e cosi' anche il suo gruppo di attivazione che era stato disattivato poice' contenente un solo
server.


Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out:
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: Sono dentro il costruttore del server.
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: E' stato invocato con successo il costruttore della superclasse Activatable,
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: passando come parametro l'ActivationID java.rmi.activation.ActivationID@b6524b43 del server.
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: La referenza al sistema di attivazione e': sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[127.0.0.1:1098](remote),objID:[0:0:0, 4]]]]
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: Ho ricavato l' ActivationDescriptor java.rmi.activation.ActivationDesc@fdd224f0, associato al server attivabile grazie all'ActivationID= java.rmi.activation.ActivationID@b6524b43
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: Ho creato un oggetto datetime.AcTrDate@81edf4 di tipo AcTrDate con cui inizializzare il server.
Mon May 24 11:56:24 CEST 2004:ExecGroup-1:out: Ho creato un nuovo ActivationDescriptor java.rmi.activation.ActivationDesc@e62ea04e contenente il nuovo oggetto AcTrDate: datetime.AcTrDate@81edf4
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Ho aggiornato l'ActivationDesc java.rmi.activation.ActivationDesc@fdd224f0 del server, con l'informazione contenuta nell'ActivationDesc appena creato.
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Questa e' l'ultima istruzione del costruttore del server attivabile
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Sono dentro l'implementazione del metodo remoto remAcTrDate() del server attivabile
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Ho ottenuto la seguente referenza al sistema di attivazione: sun.rmi.server.Activation$ActivationSystemImpl_Stub[RemoteStub [ref: [endpoint:[127.0.0.1:1098](remote),objID:[0:0:0, 4]]]]
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Ho ottenuto il seguente ActivationID del server: java.rmi.activation.ActivationID@b6524b43
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Grazie a tale ActivationID ho ricavato l' ActivationDescriptor del server: java.rmi.activation.ActivationDesc@e62ea04e
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out:Dall'Activation Descriptor del server estraggo l'oggetto di tipo AcTrDate con cui il server e' correntemente settato: datetime.AcTrDate@97a560
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out:Creo un nuovo oggetto AcTrDate con il medesimo Activation Number, incremento il Transition Number, e prendo la
data corrente
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Ho creato il nuovo oggetto AcTrDate: datetime.AcTrDate@ea5671
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Ho creato un nuovo ActivationDescriptor java.rmi.activation.ActivationDesc@b3abb720 contenente  il nuovo oggetto AcTrDate
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Ho aggiornato l'ActivationDesc java.rmi.activation.ActivationDesc@e62ea04e del server, con l'informazione contenuta nell'ActivationDesc appena creato.
Mon May 24 11:56:25 CEST 2004:ExecGroup-1:out: Questa e' l'ultima istruzione del metodo remoto del server.



26) Fate il seguente esperimento. Arrestate rmid, e cancellate la directory dei log. Dopodiche'
 rilanciate rmid e provate a lanciare il client. Vedrete che il client fallisce poiche' la referenza che ha
memorizzato nel file .RemAcTrDateTimeRef non e' piu' valida dato che il database del sistema di
attivazione e' stato distrutto. Non serve neppure cancellare il file  =.RemAcTrDateTimeRef e forzare
 il client a fare una lookup sul registro RMI, perche' come detto in tale registro non vi e' piu' uno stub al
server attivabile. L'unica possibilita' e rifare il Setup in cui si creano il gruppo di attivazione ed il
server attivabile.


27) Si noti che quando si lancia il codice di Setup avvengono le seguenti cose:

Di conseguenza, quando il client ottiene una referenza ad un server, interagira' sempre col
medesimo gruppo di attivazione di quel server.

Fate allora il seguente esperimento. Dopo aver rilanciato il sistema rmid e cancellati i file
.RemAcTrDateTimeRef,  contenenti referenze ormai obsolete, lanciate in sequenza: 
(i) la Setup dalla macchina server;  (ii) l'applicazione client da una certa macchina client,
(iii) nuovamente la Setup dalla macchina server, (iv) ed un'altra volta l'applicazione Client
ma da un'altra macchina
(e' sufficiente da un'altra directory che non abbia accesso al
file .RemAcTrDateTimeRef). Vi renderete conto che la prima applicazione
client interagisce con un'istanza del server registrata con un gruppo di attivazione, mentre la seconda
applicazione client interagisce con un'altra istanza del server registrato con un altro gruppo di attivazione.
Tale registrazione e' avvenuta durante la seconda esecuzione di Setup. E' facile osservare che le
due applicazioni ritornano valori differenti di activation  e transition number perche si riferiscono
a due server differenti registrati con gruppi di attivazione diversi. Il fatto che si lavori con gruppi
diversi puo' essere anche osservato dalle videate che appaiono sulla finestra di rmid.


28) Per ultimo rifare l'esercizio costruendo i file di policy minimi.