© 2008-2019 The original authors.

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

Preface

Spring Data LDAP makes it easier to build Spring-based applications that use the Lightweight Directory Access Protocol (LDAP).

This document is the reference guide for Spring Data - Document Support. It explains Document module concepts and semantics and the syntax for various data store namespaces.

1. Knowing Spring

Spring Data uses the Spring Framework’s core functionality, including:

While it is not important to know the Spring APIs, understanding the concepts behind them is important. At a minimum, the idea behind IoC should be familiar, no matter what IoC container you choose to use.

The core functionality of the LDAP support can be used directly, with no need to invoke the IoC services of the Spring container. This is much like JdbcTemplate, which can be used 'standalone' without any other services of the Spring container. To use all the features of Spring Data LDAP, such as the repository support, you must configure some parts of the library by using Spring.

To learn more about Spring, you can refer to the comprehensive documentation that explains the Spring Framework in detail. There are a lot of articles, blog entries, and books on Spring. See the Spring Framework home page for more information.

While it is not important to know the Spring APIs, you do need to understand the concepts behind them. At a minimum, the idea behind IoC should be familiar for whatever IoC container you choose to use.

To learn more about Spring, you can refer to the comprehensive documentation that explains the Spring Framework in detail. You can find a lot of articles, blog entries, and books on Spring. See the Spring framework home page for more information.

2. Requirements

Spring Data LDAP 2.x binaries requires JDK level 8.0 or later, Spring Framework 5.2.4.RELEASE or later, and Spring LDAP 2.3.2.RELEASE or later.

3. Additional Help Resources

Learning a new framework is not always straight forward. In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data LDAP module. However, if you encounter issues or are looking for advice, try one or more of the following resources:

Community Forum

Spring Data on Stackoverflow Stack Overflow is a tag for all of Spring Data (not just Document) users to share information and help each other. Note that registration is needed only for posting.

Professional Support

Professional, from-the-source support, with guaranteed response time, is available from Pivotal Sofware, Inc., the company behind Spring and Spring Data.

3.1. Following Development

For information on the Spring Data LDAP source code repository, nightly builds, and snapshot artifacts, see the Spring Data LDAP homepage. You can help make Spring Data best serve the needs of the Spring community by interacting with developers through the community on Stackoverflow. To follow developer activity, look for the mailing list information on the Spring Data LDAP homepage. If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Data issue tracker. To stay up-to-date with the latest news and announcements in the Spring ecosystem, subscribe to the Spring Community Portal. Finally, you can follow the Spring blog or the project team on Twitter (SpringData).

4. New and Noteworthy

4.1. What’s New in Spring Data LDAP 2.1

  • CDI extension to create LDAP repositories within a CDI container.

4.2. What’s New in Spring Data LDAP 2.0

  • Enhanced tooling support by using Spring Framework’s @NonNullApi and @Nullable annotations.

4.3. What’s New in Spring Data LDAP 1.0

  • Migration of Spring LDAP’s repository support into Spring Data LDAP.

Unresolved directive in index.adoc - include::../../../../spring-data-commons/src/main/asciidoc/dependencies.adoc[leveloffset=+1] Unresolved directive in index.adoc - include::../../../../spring-data-commons/src/main/asciidoc/repositories.adoc[leveloffset=+1]

Reference Documentation

5. LDAP Repositories

This chapter points out the specialties for repository support for LDAP. It builds on the core repository support explained in [repositories]. You should have a sound understanding of the basic concepts explained there.

You should keep in mind the following points as you work with Spring LDAP repositories:

  • Spring LDAP repositories can be enabled by using a <data-ldap:repositories> tag in your XML configuration or by using an @EnableLdapRepositories annotation on a configuration class.

  • To include support for LdapQuery parameters in automatically generated repositories, have your interface extend LdapRepository rather than CrudRepository.

  • All Spring LDAP repositories must work with entities annotated with the ODM annotations, as described in Object-Directory Mapping.

  • Since all ODM managed classes must have a Distinguished Name as the ID, all Spring LDAP repositories must have the ID type parameter set to javax.naming.Name. Indeed, the built-in LdapRepository only takes one type parameter: the managed entity class, which defaults the ID to javax.naming.Name.

  • Due to specifics of the LDAP protocol, paging and sorting are not supported for Spring LDAP repositories.

