Showing posts with label LDAP. Show all posts
Showing posts with label LDAP. Show all posts

5/17/2013

Spring LDAP Template VS UnboundID (ApacheDS 1.5.7 VS ApacheDS 2.0.0)

For Basic impl and compare of these two.
Refer to
CRUD for LDAP (Spring LDAP Template, ApacheDS).
             

CRUD for LDAP (UnboundID JDK, ApacheDS)


For efficiency,

I wrote several test cases to get the data:

Environment: Win7, 8G memory, 3.3GHz

Efficiency Compare of ApacheDS 1.5.7 & 2.0.0 (Use UnboundId)

1.5.7
2.0.0
create 1 records
20421ms
130ms
create first 50 records
1245862ms(hasn’t test increase)
3510ms(increase 700ms each time create 50 more)
Search 1 record from 200 records
50ms
45ms
Search 1 record from 5000 records
720ms
700ms
Efficiency Compare of Spring & UnboundId (Use ApacheDS 2.0.0 as LDAP server)

Spring
UnboundId
create first 1 records
93ms
118ms
Create the  5001st records
333ms
221ms
create first 50 records
7129ms
6443ms
Search 1 record from 200 records
31ms
45ms
Search 1 record from 5000 records
730-770 ms
650-700 ms
1000 Thread Search 1 record from 5000 records
Total Cost around 360000ms
Average around 360 ms
Total Cost around 360000ms
Average around 360ms

For apacheDS 2.0.0
set HEAP=-Xms2048m -Xmx4096m
200 initialize connection 800 max connection
Maximum support 1200 threads creating and searching at the same time.
But if the records number in the LDAP is increasing, the supported thread number will decrease.

In the compare, we can see, the create efficiency of ApacheDS 1.5.7 and 2.0.0 is not on the same level. V2.0.0 is much faster. The retrieval efficiency does not have that much difference. Guess all use the classic search logic...^^

While compare Spring LDAP template and UnboundID, found that when data set is small, spring may have a better performance, but as the data size increase, spring's efficiency is decreased and UnboundID is better.

While in the testing, we can prove that LDAP is definitely not designed to do frequently create and update. 
--The creating efficiency is so bad, especially in ApacheDS 1.5.7. 
--Also if you make create and search in the same time, when thread number increase and when data set size is huge, the server can easily crush. (Heap Space Exception. Memory is not enough.)
--If the server crush, you cannot access the data anymore, and cannot resume even restart the server, also the invalid EOF exception may be thrown out.




5/15/2013

CRUD for LDAP (Spring LDAP Template, ApacheDS)

As we knows, there are many LDAP SDKs, I've tried UnboundId which is good, but still have several defects when cooperate with ApacheDS.
For example,
1. The UnboundId does not support recursive delete when LDAP server does not implement the tree delete, we need to code ourselves. But Spring LDAP Template already support this.
2. The UnboundId cannot remove the old RDN when rename the old entry, even set the remove flag to true.

Afterwards, I test the Spring LDAP Template, it's also not perfect.(1.3.1.RELEASE)
1. The ODM has some issue when read binary data back from ApacheDS LDAP server.
    For example, when map the objectclass 'inetOrgPerson' with auxiliary 'tlsKeyInfo', the privatekey and publicKey and userPKCS12 attribute is read as String, only userCertificate can be read as binary. In this case, the mapping throws exceptions because it cannot map from String to Binary(byte[]). Even I mark the attribute as '@Attribute(name = "privateKey", type = Type.BINARY)'

So generally Spring Template make a more clean job. But ODM is a little bit weaker than UnboundId.

The efficiency of CRUD is not tested yet. Only compare the convenience and result.

Below is the testing code.

TestService.java


package test.common.ldap.service;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NamingException;

import test.common.ldap.dao.UserDao;
import test.common.ldap.entity.User;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.odm.core.OdmManager;
import org.springframework.ldap.pool.factory.PoolingContextSource;

public class TestService {

   ApplicationContext ctx;
   PoolingContextSource directContext;
   OdmManager manager;
   UserDao userDao;

