J2EE Naming and Directory Services
Days 1 and 2 introduced you to enterprise computing concepts and J2EE technologies such as EJBs and Servlets. This chapter will show how the Java Naming and Directory Interface (JNDI) supports the use of many of the J2EE components.
In its simplest form, JNDI is used to find the resources (such as EJBs) that you have registered via the J2EE server. Advanced use of JNDI supports sophisticated storage and retrieval of Java objects and other information.
This day's work will include
Using Naming and Directory Services
JNDI and X.500 names
Obtaining a JNDI Initial Context
Binding and looking up names
Objects and References
JNDI events and security
Naming and Directory Services
A Naming Service provides a mechanism for giving names to objects so you can retrieve and use those objects without knowing the location of the object. Objects can be located on any machine accessible from your network, not necessarily the local workstation.
A real-world example is a phone directory. It stores telephone numbers against names and addresses. To find people's phone numbers is simply a matter of using their name (and possibly address) to identify an entry in the phone book and obtaining the stored phone number. There are a few complications, such as finding the right phone book to look in, but it is essentially a simple process.
Incidentally, naming services have a similar problem to that of finding the right phone book. This is known as obtaining a context. A name can only be found if you examine the right context (phone book).
A Directory Service also associates names with objects but provides additional information by associating attributes with the objects.
The yellow pages phone directory is a simple form of a directory service. Here, businesses often include advertisements with additional information such as a list of products sold, professional qualifications, affiliated organizations, and even maps to their premises. These attributes add value to the name entry. A directory service will normally provide the ability to find entries that have particular attributes or values for attributes. This is similar to searching the yellow pages for all plumbers running a 24-hour emergency service within a certain area.
Yellow page style phone books also store names under categoriesfor example, hairdressers or lawyers. Categorizing entries can simplify searching for a particular type of entry. These categorized entries are a form of sub-context within the directory context of the local phone book.
Why Use a Naming or Directory Service?
Naming Services provide an indispensable mechanism for de-coupling the provider of a service from the consumer of the service. Naming services allow a supplier of a service to register their service against a name. Users, or clients, of the service need only know the name of the service to use it.
Think of the phone book once more, and how difficult it would be to find someone's phone number without it. Obtaining your friend's phone number would mean going to their home and asking, or waiting until you meet up with them againwhich may be difficult to organize because you can't phone them to arrange the meeting.
At the end of the day, it is very difficult to imagine a world without naming services.
What Is JNDI?
JNDI is a Java API that defines an interface to Naming and Directory Services for Java programs. JNDI is just an API and not, in itself, a Naming and Directory Service. To use JNDI, an implementation of a Naming and Directory service must be available. JNDI provides a service-independent interface to the underlying Service Provider implementation.
Figure 3.1 shows how the JNDI layer interfaces between the Java program and the underlying naming services. Additional naming services can be plugged into the JNDI layer by implementing the Service Provider Interface (SPI) for JNDI.
Figure 3.1 JNDI Architecture.
JNDI has been a standard component of J2SE since version 1.3. JNDI is available as a standard Java extension for JDK 1.2 and earlier. JNDI has always been a required component of J2EE.
Common Naming Services
Figure 3.1 shows that JNDI supports plug-in Service Providers for several well-known naming services, including the following:
Lightweight Directory Access Protocol (LDAP) is the approved standard for an Internet naming service. LDAP is a true directory service and supports attributes as well as names for objects. LDAP is fast becoming the de facto directory service for the enterprise.
Domain Name System (DNS) is the Internet naming service for identifying machines on a network.
Novell Directory Services (NDS) from Novell provides information about network services, such as files and printers. NDS is found primarily in environments where the main networking software is Novell.
Network Information Service (NIS) from Sun Microsystems provides system-wide information about machines, files, users, printers, and networks. NIS is primarily found on Solaris systems, but Linux and some other Unix platforms also support it.
JNDI also supports some more specialized naming systems. For example, CORBA for distributed component programming and RMI for distributed Java programming.
Although there is no named Service Provider for Windows Active Directory within JNDI, it is supported. Windows Active Directory supports an LDAP interface, and you can access it via the JNDI LDAP Service Provider Interface.
Each naming service has its own mechanism for supplying a name. Perhaps the most familiar naming convention is DNS, where every machine connected to the Internet has a unique name and address. Most readers will recognize the following as a host name used by DNS:
In contrast, LDAP names are based on the X.500 standard and use distinguished names that look like the following fictitious example:
cn=Martin Bond, ou=Authors, o=SAMS, c=us
This format will also be familiar to users of Microsoft's Active Directory service, whose naming system is also based on X.500 but uses a forward slash to separate the various name components:
These last two naming conventions have similarities in that they are both hierarchically structured with the more specific names (such as cn=Martin Bond) being qualified by a general name (such as o=SAMS).
JNDI applies minimal interpretation to names specified as String objects. JNDI uses the forward slash character (/) as a name separator to provide a simple name hierarchy called a Composite Name. It is conventional for these composite names to be used to group related names (such as plumbers in the phone book). As an example, JDBC data sources take names of jdbc/XXX and EJBs the form ejb/XXX. While this is only a convention, it does help separate different sorts of named objects within the JNDI name space.
Composite names can span different naming systems. An LDAP name can combine with a file system name to get a composite name:
cn=Martin Bond, ou=Authors, o=SAMS, c=us/agency/agency.ldif
Here a filename (agency/agency.ldif) is appended to an LDAP name. How JNDI interprets this is up to the individual Service Provider.
Incidentally, JNDI calls structured names like the DNS and LDAP names Compound Names. JNDI does not interpret compound names, but simply passes them through to the Service Provider.
In addition to forward slash (/), JNDI also treats backslash (\), single quote ('), and double quote (") characters as special. If a compound name or a component of a name contains any of these characters, they must be escaped using the backslash character (\). Remember that backslash and double quotes are also special characters in Java string literals and must be escaped. Therefore to insert a double quote into a JNDI name you must place \\\" into the string literal. For example the following is how to insert the name jdbc/"Agency"avoid this if you can.
If the underlying Service Provider uses the forward slash as a name separator (as does the CORBA name service for example), there appears to be a conflict between JNDI and the Service Provider. In practice, this is unlikely to be a problem because JNDI recognizes two sorts of name separationweak and strong. JNDI always passes the entire name to the Service Provider. A strong name separation implementation (such as LDAP or DNS) simply processes the first part of the composite name and returns the remainder to the JNDI Naming Manager to pass on to other name services. A weak name separation implementation will process the entire composite name. This is not something you need to worry about unless you are writing a Service Provider.
For those programmers who need to do more than use names to look up and bind objects, JNDI provides several classes for manipulating and parsing composite and compound names. The JNDI name support classes in the javax.naming package are Name, CompositeName, and CompoundName.