|
Vediamo subito l’implementazione dell’oggetto remoto:
package reverse;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
public class ReverseImpl
extends UnicastRemoteObject
implements Reverse
{
private static void log(String s) {
System.out.
println("ReverseServer "+s);
}
ReverseImpl()
throws java.rmi.RemoteException
{ super(); }
public String reverse(String s)
throws java.rmi.RemoteException
{
log("reverse: "+s);
StringBuffer sb
= new StringBuffer();
int n = s.length();
for(int i = n-1; i>=0; i--)
sb.append(s.charAt(i));
return sb.toString();
}
}
Osservazioni: innazitutto la classe deve implementare l’interfaccia che
vogliamo remotizzare, e deve essere una estensione di java.rmi.server.UnicastRemoteObject.
In realtà le classi del package java.rmi.server definiscono un framework
per lo sviluppo di vari tipi di oggetti remoti, ma si tratta di classi astratte
che oltre ad essere estese devono definire operazioni complesse. La sola classe
server pronta all’uso è UnicastRemoteObject. Tutte le operazioni di inizializzazione
e l’interazione con il registro (vedere più avanti) sono gestite dal costruttore
di questo oggetto, richiamato dal super() di ReverseImpl. In realtà così
com’è la dichiarazione del costruttore di default non sarebbe necessaria,
è solo stata esplicitata per chiarezza e per evidenziare il fatto che il
“lavoro sporco” di inizializzazione dell’oggetto è fatto dal costruttore della
classe base di ReverseImpl. Esportare l’oggetto
A questo punto il più è fatto. Ci rimane però di mettere in comunicazione
il server con il client. Quindi occorre innanzitutto fare un server che costruisce
rende disponibili ad altri l’implementazione. La classe server è la seguente:
package reverse;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
public class ReverseServer
{
private static void log(String s) {
System.out
.println("ReverseServer "+s);
}
public static void main(String[] args)
{
System.setSecurityManager
(new RMISecurityManager());
try {
log("Binding...");
ReverseImpl rs = new ReverseImpl();
Naming.rebind("reverse", rs);
log("READY");
} catch(Exception e) {
e.printStackTrace();
log(e.getMessage());
}
}
}
I passi da seguire sono:
- impostare un security manager
- creare una istanza della implementazione (l’oggetto server)
- esportarlo utilizzando le funzioni di Naming di RMI.
Il passo 1 è necessario perché un server di oggetti remoti è potenzialmente
molto pericoloso. Infatti internamente vengono caricati dalla rete le classi
stub, ed un hacker potrebbe imbrogliare le carte inviando una classe che sembra
uno stub ma in realtà fa delle cose dannose. Per questo motivo il RMISecurityManager
imposta possibilità di accesso ridotte per gli stub.
Il passo 2 è la creazione dell’oggetto server che deve essere creato prima
di poter essere esportato al passo 3. La funzione di Naming.rebind chiama
il registro di oggetti remoti e gli comunica che adesso esiste un oggetto
chiamato reverse, il quale può essere invocato remotamente. La registrazione
degli oggetti sul registro viene fatta utilizzando un URL il cui formato completo
è rmi://<host>:<port>/<object>. Abbreviando,
i default sono, per <host>, localhost, e per <port> 1099,
ma nulla vieta di registrare un oggetto in un registro che gira su un altro
host o che ascolta in un’altra porta.
|