Java Naming and Directory Service (JNDI)

Introduction to JNDI

The Java Naming and Directory Interface (JNDI) is designed by Sun Microsystems Ltd. to simplify access to the directory infrastructure, which advanced network applications are being built on, by providing an unified set of interfaces. The directory infrastructure includes directories, which are special types of databases that provide quick access to their data stores. Databases are traditionally thought of as the relational data storage model, as in Oracle or Microsoft's SQL Server. But a directory database stores its information using the hierarchical model. There are a number of different directory services such as Lightweight Directory Access Protocol (LDAP) or Network Information Service (NIS) from Sun Microsystems Inc. Each directory service will always have a naming service.

While LDAP is growing in popularity and in usage, it is still a long way from being ubiquitous. Other directory services such as NIS are still in widespread use. Also Java, as a standard programming language for server-side, enterprise-scale mission-critical distributed applications, needs a datastore to store its objects to be retrieved when necessary. There are a number of robust and open architecture such as CORBA, Java RMI and Java EJB, for promoting these sort of software development. CORBA has its own naming service for defining the location of the available objects. As Java has been blessed with two distributed computing architectures (RMI and EJB), it became critical to have a standard application programming interfaces (API) for interacting with naming and directory services, similar to what Java application developers have for databases in JDBC. A key component of Java EJB is the ability to store and retrieve Java objects on the network. A directory service like LDAP is going to be the primary data store for fairly stable Java objects. This is because, when loading objects such as a person's record or binary data like a serialized Java objects from the network, one can locate them quickly and a directory service enables the very fast lookup and retrieval of data.

The other primary cause is due to the fact that each directory service comes with their own API to access their services, which adds complexity and code bloat to client applications, which access a directory service. This can be simplified with JNDI. Though there appears there are numerous servers and APIs underneath, it is effectively a single API for an application developer, who uses JNDI. One more thing here is that even if we use the same API and and a proper service provider, there are still some differences staring out due to the fact that every directory service protocol is different. Here comes LDAP, a standard protocol, into reckoning. Thus LDAP in aligning with JNDI is supposed to be a match winner if all the directory service vendors provide LDAP interfaces to their respective protocols.

JNDI Service Providers

A service provider is a driver that enables clients to communicate with a directory services. For a service provider to be available for use in JNDI, it must implement the Context interface. This comes as a boon for clients because a client has to learn JNDI only to know the relevant API calls to connect to a naming or directory service and the service provider has to implement the APIs and other functionalities such as network protocol and encoding/decoding values.

But still a problem persists. A client has to know something about the underlying directory service so that he can correctly name his entries and build the correct search queries. To overcome this problem, in JNDI version 1.2, service providers can support a concept of federation, where a service provider can pass an operation to another service provider if the first provider does not understand the naming or operation scheme. For example, suppose one wants to find out a record in a particular domain in a directory service, but he uses a different service provider and unfortunately that would not be able to answer the request. If federation is enabled, the initial service provider would be able to pass the request to the next provider on the federation list and that would service the request. If a service provider capable of handling the request can not be found, the operation will throw an exception. Thus a service provider enables JNDI applications to communicate with a naming/directory service. The interfaces, classes and exceptions described by JNDI APIs have to be taken care of by the respective service providers such as LDAP, NIS, CORBA Object Service, and RMI registry. Many different vendors also provide service providers for other directory services. Any one can design service provider according to his requirements.

How JNDI Works

To use JNDI, we need Sun's Java Development Kit or higher, JNDI Software Development kit , the JNDI LDAP Service Provider and an LDAP-compliant directory server such as Netscape's iPlanet Directory server.

