Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java- how to tell LDAP DirContext.search(...).hasMore() to return false instead of throwing a PartialResultException

Tags:

java

ldap

I set-up the LDAP DirContext.search(...) to ignore referrals, but I still get a referral exception when I call NamingEnumeration.hasMore().

Exception in thread "main" javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'DC=company,DC=com'
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2846)
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2820)
    at com.sun.jndi.ldap.LdapNamingEnumeration.getNextBatch(LdapNamingEnumeration.java:129)
    at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreImpl(LdapNamingEnumeration.java:198)
    at com.sun.jndi.ldap.LdapNamingEnumeration.hasMore(LdapNamingEnumeration.java:171)

Can I tell DirContext.search to ignore referrals, so that NamingEnumeration.hasMore() returns false instead of throwing an exception?

this is the snipped:

import javax.naming.*;
import javax.naming.directory.*;

Properties p = new Properties();
p.setProperty(Context.INITIAL_CONTEXT_FACTORY, ldapInitContextFactory);
p.setProperty(Context.PROVIDER_URL, ldapURL);
p.setProperty(Context.SECURITY_CREDENTIALS, ldapPassword);
p.setProperty(Context.SECURITY_PRINCIPAL, ldapUser);
p.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
p.setProperty(Context.REFERRAL, "ignore");
DirContext ctx = new InitialDirContext(p);

SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setDerefLinkFlag(false);

NamingEnumeration e = ctx.search(ldapBaseDN, ldapQuery, null, searchControls);

for (; e.hasMore();) {
    SearchResult sr = (SearchResult) e.next();
    System.out.println("\nSearch Result: " + sr.getName());
}

Note: if I enable referrals, I get an LdapReferralException expcetion when I call NamingEnumeration.hasMore().

like image 529
David Portabella Avatar asked Apr 24 '12 15:04

David Portabella


2 Answers

javax/naming/NamingEnumeration.java
public interface NamingEnumeration<T> extends Enumeration<T> {
    public boolean hasMore() throws NamingException;
    public T next() throws NamingException;
    ...
}

java/util/Enumeration.java
public interface Enumeration<E> {
    boolean hasMoreElements();
    E nextElement();
}

calling e.hasMoreElements() instead of e.hasMore() solves the issue. that is, it returns false (instead of throwing an exception) when there are referrals.

however, it is not an optimal solution, in the sense that we might be missing other real NamingException exceptions (such as CommunicationException).

I still would like to find the proper way to tell DirContext.search to ignore referrals, so that NamingEnumeration.hasMore() returns false instead of throwing an exception. any idea?

I downloaded the JDK source code at http://download.java.net/openjdk/jdk6/ -> openjdk-6-src-b24-14_nov_2011.tar.gz however this source code does not correspond exactly with the JDK binaries, see how to find the exact sources of a JDK1.6 binary (including com.sun.jndi.*)

from this JDK source code below it doesn't seem possible to get a "false" instead of an exception when there are referrals.

./jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java
protected void processReturnCode(LdapResult res, Name resolvedName, Object resolvedObj, Name remainName, Hashtable envprops, String fullDN) throws NamingException {
    NamingException e;

    switch (res.status) {
    case LdapClient.LDAP_SUCCESS:

        // handle Search continuation references
        if (res.referrals != null) {
            msg = "Unprocessed Continuation Reference(s)";

            if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
                e = new PartialResultException(msg);
                break;
            }
        [...]
    }
    [...]
    throw e;
}

but still I am not sure.

I think it makes sense that we could tell DirContext.search to ignore referrals, so that NamingEnumeration.hasMore() returns false instead of throwing an exception.

any idea?

like image 72
David Portabella Avatar answered Oct 06 '22 01:10

David Portabella


From what little I understand, there is a way to ignore referrals, which can be especially helpful when dealing with Active Directory LDAP operations. You'd have to create and inject a new LdapTemplate (constructed with a configured ContextSource) instead of creating your own InitialDirContext from scratch. I can't tell if that's going to be compatible with your setup. I hope this helps.

From the Spring LDAP Core LdapTemplate documentation:

AD servers are apparently unable to handle referrals automatically, which causes a PartialResultException to be thrown whenever a referral is encountered in a search. To avoid this, set the ignorePartialResultException property to true.

like image 26
Burnest Griffin IV Avatar answered Oct 06 '22 00:10

Burnest Griffin IV