   public TestService() {

       ctx = new FileSystemXmlApplicationContext(
               "src/main/resources/spring/spring-context.xml");

       directContext = (PoolingContextSource) ctx.getBean("contextSource");

       manager = (OdmManager) ctx.getBean("odmManager");

       userDao = (UserDao) ctx.getBean("userDao");
   }

   public void create(String entryDN, String cn, byte[] p12Cert,
           byte[] publicKey, byte[] privateKey) throws InvalidNameException {

       System.out
       .println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
       System.out.println("Start CREATE record...");
       long startTime = System.currentTimeMillis();
       byte[] encodedPrivateCert = Base64.encodeBase64(privateKey);
       byte[] encodedP12Cert = Base64.encodeBase64(p12Cert);
     
       Name dn = new DistinguishedName(entryDN);
       dn.add("cn=" + cn);
     
       User user = new User();
       user.setDn(dn);
       user.setCn(cn);
       user.setSn(cn);
       user.setMail(cn);
       user.setKeyAlgorithm("RSA");
       user.setPublicKeyFormat("X.509");
       user.setPrivateKeyFormat("PKCS#8");
       user.setPrivateKey(encodedPrivateCert);
       user.setPublicKey(publicKey);
       user.setUserCertificate(publicKey);
       user.setUserPKCS12(encodedP12Cert);
     
       userDao.create(user);
     
       long endTime = System.currentTimeMillis();
     
       long duration = endTime - startTime;
     
       System.out.println("CREATE Time Cost(ms): " + duration);
   }

   public void createWithPersistObject(String entryDN, String cn,
           byte[] p12Cert, byte[] publicKey, byte[] privateKey)
           throws InvalidNameException {

       System.out
               .println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
       System.out.println("Start CREATE record...");
       long startTime = System.currentTimeMillis();
       byte[] encodedPrivateCert = Base64.encodeBase64(privateKey);
       byte[] encodedP12Cert = Base64.encodeBase64(p12Cert);

       Name dn = new DistinguishedName(entryDN);
       dn.add("cn=" + cn);

       User user = new User();
       user.setDn(dn);
       user.setCn(cn);
       user.setSn(cn);
       user.setMail(cn);
       user.setPrivateKey(encodedPrivateCert);
       user.setPublicKey(publicKey);
       user.setUserCertificate(publicKey);
       user.setUserPKCS12(encodedP12Cert);

       manager.create(user);

       long endTime = System.currentTimeMillis();

       long duration = endTime - startTime;

       System.out.println("CREATE Time Cost(ms): " + duration);

       // System.exit(result);

   }

   public void search(String dn, String filter)
           throws NamingException {

       System.out
               .println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
       System.out.println("Start SEARCH record...");
       long startTime = System.currentTimeMillis();

       List<User> result = userDao.findByDN(dn, filter);

       System.out.print("SEARCH Result count: ");
       System.out.println(result == null ? 0
               : result.size());

       for (User user : result) {
           System.out.println(user.toString());
       }

       long endTime = System.currentTimeMillis();

       long duration = endTime - startTime;

       System.out.println("SEARCH Time Cost(ms): " + duration);
   }

   public void update(String entryDN, String cn, String newDName,
           String newCn, byte[] p12Cert, byte[] publicKey, byte[] privateKey)
           throws Exception {

       System.out
               .println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
       System.out.println("Start UPDATE record...");

       long startTime = System.currentTimeMillis();

       Name dn = new DistinguishedName(entryDN);
       dn.add("cn=" + cn);

       if (StringUtils.isNotEmpty(newDName) || StringUtils.isNotEmpty(newCn)) {

           Name newDn = null;

           if (StringUtils.isNotEmpty(newDName)) {
               newDn = new DistinguishedName(newDName);
           } else {
               newDn = new DistinguishedName(entryDN);
           }
           if (StringUtils.isNotEmpty(newCn)) {
               newDn.add("cn=" + newCn);
               cn = newCn;
           } else {
               newDn.add("cn=" + cn);
           }
           userDao.rename(dn, newDn);
           System.out.println("Entry rename to" + newDn.toString());

           dn = newDn;
       }

       User user = new User();

       user.setDn(dn);

       user.setCn(cn);
       user.setMail(cn);
       user.setSn(cn);
       if (p12Cert != null) {
           user.setUserPKCS12(p12Cert);
       }
       if (publicKey != null) {
           user.setPublicKey(publicKey);
           user.setUserCertificate(publicKey);
       }
       if (privateKey != null) {
           user.setPrivateKey(privateKey);
       }
       userDao.update(user);

       long endTime = System.currentTimeMillis();

       long duration = endTime - startTime;

       System.out.println("UPDATE Time Cost(ms): " + duration);
       // System.exit(result);

   }

