Spring LDAP Template Usage

psuryan picture psuryan · Sep 30, 2011 · Viewed 11.8k times · Source

Please take a look at the test class below. I am trying to do an LDAP search with Spring LDAP Template. I am able to search and produce a list of entries corresponding to the search criteria without the Spring LDAP template by using the DirContext as shown in the method searchWithoutTemplate(). But when I use a LdapTemplate, I end up with a NPE as shown further below. I am sure I must be missing something. Can someone help please?

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapName;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
import org.springframework.ldap.core.support.LdapContextSource;

public class LDAPSearchTest {
    //bind params
    static String url="ldap://<IP>:<PORT>";
    static String userName="cn=Directory Manager";
    static String password="password123";
    static String bindDN="dc=XXX,dc=com";

    //search params
    static String base = "ou=StandardUser,ou=XXXCustomers,ou=People,dc=XXX,dc=com";
    static String filter = "(objectClass=*)";
    static String[] attributeFilter = { "cn", "uid" };
    static SearchControls sc = new SearchControls();

    public static void main(String[] args) throws Exception {
        // sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
        sc.setReturningAttributes(attributeFilter);
        searchWithTemplate(); //NPE
        //searchWithoutTemplate(); //works fine
    }

    public static void searchWithTemplate() throws Exception {
        DefaultDirObjectFactory factory = new DefaultDirObjectFactory();
        LdapContextSource cs = new LdapContextSource();
        cs.setUrl(url);
        cs.setUserDn(userName);
        cs.setPassword(password);
        cs.setBase(bindDN);
        cs.setDirObjectFactory(factory.getClass ());
        LdapTemplate template = new LdapTemplate(cs);
        template.afterPropertiesSet();
        System.out.println((template.search(new LdapName(base), filter, sc,
                new AttributesMapper() {
                    public Object mapFromAttributes(Attributes attrs)
                            throws NamingException {
                        System.out.println(attrs);
                        return attrs.get("uid").get();
                    }
                })));
    }

    public static void searchWithoutTemplate() throws NamingException{
        Hashtable env = new Hashtable(11);
        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, url);
        //env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, userName);
        env.put(Context.SECURITY_CREDENTIALS, password);
        DirContext dctx = new InitialDirContext(env);
        NamingEnumeration results = dctx.search(base, filter, sc);
        while (results.hasMore()) {
            SearchResult sr = (SearchResult) results.next();
            Attributes attrs = sr.getAttributes();
            System.out.println(attrs);
            Attribute attr = attrs.get("uid");
        }
        dctx.close();
    }
}

Exception is:

Exception in thread "main" java.lang.NullPointerException
    at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:125)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:287)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:237)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:588)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:546)
    at LDAPSearchTest.searchWithTemplate(LDAPSearchTest.java:47)
at LDAPSearchTest.main(LDAPSearchTest.java:33)

I am using Spring 2.5.6 and Spring LDAP 1.3.0

Answer

millhouse picture millhouse · Oct 24, 2011

A quick scan showed that it's the authenticationSource field of AbstractContextSource that is the culprit. That file includes the following comment on the afterPropertiesSet() method:

/**
* Checks that all necessary data is set and that there is no compatibility
* issues, after which the instance is initialized. Note that you need to
* call this method explicitly after setting all desired properties if using
* the class outside of a Spring Context.
*/
public void afterPropertiesSet() throws Exception {
    ...
}

That method then goes on to create an appropriate authenticationSource if you haven't provided one. As your test code above is most definitely not running within a Spring context, and you haven't explicitly set an authenticationSource, I think you need to edit your code as follows:

...
cs.setDirObjectFactory(factory.getClass ());

// Allow Spring to configure the Context Source:
cs.afterPropertiesSet();

LdapTemplate template = new LdapTemplate(cs);