Developing A White Pages Service with LDAP and JNDI
Pages: 1, 2, 3, 4, 5, 6, 7
Accessing A Naming Service
When accessing a naming service, you first need a service
provider. The first thing to do is to get the initial context, which
is the starting position into the namespace. You acquire the initial
context before you do any other operation. This is because all
operations on naming and directory services are performed relative to
some context. If you specify that your initial context when accessing
a filesystem is the /usr/local directory when you call
the list() method, then it's the contents of the
/usr/local directory that will be returned. You can think
of the initial context as the application default directory.
To obtain the initial context, you call the
InitialContext() constructor, passing all the necessary
environment information in a Hashtable object:
Hashtable env = new Hashtable();
Into the Hashtable, you then put the service provider. For example, if you are using the filesystem service provider from Sun, this is the line of code you need.
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
The filesystem service provider can be downloaded here.
If you are using a different service provider, replace
put()'s second argument.
Another important environment property that you need to get the
initial context is the PROVIDER_URL. This property is
assigned the location of the initial context. This could be a URL on
the Internet or it could just be a directory in a file system. For
instance, if you decide that your initial context when accessing a
Unix filesystem is the /usr/local directory, then you
need the following line of code.
env.put(Context.PROVIDER_URL, "file:/usr/local");
Or, on a Windows system, if you want the C:\data
directory to be the initial context, your code would look like
the following.
env.put(Context.PROVIDER_URL, "file:C:\\data");
And, optionally, you can also put the user credentials such as the username and password.
env.put(Context.SECURITY_PRINCIPAL, "james");
env.put(Context.SECURITY_CREDENTIALS, "secret");
Having the environment information ready, you can now create the initial context.
Context ctx = new InitialContext(env);
If the object is created successfully, you can use the resulting Context object to access the naming service. The lookup method of the Context interface can be used to retrieve an object by passing its name.
Object obj = ctx.lookup("info.txt");
For example, the following code prepares an environment Hashtable
object, creates an initial context, and retrieves the
info.txt file.
import java.util.Hashtable;
import javax.naming.*;
import java.io.File;
public class Naming {
public static void main(String[] args) {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL,
"file:C:\\123data\\MyArticles\\WhitePagesWithLDAP");
env.put(Context.SECURITY_PRINCIPAL, "james");
env.put(Context.SECURITY_CREDENTIALS, "secret");
try {
Context ctx = new InitialContext(env);
File f = (File)ctx.lookup("info.txt");
}
catch (NamingException e) {
System.out.println(e.toString());
}
}
}
The Object object from the lookup method is cast to a
File object. If the object is a Printer, you can do
something similar:
Printer printer = (Printer) ctx.lookup("BigMomma");
printer.print(report);
Some of the code is in a try-catch wrapper because many methods in the JNDI packages can throw a NamingException.
Other useful methods of the Context interface include the following.
bind-- Binds an object to a name. After the binding, you can retrieve the object by looking up the name.rebind-- Adds or replaces a binding. If the name is already bound to an object, it will be unbound and bound with the new object specified as the argument of this method.unbind-- Removes a binding.list-- Enumerates the names bound in the named context, along with the class names of objects bound to them.
Every naming method in the Context interface has two overloads: one
that accepts a Name argument and one that accepts a
java.lang.String name. Name is an interface that
represents a generic name; an ordered sequence of zero or more
components.
The overloads that accept Name are useful for applications
that need to manipulate names, that is, composing them, comparing
components, and so on.
A java.lang.String name argument represents a
composite name. The overloads that accept
java.lang.String names are likely to be more useful for
simple applications, such as those that read in a name and look up the
corresponding object.
Accessing A Directory Service
When you access a directory service, there are several initial
steps to perform. The first is to prepare an environment
Hashtable object to get the initial context.
Hashtable env = new Hashtable();
One of the environment properties you need to set is the
INITIAL_CONTEXT_FACTORY. For example, if you are
accessing an LDAP service, you can use the service provider from
Sun. The code would then look like the following.
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
If you are using a service provider from another vendor, just
replace the second argument to put(). Next, you supply
the location of the service. For example, the following specifies a
location of an LDAP server at
ldap://sendal.jepit.edu.au:389 (389 is the default port for the
LDAP service).
env.put(Context.PROVIDER_URL,
"ldap://sendal.jepit.usyd.edu.au:389");
You can then acquire an initial context by passing the environment
Hashtable. However, unlike accessing a naming system, you use the
DirContext interface instead of the Context
interface.
DirContext ctx = new InitialDirContext(env);
Having a DirContext object, you can access the
directory service using the methods of the DirContext
interface; the important methods of which include
getAttributes, getSchema and
search.
getAttributes-- Returns the attributes of an object in the directory. For this method to work, you need to pass the name of the object for which you want the attributes. If you have an object whose name is "cn=boni, ou=person", you can retrieve the object's attributes using the following line of code.Attributes attr = ctx.getAttributes("cn=boni, ou=person");getSchema-- Retrieves the schema associated with the named object.search-- Search for entries in a named context or object. The search must satisfy a given search filter. The syntax of one of the many search methods is as follows.public NamingEnumeration search(String name, String filter, SearchControls cons) throws NamingExceptionThe parameters are given below.
name-- The name of the context or object to search.filter-- The filter expression to use for the search; may not be nullcons-- These control the search. If null, the default search controls are used (equivalent to(new SearchControls())).
You can create a SearchControls object by using the following code.
SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);