JNDI—JNDI operations—Providers—Examples—Other features and setup—Other JNDI Service providers—Naming in Jini—Exercises
This chapter describes the Java Naming and Directory Interface (JNDI) and the Jini Discovery and Lookup Services.
Chapter 6 introduced the RMI registry, which provides a namespace for registering RMI servers, thus providing a “bootstrap” mechanism by which an RMI client can obtain an initial remote reference.
The RMI registry only implements a “flat” namespace, and is subject to elementary security restrictions. For example, RMI servers can only be bound to an RMI registry running in the same host as the program which does the binding.
For a more powerful naming solution, we need to look further afield.
JNDI provides naming and directory functions to Java applications. It is independent of any specific naming or directory service implementation. Its architecture consists of an API which provides a uniform interface to the various supported naming services, and a service provider's Interface (SPI) which specifies a back-end interface to be implemented by the plugin or “provider” for each such naming service. JNDI ships with service providers for:
In addition, vendor-supplied JNDI service providers are available for other services such as Novell's Network Directory Service (NDS) and several other components of NetWare.
The JNDI API is the same regardless of which service provider(s) is/are being actually used. The only differences that a JNDI client program encounters between different service providers are (a) different specifications of which service providers is selected, and (b) the possibility that a requested operation—for example, sub-directory lookup—is not supported by a particular service provider, when a javax.naming.OperationNotSupportedException
is thrown.
JNDI is shipped as part of the Java 2 platform as from JDK 1.3. It is also available separately for use with JDK 1.1.x and JDK 1.2.x.
JNDI supports the same fundamental naming operations as the RMI registry:
JNDI also supports a rename operation, which changes the name to which an object is bound.
These operations all act on a JNDI context, which is a name space. In some naming service implementations, contexts can have sub-contexts: these are like sub-directories in a file system, and allow name-spaces to be organized into a hierarchy.
The JNDI framework supports the ability to federate one or more distinct naming services together, so that a different parts of a JNDI name can be handled by different JNDI service providers.
JNDI also supports directory contexts. A JNDI directory is a particular kind of JNDI context which contains a set of attributes, each of which has a name and a set of values. Directory contexts are used to record sets of attributes, such as the attributes of an employee (name, location, extension, department, e-mail) or department (name, division, domain, location). A directory also behaves as a naming context: for example, a department directory might contain named directory objects for all its employees, servers, printers, and so on. Directories also support a content-based search operation, which searches for contained directories matching a specified set of attributes.
In JNDI, specific naming services are accessed via plugins called providers. JNDI providers must support the bind, lookup, and list operations. In addition, a provider may support directory operations; a provider may support federation. Behind the scenes, the naming service accessed via a provider may offer facilities such as persistence (bindings are saved and restored across system restarts) and distribution over a network.
It is important to understand that a JNDI provider is not the real service itself: it is a Java interface to the service, written to a “back-end” API called the JNDI Service Provider Interface (SPI) called by the JNDI framework. Typically, the real naming service is an external server, as in the case of the RMI registry, COS Naming, and LDAP. For example, when accessing the RMI registry via JNDI, the RMI registry program does still need to be running.
The JNDI SPI is open and documented, allowing you to write your own JNDI provider. This topic is beyond the scope of this book. A tutorial on this topic is available at the JavaSoft website, via the “Tutorial” link in the JDK JNDI Guide.
The provider accessed by JNDI is controlled by the setting of the property java.naming.factory.initial
. The value of this property names a class which satisfies the javax.naming.spi.ContextFactory
interface. In most cases, the factory is further configured by setting the property java.naming.provider.url
to the URL of the actual naming service.
The JNDI provider for the RMI registry mediates between the JNDI API and the RMI registry.
You may ask, why go to all the trouble of using JNDI if we are still going to be stuck with the RMI registry at the end of it? One answer might be that you can use the RMI registry provider in early development, while the infrastructure necessary to support a more powerful naming service such as LDAP is still in preparation. Once this is ready, changing your clients from the RMI registry provider to another JNDI provider is a much simpler matter if the clients have already been coded to the JNDI API.
One way to configure this provider is by setting Java system properties as shown in Table 13.1.
JNDI provides an interface to the CORBA COS Naming service. You must use this service rather than the RMI registry if you want to use portable remote objects (remote objects exported via RMI/IIOP, discussed in Chapter 14); conversely, the COS Naming provider can only be used with portable remote objects. The COS Naming Provider mediates between the JNDI API and the COS Naming service, an implementation of which is provided with Java 2 as the tnameserv program.
One way to configure this provider is by setting Java system properties as shown in Table 13.2.
The LDAP provider mediates between the JNDI API and one or more LDAP servers. The LDAP provider supports many more features than the other plugins, including the client authentication technique discussed in § 16.6. Implementations of LDAP are available from numerous vendors including Netscape Communications, Novell, and Sun Microsystems. Novell's NDS and Microsoft's Active Directory are both accessible via LDAP.
One way to configure this provider is by setting Java system properties as shown in Table 13.3.
A normal RMI client's registry lookup operation looks like Example 13.1.
Example 13.1. RMI registry lookup
import java.rmi.Naming; MyRemote myRemote = (MyRemote)Naming.lookup ("rmi://server/"+MyRemote.class.getName());
This operation may throw any of the following exceptions:
The same operation using JNDI looks like Example 13.2.
Example 13.2. JNDI registry lookup
import javax.naming.*; Hashtable env = new Hashtable(); env.put("Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); InitialContext ctx = new InitialContext(env); MyRemote myRemote = (MyRemote)ctx.lookup (MyRemote.class.getName());
These JNDI operations may throw a javax.naming.NamingException
.
You can avoid coding the initial context factory into the application by setting the Java system property java.naming.factory.initial
to the appropriate value. in the case of the RMI registry provider for JNDI, the value required is com.sun.jndi.rmi.registry.RegistryContextFactory
. You can set the property externally in either of two ways:
Setting the JNDI and provider properties externally makes applications genuinely independent of the specifics of JNDI service providers.
In Example 13.2, the URL of the RMI registry (e.g. rmi://server
or rmi://server:1099
) must have been set externally into the Java system property java.naming.provider.url
, or the program must have set it into the initial context's environment under the name given by Context.PROVIDER_URL
.
If you don't mind embedding both the naming protocol and the registry location into the lookup string, you can avoid specifying the context factory and URL altogether, as shown in Example 13.3.
Example 13.3. JNDI registry lookup with embedded protocol and registry location
import javax.naming.*; InitialContext ctx = new InitialContext(); MyRemote myRemote = (MyRemote)ctx.lookup ("rmi://server/"+MyRemote.class.getName());
Again, these operations may throw a javax.naming.NamingException
.
A complete discussion of JNDI and its setup is a non-trivial topic, and is beyond the scope of this book. For further information, consult the JNDI Specification, tutorial, and reference documentation provided by Sun.
Java Software maintains a list of available JNDI service providers at:
Perhaps the most immediately interesting is the “File System Provider”, which provides JNDI-style access to the local file system. This could be used to implement a persistent, hierarchical registry.
Jini™ is an architecture “designed to bring reliability and simplicity to the construction of networked services and devices”.[3] Jini services usually communicate via RMI. However, instead of using the RMI registry, Jini provides two services which are used together to provide a naming service: the Discovery Service and the Lookup Service.
You can use the Jini Discovery and Lookup Services as a naming service for RMI even if you aren't deploying the rest of Jini or writing Jini-style services.
The Discovery Service provides a means of locating a Jini Lookup Service on the network. The Lookup Service provides a central registry of service items—remote services. Once located, the Lookup Service provides servers with mechanisms to register themselves, and clients with mechanisms to find an instance of a particular type of service, by matching on:
zero or more service types—Java interfaces implemented by the service item
zero or more service attributes—either those predefined by the Jini Lookup Attribute Schema Specification, or arbitrary attributes understood by both the client and the service.
The combination of the Jini Discovery and Lookup mechanisms is much more powerful than either the “flat” RMI registry namespace or any hierarchical JNDI naming service.
For further information on Jini see:
the Jini Network Technology page at http://www.sun.com/jini
the Jini Community Page at http://www.jini.org.
1: | Adapt the |
2: | Adapt the registry dump and restore programs of the exercises in Chapter 6 to use JNDI with the RMI registry plugin. |
3: | Modify the |
4: | Modify the |
5: | The JNDI API supports a rename operation. The RMI registry does not. Show how you would implement the JNDI rename in an RMI registry provider. Is this an ideal implementation? |
6: | [Term project] According to the Jini Lookup Service specification, “although the collection of service items is flat, a wide variety of hierarchical views can be imposed on the collection by aggregating items according to service types and attributes”.[4] Can you write a JNDI provider which uses the Jini Discovery and Lookup services as a back-end, and provides a variety of hierarchical views as a name-space? (There are two parts to this exercise: (a) designing the views, and (b) implementing the provider.) |
[1] The COS Naming service is specified by the Object Management Group. OMG specifications are available at http://www.omg.org.
[2] LDAP is specified by IETF RFCs 1777 (LDAP v2) and 2251 to 2256 (LDAP v3).
[3] Waldo et al., The Jini Specification Second Edition, p. xxi.
[4] Waldo et al., The Jini Specification Second Edition, § LU1.1.
3.133.127.37