Binding and Modifying Using DirContextAdapter

While very useful when extracting attribute values, DirContextAdapter is even more powerful for hiding attribute details when binding and modifying data.

Binding

This is an example of an improved implementation of the create DAO method. Compare it with the previous implementation in the section called “Binding Data”.

Example 3.4. Binding using DirContextAdapter

package com.example.dao;

public class PersonDaoImpl implements PersonDao {
   ...
   public void create(Person p) {
      Name dn = buildDn(p);
      DirContextAdapter context = new DirContextAdapter(dn);

      context.setAttributeValues("objectclass", new String[] {"top", "person"});
      context.setAttributeValue("cn", p.getFullname());
      context.setAttributeValue("sn", p.getLastname());
      context.setAttributeValue("description", p.getDescription());

      ldapTemplate.bind(context);
   }
}

Note that we use the DirContextAdapter instance as the second parameter to bind, which should be a Context. The third parameter is null, since we're not using any Attributes.

Also note the use of the setAttributeValues() method when setting the objectclass attribute values. The objectclass attribute is multi-value, and similar to the troubles of extracting muti-value attribute data, building multi-value attributes is tedious and verbose work. Using the setAttributeValues() mehtod you can have DirContextAdapter handle that work for you.

Modifying

The code for a rebind would be pretty much identical to Example 3.4, “Binding using DirContextAdapter, except that the method called would be rebind. As we saw in the section called “Modifying using modifyAttributes a more correct approach would be to build a ModificationItem array containing the actual modifications you want to do. This would require you to determine the actual modifications compared to the data present in the LDAP tree. Again, this is something that DirContextAdapter can help you with; the DirContextAdapter has the ability to keep track of its modified attributes. The following example takes advantage of this feature:

Example 3.5. Modifying using DirContextAdapter

package com.example.dao;

public class PersonDaoImpl implements PersonDao {
   ...
   public void update(Person p) {
      Name dn = buildDn(p);
      DirContextOperations context = ldapTemplate.lookupContext(dn);

      context.setAttributeValues("objectclass", new String[] {"top", "person"});
      context.setAttributeValue("cn", p.getFullname());
      context.setAttributeValue("sn", p.getLastname());
      context.setAttributeValue("description", p.getDescription());

      ldapTemplate.modifyAttributes(context);
   }
}

When no mapper is passed to a ldapTemplate.lookup() operation, the result will be a DirContextAdapter instance. While the lookup method returns an Object, the convenience method lookupContext method automatically casts the return value to a DirContextOperations (the interface that DirContextAdapter implements.

The observant reader will see that we have duplicated code in the create and update methods. This code maps from a domain object to a context. It can be extracted to a separate method:

Example 3.6. Binding and modifying using DirContextAdapter

package com.example.dao;

public class PersonDaoImpl implements PersonDao {
   private LdapTemplate ldapTemplate;

   ...
   public void create(Person p) {
      Name dn = buildDn(p);
      DirContextAdapter context = new DirContextAdapter(dn);
      mapToContext(p, context);
      ldapTemplate.bind(context);
   }

   public void update(Person p) {
      Name dn = buildDn(p);
      DirContextOperations context = ldapTemplate.lookupContext(dn);
      mapToContext(person, context);
      ldapTemplate.modifyAttributes(context);
   }

   protected void mapToContext (Person p, DirContextOperations context) {
      context.setAttributeValues("objectclass", new String[] {"top", "person"});
      context.setAttributeValue("cn", p.getFullName());
      context.setAttributeValue("sn", p.getLastName());
      context.setAttributeValue("description", p.getDescription());
   }
}