Make your ldap search fast

Problem- I am using JNDI to connect to ldap active directory, and i want to search for users with the name contains the search string,. Its very slow.
my search method is as follows:

public static List<LDAPUser> searchContactsByName(
        ExtendedDirContext extendedDirContext, String name) {

    try {

        LdapContext ldapContext = extendedDirContext.getLdapContext();
        String searchBaseStr = extendedDirContext.getSearchBase();

        String sortKey = LDAPAttributes.NAME;
        ldapContext.setRequestControls(new Control[] { new SortControl(
                sortKey, Control.CRITICAL) });

        SearchControls searchCtls = new SearchControls();
        searchCtls.setTimeLimit(1000 * 10);

        String returnedAtts[] = { LDAPAttributes.USER_NAME,
                LDAPAttributes.NAME };
        searchCtls.setReturningAttributes(returnedAtts);

        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String searchFilter = "(&(ObjectCategory=person)(cn=*" + name
                + "*))";

        NamingEnumeration<SearchResult> results = ldapContext.search(
                searchBaseStr, searchFilter, searchCtls);

        List<LDAPUser> users = new ArrayList<LDAPUser>(0);
        while (results.hasMoreElements()) {
            SearchResult sr = (SearchResult) results.next();
            Attributes attrs = sr.getAttributes();
            LDAPUser user = new LDAPUser();
            user.setName(attrs.get(LDAPAttributes.NAME).toString()
                    .replace("cn: ", ""));
            user.setUserName(attrs.get(LDAPAttributes.USER_NAME).toString()
                    .replace("sAMAccountName: ", ""));
            users.add(user);
        }

        return users;

    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
 

connection to ldap:

public static ExtendedDirContext connectToLdap(MessageSource messageSource) {

    try {
        log.debug("connectToLdap");
        String providerUrl = messageSource.getMessage("provider.url", null,
                null);
        String securityPrincipal = messageSource.getMessage(
                "security.principal", null, null);
        String securityCredentials = messageSource.getMessage(
                "security.credentials", null, null);
        String searchBase = messageSource.getMessage("search.base", null,
                null);
        boolean ssl = Boolean.parseBoolean(messageSource.getMessage("ssl",
                null, null));
        LdapContext ldapContext;

        Hashtable<String, String> ldapEnv = new Hashtable<String, String>(
                11);
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, providerUrl);
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, securityPrincipal);
        ldapEnv.put(Context.SECURITY_CREDENTIALS, securityCredentials);
        if (ssl)
            ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
        // To get rid of the PartialResultException when using Active
        // Directory
        ldapEnv.put(Context.REFERRAL, "follow");
        ldapContext = new InitialLdapContext(ldapEnv, null);
        ExtendedDirContext extendedDirContext = new ExtendedDirContext();
        extendedDirContext.setLdapContext(ldapContext);
        extendedDirContext.setSearchBase(searchBase);
        log.debug("success connection to ldap");
        return extendedDirContext;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }

}
 

ldap credentials:

provider.url=ldap://abc.techartifact.com:389
security.principal=CN=administrator,CN=Users,DC=techartifact,DC=com
security.credentials=password
search.base=dc=techartifact,dc=com
 

its very difficult to understand why the search takes too much time to retrieve the data.

Solution -To change

ldapEnv.put(Context.REFERRAL, "follow");  to ldapEnv.put(Context.REFERRAL, "ignore");

 

Happy coding with Vinay in techartifact…

Open and close all af:showDetail in Oracle ADF

Requirement- functionality to open/close all
Implementation- Use forEach instead of iterator so that you can access children from panelGroupLayout parent component.

Here is the sample code:

    <af:commandButton id="cbShow" text="Show All" icon="/gfx/icons/show.gif" action="#{toggleShowDetails.showAll}"   styleClass="info showHide" iconPosition="trailing" partialSubmit="true"/>  
    <af:panelGroupLayout binding="#{toggleShowDetails.pglDetails}">  
        <af:forEach items="#{pageFlowScope.informationList}" var="blok" varStatus="status">  
              <af:showDetail id="sdInfo" disclosedText="Disclosed" undisclosedText="Undisclosed" partialTriggers="cbShow">  
                   <af:outputText value="Some value"/>  
             </af:showDetail>  
         </af:forEach>  
    </af:panelGroupLayout>  
 
 

    public String showAll() {  
        for(UIComponent child : pglDetails.getChildren()){  
            if(child instanceof RichShowDetail){  
                RichShowDetail showDetail = (RichShowDetail)child;  
                showDetail.setDisclosed(true);  
            }  
          DisclosureEvent event = new DisclosureEvent(showDetail, false);
          event.queue();
        }  
        return null;  
    }  
 

af:iterator is a component by ADF whereas af:forEach is an ADF extension to the JSTL tag c:forEach.
af:iterator doesn’t create multiple copies of each sub component, hence you can’t access all dynamically generated instances for modifying from bean and should not use af:iterator

Happy Learning wit Vinay Kumar