   public void delete(String entryDN) {

       System.out
               .println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
       System.out.println("Start DELETE record...");
       long startTime = System.currentTimeMillis();

       Name dn = new DistinguishedName(entryDN);
     
       User user = new User();
       user.setDn(dn);
       userDao.delete(user);

       long endTime = System.currentTimeMillis();

       long duration = endTime - startTime;

       System.out.println("DELETE Time Cost(ms): " + duration);
   }

 

   public byte[] readDataFromFile(String path) {

       InputStream is = null;
       ByteArrayOutputStream out = new ByteArrayOutputStream();

       try {
           is = new BufferedInputStream(new FileInputStream(path));
           byte[] b = new byte[1024];
           int n;
           while ((n = is.read(b)) != -1) {
               out.write(b, 0, n);
           }

       } catch (Exception e) {
           // e.printStackTrace();
           return null;
       } finally {
           if (is != null) {
               try {
                   is.close();
               } catch (Exception e) {
                   e.printStackTrace();
               }
           }
       }
       return out.toByteArray();
   }
}




UserDao.java

package test.common.ldap.dao;

import java.util.List;

import javax.naming.Name;
import javax.naming.directory.SearchControls;
import test.common.ldap.entity.User;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.EqualsFilter;

public class UserDao {

   private LdapTemplate ldapTemplate;

   public void setLdapTemplate(LdapTemplate ldapTemplate) {
       this.ldapTemplate = ldapTemplate;
   }

   public void create(User user) {
       DirContextAdapter context = new DirContextAdapter(buildDn(user));
       mapToContextForCreate(user, context);
       ldapTemplate.bind(context);
   }

   public void update(User user) throws Exception {
       Name dn = buildDn(user);
       DirContextOperations context = ldapTemplate.lookupContext(dn);
       if (context == null) {
           throw new Exception("Entry " + dn.toString() + " does not exist");
       }
       mapToContextForUpdate(user, context);
       if (context != null) {
           ldapTemplate.modifyAttributes(context);
       }

   }

   public void rename(Name oldDn, Name newDn) {
       ldapTemplate.rename(oldDn, newDn);
   }

   public void delete(User user) {
       ldapTemplate.unbind(buildDn(user), true);
   }

   @SuppressWarnings("unchecked")
   public List<User> findAll() {
       EqualsFilter filter = new EqualsFilter("objectclass""inetOrgPerson");
       System.out.println(filter.toString());
       return ldapTemplate.search(DistinguishedName.EMPTY_PATH,
               filter.encode(), getContextMapper());
   }

   @SuppressWarnings("unchecked")
   public List<User> findByDN(String dn, String filter) {
     
       if (StringUtils.isEmpty(filter)) {
           filter = new EqualsFilter("objectclass""inetOrgPerson").encode();
       }
       return ldapTemplate.search(dn, filter, SearchControls.SUBTREE_SCOPE,
               getContextMapper());
   }

   protected ContextMapper getContextMapper() {
       return new PersonContextMapper();
   }

   protected Name buildDn(User user) {
       return user.getDn();
   }

   protected Name buildDn(String dn) {
       DistinguishedName dName = new DistinguishedName(dn);

       return dName;
   }

