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
- getActNumber() , per fornire il numero di attivazione,
- getTransNumber() , per fornire il numero della transizione,
- getTransDateTime(), per fornire l'ora presso la macchina remota.
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:
- Si crea un gruppo di attivazione che viene registrato col
sistema di attivazione.
- Si crea un'istanza del server attivabile che viene
registrata col gruppo creato.
- Si registra il server attivabile su un registro RMI (in
questo caso quello alla porta 1098 usato da rmid)
- Infine, viene invocato un metodo di test che fa le seguenti cose:
- Una lookup sul registro 1098 per ottenere una referenza remota al
server.
- Invoca il metodo remoto del server attraverso lo stub ricavato
con la lookup.
- Visualizza il risultato dell'invocazione remota.
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:
- Viene creato un nuovo gruppo di attivazione che viene registrato
con il sistema di attivazione.
- Viene creato un nuovo server attivabile di cui si ottiene una
referenza remota.
- Si registra il server appena creato con il gruppo di attivazione
creato precedentemente.
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.