BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  37 Posts :: 3 Stories :: 24 Comments :: 0 Trackbacks
The primary reason that JNDI is commonly-used for directory-enabled applications is that it is part of the core Java platform. In fact, that is perhaps the only reason for its popularity, since the API itself is absolutely horrible. It is very abstract (in fact, it is intended for use in communicating with a number of different types of systems, so it really isn't an LDAP API as much as an API that happens to provide LDAP support), which means that performing simple tasks often require significantly more code than should be required, and that it uses terminology that can be extremely confusing (e.g., in JNDI, the "bind" method is used to add an entry to the directory rather than performing an LDAP bind operation). Further, the abstract nature of the API may make some tasks either difficult (e.g., performing an LDAP compare operation) or impossible (e.g., retrieving the result code from an operation). Finally, JNDI provides virtually no support for anything but the most basic functionality. It provides no facilities for interacting with data in LDIF form, or for performing ASN.1 encoding/decoding needed to support development of custom controls and extensions.

Establishing a Connection

This section will demonstrate the process for establishing a simple LDAPv3 connection (with no SSL or other security) and performing a simple bind operation.


In JNDI, when you wish to establish a connection to an LDAP directory server, you should create an InitialLdapContext object. This can be quite a daunting task, because the only way that you have to specify the target server, whether or not to use SSL or some other security mechanism, whether or not to authenticate, etc. is by providing a set of properties. There aren't any convenience methods to help you figure out what those properties might be (although there are constants in some cases), so you have to look through the documentation to try to find them, and in fact some of these properties and/or values use "com.sun.*" prefixes, so it isn't even clear whether they are safe to use in code that might run on Java implementations provided by vendors other than Sun.

Here is an example of the work required to do this in JNDI:

Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://");
env.put(Context.SECURITY_CREDENTIALS, "password");
env.put("java.naming.ldap.version", "3");

LdapContext connection = new InitialLdapContext(env, null);

Performing a Search Operation

This section will demonstrate the process for performing a search to find a user entry and then retrieve that user's e-mail address from the mail attribute. In each of these cases, it will be assumed that only one entry will be returned, so we don't need to worry about the possibility of multiple entries matching the search criteria.


The JNDI "search" methods may be used to perform searches in the directory, and the simplest of these in most cases is the variant that takes string representations of the base DN and filter and a SearchControls object. This is another case where JNDI suffers from a poor choice of terminology because "controls" in this case does not have anything at all to do with LDAP controls but rather with a set of miscellaneous options used to perform the search (e.g., the search scope, attributes to return, size and time limits, etc.).

Something else that directory developers may find confusing is that the methods used to get attribute values have a generic return type of Object. It is not clear from the JNDI specification whether these objects will always be strings or whether they may be other types of objects. Further, it is not necessarily clear if it is possible to obtain the values in any other form (e.g., the raw bytes that make up the value).

The following code illustrates the process for performing the desired search processing in JNDI:

SearchControls searchControls = new SearchControls();
searchControls.setReturningAttributes(new String[] { "mail" });

String mail = null;
NamingEnumeration<SearchResult> results ="dc=example,dc=com", "(uid=john.doe)", searchControls);
while (results.hasMore())
  SearchResult result =;
  Attributes attributes = result.getAttributes();
  Attribute attribute = attributes.get("mail");
  if (attribute != null)
    Object o = attribute.get();
    if (o != null)
      mail = String.valueOf(o);

Performing an Add Operation

This section will demonstrate the process for adding a simple entry to the server. In this case, the entry added will have the following LDIF representation:

dn: dc=example,dc=com
objectClass: top
objectClass: domain
dc: example


As noted above, JNDI uses the poorly-named "bind" method to add an entry to the server (and "unbind" to delete an entry). The basic reasoning for this is that it is trying to associate the provided set of data (the attributes) with a name (the DN), but this can be very confusing and frustrating for developers familiar with LDAP directories but not very familiar with JNDI because obviously the terms "bind" and "unbind" have very different meanings in LDAP. Another nit with JNDI is that Attributes and Attribute are interfaces rather than classes, so it is necessary to create BasicAttributes and BasicAttribute objects instead, and it appears that there is no way to create an attribute with multiple values so it is first necessary to create a BasicAttribute with a single value and then add additional values to it.

The code to use to add an entry in JNDI is as follows:

Attributes attributes = new BasicAttributes();

Attribute objectClassAttribute = new BasicAttribute("objectClass", "top");

attributes.put("dc", "example");

connection.bind("dc=example,dc=com", null, attr
posted on 2012-06-16 17:13 Life is no respector of any genius. 阅读(485) 评论(0)  编辑  收藏 所属分类: Java