inhoudstafel en auteursrecht
* STER *


6b. Java Naming and Directory Interface (JNDI)

6b.1. Wat, waarom, wanneer ?

In de praktijk van de systeemontwikkeling komt het vaak voor dat we een 'catalogus' met objecten moeten aanleggen of aanspreken. Een naming service (vertaling: benoemingsdienst, maar we blijven de goed ingeburgerde Engelse term gebruiken) associeert namen met objecten. Dat is een heel algemene definitie, die in de informaticawereld onder verschillende concrete gedaanten erg nuttig wordt. Voorbeelden van naming services waar we als informatica-gebruiker een beroep op kunnen doen, zijn:

  1. mappen: een map in het beheerssysteem associeert namen met bestanden
  2. de Domain Name Service op het Internet associeert met een domeinnaam (bv. www.ster.be) het IP-adres van de bijhorende computer (in dit geval 80.65.128.150)
  3. (zie hoofdstuk 7 "gedistribueerd programmeren") de RMI Registry associeert namen met Java-objecten die in mogelijk verafgelegen virtuele machines leven;
  4. (zie hoofdstuk 7 "gedistribueerd programmeren") de CORBA naming service associeert namen met CORBA-objecten die door mogelijk verafgelegen servers worden aangeboden;
  5. (zie hoofdstuk 11 "enterprise JavaBeans") iedere application server biedt een naming service om namen met Enterprise JavaBeans en andere Java-objecten te associëren.

De Java Naming and Directory Interface is een overkoepelend stel Java-interfaces waarmee naming services kunnen worden aangesproken. Als programmeur gebruik je dus gelijkaardige datatypes, methoden en attributen om te communiceren met verschillende soorten naming services. JNDI maakt deel uit van de gewone Java Development Kit (vanaf versie 1.3).

