In this example we will use an AttributesMapper
to easily build a List of all common names of all person objects.
Example 2.1. AttributesMapper that returns a single attribute
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
public List getAllPersonNames() {
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
}
}
The inline implementation of AttributesMapper
just gets the desired attribute value from the
Attributes
and returns it. Internally,
LdapTemplate
iterates over all entries found, calling
the given AttributesMapper
for each entry, and collects
the results in a list. The list is then returned by the
search
method.
Note that the AttributesMapper
implementation
could easily be modified to return a full Person
object:
Example 2.2. AttributesMapper that returns a Person object
package com.example.dao; public class PersonDaoImpl implements PersonDao { private LdapTemplate ldapTemplate; ... private class PersonAttributesMapper implements AttributesMapper { public Object mapFromAttributes(Attributes attrs) throws NamingException { Person person = new Person(); person.setFullName((String)attrs.get("cn").get()); person.setLastName((String)attrs.get("sn").get()); person.setDescription((String)attrs.get("description").get()); return person; } } public List getAllPersons() { return ldapTemplate.search("", "(objectclass=person)", new PersonAttributesMapper()); } }
If you have the distinguished name (dn
) that
identifies an entry, you can retrieve the entry directly, without
searching for it. This is called a lookup in Java
LDAP. The following example shows how a lookup results in a Person
object:
Example 2.3. A lookup resulting in a Person object
package com.example.dao; public class PersonDaoImpl implements PersonDao { private LdapTemplate ldapTemplate; ... public Person findPerson(String dn) { return (Person) ldapTemplate.lookup(dn, new PersonAttributesMapper()); } }
This will look up the specified dn
and pass the
found attributes to the supplied AttributesMapper
, in
this case resulting in a Person
object.
We can build dynamic filters to use in searches, using the classes
from the org.springframework.ldap.filter
package. Let's say that we want the following filter:
(&(objectclass=person)(sn=?))
, where we want the
?
to be replaced with the value of the parameter
lastName
. This is how we do it using the filter support
classes:
Example 2.4. Building a search filter dynamically
package com.example.dao; public class PersonDaoImpl implements PersonDao { private LdapTemplate ldapTemplate; ... public List getPersonNamesByLastName(String lastName) { AndFilter filter = new AndFilter(); filter.and(new EqualsFilter("objectclass", "person")); filter.and(new EqualsFilter("sn", lastName)); return ldapTemplate.search( "", filter.encode(), new AttributesMapper() { public Object mapFromAttributes(Attributes attrs) throws NamingException { return attrs.get("cn").get(); } }); } }
To perform a wildcard search, it's possible to use the
WhitespaceWildcardsFilter
:
Example 2.5. Building a wildcard search filter
AndFilter filter = new AndFilter(); filter.and(new EqualsFilter("objectclass", "person")); filter.and(new WhitespaceWildcardsFilter("cn", cn));
Filter
classes also provide proper escaping
of any unsafe characters. This prevents "ldap injection",
where a user might use such characters to inject unwanted operations
into your LDAP operations.
The standard Name
interface represents a generic name, which is basically an ordered
sequence of components. The Name
interface also
provides operations on that sequence; e.g., add
or
remove
. LdapTemplate provides an implementation of the
Name
interface: DistinguishedName
.
Using this class will greatly simplify building distinguished names,
especially considering the sometimes complex rules regarding escapings and
encodings. As with the Filter
classes this helps preventing
potentially malicious data being injected into your LDAP operations.
The following example illustrates how
DistinguishedName
can be used to dynamically construct
a distinguished name:
Example 2.6. Building a distinguished name dynamically
package com.example.dao;
import org.springframework.ldap.core.support.DistinguishedName;
import javax.naming.Name;
public class PersonDaoImpl implements PersonDao {
public static final String BASE_DN = "dc=example,dc=com";
...
protected Name buildDn(Person p) {
DistinguishedName dn = new DistinguishedName(BASE_DN);
dn.add("c", p.getCountry());
dn.add("ou", p.getCompany());
dn.add("cn", p.getFullname());
return dn;
}
}
Assuming that a Person has the following attributes:
country | Sweden |
company | Some Company |
fullname | Some Person |
The code above would then result in the following distinguished name:
cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com
In Java 5, there is an implementation of the Name interface: LdapName.
If you are in the Java 5 world, you might as well use
LdapName
. However, you may still use
DistinguishedName
if you so wish.
Inserting data in Java LDAP is called binding. In order to do that, a distinguished name that uniquely identifies the new entry is required. The following example shows how data is bound using LdapTemplate:
Example 2.7. Binding data using Attributes
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void create(Person p) {
Name dn = buildDn(p);
ldapTemplate.bind(dn, null, buildAttributes(p));
}
private Attributes buildAttributes(Person p) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", "Some Person");
attrs.put("sn", "Person");
return attrs;
}
}
The Attributes building is--while dull and verbose--sufficient for many purposes. It is, however, possible to simplify the binding operation further, which will be described in Chapter 3, Simpler Attribute Access and Manipulation with DirContextAdapter.
Removing data in Java LDAP is called unbinding. A distinguished name (dn) is required to identify the entry, just as in the binding operation. The following example shows how data is unbound using LdapTemplate:
Example 2.8. Unbinding data
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void delete(Person p) {
Name dn = buildDn(p);
ldapTemplate.unbind(dn);
}
}
In Java LDAP, data can be modified in two ways: either using rebind or modifyAttributes.
A rebind
is a very crude way to modify data.
It's basically an unbind
followed by a
bind
. It looks like this:
Example 2.9. Modifying using rebind
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void update(Person p) {
Name dn = buildDn(p);
ldapTemplate.rebind(dn, null, buildAttributes(p));
}
}
If only the modified attributes should be replaced, there is a
method called modifyAttributes
that takes an array of
modifications:
Example 2.10. Modifying using modifyAttributes
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void updateDescription(Person p) {
Name dn = buildDn(p);
Attribute attr = new BasicAttribute("description", p.getDescription())
ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
ldapTemplate.modifyAttributes(dn, new ModificationItem[] {item});
}
}
Building Attributes
and
ModificationItem
arrays is a lot of work, but as you
will see in Chapter 3, Simpler Attribute Access and Manipulation with DirContextAdapter, the update operations
can be simplified.
It is recommended that you review the Spring LDAP sample applications included in the release distribution for best-practice illustrations of the features of this library. A description of each sample is provided below:
spring-ldap-person - the sample demonstrating most features.
spring-ldap-article - the sample application that was written to accompany a java.net article about Spring LDAP.