MokaByte Numero  43 - Luglio Agosto 2000
Networking in Java  
V puntata: RMI  
la pratica
di 
Andrea Trentini
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):





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.
 

Chi volesse mettersi in contatto con la redazione può farlo scrivendo a mokainfo@mokabyte.it