当尝试运行上面的代码时,我收到了带有消息的javax.naming.OperationNotSupportedException: [LDAP:错误代码12 - 00000057:LdapErr:DSID-0C09079A,注释:处理控制错误,数据0,v2580]。 成功检索到第一个页面,仅在第二次循环迭代时抛出异常。
public void pagedResults() {
PagedResultsCookie cookie = null;
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
int page = 1;
do {
logger.info("Starting Page: " + page);
PagedResultsDirContextProcessor processor = new PagedResultsDirContextProcessor(20, cookie);
List<String> lastNames = ldapTemplate.search("", initialFilter.encode(), searchControls, UserMapper.USER_MAPPER_VNT, processor);
for (String l : lastNames) {
logger.info(l);
}
cookie = processor.getCookie();
page = page + 1;
} while (null != cookie.getCookie());
}
但是,当我使用上面的纯实现删除Spring LDAP时,它可以工作!
try {
LdapContext ctx = new InitialLdapContext(env, null);
// Activate paged results
int pageSize = 5;
byte[] cookie = null;
ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.CRITICAL) });
int total;
do {
/* perform the search */
NamingEnumeration results = ctx .search("",
"(&(objectCategory=person)(objectClass=user)(SAMAccountName=vnt*))",
searchCtls);
/* for each entry print out name + all attrs and values */
while (results != null && results.hasMore()) {
SearchResult entry = (SearchResult) results.next();
System.out.println(entry.getName());
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
total = prrc.getResultSize();
if (total != 0) {
System.out.println("***************** END-OF-PAGE "
+ "(total : " + total
+ ") *****************\n");
} else {
System.out.println("***************** END-OF-PAGE "
+ "(total: unknown) ***************\n");
}
cookie = prrc.getCookie();
}
}
} else {
System.out.println("No controls were sent from the server");
}
// Re-activate paged results
ctx.setRequestControls(new Control[] { new PagedResultsControl(
pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
ctx.close();
} catch (NamingException e) {
System.err.println("PagedSearch failed.");
e.printStackTrace();
} catch (IOException ie) {
System.err.println("PagedSearch failed.");
ie.printStackTrace();
}
任何提示?
答案 0 :(得分:1)
LDAP分页结果的坏处是,只有在所有请求使用相同的底层连接时,它们才有效。 Spring LDAP的内部为每个LdapTemplate操作获取一个新连接,除非使用事务支持。
确保将一系列LDapTemplate操作用于相同连接的最简单方法是使用事务支持,即为Spring LDAP配置事务并使用Transactional注释包装目标方法。
答案 1 :(得分:0)
我设法使用SingleContextSource.doWithSingleContext方法让我的上面的例子工作。
但是我的情况不同,我的应用程序是面向服务的,分页结果以及cookie应该发送到外部客户端,以便他决定是否请求下一页。
据我所知,spring-ldap不支持这种情况。我必须使用纯实现,以便我可以在请求期间跟踪底层连接。事务支持可以和SingleContextSource一样有用,但不能在不同的请求中提供帮助。
@marthursson 今年春天是否有任何计划支持这种支持?
答案 2 :(得分:0)
我发现我可以使用你的第一个例子(Spring),只要我在ldapTemplate配置中将ignorePartialResultException属性设置为true,并按照建议将@Transactional放在我的方法上。
答案 3 :(得分:0)
您可以像这样替换ldapTemplate
DirContext
ldapTemplate.setContextSource(new SingleContextSource(ldapContextSource().getReadWriteContext()));