You must use ODM annotations, such as org.springframework.ldap.odm.annotations.Id. Using Spring Data’s annotation does not work, because Spring LDAP uses its own mapping layer.

5.1. Usage

To access domain entities stored in a LDAP-compliant directory, you can use our sophisticated repository support that significantly eases implementation. To do so, create an interface for your repository, as the following example shows:

Example 1. Sample Person entity
@Entry(objectClasses = { "person", "top" }, base="ou=someOu")
public class Person {

   @Id
   private Name dn;

   @Attribute(name="cn")
   @DnAttribute(value="cn", index=1)
   private String fullName;

   @Attribute(name="firstName")
   private String firstName;

   // No @Attribute annotation means this is bound to the LDAP attribute
   // with the same value
   private String firstName;

   @DnAttribute(value="ou", index=0)
   @Transient
   private String company;

   @Transient
   private String someUnmappedField;
   // ...more attributes below
}

We have a simple domain object here. Note that it has a property named dn of type Name. With that domain object, we can create a repository to persist objects of that type by defining an interface for it, as follows:

Example 2. Basic repository interface to persist Person entities
public interface PersonRepository extends CrudRepository<Person, Long> {

  // additional custom finder methods go here
}

Right now, this interface serves only typing purposes, but we can add additional methods to it later. In your Spring configuration, add the following:

Example 3. General LDAP repository Spring configuration
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ldap="http://www.springframework.org/schema/ldap"
  xmlns:data-ldap="http://www.springframework.org/schema/data/ldap"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/ldap
    https://www.springframework.org/schema/ldap/spring-ldap.xsd
    http://www.springframework.org/schema/data/ldap
    https://www.springframework.org/schema/data/ldap/spring-ldap.xsd">

  <ldap:context-source url="ldap://127.0.0.1:389"
                     username="cn=Admin"
                     password="secret" />

  <ldap:ldap-template />

  <data-ldap:repositories base-package="com.acme.*.repositories" />

</beans>

This namespace element causes the base packages to be scanned for interfaces that extend LdapRepository and create Spring beans for each one found. By default the repositories get an autowired LdapTemplate Spring bean that is called ldapTemplate, so you only need to configure ldap-template-ref explicitly if you deviate from this convention.

If you want to go with Java configuration, use the @EnableLdapRepositories annotation. The annotation carries the same attributes as the namespace element. If no base package is configured, the infrastructure scans the package of the annotated configuration class. The following example shows how to set up Java configuration:

Example 4. Java configuration for repositories
@Configuration
@EnableLdapRepositories
class ApplicationConfig {

    @Bean
    ContextSource contextSource() {

        LdapContextSource ldapContextSource = new LdapContextSource();
        ldapContextSource.setUrl("ldap://127.0.0.1:389");

        return ldapContextSource;
    }

    @Bean
    LdapTemplate ldapTemplate(ContextSource contextSource) {
        return new LdapTemplate(contextSource);
    }
}

Because our domain repository extends CrudRepository, it provides you with CRUD operations as well as methods for access to the entities. Working with the repository instance is a matter of dependency injecting it into a client.

We can add paging access to our repository, as follows:

Example 5. Paging access to Person entities
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class PersonRepositoryTests {

    @Autowired PersonRepository repository;

    @Test
    public void readAll() {

      List<Person> persons = repository.findAll();
      assertThat(persons.isEmpty(), is(false));
    }
}

The sample creates an application context with Spring’s unit test support, which will perform annotation-based dependency injection into test cases. Inside the test method, we use the repository to query the datastore.

5.2. Query Methods

Most of the data access operations you usually trigger on a repository result in a query being executed against the LDAP directory. Defining such a query is a matter of declaring a method on the repository interface, as the following example shows:

