Using JNDI to Get to eDirectory
Articles and Tips: article
Senior Research Engineer
Novell, Inc.
kburnett@novell.com
01 Jul 2003
The Java Naming and Directory Interface (JNDI) is an application programming interface (API) that provides naming and directory functionality to applications written using the Java programming language.
Introduction to JNDI
The JNDI architecture consists of an APU and a service provider interface (SPI). Java applications use the JNDI API to access a variety of naming and directory services. The SPI enables a variety of naming and directory services to be plugged in transparently, thereby allowing the Java applications using the JNDI API to access their services.
So, I mention the term naming service and also directory service. I suspect that most of you know what these are, but for those who don't....
Naming Concepts
The basic definition of Naming is the means by which names are associated with an object and objects are found based on their names. Naming is used to encrypt objects to people-friendly names such as:
Addresses
Identifiers
Objects used by computer programs
To look up an object in a naming system, you supply the name of the object. The naming system then determines the syntax that the name must follow. The syntax is sometimes called the naming system's naming convention.
Bindings.
The association of a name with an object is called a binding. For example, the LDAP name is bound to an LDAP entry.
References and Addresses.
References and addresses give information on how to access an object. Some naming services can't support the full object due to size or other reasons, hence they need a pointer to the object. Others use it for speed. Also, references and addresses are typically smaller than the actual object.
Context.
The idea of context is a set of name- to-object bindings. Every context has an associated naming context which provides a look-up (resolution) operation that returns the object. Context may also provide operations for binding names, unbinding names and listing bound names.
Naming Systems and Namespaces.
A naming system is a connected set of contexts of the same type (they have the same naming convention) and provides a common set of operations. A namespace is the set of names in a naming system. For example:
Unix file system
DNS naming system
LDAP naming system
Directory Concepts.
In real-world situations, many naming services are extended with a directory service. In these directories, directory objects represent objects in a computing environment. Most of these objects contain attributes. So the directory can be looked at as an entity that is a connected set of objects.
To take this concept one step further, a directory service is a service that provides operations for creating, adding, removing, and modifying the attributes associated with an object in a directory. In less words--eDirectory, which does all of this and more!
Directory-Enabled Java Applications
Why would you want to develop an application that uses JNDI? Here are a few reasons:
It is essential for creating enterprise-wide applications.
Java can store and retrieve objects from the directory database.
Applications can share the common infrastructure provided by the directory.
You can make applications across the network more coherent and manageable.
JNDI Packaging
Let's take a moment and look at where JNDI is available and what you need to take advantage of JNDI in your own applications. JNDI is included in the Java 2 SDK v1.3 and later releases. It is also available as a Java Standard Extension for JDN 1.1 and Java 2 SDK. To use JNDI, you must have the JNDI classes and one or more service providers.
The JDK includes the following service providers:
LDAP
Common Object Request Broker Architecture (CORBA) / Common Object Services (COS) name service
Java Remote Method Invocation (RMI) Registry
There are several more that are available on Sun's website at http://java.sun.com/jndi/ . However, eDirectory is available as a part of the Novell JNDI SDK. (This will be discussed a little bit later.)
JNDI is divided into five packages, including:
javax.naming
javax.naming.directory
javax.naming.event
javax.naming.ldap
javax.naming.spi
A short description of each of these packages follows.
Naming Package.
The javax.naming API package contains classes and interfaces for accessing naming services.
Directory Package.
The javax.naming.directory API package extends the javax.naming API package to provide functionality for accessing directory services, in addition to naming services. The package allows applications to retrieve attributes associated with objects stored in the directory and to search for objects using specific names.
Event Package.
The javax.naming.event API package contains classes and interfaces for supporting event notification and directory services.
LDAP Package.
The javax.naming.ldap API package contains classes and interfaces for using features that are specific to LDAP v3 that are not covered by the more generic javax.naming.directory API package. Most networking applications can use the javax.naming.directory package. The LDAP package is for those applications that need "extended" operations, controls, or unsolicited notifications.
Service Provider Package.
The javax.naming.spi API package provides the means by which developers of different naming/directory service providers can develop and hook up their implementations so that the corresponding services are accessible from applications that use JNDI. The javax.naming.spi package also allows different implementations to be plugged in dynamically.
Novell Extensions and Controls for JNDI
Novell provides a JNDI SDK, which is labeled as an extension to the existing JNDI SDK--an extension, because it provides packages and classes that allow accessing specific eDirectory functionality. Technically called the LDAP Extensions and Controls for JNDI, these are LDAP v3 compliant and include support for the virtual list views and server-side sorting controls available on eDirectory. Also, since they use LDAP, there is no dependencies on the Novell Client software.
Dependencies.
In addition to the LDAP Extensions and Controls for JNDI Jar file, you will need the following to take full advantage of the functionality offered in the libraries:
JDK 1.1.7b or higher - to - JDK 1.3.1 or higher is preferred, since all JNDI components are included here
JSSE-compliant security provider to create SSL connections
NDS eDirectory 8.5 or greater as directory
Configuration.
Setting up Novell's LDAP Extensions and Controls for JNDI is per JDK. For JDK 1.3 and greater, you need to do the following:
Set JAVA_HOME to your JDK directory. For example, set JAVA_HOME=C:\jdk1.3
Include Novell's novbp.jar, which is part of the Novell SDK, in your CLASSPATH
For JDK 1.2, you need to do the following:
Set JAVA_HOME to your JDK directory
Include Sun's jndi.jar, ldap.jar and providerutil.jar in your CLASSPATH
Include Novell's novbp.jar in your CLASSPATH
For JDK 1.1.7b, you need to do the following:
Include JDK 1.1.7b classes.zip in your CLASSPATH
Include Sun's jndi.jar, ldap.jar and providerutil.jar in your CLASSPATH
Include Novell's novbp.jar in your CLASSPATH
Note: Version of the JDK that are earlier than JDK 1.1.7b are not supported by the Novell JNDI SDK.
Installation.
You can download the Novell LDAP Extensions and Controls for JNDI from http://developer.novell.com . Once downloaded, you can install the jar file by following the install wizard's straight-forward instructions. Then after the configuration that is explained above, you are ready to compile and run some code.
Sample Code
Take a look at the following code.
1 /***************************************************************************** * Copyright (c) 2002 Novell, Inc. All Rights Reserved. * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND * TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE 5 * AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS * THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO * DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE * CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS * TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF 10 * DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR * DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE. * $name: TriggerBackgroundProcess.java * $description: TriggerBackgroundProcess.java demonstrates the way to trigger * one of the NDS background processes. 15 ***************************************************************************/ import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.ldap.InitialLdapContext; 20 import javax.naming.ldap.LdapContext; import com.novell.service.ndssdk.jndi.ldap.ext. TriggerBackgroundProcessRequest; public class TriggerBackgroundProcess { 25 public static void main(String[] args) { if( args.length != 4 ) { usage(); 30 } String hostURL = args[0]; String loginDN = args[1]; String passWord = args[2]; 35 int processID = Integer.parseInt(args[3]); try { String backgroundProcess; 40 // create a Hashtable object. Hashtable env = new Hashtable(5, 0.75f); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 45 env.put(Context.PROVIDER_URL, hostURL); env.put(Context.SECURITY_AUTHENTICATION, "simple" ); env.put(Context.SECURITY_PRINCIPAL, loginDN ); env.put(Context.SECURITY_CREDENTIALS, passWord );
50 // Construct a LdapContext object. LdapContext ctx = new InitialLdapContext(env, null);
/* create extended operation request object to trigger * one of the following NDS background processes. 55 * The process IDs used are: * BACKGROUND_PROCESS_BKLINKER = 1; * BACKGROUND_PROCESS_JANITOR = 2; * BACKGROUND_PROCESS_LIMBER = 3; * BACKGROUND_PROCESS_PART_PURGE = 4; 60 * BACKGROUND_PROCESS_SCHEMA_SYNC = 5; * BACKGROUND_PROCESS_SKULKER = 6; */ TriggerBackgroundProcessRequest reqs = new TriggerBackgroundProcessRequest( processID ); 65 // call extended operation to trigger background process ctx.extendedOperation(reqs); System.out.println("Background process" + 70 reqs.getBackgroundProcessName() + "is scheduled."); } catch(NamingException e) { System.err.println("Background process could not be scheduled."); 75 e.printStackTrace(); } finally { System.exit(0); 80 } } public static void usage() { 85 System.out.println("Usage : java TriggerBackgroundProcess" + " <host URL> <login dn> <password>"); System.out.println("Example: java TriggerBackgroundProcess" + " ldap://Acme.com:389 cn=admin,o=Acme secret"); System.exit(1); 90 } }
This code is available as a part of the Novell SDK. The SDK contains quite a lot of JNDI source code, with examples for most methods being provided. This particular piece of source code allows you to schedule eDirectory background processes. Let's look at it in greater detail, as this will be a good basis for all JNDI programs.
In lines 16-21, we have the imports. You will notice that lines 16-20 import several of the javax libraries. The javax libraries are the JNDI specific libraries available with the JDK download. The last import (line 21) is for the Novell-specific JNDI extension method to queue the eDirectory background process.
Line 23 creates a new class, with line 25 being the declaration for our main method, required by all Java programs. Lines 27-30 check for command line parameters, calling the usage() method if they are wrong.
Lines 32-35 initialize several variables that the program will use. Lines 42-48 collect required information including: context, provider URL, name, and password, from the command line, and store them in a hash table. The hash table is then passed in to InitialLdapContext to construct a LdapContext object (line 51). This object is key to determining where the directory requests will get processed. In our case, it is eDirectory.
Once we have the LdapContext object, lines 63- 67 take the selected processID and use that process to create a TriggerBackgroundProcessRequest object, which is executed via the extendedOperation JNDI method.
Lines 69 and 70 print out a message indicating that the chosen eDirectory background process has been queued in eDirectory. If there is an error, lines 72-80 catch it and print out an error message and the contents of the process stack.
Conclusion
This month we discussed Java's directory interface called JNDI. We have explored Novell's LDAP extensions and controls for JNDI and we have looked at some real-world sample code. Hopefully this will help you get started designing and programing Java applications that take advantage of Novell's eDirectory.
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.