   protected void mapToContextForUpdate(User user, DirContextOperations context) {

       boolean update = false;

       if (StringUtils.isNotEmpty(user.getCn())) {
           context.setAttributeValue("cn", user.getCn());
           context.setAttributeValue("sn", user.getCn());
           context.setAttributeValue("mail", user.getCn());
           update = true;
       }

       if (user.getPrivateKey() != null) {
           context.setAttributeValue("privateKey", user.getPrivateKey());
           update = true;
       }
       if (user.getPublicKey() != null) {
           context.setAttributeValue("publicKey", user.getPublicKey());
           context.setAttributeValue("userCertificate",
                   user.getUserCertificate());
           update = true;
       }
       if (user.getUserPKCS12() != null) {
           context.setAttributeValue("userPKCS12", user.getUserPKCS12());
           update = true;
       }

       if (update) {
           context.setAttributeValues("objectclass"new String[] { "top",
                   "tlsKeyInfo""inetOrgPerson" });

       } else {
           context = null;
       }

   }

   protected void mapToContextForCreate(User user, DirContextOperations context) {

       context.setAttributeValues("objectclass"new String[] { "top",
               "tlsKeyInfo""inetOrgPerson" });
       context.setAttributeValue("cn", user.getCn());
       context.setAttributeValue("sn", user.getCn());
       context.setAttributeValue("mail", user.getCn());
       context.setAttributeValue("keyAlgorithm",user.getKeyAlgorithm());
       context.setAttributeValue("privateKeyFormat", user.getPrivateKeyFormat());
       context.setAttributeValue("publicKeyFormat", user.getPublicKeyFormat());
       context.setAttributeValue("privateKey", user.getPrivateKey());
       context.setAttributeValue("publicKey", user.getPublicKey());
       context.setAttributeValue("userCertificate", user.getUserCertificate());
       context.setAttributeValue("userPKCS12", user.getUserPKCS12());

   }

   private static class PersonContextMapper extends AbstractContextMapper {
       public Object doMapFromContext(DirContextOperations context) {
           User user = new User();
           user.setDn(new DistinguishedName(context.getDn()));
           user.setCn(context.getStringAttribute("cn"));
           user.setSn(context.getStringAttribute("sn"));
           user.setMail(context.getStringAttribute("mail"));
           user.setKeyAlgorithm(context.getStringAttribute("keyAlgorithm"));
           user.setPrivateKeyFormat(context
                   .getStringAttribute("privateKeyFormat"));
           if(StringUtils.isNotEmpty(context.getStringAttribute("privateKey"))){
               user.setPrivateKey(context.getStringAttribute("privateKey")
                       .getBytes());
           }
         
           user.setPublicKeyFormat(context
                   .getStringAttribute("publicKeyFormat"));
           if(StringUtils.isNotEmpty(context.getStringAttribute("publicKey"))){
               user.setPublicKey(context.getStringAttribute("publicKey")
                       .getBytes());
           }
         
         
           user.setUserCertificate((byte[]) context
                   .getObjectAttribute("userCertificate"));
         
           if(StringUtils.isNotEmpty(context.getStringAttribute("userPKCS12"))){
               user.setUserPKCS12(context.getStringAttribute("userPKCS12")
                       .getBytes());
           }

           return user;
       }
   }
}

User.java


package test.common.ldap.entity;

import javax.naming.Name;

import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Attribute.Type;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;

@Entry(objectClasses = { "inetOrgPerson""tlsKeyInfo" })
public class User {

   @Id
   private Name dn;
 
   // The field used for RDN attribute myStringAttr.
   @Attribute(name = "cn")
   private String cn;

   @Attribute(name = "sn")
   private String sn;
 
   @Attribute(name = "mail")
   private String mail;

   @Attribute(name = "keyAlgorithm")
   private String keyAlgorithm = "RSA";

   @Attribute(name = "privateKeyFormat")
   private String privateKeyFormat = "PKCS#8";

   @Attribute(name = "publicKeyFormat")
   private String publicKeyFormat = "X.509";

   @Attribute(name = "privateKey", type = Type.BINARY)
   private byte[] privateKey;

   @Attribute(name = "publicKey", type = Type.BINARY)
   private byte[] publicKey;

   @Attribute(name = "userCertificate", type = Type.BINARY)
   private byte[] userCertificate;

