eightmd eightmd - 1 month ago 13
Java Question

Can not get LDAP VirtualListView to work

I'm having trouble getting the VLV control to work. I'm using ApacheDS 2.0.0 and talking to it using Java JNDI with Sun's ldapbp-1.0.jar. When queried the server says it supports the VLV control. I'm not getting any errors but, I set up the searches and I get back all of the results instead of a subset. I set up a new ApacheDS instance and it has 10 users in it. I always get all 10 in the results.

I also get a SortResponseControl back and never a VirtualListViewResponseControl.

I have seen many examples and I'm essentially doing what they are. This code example I took verbatim and just changed the connection information and search criteria and I still get the same problem.
Post from LDAP Pro forum

Some of the parameters I've tried for the VirtualListViewControl are:

new VirtualListViewControl(1, 0, 0, 19, Control.CRITICAL); // original - gets all
new VirtualListViewControl(1, 10, 1, 2, Control.CRITICAL); // target offset -gets all
new VirtualListViewControl(20, 3, Control.CRITICAL); // target percentage - gets all
new VirtualListViewControl("Tryit4", 3, Control.CRITICAL); // target value, view size - gets all
new VirtualListViewControl("Tryit4", 2, 1, Control.CRITICAL); // target value, before count, after count


I must be doing something wrong but I can't see what it is. Any help would be appreciated.
Thanks

Sorry the link doesn't work. It did for me. Here is the code example I am using which always returns a SortResponseControl and all the LDAP entries.

/**
*
* VLVJndiClient.java
* Sample code to demostrate how Virtual List View (VLV) Control works.
* Note:
* 1) Note: JNDI Boost package is required for this example to run.
* 2) VLV Control MUST be used in conjunction with Sort Control.
* Otherwise, you will be braced by: [LDAP: error code 60 - VLV Control]
* 3) SunOne Directory Server supports VLV & Microsoft supports VLV since AD2003
*
*/

import java.util.Hashtable;
import java.io.*;

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

import com.sun.jndi.ldap.ctl.VirtualListViewControl;
import com.sun.jndi.ldap.ctl.VirtualListViewResponseControl;
import com.sun.jndi.ldap.ctl.SortControl;

public class VLVJndiClientShort
{

static final String VLV_CONTROL_OID = "2.16.840.1.113730.3.4.9";

public static void main(String[] args) throws IOException
{
Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");

env.put(Context.PROVIDER_URL, "ldap://172.16.2.23:10389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "test");

try {
/* Create initial context with no connection request controls */
LdapContext ctx = new InitialLdapContext(env, null);

/* Query the server to see if the VLV Control is supported */
if (!isVLVControlSupported(ctx)){
System.out.println(
"The server does not support Virtual List View (VLV) Control.");
System.exit(1);
}

/* Sort Control is required for VLV to work */
SortControl sctl = new SortControl(
new String[]{"cn"}, // sort by cn
Control.CRITICAL
);

/* VLV that returns the first 20 answers 0 to 19 changed 19 to 2 */
VirtualListViewControl vctl =
// new VirtualListViewControl(1, 0, 0, 19, Control.CRITICAL); // original - gets all
// new VirtualListViewControl(1, 10, 1, 2, Control.CRITICAL); // target offset, list size, before count, after count, criticality - gets all
// new VirtualListViewControl(20, 3, Control.CRITICAL); // target percentage, view size, criticality - gets all
// new VirtualListViewControl("Tryit4", 3, Control.CRITICAL); // target value, view size, criticality - gets all
new VirtualListViewControl("Tryit4", 2, 1, Control.CRITICAL); // target value, before count, after count, criticality

/* Set context's request controls */
ctx.setRequestControls(new Control[]{sctl, vctl}); // returns only a sorted control but no VLV control

/* Perform search */
NamingEnumeration answer =
ctx.search("dc=mir3,dc=example,dc=com", "(objectclass=*)", null);

/* Enumerate search results */
while (answer.hasMore()) {
SearchResult si = (SearchResult)answer.next();
System.out.println(si.getName());
}

/* examine the response controls (if any) */
printControls(ctx.getResponseControls());

ctx.close();

} catch (NamingException e) {
e.printStackTrace();
}
}

static void printControls(Control[] controls)
{
if(controls == null){
System.out.println("No response controls");
return;
}

for(int j = 0; j < controls.length; j++) {
if(controls[j] instanceof SortResponseControl){
SortResponseControl src = (SortResponseControl)controls[j];
if (src.isSorted()) {
System.out.println("Sorted-Search completed successfully");
} else {
System.out.println(
"Sorted-Search did not complete successfully: error (" +
src.getResultCode() + ") on attribute '" +
src.getAttributeID() + "'");
}
}else if(controls[j] instanceof VirtualListViewResponseControl){
VirtualListViewResponseControl vlv =
(VirtualListViewResponseControl)controls[j];
if (vlv.getResultCode() == 0) {
System.out.println("Sorted-View completed successfully");
System.out.println("TargetOffset: " + vlv.getTargetOffset());
System.out.println("ListSize: " + vlv.getListSize());
} else {
System.out.println("Sorted-View did not complete successfully: "
+ vlv.getResultCode());
}
} else {
System.out.println("Received control: "+ controls[j].getID());
}
}
}

/**
* Is VLV Control supported?
*
* Query the rootDSE object to find out if VLV Control
* is supported.
*/
static boolean isVLVControlSupported(LdapContext ctx)
throws NamingException
{
SearchControls ctl = new SearchControls();
ctl.setReturningAttributes(new String[]{"supportedControl"});
ctl.setSearchScope(SearchControls.OBJECT_SCOPE);

/* search for the rootDSE object */
NamingEnumeration results = ctx.search("", "(objectClass=*)", ctl);

while(results.hasMore()){
SearchResult entry = (SearchResult)results.next();
NamingEnumeration attrs = entry.getAttributes().getAll();
while (attrs.hasMore()){
Attribute attr = (Attribute)attrs.next();
NamingEnumeration vals = attr.getAll();
while (vals.hasMore()){
String value = (String) vals.next();
if (value.equals(VLV_CONTROL_OID))
return true;
}
}
}
return false;
}

}

Answer

No one seems to have any input on this but I'll tell you what I found. As said above I tried to get the VLV to work on OpenLDAP and apacheDS. When queried the servers say they support the control but when you use it you get back all of the entries, instead of the subset that was requested.

Since my customer was using the SunOne LDAP server I figured I'd try that. SunOne was only around for a couple of years in early 2000s but it was supported as the Oracle Directory Service till 2011. You can download it from their site at Oracle site for download. Look for the Oracle Directory Server Enterprise Edition (11.1.1.7.0). I believe you need an Oracle Developers login. The installation instructions are here Installation Documentation.

The Oracle Directory Service is the only LDAP Server that I found in my limited search that correctly supports the VLV control as it is documented.

NOTE that servers will say they support VLV but when they support the Paged search also, VLV will not be implemented correctly.

This is what I have found and if I am in error I would love to hear how the other LDAP servers support VLV for paging. For anyone that viewed this post Thank you!