JNDI-LDAP paging

2019-05-15 22:45发布

问题:

I managed to get pagination working like described here. The problem is I need to expose an API which would look like this:getUsers(pageSize, pageNumber), which does not really go well with the way JNDI/LDAP does the paging(with a cookie you pass each time to the search method). The code looks like this:

private NamingEnumeration ldapPagedSearch(String filter, int pageSize, int pageNumber){
    InitialLdapContext ctx = getInitialContext();

    //TODO: get the id also, need to spec it in UI
    // Create the search controls
    SearchControls searchCtls = new SearchControls();
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    //keep a session
    byte[] cookie = null;

    //Request the paged results control
    Control[] ctls = new Control[]{new PagedResultsControl(pageSize, true)};
    ctx.setRequestControls(ctls);

    //Specify the search scope
    NamingEnumeration results = null;
    int currentPage = 1;
    do {
        results = ctx.search(getConfiguration().get(BASEDN_KEY), filter, searchCtls);

        //we got to the right page, return this page
        if(currentPage == pageNumber) {
            return results;
        }

        // loop through this page, because we cannot get a proper cookie otherwise
        // WARN: this could be a problem of performance
        while (results.hasMore()) results.next();

        // examine the paged results control response
        Control[] controls = ctx.getResponseControls();
        if (controls != null) {
            for (Control control : controls) {
                if (control instanceof PagedResultsResponseControl) {
                    cookie = ((PagedResultsResponseControl) control).getCookie();
                } 
            }
        }

        // pass the cookie back to the server for the next page
        ctx.setRequestControls(new Control[]{new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });

        //increment page
        currentPage++;
    } while (cookie != null);


    ctx.close();

    //if we get here, means it is an empty set(consumed by the inner loop)
    return results;
}

It seems I need to iterate through all the pages to get the required page. Moreover, I need to iterate through all the entries on a page, to be able to get the next page.

Is there a better way? I worry about performance issues.

回答1:

There is something called "Virtual List View" control. It is supported by a couple of LDAP servers. Not sure if the implementation is still in the JNDI. If not, you may consider to implement it yourself. You have to use it together with server side sorting.

See also http://tools.ietf.org/html/draft-ietf-ldapext-ldapv3-vlv-04 and http://www.cs.rit.edu/usr/local/pub/jeh/rit/java/lib/doc/ldapcontrols/com/sun/jndi/ldap/ctl/VirtualListViewControl.html



回答2:

You are correct. The APIs don't jell. You need to redesign the API you are supposed to be delivering.



标签: ldap paging jndi