   @Attribute(name = "userPKCS12", type = Type.BINARY)
   private byte[] userPKCS12;

   public Name getDn() {
       return dn;
   }

   public void setDn(Name dn) {
       this.dn = dn;
   }

   public String getCn() {
       return cn;
   }

   public void setCn(String cn) {
       this.cn = cn;
   }

   public String getSn() {
       return sn;
   }

   public void setSn(String sn) {
       this.sn = sn;
   }

   public String getMail() {
       return mail;
   }

   public void setMail(String mail) {
       this.mail = mail;
   }

   public String getKeyAlgorithm() {
       return keyAlgorithm;
   }

   public void setKeyAlgorithm(String keyAlgorithm) {
       this.keyAlgorithm = keyAlgorithm;
   }

   public String getPrivateKeyFormat() {
       return privateKeyFormat;
   }

   public void setPrivateKeyFormat(String privateKeyFormat) {
       this.privateKeyFormat = privateKeyFormat;
   }

   public String getPublicKeyFormat() {
       return publicKeyFormat;
   }

   public void setPublicKeyFormat(String publicKeyFormat) {
       this.publicKeyFormat = publicKeyFormat;
   }

   public byte[] getPrivateKey() {
       return privateKey;
   }

   public void setPrivateKey(byte[] privateKey) {
       this.privateKey = privateKey;
   }

   public byte[] getPublicKey() {
       return publicKey;
   }

   public void setPublicKey(byte[] publicKey) {
       this.publicKey = publicKey;
   }

   public byte[] getUserCertificate() {
       return userCertificate;
   }

   public void setUserCertificate(byte[] userCertificate) {
       this.userCertificate = userCertificate;
   }

   public byte[] getUserPKCS12() {
       return userPKCS12;
   }

   public void setUserPKCS12(byte[] userPKCS12) {
       this.userPKCS12 = userPKCS12;
   }
 
   @Override
   public String toString(){
       /*StringBuilder privateKeyString =new StringBuilder();
       if (privateKey!=null) {
           for (byte b:privateKey) {
               privateKeyString.append(Byte.toString(b));
           }
       }
       StringBuilder publicKeyString =new StringBuilder();
       if (publicKey!=null) {
           for (byte b:publicKey) {
               publicKeyString.append(Byte.toString(b));
           }
       }
       StringBuilder userCertificateString =new StringBuilder();
       if (userCertificate!=null) {
           for (byte b:userCertificate) {
               userCertificateString.append(Byte.toString(b));
           }
       }
     
       StringBuilder userPKCS12String =new StringBuilder();
       if (userPKCS12!=null) {
           for (byte b:userPKCS12) {
               userPKCS12String.append(Byte.toString(b));
           }
       }*/
     
       return String.format(
               "dn=%1$s \ncn=%2$s \nsn=%3$s \nmail=%4$s \nkeyAlgorithm=%5$s \nprivateKeyFormat=%6$s \nprivateKey=%7$s \npublicKeyFormat=%8$s \npublicKey=%9$s \nuserCertificate=%10$s \nuserPKCS12=%11$s",
               dn.toString(), cn, sn, mail, keyAlgorithm, privateKeyFormat, privateKey==null?"":new String(privateKey),publicKeyFormat, publicKey==null?"":new String(publicKey), userCertificate==null?"":new String(userCertificate),userPKCS12==null?"":new String(userPKCS12));
     
   }
}

App.java

package test.common.ldap.tool;

import java.util.Scanner;

import test.common.ldap.service.TestService;

import org.apache.commons.lang.StringUtils;



/**
*
*/
public class App
{
   public static void main( String[] args ) throws Exception
   {  
       TestService service = new TestService();
       manu(service);
   }
 
