CERCA SITEMAP FEED RSS 1280
Ultimo aggiornamento: 30 Agosto 2009

Java Naming and Directory Interface (JNDI)

Java Naming and Directory Interface (JNDI) è un’API che fornisce funzionalità di directory e naming alle applicazioni Java ovvero permette di scoprire ed identificare oggetti nella rete mediante namespaces logici.
JNDI quindi va collocato in uno strato intermedio fra le applicazioni java ed i servizi da queste richieste.
Un servizio di directory fornisce accesso a diversi tipi di informazioni e risorse utilizzando un naming system ovvero fornendo un’associazione fra attributi e valori: questo significa che un oggetto (o il riferimento a questo) può essere recuperato a partire da un nome logico di facile memorizzazione per l’utente finale.
Generalmente un servizio di naming viene associato a servizi di directory, database, file system, desktop, servizi di e-mail ed altro ancora.
Applicazioni JNDI
JNDI si colloca fra lo strato dell’applicazione e quello dei servizi da questa richiesti.

Costituisce una sorta di servizio per la reperibilità di oggetti attraverso l’associazione a namespaces logici.
Ogni nome all’interno di un naming system deve rispettare una serie di regole sintattiche (naming convention): un nome atomico è una parte indivisibile di un nome, un nome composto è una sequenza di zero o più nomi atomici.
Nel Domain Naming System (DNS) ad esempio i nomi atomici sono separati da un punto (www.sito.it).
L’associazione di un nome atomico con un oggetto è chiamata binding.
Un contesto (context) è un oggetto il cui stato è caratterizzato da un insieme di associazioni (binding) e da una propria naming convention e che fornisce metodi di:
  • risoluzione di nomi (lookup) ovvero di recupero di un oggetto a partire dal nome ad esso associato
  • creazione di associazioni (bind) fra oggetti e nomi
  • recupero di tutte le associazioni (list) del contesto
  • eliminazione di un’associazione (unbind) fra oggetto e nome associato
Un nome atomico all’interno di un contesto può fare riferimento ad un altro contesto dello stesso tipo (sottocontesto) dando vita ad un nome composto: risolvere un nome composto significa quindi risolvere ciascuna sua parte atomica in attraverso contesti successivi.
Un naming system è quindi un’insieme connesso di contesti dello stesso tipo che forniscono le stesse operazioni e la stessa semantica ed un namespace è l’insieme di tutti i nomi di un naming system.
Un client può quindi ottenere un contesto iniziale (Initial Context) che è il punto di partenza nella risoluzione di un nome composto.
Un oggetto Directory è un oggetto che viene utilizzato per rappresentare una varietà di informazioni: esso fornisce operazioni per creare, aggiungere, modificare ed eliminare attributi ad esso associati.
Un oggetto Directory quindi può essere rappresentato mediante un albero i cui nodi contengono un set di attributi.
JNDI è organizzato in cinque package:
  • javax.naming contiene classi ed interfacce per accedere ai naming services
  • javax.naming.directory fornisce accesso alle directory
  • javax.naming.event contiene classi ed interface per gestire le notifiche di eventi nei servizi di naming e directory
  • javax.naming.ldap contiene classi ed interfacce per supportare LDAP
  • javax.naming.spi contiene classi ed interfacce per il plugin automatico di provider di servizi di naming e directory

Il Context

Il package javax.naming contiene quelle che sono le classi principali dell’architettura JNDI.

L’interfaccia Context definisce un contesto e le operazioni necessarie per:
  • aggiungere associazioni nome-oggetto bind(Name name, Object obj)
  • creare un’associazione sovrascrivendo eventualmente quella esistente rebind(Name name, Object obj)
  • eliminare associazioni unbind(Name name)
  • cercare oggetti a partire dal nome associato lookup(Name name)
  • rinominare un’associazione rename(Name oldname, Name newname)
  • ottenere un elenco delle associazioni presenti nel contesto listBindings(Name name)
  • creare un sottocontesto createSubcontext(Name subcontext)
  • distruggere un sottocontesto destroySubcontext(Name subcontext)
Per ogni operazione occorre definire un nome, anche composto, rappresentato dalla classe Name.

L’interfaccia Context contiene anche metodi per:
  • aggiungere variabili d’ambiente addToEnvironment(String propName, Object propVal)
  • rimuovere variabili d’ambiente removeFromEnvironment(String propName)
