Un piccolo esempio di proxy di un filesystem allo scopo di fare eseprimenti con RMI
Dopo che Stefano vi ha raccontato un po' di teoria sull'RMI, vediamo un piccolo esempio pratico.
Per l'impaziente...
Potete provare subito l'esempio di questa volta: scaricate il sorgente da qui e lanciate "remot.bat", l'esempio verrà compilato e lanciato. Vedrete che si apriranno due finestre (se tutto è andato bene :-) aggiuntive (rmiregistry e il server), mentre nella finestra da dove avete lanciato il ".bat" vedrete il contenuto di due directory e di un file.
Scopo dell'esempio
Per sperimentare un po' con RMI ho deciso di inventarmi un "proxy remoto" (parziale) di un oggetto File (proprio il java.io.File). Un RemoteFile che mi permetta di effettuare alcune operazioni sul filesystem del server via rete.
Partiamo col vederne le specifiche (UML naturalmente):
Figura 1 – Class diagram UML di RemoteFile
L'oggetto RemoteFile (è l'oggetto remoto) pubblica via RMI alcune operazioni che poi effettua sull'oggetto File a cui è stato associato in fase di creazione (vedere i costruttori).
Le operazioni effettuabili sono poche, data la necessità didattica dell'esempio, però nulla vieta di rendere più corposa la classe RemoteFile. Ecco i dettagli:
public String[] list()
serve a ottenere l'elenco dei contenuti (directory/files) del RemoteFile corrente
public RemoteFileI newFile(String nomeFile)
FACTORY METHOD (vedere articolo di Giovanni)
serve a creare un nuovo oggetto remoto (che quindi resta sul server) senza passare per bind/lookup
public RemoteFileI getParent()
ritorna un nuovo RemoteFile che punta alla directory superiore rispetto al corrente; usa newFile(...)
public InMemoryFile getContent()
ritorna una immagine (in memoria) del contenuto del file rappresentato
La classe InMemoryFile serve solo come wrapper di un array di byte, per poter spedire l'intero contenuto del file puntato da RemoteFile (attenzione a spedire file grossi!). Di per sé InMemoryFile NON è un vero proxy dato che contiene una copia del contenuto del file, se modificate la copia il file originario rimane invariato.
Implementazione
La cosa interessante e divertente è che RemoteFile non ha quasi nulla al suo interno: delega pressoché tutte le sue funzioni al File che rappresenta.
Ad esempio guardiamo il metodo getParent(), esso non fa altro che chiedere il parent al File e costruirgli attorno un nuovo RemoteFile:
public RemoteFileI getParent() throws RemoteException{
return newFile(file.getParent());
}
Idem per il metodo list(), che è ancora più banale.
Suggerimenti
Si può pensare di aggiungere il simmetrico del metodo getContent(), un qualche metodo che accetti (invece di fornire) un InMemoryFile e lo salvi su disco (o da qualche altra parte), qualcosa di questo tipo:
public void takeContent(InMemoryFile contentToWrite)
throws RemoteException{
System.out.println("Richiesto salvataggio su " + this);
FileOutputStream out=new FileOutputStream(this);
out.write(contentToWrite.content);
}
(più il try&catch naturalmente)
Per gli amanti dei pattern, la classe InMemoryFile sostanzialmente è uno State mentre il RemoteFile in questo caso farebbe le veci del CareTaker... :-)
Volendo si potrebbero aggiungere anche dei metodi read() e write() per permettere (con molta cautela) l'accesso diretto al File puntato.
Naturalmente grande cautela in realtà va usata in tutte quelle situazioni in cui (potenzialmente) più clienti accedono alla stessa risorsa, per di più in scrittura.
MokaByte®
è un marchio registrato da MokaByte s.r.l.
Java®, Jini® e tutti i nomi derivati sono marchi
registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione
anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it