Example 6. PersonRepository with query methods
public interface PersonRepository extends PagingAndSortingRepository<Person, String> {

    List<Person> findByLastname(String lastname);                            (1)

    List<Person> findByLastnameFirstname(String lastname, String firstname); (2)
}
1 The method shows a query for all people with the given lastname. The query is derived by parsing the method name for constraints that can be concatenated with And and Or. Thus, the method name results in a query expression of (&(objectclass=person)(lastname=lastname)).
2 The method shows a query for all people with the given lastname and firstname. The query is derived by parsing the method name. Thus, the method name results in a query expression of (&(objectclass=person)(lastname=lastname)(firstname=firstname)).

The following table provides samples of the keywords that you can use with query methods:

Table 1. Supported keywords for query methods
Keyword Sample Logical result

LessThanEqual

findByAgeLessThanEqual(int age)

(attribute⇐age)

GreaterThanEqual

findByAgeGreaterThanEqual(int age)

(attribute>=age)

IsNotNull, NotNull

findByFirstnameNotNull()

(firstname=*)

IsNull, Null

findByFirstnameNull()

(!(firstname=*))

Like

findByFirstnameLike(String name)

(firstname=name)

NotLike, IsNotLike

findByFirstnameNotLike(String name)

(!(firstname=name*))

StartingWith

findByStartingWith(String name)

(firstname=name*)

EndingWith

findByFirstnameLike(String name)

(firstname=*name)

Containing

findByFirstnameLike(String name)

(firstname=*name*)

(No keyword)

findByFirstname(String name)

(Firstname=name)

Not

findByFirstnameNot(String name)

(!(Firstname=name))

5.2.1. QueryDSL Support

Basic QueryDSL support is included in Spring LDAP. This support includes the following:

  • An Annotation Processor, LdapAnnotationProcessor, for generating QueryDSL classes based on Spring LDAP ODM annotations. See Object-Directory Mapping for more information on the ODM annotations.

  • A Query implementation, QueryDslLdapQuery, for building and executing QueryDSL queries in code.

  • Spring Data repository support for QueryDSL predicates. QueryDslPredicateExecutor includes a number of additional methods with appropriate parameters. You can extend this interface (along with LdapRepository) to include this support in your repository.

5.3. Miscellaneous

5.3.1. CDI Integration

Instances of the repository interfaces are usually created by a container, for which Spring is the most natural choice when working with Spring Data. As of version 2.1, Spring Data LDAP includes a custom CDI extension that lets you use the repository abstraction in CDI environments. The extension is part of the JAR. To activate it, drop the Spring Data LDAP JAR into your classpath. You can now set up the infrastructure by implementing a CDI Producer for the LdapTemplate, as the following example shows:

class LdapTemplateProducer {

    @Produces
    @ApplicationScoped
    public LdapOperations createLdapTemplate() {

        ContextSource contextSource = …
        return new LdapTemplate(contextSource);
    }
}

The Spring Data LDAP CDI extension picks up the LdapTemplate as a CDI bean and creates a proxy for a Spring Data repository whenever a bean of a repository type is requested by the container. Thus, obtaining an instance of a Spring Data repository is a matter of declaring an injected property, as the following example shows:

class RepositoryClient {

  @Inject
  PersonRepository repository;

  public void businessMethod() {
    List<Person> people = repository.findAll();
  }
}

Appendix

Unresolved directive in index.adoc - include::../../../../spring-data-commons/src/main/asciidoc/repository-namespace-reference.adoc[leveloffset=+1] Unresolved directive in index.adoc - include::../../../../spring-data-commons/src/main/asciidoc/repository-populator-namespace-reference.adoc[leveloffset=+1] Unresolved directive in index.adoc - include::../../../../spring-data-commons/src/main/asciidoc/repository-query-keywords-reference.adoc[leveloffset=+1] Unresolved directive in index.adoc - include::../../../../spring-data-commons/src/main/asciidoc/repository-query-return-types-reference.adoc[leveloffset=+1]