There are several ways in which a connection is created. The most common way is from the creation of an initial context. When you create an InitialContext, InitialDirContext, or InitialLdapContext by using the LDAP service provider, a connection is set up immediately with the target LDAP server named in the Context.PROVIDER_URL property. Each time an initial context is created, a new LDAP connection is created. See the Connection Pooling section for information on how to change this behavior.
If the property value contains more than one URL, then each URL is tried in turn until one is used to create a successful connection. The property value is then updated to be the successful URL. See the LDAP & LDAPS URLS section for an example of how to create an initial context using a list of URLs.
There are three other direct ways in which a connection is created. The first way is by passing a URL as the name argument to the initial context. When an LDAP or LDAPS URL is pass as a name parameter to the initial context, the information in the URL is used to create a new connection to the LDAP server, regardless of whether the initial context instance itself has a connection to an LDAP server. In fact, the initial context might not be connected to any server. See the URLs lesson for more information on how URLs are used as names.
Another way that a connection is created is by use of a Reference. When a Reference containing an LDAP or LDAPS URL is passed to NamingManager.getObjectInstance() or DirectoryManager.getObjectInstance(), a new connection is created using information specified in the URL.
Finally, when a referral is followed manually or automatically, the information in the referral is used to create a new connection. See the Referrals lesson for information on referrals.
Shared ConnectionsContext instances and NamingEnumerations that are derived from one Context instance share the same connection until changes to one of the Context instances make sharing no longer possible. For example, if you invoke Context.lookup(), Context.listBindings() or DirContext.search() from the initial context and get back other Context instances, then all of those Context instances will share the same connection.
Here is an example.In this example, ctx, ctx2, and ctx3 will share the same connection.// Create initial context DirContext ctx = new InitialDirContext(env); // Get a copy of the same context Context ctx2 = (Context)ctx.lookup(""); // Get a child context Context ctx3 = (Context) ctx.lookup("ou=NewHires");
Sharing is done regardless of how the Context instance came into existence. For example, a Context instance obtained by following a referral will share the same connection as the referral.
When you change a Context instance's environment properties that are related to a connection, such as the principal name or credentials of the user, the Context instance on which you make these changes will get its own connection (if the connection is shared). Context instances that are derived from this Context instance in the future will share this new connection. Context instances that previously shared the old connection are not affected (that is, they continue to use the old connection).
Here is an example that uses two connections.ctx2 initially shares the same connection with ctx. But when its principal and password properties are changed, it can no longer use ctx's connection. The LDAP provider will automatically create a new connection for ctx2.// Create initial context (first connection) DirContext ctx = new InitialDirContext(env); // Get a copy of the same context DirContext ctx2 = (DirContext)ctx.lookup(""); // Change authentication properties in ctx2 ctx2.addToEnvironment(Context.SECURITY_PRINCIPAL, "cn=C. User, ou=NewHires, o=JNDITutorial"); ctx2.addToEnvironment(Context.SECURITY_CREDENTIALS, "mysecret"); // Method on ctx2 will use new connection System.out.println(ctx2.getAttributes("ou=NewHires"));
Similarly, if you use LdapContext.reconnect() to change the Context instance's connection controls, the Context instance will get its own connection if the connection was being shared.
If the Context instance's connection was not being shared (i.e., no Contexts have been derived from it), then changes to its environment or connection controls will not cause a new connection to be created. Instead, any changes relevant to the connection will be applied to the existing connection.
Creation TimeoutsNot all connection creations are successful. If the LDAP provider cannot establish a connection within a certain timeout period, it aborts the connection attempt. By default, this timeout period is the network (TCP) timeout value, which is in the order of a few minutes. To change the timeout period, you use the "com.sun.jndi.ldap.connect.timeout" environment property. The value of this property is the string representation of an integer representing the connection timeout in milliseconds.
Here is an example.In this example, if a connection cannot be created within 5 seconds, an exception will be thrown.// Set up environment for creating initial context Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial"); // Specify timeout to be 5 seconds env.put("com.sun.jndi.ldap.connect.timeout", "5000"); // Create initial context DirContext ctx = new InitialDirContext(env); // do something useful with ctx
If the Context.PROVIDER_URL property contains more than one URL, the provider will use the timeout for each URL. For example, if there are 3 URLs and the timeout has been specified to be 5 seconds, then the provider will wait for a maximum of 15 seconds in total.
See the Connection Pooling section for information on how this property affects connection pooling.
Note: On systems earlier than the Java 2 SDK, v 1.4, this property is ignored because there is no support in the SDK for connection creation timeouts.
Automatic Discovery of LDAP ServersUnlike the examples in this tutorial, you usually do not hardwire hostname and port information into your JNDI program. The program usually reads such information from a configuration file or user input. In some environments, such as the Windows 2000 networks, information about LDAP servers are published in the DNS. In such environments, the JNDI program has the additional option of using the information in the DNS instead of from configuration files or users. This use of information from DNS to locate LDAP servers is called service location or service discovery; LDAP is but one type of service that can be located in this way.
The LDAP service provider supports LDAP service discovery. If the LDAP service provider is given an LDAP or LDAPS URL that contains only a distinguished name, (that is, no hostname or port number), it will use the distinguished name to find information about the LDAP server(s) in the DNS. Here is an example.This example uses the distinguished name o=JNDITutorial,dc=example,dc=com. The LDAP service provider uses the dc components to construct the DNS domain name, example.com. It then looks for LDAP service records for the DNS domain example.com. If records for more than one server are found, it will order the servers according to the weight information in the records and then try each in order. The algorithms of how the domain name is determined and the ordering of servers are described in the Internet draft draft-ietf-ldapext-locate-08.txt and RFC 2782.// Set up environment for creating initial context Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // Omit server and port number when specifying URL env.put(Context.PROVIDER_URL, "ldap:///o=JNDITutorial,dc=example,dc=com"); // Create initial context DirContext ctx = new InitialDirContext(env); // do something useful with ctx
For locating the service records of the LDAP service, the LDAP service provider uses the DNS service configured for the underlying platform. On Solaris and Linux, the DNS client configuration is read from the /etc/resolv.conf file. On Windows, it is the DNS service configured for the Windows client. If DNS has not been configured for the underlying platform, the LDAP service provider will use localhost and 53 as the hostname and port of the DNS server. If no DNS service is available, or if the DNS service does not have the LDAP service's service records, the LDAP service provider will use localhost and 389 as the hostname and port of the LDAP server.
Note: Automatic discovery of the LDAP service using the URL's distinguished name is supported in Java 2 SDK, v1.4.1 and later releases. In earlier releases, localhost and 389 are used if the hostname and port number are missing from the URL.