Om de voorbeelden van dit hoofdstuk op je eigen machine te kunnen uitvoeren, heb je niet alleen de JNDI nodig, maar ook een concrete implementatie van een naming service. We gebruiken hier een eenvoudige naming service die Sun gratis aanbiedt op zijn website (http://java.sun.com/products/jndi/downloads/index.html, klik op "Download JNDI 1.2.1 & More" en daarna rechts van "File System Service Provider"): de File System Service Provider. FSSP biedt toegang tot de bestanden op een lokale of genetwerkte harde schijf. Er zijn eenvoudiger manieren om via Java lokale bestanden te manipuleren, met name via java.io.File. Maar we gebruiken FSSP als voorbeeld van een JNDI-compatibele naming service.

Een directory service (vertaling: opzoekdienst, maar ook deze Engelse term is voldoende ingeburgerd om in Nederlandse teksten op te duiken) is een naming service waarin objecten verrijkt worden met aanvullende informatie, opgeslagen in zogenaamde attributen. De eerste twee hogergenoemde voorbeelden van naming services zijn eigenlijk directory services. Zo zal een map in een beheerssysteem door middel van attributen onthouden wie toegang heeft tot een bestand, hoe groot het bestand is, wanneer het bestand voor het laatst is gewijzigd, enz.

6b.2. De belangrijkste interfaces: Context en InitialContext

De Java Development Kit bevat de JNDI in een reeks pakketten waarvan de naam begint met javax.naming; het belangrijkste is het pakket javax.naming zelf. De JDK bevat géén eigenlijke naming services: die moeten afzonderlijk toegankelijk zijn in de productie-omgeving.

Het interface-type Context modelleert een algemene naming service. Belangrijke methoden zijn:

public Object lookup(String name) throws NamingException
Deze methode gaat na of er een object is geassocieerd met de gegeven naam. Zoniet wordt een exception gegenereerd.
public void bind(String name, Object obj) throws NamingException
Deze methode associeert het gegeven object met de gegeven naam. Er mag nog geen object met die naam geassocieerd zijn. Bij het alternatief rebind mag dat wel, en wordt de oude associatie gewoon vergeten.
public void unbind(String name) throws NamingException
Deze methode maakt een bestaande associatie van een object met de gegeven naam ongedaan.

Een object van de klasse InitialContext vormt de toegang tot een naming service. Bij de constructie van een dergelijk object moet bepaalde informatie worden geleverd, afhankelijk van het soort naming service. Ook de vorm waarin de informatie wordt geleverd, kan vrij gekozen worden:

De programmeur moet de documentatie van de gewenste naming service raadplegen om te weten welke properties een waarde nodig hebben, en wat de interpretatie van de verschillende mogelijke waarden is. In ieder geval moet een "factory"-klasse bekend zijn die objecten van het type Context kan genereren. Voor de File System Service Provider in ons voorbeeld is dit de klasse com.sun.jndi.fscontext.RefFSContextFactory; deze naming service vereist ook een URL via dewelke een concreet bestandensysteem toegankelijk is. Met een URL van het type "file:///" spreken we een lokaal toegankelijke harde schijf aan.

6b.3. Voorbeeld

Om onderstaand voorbeeld te doen werken, moet je de FSSP van Sun downloaden en installeren. Ga naar de Java-website van Sun (http://java.sun.com/products/jndi/downloads/index.html), klik op "Download JNDI 1.2.1 & More" en daarna rechts van "File System Service Provider". Download het Zip-archief. Dit Zip-archief bevat een mappenstructuur die begint bij het niveau lib, waarin zich twee jarfiles bevinden. Hoofdstuk 5b bevat toelichting bij het begrip jarfile, maar voorlopig volstaat het deze twee bestanden ergens binnen bereik van de Java Runtime-omgeving te plaatsen. Hierna verwijzen we met het symbool %FSSP_HOME% naar de map waarin je lib als deelmap hebt geïnstalleerd. De namen van de jarfiles zijn:

  fscontext.jar
  providerutil.jar

Hier is de broncode van ons voorbeeldprogramma.

import javax.naming.Context;
import javax.naming.InitialContext;

/** Programma om het elementaire gebruik van een naming service
 *  te illustreren. We gaan ervan uit dat de omgevingsveranderlijken
 *  een naming service definiëren die naar een bestandensysteem
 *  verwijst. Het programma bevestigt dat een bestand met een gegeven
 *  naam aanwezig is. Het programma eindigt met een Exception als
 *  geen bestand met een gegeven naam wordt gevonden.
 */
public class ZoekBestand {
  /** Zoek een bestand met gegeven naam.
   *  @param args[0]
   *    de naam van het gezochte bestand
   */
  public static void main(String[] args) throws Exception {
    /* Indien geen bestandsnaam gespecificeerd via de opdrachtregel:
       neem de lege streng aan.
    */
    String bestandsnaam = "";
    if (args.length > 0) bestandsnaam = args[0];

    // Construeer een initiële context a.d.h.v. omgevingsveranderlijken
    Context c = new InitialContext();

    // Zoek het bestandsobject - dit kan een Exception genereren
    Object obj = c.lookup(bestandsnaam);

    // Toon de padnaam van het gevonden bestand, indien relevant
    if (bestandsnaam.equals(""))
      System.out.println("InitialContext geconstrueerd zonder problemen.");
    else
      System.out.println(bestandsnaam + " is geassocieerd met: " + obj);
  }
}

Je kan het programma eenvoudig compileren met de opdracht

javac ZoekBestand.java

Het uitvoeren is op het eerste gezicht iets minder eenvoudig, omdat we de runtime-omgeving twee soorten informatie moeten meegeven:

De jarfiles worden aan het klassenpad toegevoegd met de parameter cp (let op de aanwezigheid van de punt, die de huidige map aangeeft - we moeten ook de gecompileerde klasse ZoekBestand kunnen terugvinden). De omgevingsveranderlijken krijgen een waarde met de parameter D, in de algemene vorm

  -Dveranderlijke=waarde

In ons geval ziet de opdrachtregel er dus als volgt uit. Voor de leesbaarheid splitsen we een en ander op in verscheidene regels, maar in principe moet je dit achter elkaar invoeren:

java
  -cp %FSSP_HOME%\lib\fscontext.jar;%FSSP_HOME%\lib\providerutil.jar;.
  -Djava.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory
  -Djava.naming.provider.url=file:///
  ZoekBestand bestandsnaam

inhoudstafel en auteursrecht
* STER *

Valid HTML 4.0! Valid CSS!