   public static void manu(TestService service) throws Exception{
       System.out.println("----------------------------------------");
       System.out.println("----------------MODE--------------------");
       System.out.println("1: create");
       System.out.println("2: retrieve");
       System.out.println("3: update");
       System.out.println("4: delete");
     
       Scanner input = new Scanner(System.in);
       System.out.print("Key in the selection : ");
     
       String selectionString = input.next();
     
       boolean isValid = StringUtils.isNumeric(selectionString);
       if(isValid) {
           int option = Integer.parseInt(selectionString);
           if(option==1){
             
               System.out.print("Please input the entry dn: ");
               Scanner inputScanner = new Scanner(System.in);
               String dn = inputScanner.next();
               System.out.println("entry dn: " + dn);
             
               System.out.print("Please input the entry cn: ");
               inputScanner = new Scanner(System.in);
               String cn = inputScanner.next();
               System.out.println("entry cn: " + cn);
             
               System.out.print("Please input the p12 cert location: ");
               byte[] p12certData = getCertDataFromPath(service);

             
               System.out.println("p12 cert data read: " + new String(p12certData) );
             
             
             
               System.out.print("Please input the public cert location: ");
               byte[] publicCertData =getCertDataFromPath(service);

             
               System.out.println("public cert data read: " + new String(publicCertData));
             
             
             
               System.out.print("Please input the private cert location: ");
               byte[] privateCertData = getCertDataFromPath(service);

             
               System.out.println("private cert data read: " + new String(privateCertData));
             
             

               service.createWithPersistObject(dn, cn, p12certData, publicCertData, privateCertData);
           }else if(option ==2){
             
               System.out.print("Please input the entry dn: ");
               Scanner inputScanner = new Scanner(System.in);
               String dn = inputScanner.next();

               System.out.println("entry dn: " + dn);
             
             
               System.out.print("Please input the filter(if do not have, input n): ");
               inputScanner = new Scanner(System.in);
               String filter = inputScanner.next();

               if(filter.equalsIgnoreCase("n")){
                   filter = null;
               }else{
                   System.out.println("entry filter: " + filter);
               }
                 
               service.search(dn, filter);
 
             
           }else if(option ==3){
             
               System.out.print("Please input the entry dn: ");
               Scanner inputScanner = new Scanner(System.in);
               String dn = inputScanner.next();

               System.out.println("entry dn: " + dn);
             
               System.out.print("Please input the entry cn: ");
               inputScanner = new Scanner(System.in);
               String cn = inputScanner.next();

               System.out.println("entry cn: " + cn);
             
               System.out.print("Please input the new entry dn(if do not want to update, input n): ");
               inputScanner = new Scanner(System.in);
               String newDn = inputScanner.next();

               if(newDn.equalsIgnoreCase("n")){
                   newDn = null;
               }else{
                   System.out.println("New entry dn: " + newDn);
               }
             
               System.out.print("Please input the new cn(if do not want to update, input n): ");
               inputScanner = new Scanner(System.in);
               String newCn = inputScanner.next();

               if(newCn.equalsIgnoreCase("n")){
                   newCn = null;
               }else{
                   System.out.println("New cn: " + newCn);
               }
             
             
               System.out.println("For below options, if no update, please input n or any other invalid path");

               System.out.print("Please input the p12 cert location: ");
               inputScanner = new Scanner(System.in);
               String certLocation = inputScanner.next();
               byte[] p12certData = getCertData(service,certLocation);

               if(p12certData!=null){
                   System.out.println("p12 cert data read: " + new String(p12certData) );
               }
             
             
             
             
               System.out.print("Please input the public cert location: ");
               inputScanner = new Scanner(System.in);
               certLocation = inputScanner.next();
               byte[] publicCertData = getCertData(service,certLocation);

               if(publicCertData!=null){
                   System.out.println("public cert data read: " + new String(publicCertData));
               }
             
               System.out.print("Please input the private cert location: ");
               inputScanner = new Scanner(System.in);
               certLocation = inputScanner.next();
               byte[] privateCertData = getCertData(service,certLocation);

               if(privateCertData!=null){
                   System.out.println("private cert data read: " + new String(privateCertData));
               }
             
             
             

               service.update(dn, cn, newDn, newCn, p12certData, publicCertData, privateCertData);
             
           }else if(option ==4){
               System.out.println("WARN: DELETE will delete all the sub-entries too, if exist.");
               System.out.print("Please input the entry dn: ");
               Scanner inputScanner = new Scanner(System.in);
               String dn = inputScanner.next();

               System.out.println("entry dn: " + dn);
             
               service.delete(dn);
             
           }else{
               System.out.println("Invalid option: " + selectionString);
               manu(service);
           }
       } else {
           System.out.println("Invalid option: " + selectionString);
           manu(service);
       }
     
       manu(service);
   }
 
