Locating Resources Using JNDI (Java Naming and Directory Interface)
The javax.naming.Name Interface
This interface symbolizes a generic name of an object that is bound into a naming service. There can be many different implementations of a name, such as URLs or host names, but the Name interface provides methods for accessing the name that are independent of the underlying naming service. A name typically consists of a string or a group of name components.
In general, applications that need to manipulate individual components in a name would use the Name interface to build a name or compare with another name, for instance. Simple applications generally use a java.lang.String to perform a lookup operation.
The javax.naming.Reference Class
JNDI defines the javax.naming.Reference class that represents a reference to an object. A reference contains information that enables you to access an object. JNDI maintains the illusion that what the client looks up in the naming service (a reference) is in fact an object.
The javax.naming.directory Package
The javax.naming.directory package contains classes and interfaces that you can use to access directory services. For example, you can retrieve the attributes that are associated with an object. You can also perform searches for objects whose attributes match certain search criteria that you specify.
The two most important interfaces in the javax.naming.directory package are Attribute and DirContext.
The javax.naming.directory.Attribute Interface
This interface represents an attribute of a named object in the directory service. The actual forms that an attribute's name and value can take are dictated by the directory service. Some directory services allow you to specify a schema that sets the forms for the name and value.
An attribute has zero or many values associated with it. It is perfectly legal for a particular attribute value to be null. You can use the get and getAll methods to obtain the attribute values; the set method allows you to set a value at a specified index; and the remove method deletes an attribute at a specified index.
The javax.naming.directory.DirContext Interface
This interface represents a directory context, and defines methods that enable you to write software that examines (getAttributes) and updates (modifyAttributes) the attributes of a named object in the directory service.
There is also a set of overloaded search methods that enable you to search the directory service based on the name of a context (or object) and attribute values.
The DirContext interface extends the javax.naming.Context interface, and thus you can also use it as a naming context. This means that any object in the directory service can act as a naming context. For example, there could be an object in the directory service that represents an employee in your company. The employee object can have attributes associated with it as well as act as a naming context so that you could locate objects that belong to the employee such as their PCs, mobile telephones, and PDAs.
The javax.naming.event Package
The javax.naming.event package defines classes and interfaces that support event notification mechanisms in naming and directory services.
If you have used the Java Event Model (as used in GUIs and by JavaBeans) that has been available since JDK 1.1, the mechanism described here will sound familiar. The basic idea is that an event source generates events that are sent to registered event listeners. The event mechanism is of an asynchronous nature, and means that applications can register an interest in changes to the directory service without having to poll the directory service for changes.
The NamingEvent class and the NamingListener interface described later are part of the javax.naming.event package.
The javax.naming.event.NamingEvent Class
The javax.naming.event.NamingEvent class represents an event object that is generated when something changes in a naming or directory service. The object contains information about the event that occurred, such as the source of the event, as well as a type that indicates the form that the event took. Events are classified into those that affect the namespace, and those that do not. An example of the former category would be when an object is added, whereas an example of the latter category is when an object is changed.
Other information about the change, such as information before and after the change, is also stored in the NamingEvent object.
An event source creates an instance of the NamingEvent class, and passes it to the registered listeners who can then use the instance methods of the object to extract information about the event.
The javax.naming.event.NamingListener Interface
You can implement the javax.naming.event.NamingListener interface to listen for NamingEvents. However, there are several subinterfaces of NamingListener that correspond to the different categories of event that can occur.
For example, there is a NamespaceChangeListener for events that change the namespace, such as the addition, removal, or renaming of an object. There is also the ObjectChangeListener for notification of modifications to objects in the namespace, which covers when an object's binding is replaced with another and when an object's attributes are replaced or removed.
Typically, you implement a subinterface rather than directly implement NamingListener.
The javax.naming.ldap Package
You can find classes and interfaces in the javax.naming.ldap package that enable you to access features specific to LDAP v3 that are not already covered by the classes and interfaces in the javax.naming.directory package.
Most JNDI applications will not need to use the javax.naming.ldap package. The only time that you will is if you are writing software that needs access to LDAP functions such as Controls, Extended Operations, and Unsolicited Notifications. You can find more information about these in the LDAP RFC at http://www.ietf.org/ rfc/rfc2251.txt.
The javax.naming.spi Package
The classes and interfaces defined in the javax.naming.spi package are primarily for use by developers of naming/directory service providers.
As mentioned earlier in this chapter, JNDI is a standard component of JDK 1.3 and higher, and as such, is also shipped as part of J2EE 1.2 and above. If you want to run JNDI applications under JDK 1.2 then you can download a standard extension from Sun's Web site at http://java.sun.com/products/jndi.
While you are developing an application, you must ensure that the CLASSPATH contains the location of the JNDI libraries so that the Java compiler has access to them. This will be the case as long as the JAVA_HOME environment variable has been set to correctly point to the installation directory of a compatible JDK.
When you run a JNDI-aware application, whether it is a simple command-line client or a Web application, there must be a JNDI service running, and the classes for that service must be available to the program. Again, this means setting the CLASSPATH correctly, usually by placing one or more vendor-supplied JAR files on the CLASSPATH. For specifics, you should consult the documentation supplied by either the JNDI provider or J2EE server vendor.
When you start a J2EE server, the default behavior is that a naming service is automatically started, too. If this default behavior is not required, for example, if you want to use an existing JNDI server, you need to change the J2EE server configuration appropriately.
In this part of the chapter you will see a command-line example that uses Sun's J2EE Reference Implementation (RI) to bind and look up an object. Later in the chapter you can find an example that uses BEA's WebLogic J2EE server to publish an Enterprise JavaBean (EJB) that a JSP uses.
JNDI and Sun's J2EE Reference Implementation
It is straightforward to set up your machine so that you can use JNDI with Sun's J2EE RI. All you must do is ensure that
The J2EE_HOME environment variable is set to the directory in which the J2EE SDK is installed. You can download the J2EE SDK from http://java.sun.com/products/j2ee.
The CLASSPATH environment variable contains the j2ee.jar file that is in the lib directory under the J2EE home directory, for use by JNDI clients.
The way that I tend to set up my development machines is to set a system-wide environment variable for J2EE_HOME, and then have a command-line script that I can run from a command prompt to set up the CLASSPATH when I need it. This prevents unnecessary clutter, and means that I know exactly what is on the CLASSPATH at any given point! Setting the CLASSPATH as a system-wide variable can lead to all sorts of confusion when you have multiple JAR files from different vendors, especially when they ship different versions of the same JARs.
The batch file on my Windows XP machine looks like this:
set path=%J2EE_HOME%\bin;%PATH% set classpath=%J2EE_HOME%\lib\j2ee.jar;%CLASSPATH%;.
Under Unix or Linux, you could use a line like this:
To start the J2EE server, all you need to do is issue the following command at a command prompt:
The J2EE server runs until you either close its window, or issue the following command at another command prompt:
Page 3 of 7