La classe InitialContext implementa l’interfaccia Context e rappresenta appunto un contesto iniziale nella risoluzione di nomi.
Quando viene costruito un InitialContext l’ambiente viene inizializzato con i parametri di configurazione passati al suo costruttore.
La classe Binding rappresenta un’associazione nome-oggetto all’interno di un contesto: di fatto costituisce una tupla con nome dell’associazione, nome della classe dell’oggetto ed oggetto stesso.
E’ possibile recuperare tutte le associazioni presenti al’interno di un contesto mediante il metodo listbindings(Name name) dell’interfaccia Context.
Se non si ha alcun interesse a recuperare gli oggetti ma si vuole soltanto recuperare i nomi delle classi e delle associazioni presenti all’interno di un contesto è possibile utilizzare il metodo list(Name name) che restituisce un oggetto Enumeration di NameClassPair una classe che rappresenta appunto una coppia nome associazione-classe oggetto.
Un oggetto particolarmente interessante è rappresentato dalla classe Reference che rappresenta un oggetto esterno alla directory: quando un’operazione di lookup produce come risultato un oggetto Reference JNDI provvede automaticamente a convertire tale riferimento nell’oggetto che rappresenta.
Gli oggetti che sono in grado di essere rappresentati tramite riferimenti dovrebbero implementare l’interfaccia Referenceable il cui unico metodo getReference() restituisce la classe Reference rappresentativa dell’oggetto stesso.
Un riferimento potrebbe contenere il nome della classe dell’oggetto oppure l’indirizzo al quale poterne recuperare il file .class.

L'oggetto Directory

Un oggetto Directory permette di recuperare informazioni rappresentate mediante una struttura ad albero i cui nodi sono in grado di immagazzinare attributi.

L’interfaccia DirContext contiene appunto metodi per esaminare e aggiornare attributi associati ad oggetti:
  • getAttributes(Name nome) recupera gli attributi associati all’oggetto identificato dal nome
  • modifyAttributes(Name name, int mod_op, Attributes attrs) permette di sostituire (mod_op= REPLACE_ATTRIBUTE), aggiungere (mod_op= ADD_ATTRIBUTE) e cancellare (mod_op= REMOVE_ATTRIBUTE) attributi
Ogni attributo è rappresentato dall’interfaccia Attribute la quale contiene metodi per aggiungere add(Object obj)e rimuovere remove(Object obj) valori mentre l’interfaccia Attributes rappresenta una collezione di attributi e contiene metodi per aggiungerne di nuovi e per recuperare o cancellare quelli esistenti.
BasicAttribute e BasicAttributes rappresentano delle implementazioni concrete delle interfacce Attribute e Attributes.

L’interfaccia DirContext contiene anche metodi per la ricerca di oggetti directory che soddisfano determinati requisiti:
  • search(Name name, Attributes matchingAttributes) restituisce gli oggetti directory che soddisfano determinati attributi
  • search(Name name, Attributes matchingAttributes, String[] attributesToReturn) restituisce un sottoinsieme degli attribute (attributesToReturn) degli oggetti directory che soddisfano determinati requisiti di ricerca (matchingAttributes)
Il risultato viene restituito sottoforma di SearchResult.

Gli eventi

La classe NamingEvent è rappresentativa di un evento che viene generato da un servizio di naming/directory.

Essa definisce quattro tipi di eventi:
  • OBJECT_ADDED viene aggiunto un oggetto
  • OBJECT_REMOVED viene rimosso un oggetto
  • OBJECT_RENAMED viene rinominato un oggetto
  • OBJECT_CHANGED viene modificato un oggetto
Oltre al tipo di evento la classe NamingEvent mantiene informazioni circa l’eventuale cambiamento delle informazioni mediante i metodi getOldNinding(), getNewBinding() e getChangeInfo()
L’interfaccia NamingListener permette di registrare tali eventi mediante le due sue implementazioni concrete NamespaceChangeListener e ObjectChangeListener.

Il primo cattura eventi di aggiunta, rimozione e rinominazione di oggetti mediante i metodi:
  • objectAdded(NamingEvent evt)
  • objectRemoved(NamingEvent evt)
  • objectRenamed(NamingEvent evt)
Il secondo invece gestisce l’evento di cambiamento di un oggetto mediante il metodo objectChanged(NamingEvent evt).
Per aggiungere e rimuovere i listener da un contesto è sufficiente utilizzare i metodi addNamingListener(Name target, int scope, NamingListener l) e removeNamingListener(NamingListener l) delle classi EventContext che estende l’interfaccia Context e EventDirContext che estende l’interfaccia DirContext.

Quando viene aggiunto un NamingListener occorre specificare il target ovvero un Name risolvibile dal contesto sul quale il NamingListener agisce e la visibilità che può essere:
  • OBJECT_SCOPE se il NamingListener deve agire solo a livello di oggetto
  • ONELEVEL_SCOPE se il NamingListener deve agire solo sul contesto specificato dal target
  • SUBTREE_SCOPE se il NamingListener deve agire a livello del target e nei suoi sottoalberi