   public static byte[] getCertDataFromPath(TestService service){
     
       Scanner inputScanner = new Scanner(System.in);
       String certLocation = inputScanner.next();
     
       byte[] data = null;
       try{
           data = service.readDataFromFile(certLocation);
         
       }catch(Exception e){
           e.printStackTrace();
           data = null;
       }
       if(data==null){
           System.out.println("Invalid cert path: " + certLocation);
           System.out.print("Please enter again: ");
           return getCertDataFromPath(service);
       }
     
       return data;
   }

   static byte[] getCertData(TestService service, String certLocation){
     
       byte[] data = null;
       try{
           data = service.readDataFromFile(certLocation);
       }catch(Exception e){
           e.printStackTrace();
           data = null;
       }
       return data;
   }
 
}




spring-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
   xmlns:task="http://www.springframework.org/schema/task"
   xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <description>Test Services bean definition </description>
   <context:component-scan base-package="test.common"></context:component-scan>

   <!-- <context:property-placeholder location="file:${instance.properties}/conf.properties" 
       ignore-unresolvable="true" /> -->

   <bean id="contextSource"
       class="org.springframework.ldap.pool.factory.PoolingContextSource">
       <property name="contextSource" ref="contextSourceTarget" />
       <property name="maxActive" value="50" />
   </bean>

   <bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
       <property name="url" value="ldap://localhost:10389" />
       <!-- <property name="base" value="ou=users,ou=system" /> -->
       <property name="userDn" value="uid=admin,ou=system" />
       <property name="password" value="Welcome1234" />
       <property name="pooled" value="false" />

   </bean>

   <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
       <constructor-arg ref="contextSourceTarget" />
   </bean>

   <bean id="userDao" class="test.common.ldap.dao.UserDao">
       <property name="ldapTemplate" ref="ldapTemplate" />
   </bean>

   <bean id="fromStringConverter"
       class="org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter" />
   <bean id="toStringConverter"
       class="org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter" />
   <bean id="converterManager"
       class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean">
       <property name="converterConfig">
           <set>
               <bean
                   class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
                   <property name="fromClasses">
                       <set>
                           <value>java.lang.String</value>
                       </set>
                   </property>
                   <property name="toClasses">
                       <set>
                           <value>java.lang.Byte</value>
                           <value>java.lang.Short</value>
                           <value>java.lang.Integer</value>
                           <value>java.lang.Long</value>
                           <value>java.lang.Float</value>
                           <value>java.lang.Double</value>
                           <value>java.lang.Boolean</value>
                       </set>
                   </property>
                   <property name="converter" ref="fromStringConverter" />
               </bean>

               <bean
                   class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
                   <property name="fromClasses">
                       <set>
                           <value>java.lang.Byte</value>
                           <value>java.lang.Short</value>
                           <value>java.lang.Integer</value>
                           <value>java.lang.Long</value>
                           <value>java.lang.Float</value>
                           <value>java.lang.Double</value>
                           <value>java.lang.Boolean</value>
                       </set>
                   </property>
                   <property name="toClasses">
                       <set>
                           <value>java.lang.String</value>
                       </set>
                   </property>
                   <property name="converter" ref="toStringConverter" />
               </bean>
           </set>
       </property>
   </bean>

   <bean id="odmManager"
       class="org.springframework.ldap.odm.core.impl.OdmManagerImplFactoryBean">
       <property name="converterManager" ref="converterManager" />
       <property name="contextSource" ref="contextSourceTarget" />
       <property name="managedClasses">
           <set>
               <value>test.common.ldap.entity.User</value>
           </set>
       </property>
   </bean>
</beans>