Prefazione
Per
chi fosse digiuno di JINI, l’argomento di cui trattiamo è la famigerata
“distributed computing”. JINI è una tecnologia Java basata sul concetto
di federazione di dispositivi. In pratica, una rete JINI è composta
di una serie di entità in grado di fornire dei servizi ( computer,stampanti,scanner,programmi
etc.), che al loro ingresso nella rete si registrano, comunicando la loro
presenza a tutta la rete e rendendo altresì disponibili i drivers
per il loro utilizzo. Nel momento in cui una macchina accede alla federazione
, tramite un servizio di “lookup” ha la possibilità di sapere quali
servizi sono resi disponibili e da chi. A questo punto ( privilegi permettendo)
è in grado di accedervi e di utilizzarli. Grossomodo questa è
la descrizione più semplice e banale di una struttura JINI.
JavaSpaces
è una tecnologia JINI basata sulla creazione di spazi virtuali (
Spaces appunto), in grado di “ospitare” degli oggetti.Tramite questi spazi
condivisi e accessibili in rete, diversi applicativi possono comunicare
scambiandosi dati. Niente di particolare fin qui. Già, però
se consideriamo che gli oggetti ospitati in un Java Space possono anche
essere del codice, che la tecnologia mette a disposizione, spazi virtuali
sia estemporanei che persistenti ( cioè in grado di conservare i
dati anche in seguito ad un crash), che è già implementata
la gestione delle transazioni, e che gli applicativi che vi accedono possono
risiedere su macchine diverse, il tutto si fa molto più interessante.
In pratica ci troviamo in mano uno strumento che permette di costruire
applicativi distribuiti con una semplicità quasi sconvolgente (si,
ho esagerato un pò !!!) senza dover rinunciare a caratteristiche
di sicurezza ed affidabilità di tutto rispetto.
Uno
degli infiniti campi di applicazione degli spaces è l’elaborazione
di dati distribuita, ad esempio il rendering di realtà virtuale.
Possiamo immaginare un processo server che suddivide il lavoro in una serie
di task e mette i task in uno space. I client, prenderanno ognuno un task
dallo space e lo elaboreranno, restituendone poi il risultato. Quando tutti
i task saranno stati completati, il server potrà prendere tutti
i risultati parziali e comporre quello finale( nel nostro caso l’immagine).
Non importa quanti e quali client siano connessi, ognuno dei client
è in grado di svolgere il task assegnatogli. Naturalmente più
saranno i client connessi maggiore sarà la velocità di elaborazione
complessiva.
Unica
nota dolente: l’installazione. La preparazione dell’ambiente richiede l’installazione
di tutta una serie di packages, che poi sono quelli di JINI. Ma niente
paura, esiste una guida passo passo di estrema utilità per l’installazione
e il test del tutto. La possiamo trovare al seguente URL: http://developer.java.sun.com/developer/technicalArticles/Programming/javaspaces/
Introduzione all’API
La
vera potenza degli Spaces stà nella loro semplicità di utilizzo;
fondamentalmente le operazioni possibili su un oggetto che stia in uno
Space sono: read, take, write. Quindi possiamo leggere un oggetto( in pratica
ne prendiamo una copia ma l’originale resta nello Space), scriverlo(write)
oppure prenderlo(take), che equivale a leggerlo sottraendolo allo Space.
La magia è tutta quì.
A
questo punto direi di passare direttamente ad un primo semplice esempio
di utilizzo della API.
Prima
di iniziare a scrivere codice, all’indirizzo http://java.sun.com/docs/books/jini/javaspaces/
scarichiamo il file JSBookExamples.zip che, oltre a contenere il codice
degli esempi presenti nel testo indicato in bibliografia, contiene alcune
classi utility delle quali ci serviremo.
Supponiamo
di voler utilizzare uno space per la pubblicazione di annunci di vendita
di oggetti. Intanto avremo bisogno di un oggetto che rappresenti l’inserzione
vera e propria da scrivere nello space:
import
net.jini.core.entry.Entry;
public
class Inserzione implements Entry {
public
String Categoria;
public
String Descrizione;
public
Integre Accessi;
public
Inserzione(){
}
}
La
classe implementa l’interfaccia Entry, in quanto l’oggetto rappresenta
appunto una Entry nello space. Le variabili accessibili dall’esterno devono
essere dichiarate public.
Veniamo
ora al processo responsabile di “mettere” l’inserzione nello space.
import
net.jini.core.lease.Lease;
import
net.jini.space.JavaSpace;
import
jsbook.util.SpaceAccessor;
public
class ScriviInserzione {
public static void main(String[] args) {
try {
Inserzione inserzione = new Inserzione ();
inserzione.Categoria = args[1];
inserzione.Descrizione = args[2];
JavaSpace space = SpaceAccessor.getSpace();
space.write(inserzione, null, Lease.FOREVER);
System.out.println(“Inserzione inserita nel Java Space);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Le
classi importate, JavaSpace non ha bisogno di spiegazioni, mentre
Lease è la classe che si occupa di gestire il tempo di validità
di un oggetto.
Quando
viene effettuato il write dell’oggetto, il terzo parametro è un
valore che fissa per quanto tempo l’oggetto sarà disponibile nello
space. Alla scadenza del tempo fissato l’oggetto verrà rimosso.
In questo caso è stato fissato un tempo infinito, per cui l’oggetto
potrà essere rimosso solo tramite un’operazione di “take”.
SpaceAccessor è una di quelle classi utility di cui accennavamo
prima, che si occupa della ricerca di uno space attivo. Per il momento
trascuriamo ciò che ci sta dietro, che vedremo invece in dettaglio
nei prossimi articoli. Infatti non dimentichiamo che uno space può
essere situato ovunque sulla rete, quindi i meccanismi necessari per accedervi
non sono semplicissimi e in questo primo articolo ciò che
più ci preme è di dare un “quick start” per poter subito
“assaggiare” la potenza dei Java Spaces.
Andiamo
avanti; il codice è piuttosto semplice: creiamo un oggetto Inserzione,
gli assegnamo Categoria e Descrizione ( passati come parametri al lancio
della classe) e scriviamo l’oggetto nello space. Solo una nota: il
secondo parametro del metodo write, che nel nostro caso è fissato
a null; questo significa che stiamo rinunciando ad operare sull’oggetto
sotto transazione. L’altra possibilità sarebbe stata di indicare
al posto del null un oggetto Transaction, ma anche questo lo terremo in
serbo per successivi approfondimenti.
Veniamo
ora all’ultima fase del processo: la lettura dell’oggetto dallo space.
import
net.jini.core.lease.Lease;
import
net.jini.space.JavaSpace;
import
jsbook.util.SpaceAccessor;
public
class CercaInserzione {
public static void main(String[] args) {
try {
JavaSpace space = SpaceAccessor.getSpace();
Inserzione modello = new Inserzione ();
Inserzione
inserzione=(Inserzione)space.read(modello,null,Long.MAX_VALUE);
System.out.println(inserzione.Descrizione);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Il
client crea un’oggetto inserzione che serve da modello, cioè da
filtro per la ricerca dell’inserzione all’interno dello space. Nel nostro
caso il filtro non è molto selettivo, per cui restituirà
qualsiasi inserzione ci sia dentro lo space. Per effettuare una selezione
è sufficiente, prima di chiamare il “read”, assegnare i valori di
filtro. Mi spiego: supponiamo di voler leggere le inserzioni della categoria
“animali domestici”; prima di chiamare lo space.read scriveremo:
modello.Categoria=”animali
domestici”;
in
questo modo solo le inserzioni con la categoria voluta saranno considerate.
Per
quanto riguarda i parametri del metodo read, il primo è l’oggetto
modello, cioè quello che funge da filtro per la ricerca, il secondo
è ancora legato all’utilizzo o meno delle transazioni e il terzo
indica quanto tempo il metodo read debba rimanere in attesa nel caso in
cui al momento della richiesta non sia presente nello space l’oggetto cercato.
Nel nostro caso è stato specificato un tempo Long.MAX_VALUE che
indica che il read attenderà all’infinito.
Cosa
accadrebbe se nello spazio ci fosse più di una inserzione che “matchasse”
il nostro modello?
Il
read legge un oggetto alla volta che viene passato dallo space in maniera
arbitraria. Ciò significa che per letture successive non sappiamo
in che ordine ci verrebbero passate le inserzioni e non possiamo neanche
essere sicuri che non ci venga passata più di una volta la stessa.
La soluzione è creare delle nuove proprietà per il nostro
oggetto inserzione in modo da poter rendere la ricerca il più selettiva
possibile. Ad esempio si potrebbe aggiungere la data di inserimento, un
indice progressivo etc., e in lettura specificherebbero più dati
possibili per poter accedere effettivamente all’inserzione alla quale si
è interessati. Nel caso in cui invece si volesse vedere ad esempio
tutte le inserzioni di una certa categoria, si farebbe un ciclo di read
specificando appunto la categoria e l’indice progressivo.
Il
problema non si pone per la maggior parte delle applicazioni in quanto
in generale si ha necessità di scrivere qualcosa di specifico nello
space che poi verrà rimosso una volta utilizzato.
Conclusione
Nel
prossimo articolo oltre naturalmente a vedere nuovi esempi più complessi
di utilizzo della API, cominceremo ad entrare nel dettaglio di funzionamento
della tecnologia, parte che per ora è stata volutamente tralasciata,
per capire meglio come funzioni il giocattolino. Nel frattempo chi vorrà
cimentarsi nell’installazione non si scoraggi se dovesse insorgere
qualche problema, perchè alla fine sarà ripagato delle proprie
fatiche............
Bibliografia
Java
Spaces Principles,Patterns, and Practice-Freeman,Hupfer,Arnold-Addison
Wesley |