Firstly we have to get a reference to an object that implements the DirContext interface. But mostly an InitialDirContext object has been used. This object takes a hash table as a parameter and this hash table can contain a number of different references and at the minimum, it should contain a reference to a field with the key Context.INITIAL_CONTEXT_FACTORY with a value of the fully qualified class name of the service provider, and a field with the key Context.PROVIDER_URL with a value containing the protocol, hostname and port number to the LDAP server like this: ldap://localhost:389, where 389 is the default LDAP port. Next create a Hashtable to store the environment variables that JNDI will to connect to the directory service. And we have to specify the fully qualified package name of our JNDI provider as specified in the API followed by specifying the hostname and port number to our LDAP server. Finally we get a reference to our initial directory context with a call to the InitialDirContext constructor, giving it our Hashtable as its only parameter. A directory context tells JNDI what service provider we will be using, what naming/directory server we will be connecting to, what location we will be accessing the directory from initially and any authentication information.

The most important operation we use on a LDAP server is searching. The search is being performed using the search() method of an object that implements the DirContext interface such as the InitialDirContext class. The minimum requirement for this is the search base and a filter. There are other parameters we can use to help manage the results. If the search is successful, a NamingEnumeration object will be returned. Once we get the initial context, we next specify the scope of our search, which is set in the SearchControls object, which is an optional parameter to the search() method of a DirContext object. After specifying the scope, we can perform the actual search. Each element in a NamingEnumeration object will contain a single SearchResult object, which we can retrieve as below:

SearchResult sr = (SearchResult) results.next();. We can get the DN of an entry by String dn = sr.getName(). To get the attributes of an entry we can use the getAttributes() method of the SearchResult class. This will return a concrete object that implements the Attributes interface like the InitialDirContext class returns a BasicAttributes object. Once we have an Attributes object, we can use a NamingEnumeration object, which contains methods to step through each attribute that was returned by the search process. There are many methods for returning the name of the attribute and values of the individual attribute. Retrieving a specific set of attributes from an individual entry is very quick and but general searching seems to be quite not practical.

JNDI also can be used to add new entries to the server, delete entries and modify existing entries. Actually adding entries to a LDAP server using JNDI is not that much easy. Actually the primary goal of JNDI is to read/write Java objects to the network. To store an entry in a LDAP server using JNDI, we have to bind an object to a Distinguished Name (DN). That is, each and every object we store in the server must have a DN associated with it. DN is actually the unique name that each entry in a LDAP server must possess. Every directory service is bound to have a unique name for each object just like no two files in the same directory in our file system is the same.

To store an entry in the LDAP server, we must create a class that implements the DirContext interface. This interface depicts how the object should be stored in and retrieved from the directory server and provides various sophisticated data handling techniques and is the most basic interface for building a directory service provider. The InitialDirContext interface will actually perform an LDAP add operation. Modifications to an entry can be accomplished with the ModificationItem and BasicAttribute classes. For deleting entries from the LDAP server, we have to call the destroySubContext() method of the DirContext interface.

Benefits of JNDI

One of JNDI's strongest features is its ability to use LDAP as a network store. That we can use LDAP to store Java objects that can be shared by different applications or can be stored for later use. A number of applications can benefit from a directory service's address book features. For example, our email program can use it to find the email address of our colleagues. JNDI allows to store several types of Java related objects into the LDAP server. JNDI can use Java's serialization technique to store pre-built objects into the LDAP server. When an application needs a particular object, it can retrieve it from the LDAP server. If we are in all-Java environment, we can make use of the advantage a Java reference brings. References actually reduce the storage and bandwidth requirements of storing and retrieving entries because they do not store the entire object in the directory, only the key components that are need to rebuild the object in a factory class. Often the component stored is a URL that points to the real location of the object.

For larger organisations, there are significant benefits in having a centralised service for employee data, logon authorization, looking up phone numbers and email address, determining user groups and printer rights and many more similar works. This pushed organisations to turn to directory servers to act as a central point of access for information and increasingly standardized LDAP based servers. With the strong presence of JNDI, it is really a bonanza for such organisations.

There are a host of distinct advantages for using a single, standardized API for programming directory service applications. The main one is that JNDI makes it easier to switch between the JNDI service providers without making any significant code changes in the client applications and even the client requests will be forwarded transparently to the right service provider with the help of federation facility that has been added in the latest version of JNDI.

Click for Web resources for JNDI

Back to my Home Page