In questo articolo sarà descritta l'interfaccia JNDI di Java2, mentre nel prossimo sarà mostrato un piccolo esempio client/server per evidenziare le principali innovazioni della nuova architettura
L'evoluzione sempre più spinta dei modelli architetturali distribuiti (DCOM, CORBA) fa sentire con crescente insistenza l'esigenza di una comunicazione efficiente fra i moduli della stessa applicazione: Sun con l'interfaccia JNDI propone una soluzione proprietaria per la comunicazione, altamente innovativa per la sua versatilità.
Con l'interfaccia JNDI (Java Naming Directory Interface) Sun propone una struttura molto versatile per gestire la comunicazione fra moduli software: prima di descriverla, però, è opportuno capire quali funzioni svolgono, all'interno di un'architettura distribuita, i servizi di Naming e di Directory, e di introdurre un po' di terminologia specifica.
La funzione principale di un servizio di Naming è quella di associare (mapping) nomi ad oggetti: in questo senso, un classico esempio può essere quello dei Domain Name Server (DNS) che offrono la risoluzione dei nomi su Internet, che associano ad un nome simbolico (www.qqq.com) un indirizzo IP nel formato standard (127.127.127.127).
Con il termine "naming convention" si intende la sintassi con cui si indicano gli oggetti: ad esempio, per indicare i path del file system in Unix si utilizza lo "/" (es: /usr/bin/hello.c, file hello.c situato nella directory bin, che a sua volta è sottodirectory di usr, che si trova nella root), per i DNS si usa la "dotted notation" (la classica notazione che si usa per indicare gli URL, www.altavista.digital.com). Nel Lightweight Directory Access Protocol (LDAP) per convenzione i componenti sono ordinati da destra a sinistra, delimitati dalla virgola (","), e sono definiti da una coppia nome/valore, separati dal carattere "=": così con la notazione nc=Giovanni Rossi, o=Sun, n=IT si indica un elemento LDAP nc=Giovanni Rossi relativo all'elemento o=Sun, che a sua volta è relativo all'elemento n=IT (nome completo, organizzazione, nazione).
Un Contesto è un insieme di associazioni nome-oggetto. Ad ogni contesto è associata una naming convention, ed offre un sistema di risoluzione ('lookup') dei nomi, che offre il riferimento all'oggetto desiderato.
Un Naming System è un insieme di Contesti dello stesso tipo (cioè caratterizzati dalla stessa naming convention) ed offre un insieme di operazioni in comune: ad esempio, il DNS è un Name System.
Un Namespace è un insieme di nomi all'interno di un Naming System.
Un Directory Object rappresenta un oggetto in un ambiente computazionale, ed è descritto da una serie di attributi. Gli attributi, come per le classi, identificano un oggetto all'interno di un contesto: ad esempio un 'utente' può essere rappresentato da un Directory Object che abbia come attributi un indirizzo di posta elettronica, un numero di telefono, un numero di fax, ...
Una Directory è costituita da un insieme di Directory Object.
Un servizio di Directory offre la possibilità di manipolare questi oggetti, crearli, modificarli, cancellarli, e soprattutto selezionarli in base agli attributi tramite opportuni filtri di ricerca (search filter): un'operazione possibile, ad esempio, può essere quella di selezionare, all'interno di una Directory contenente oggetti di tipo 'utente' tutti gli elementi che hanno un indirizzo di posta elettronica che termina con la stringa "@hotmail.com".
Fatte le dovute premesse, passiamo ora ad esaminare l'oggetto dell'articolo, ed iniziamo dall'acronimo: JNDI, Java Naming and Directory Interface.
Sun ha quindi scelto di offrire al programmatore un'interfaccia, poiché in questo modo il servizio di Naming può essere utilizzato indipendentemente dalla sua implementazione, coerentemente con la filosofia che propone Java come un linguaggio aperto, al quale tutti possono aggiungere in maniera semplice componenti.
Per capire meglio quanto affermato si osservi la figura seguente:
Figura 1
L'applicazione Java vede solamente le API della JNDI, la quale al suo interno ha una struttura a livelli, e di questi l'ultimo è quello che caratterizza il tipo di comunicazione: la stessa interfaccia, quindi, supporta diversi protocolli di comunicazione in maniera del tutto trasparente al programmatore. Per la precisione, la versione 1.3 delle SDK di Java2 contiene le classi che implementano i seguenti protocolli:
Lightweight Directory Access Protocol (LDAP)
CORBA services (COS) naming service
Java Remote Method Invocation (RMI) Registry
mentre per la versione 1.2 bisogna scaricare le classi opportune dal sito http://java.sun.com/products/jndi, a seconda del protocollo che si desidera implementare.
Si passa ora ad esaminare la struttura delle classi di JDNI, che è divisa in cinque package (contenuti dalla Enterprise Edition di Java2):
Di questi package descriveremo le classi più significative, trascurando, ad esempio, gli svariati tipi di eccezioni, per non perderci nei dettagli della realizzazione: ricordiamo che la maggior parte delle classi descritte in seguito sono in realtà interfacce, poiché da soli questi package non possono essere utilizzati, se non in combinazione con una delle possibili implementazioni (si vedrà nell'articolo successivo come scegliere l'implementazione desiderata).
Il package javax.naming
Il package naming contiene le classi Context, Name, Binding, Reference, InitialContext, NamingException.
La classe Context definisce il contesto in cui si lavora, sul quale si effettuano le operazioni di lookup, bind, rename degli oggetti.
La classe Name rappresenta una maniera alternativa di definizione dei nomi degli oggetti: comunque ogni metodo che accetta come parametro il nome di un oggetto è riscritto per poterlo accettare sia come stringa sia come elemento di classe Name. Questa funzionalità può essere utile nel caso in cui gli oggetti hanno nomi complessi, che possono anche rispecchiare una gerarchia nello spazio di naming.
Gli oggetti di classe Binding sono terne contenenti il nome dell'oggetto, il nome della classe e l'oggetto stesso: questi oggetti sono utili quando si chiede l'elenco degli oggetti pubblicati in un contesto con il metodo listBindings().
Alcuni sistemi non supportano la serializzazione Java: in questi casi JNDI offre la classe Reference per dare l'illusione al programmatore che l'oggetto memorizzato dal servizio di Naming o di Directory sia comunque un oggetto Java.
La classe InitialContext è il punto iniziale per la creazione di oggetti JNDI: dopo aver istanziato un oggetto di questa classe, al suo interno possono essere creati oggetti e contesti.
La classe NamingException funge da root per le eccezioni generate dai moduli JNDI.
Il package javax.naming.directory
Il package naming.directory contiene la classe DirContext.
La classe DirContext offre i servizi di Naming, poiché estende l'interfaccia Context, ed in più offre i servizi di Directory, ovvero di gestione degli attributi degli oggetti.
Il package javax.naming.event
Il package naming.event contiene le classi NamingEvent, NamingListener, NamespaceChangeListener e ObjectChangeListener.
La classe NamingEvent rappresenta gli eventi caratteristici di un sistema di Naming, ovvero la creazione, la modifica degli attributi o del valore, e la cancellazione degli oggetti.
Gli oggetti di classe NamingListener sono "interessati", con la stessa politica degli eventi gestita per gli oggetti grafici, agli eventi della classe NamingEvent: in particolare quelli di classe NamespaceChangeListener sono interessati agli eventi di variazione del contesto (creazione e cancellazione di oggetti), mentre gli ObjectChangeListener sono interessati agli eventi di variazione degli oggetti.
I corrispondenti eventi sono definiti dalle classi EventContext ed EventDirContext.
Il package javax.naming.ldap
Il package naming.ldap contiene classi che estendono le funzioni del package naming.directory, particolarizzandole per il caso del protocollo LDAP v3 (RFC 2251).
Il package javax.naming.spi
Il package naming.spi può essere utilizzato dagli sviluppatori che interagiscono con provider di servizi di Naming e di Directory differenti, per incapsularli con una semplice architettura di tipo plug-in.
Tramite la classe ObjectFactory è possibile sia importare ed utilizzare oggetti offerti da provider diversi, sia gestirli con JNDI ed esportarli nel formato richiesto dai provider esterni.
Conclusione
Nel presente articolo sono state descritte le funzionalità caratteristiche dell'interfaccia JNDI, facendo una breve carrellata delle classi più significative: gli "smanettoni" possono dedicarsi allo studio del tutorial indicato nella bibliografia, che presenta esempi utilizzando l'implementazione LDAP, mentre nel prossimo articolo sarà presentato un codice esemplificativo di colloquio client/server con l'implementazione RMI, confrontandolo con la comunicazione RMI e CORBA, ed evidenziandone pregi e difetti.
Bibliografia
Il sito della Sun è una fonte insostituibile di documentazione, in particola sull'argomento si può consultare il seguente tutorial:
Laureato a Napoli alla facoltà Federico II in Ingegneria Informatica nel 1999, ho partecipato al master in "Internet Software Design" tenuto presso l'istituto Cefriel di Milano nello stesso anno (da maggio a dicembre): da gennaio lavoro presso la Siemens Informatica S.p.A. di Roma come Analista e System Integrator.
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