Chapter 13. Naming II—JNDI and Jini

  • JNDIJNDI operations—Providers—Examples—Other features and setup—Other JNDI Service providers—Naming in Jini—Exercises

In this chapter

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

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:

  • the RMI registry

  • the CORBA COS Naming service[1]

  • the Lightweight Directory Access Protocol (LDAP)[2]

  • others not discussed in this chapter.

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 operations

Basic operations

JNDI supports the same fundamental naming operations as the RMI registry:

  • bind an object to a name

  • unbind a name

  • rebind an object to a name (overriding any previous binding of the name)

  • lookup the object bound to a given name

  • list the available names.

JNDI also supports a rename operation, which changes the name to which an object is bound.

Sub-contexts

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.

Federation

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.

Directory contexts

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.

Event notification

Finally, JNDI allows applications to register listeners for JNDI events (such as binds or unbinds), so that applications can be notified of, and respond to, asynchronous changes in the naming service.

JNDI providers

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.

Provider properties

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.

RMI registry provider

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.

Table 13.1. Configuring the RMI registry provider

PropertyValue
java.naming.factory.initial com.sun.jndi.rmi.registry.RegistryContextFactory
java.naming.provider.url Set this to point to the RMI registry, e.g. rmi://server. The default value for this property is rmi://localhost:1099.

COS Naming provider

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.

Table 13.2. Configuring the COS Naming provider

PropertyValue
java.naming.factory.initial com.sun.jndi.cosnaming.CNCtxFactory
java.naming.provider.url See the JNDI documentation for the provider.

LDAP provider

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.

Table 13.3. Configuring the LDAP provider

PropertyValue
java.naming.factory.initial com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url This is complex: see the JNDI documentation for the provider.

Examples

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:

  • java.rmi.NotBoundException—the name is unknown

  • java.net.MalformedURLException—the URL is badly formed

  • java.rmi.RemoteException—some remote error.

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:

  1. On the command line, by specifying -Djava.naming.factory.initial = value.

  2. In a jndi.properties file, which is read by any program which uses JNDI. This file can also contain settings for other JNDI and provider properties, and indeed any system properties.

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.

Other features and setup

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.

Other JNDI service providers

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 naming

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:

Exercises

1:

Adapt the RemoteEcho server example of Chapter 1 to use JNDI with the RMI registry plugin.

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 RemoteEcho server example to use JNDI with the LDAP plugin.

4:

Modify the RemoteEcho server example to use JNDI with the File System plugin.

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.123.23