i have web application daily search on ldap database. done through spring ldap library on sheduled task. search return 20000 results. wish modify attribute on of these users problems start. wish there group modify function in relational database (set a=x b
so have tried 2 approaches:
loop on each user, , looks this:
distinguishedname userdn = builddn(user); dircontextoperations dtctx = ldaptemplate.lookupcontext(userdn); for(int = 0; < attributes.length; i++){ dtctx.setattributevalue(attributes[i], values[i]); } ldaptemplate.modifyattributes(dtctx); which works, time consuming.
the second approach same first, chop list of users , multi thread modify. works faster, still not scale well. ldap opends datastore.
is there better way batch modify on ldap web application?
you @ spring batch pattern single list of users built up, then, using thread pool, each user passed, modified , committed ldap server.
a configuration might this;
<batch:job id="ldapjob"> <batch:step id="ldapjob.step1"> <batch:tasklet task-executor="taskexecutor"> <batch:chunk reader="ldapreader" processor="ldapmodifier" writer="ldapwriter" commit-interval="1"/> </batch:tasklet> </batch:step> </batch:job> <task:executor id="taskexecutor"/> with reader this
package de.incompleteco.spring.batch.item.reader; import java.util.queue; import org.springframework.batch.item.itemreader; import org.springframework.batch.item.nontransientresourceexception; import org.springframework.batch.item.parseexception; import org.springframework.batch.item.unexpectedinputexception; import org.springframework.ldap.core.dircontextoperations; public class ldapitemreader implements itemreader<dircontextoperations> { private queue<dircontextoperations> dircontextoperations; public dircontextoperations read() throws exception, unexpectedinputexception, parseexception, nontransientresourceexception { if (dircontextoperations == null) { synchronized (this) { //load dircontextoperations queue }//end synch }//end if //retrieve return dircontextoperations.poll(); } } a processor;
package de.incompleteco.spring.batch.item.processor; import org.springframework.batch.item.itemprocessor; import org.springframework.ldap.core.dircontextoperations; public class ldapitemprocessor implements itemprocessor<dircontextoperations, dircontextoperations> { public dircontextoperations process(dircontextoperations item) throws exception { //do update item.setattributevalue(null, null); //return return item; } } and writer ldap server
package de.incompleteco.spring.batch.item.writer; import java.util.list; import org.springframework.batch.item.itemwriter; import org.springframework.ldap.core.dircontextoperations; import org.springframework.ldap.core.ldaptemplate; public class ldapitemwriter implements itemwriter<dircontextoperations> { private ldaptemplate ldaptemplate; public void write(list<? extends dircontextoperations> items) throws exception { (dircontextoperations operation : items) { ldaptemplate.modifyattributes(operation); } } public void setldaptemplate(ldaptemplate ldaptemplate) { this.ldaptemplate = ldaptemplate; } } the key thing in pattern use of taskexecutor allow multi-thread process, reader being responsible first building queue/list (of 20k records) each thread poll user, make changes, put back.
this pattern doesn't allow retries may want @ loading strategy, give decent thread pool scalable update solution can run in war.
have @ spring-batch more information
Comments
Post a Comment