CHAPTER 3

image

Introducing Spring LDAP

In this chapter, we will discuss

  • The basics of Spring LDAP.
  • Downloading and setting up Spring LDAP.
  • Setting up the STS development environment.
  • Setting up a test LDAP server.
  • Creating a Hello World application.

Spring LDAP provides simple, clean and comprehensive support for LDAP programming in Java. This project originally started out on Sourceforge in 2006 under the name LdapTemplate with the intention of simplifying access to LDAP using JNDI. The project later became part of the Spring Framework portfolio and has since come a long way. Figure 3-1 depicts the architecture of a Spring LDAP-based application.

9781430263975_Fig03-01.jpg

Figure 3-1. Spring LDAP architecture directory

The application code uses the Spring LDAP API for performing operations on a LDAP server. The Spring LDAP framework contains all of the LDAP-specific code and abstractions. Spring LDAP, however, will rely on the Spring Framework for some of its infrastructural needs.

The Spring Framework has become today’s de facto standard for developing Java-based enterprise applications. Among many other things, it provides a dependency-injection based lightweight alternative to the JEE programming model. The Spring Framework is the base for Spring LDAP and all other Spring portfolio projects such as Spring MVC and Spring Security.

Motivation

In the previous chapter, we discussed the shortcomings of the JNDI API. A notable drawback of JNDI is that it is very verbose; almost all of the code in Chapter 2 has to do with plumbing and very little with application logic. Spring LDAP addresses this problem by providing template and utility classes that take care of the plumbing code so that the developer can focus on business logic.

Another notable issue with JNDI is that it requires the developer to explicitly manage resources such as LDAP contexts. This can be very error-prone. Forgetting to close resources can result in leaks and can quickly bring down an application under heavy load. Spring LDAP manages these resources on your behalf and automatically closes them when you no longer need them. It also provides the ability to pool LDAP contexts, which can improve performance.

Any problems that might arise during the execution of JNDI operations will be reported as instances of NamingException or its subclasses. NamingException is a checked exception and thus the developer is forced to handle it. Data access exceptions are usually not recoverable and most often there is not much that can be done to catch these exceptions. To address this, Spring LDAP provides a consistent unchecked exception hierarchy that mimics NamingException. This allows the application designer to make the choice of when and where to handle these exceptions.

Finally, plain JNDI programming is hard and can be daunting for new developers. Spring LDAP with its abstractions makes working with JNDI more enjoyable. Additionally, it provides a variety of features such as object directory mapping and support for transactions, making it an important tool for any enterprise LDAP developer.

Obtaining Spring LDAP

Before you can install and start using Spring LDAP, it is important to make sure that the Java Development Kit (JDK) is already installed on your machine. The latest Spring LDAP 1.3.2 version requires JDK 1.4 or higher and Spring 2.0 or higher. Since I am using Spring 3.2.4 in the examples in the book, it is strongly recommended to install JDK 6.0 or higher.

Spring Framework and its portfolio projects can be downloaded from www.springsource.org/download/community. A direct link is available on the Spring LDAP web site at www.springsource.org/ldap. The Spring LDAP download page allows you to download the latest as well as previous versions of the framework, as shown in Figure 3-2.

9781430263975_Fig03-02.jpg

Figure 3-2. Spring LDAP download

The spring-ldap-1.3.2.RELEASE-dist.zip includes the framework binaries, source code, and documentation. Since the latest LDAP distribution bundle does not include Spring distributions, you need to separately download Spring Framework. Figure 3-3 shows the latest available Spring Framework distribution, 3.2.4.RELEASE. Download both Spring LDAP and Spring distributions, as shown in Figure 3-3, and unzip them on your machine.

9781430263975_Fig03-03.jpg

Figure 3-3. Spring Framework download

Spring LDAP Packaging

Now that you have successfully downloaded the Spring LDAP framework, let’s delve into its subfolders. The libs folder contains Spring LDAP binary, source, and javadoc distribution. The LDAP framework is packaged into six different components. Table 3-1 provides a brief description of each component. The docs folder contains the javadoc for the API and the reference guide in different formats.

Table 3-1. Spring LDAP Distribution Modules

Component Jar Description
spring-ldap-core Contains all the classes necessary for using the LDAP framework. This jar is required in all the applications.
spring-ldap-core-tiger Contains classes and extensions that are specific to Java 5 and higher. Applications running under Java 5 should not use this jar.
spring-ldap-test Contains classes and utilities that make testing easier. It also includes classes for starting and stopping in-memory instances of ApacheDS LDAP server.
spring-ldap-ldif-core Contains classes for parsing ldif format files.
spring-ldap-ldif-batch Contains classes necessary to integrate ldif parser with Spring Batch Framework.
spring-ldap-odm Contains classes for enabling and creating object directory mappings.

Along with Spring Framework, you need additional jar files for compiling and running applications using Spring LDAP. Table 3-2 lists some of these dependent jars files along with a description of why they are used.

Table 3-2. Spring LDAP Dependent Jars

Library Jar Description
commons-lang A required jar used internally by Spring LDAP and Spring Framework.
commons-logging Logging abstraction used internally by Spring LDAP and Spring Framework. This is a required jar to be included in applications. An alternative (and advocated by Spring) is to use SLF4J logging framework using the SLF4J-JCL bridge.
log4j Required library for logging using Log4J.
spring-core Spring library that contains core utilities used internally by Spring LDAP. This is a required library for using Spring LDAP.
spring-beans Spring Framework library used for creating and managing Spring beans. Another library required by Spring LDAP.
spring-context Spring library that is responsible for dependency injection. This is required when using Spring LDAP inside a Spring application.
spring-tx Spring Framework library that provides transaction abstractions. This is required when using Spring LDAP transaction support.
spring-jdbc Library that simplifies access to database using JDBC under the covers. This is an optional library and should be used for transaction support.
commons-pool Apache Commons Pool library provides support for pooling. This should be included when using Spring LDAP pooling support.
ldapbp Sun LDAP booster pack that includes additional LDAP V3 Server controls. This jar is needed when you are planning to use these additional controls or running under Java 5 or lower.

Downloading Spring LDAP Source

The Spring LDAP project uses Git as their source control system. The source code can be downloaded from https://github.com/SpringSource/spring-ldap.

Spring LDAP source code can provide valuable insights into the framework architecture. It also includes a rich test suite that can serve as additional documentation and help you understand the framework. I strongly recommend that you download and look at the source code. The Git repository also holds a sandbox folder that contains several experimental features that may or may not make it into the framework.

Installing Spring LDAP Using Maven

Apache Maven is an open source, standards-based project management framework that makes building, testing, reporting, and packaging of projects easier. If you are new to Maven and are wondering about the tool, the Maven web site, http://maven.apache.org, provides information on its features along with tons of helpful links. Here are some advantages of adopting Maven:

  • Standardized directory structure: Maven standardizes the layout and organization of a project. Every time a new project starts, considerable time is spent on decisions such as where the source code should go or where the configuration files should be placed. Also, these decisions can vary vastly between projects and teams. Maven’s standardized directory structure makes adoption easy across developers and even IDEs.
  • Declarative dependency management: With Maven, you declare your project dependencies in a separate pom.xml file. Maven then automatically downloads those dependencies from repositories and uses them during build process. Maven also smartly resolves and downloads transitive dependencies (dependencies of dependencies).
  • Archetypes: Maven archetypes are project templates that can be used to easily generate new projects. These archetypes are great way to share best practices and enforce consistency beyond Maven’s standard directory structure.
  • Plug-ins: Maven follows a plug-in based architecture that makes it easy to add or customize its functionality. Currently there are hundreds of plug-ins that can be used to carry out variety of tasks from compiling code to creating project documentation. Activating and using a plug-in simply involves declaring a reference to the plug-in in the pom.xml file.
  • Tools support: All major IDEs today provide tooling support for Maven. This includes wizards for generating projects, creating IDE-specific files, and graphical tools for analyzing dependencies.

Installing Maven

To install Maven, simply download the latest version from http://maven.apache.org/download.html. Once the download is complete, unzip the distribution to a local directory on your machine. Then make the following modifications to your development box:

  • Add a M2_HOME environment variable pointing to the maven installation directory.
  • Add a MAVEN_OPTS environment variable with the value of – Xmx512m.
  • Add to the Path environment variable the M2_HOME/bin value.

image Note   Maven requires an Internet connection for downloading dependencies and plug-ins. If you or your company uses a proxy to connect to Internet, make changes to the settings.xml file. Otherwise you may experience “Unable to download artifact” errors.

This completes Maven installation. You can verify the installation by running the following command on your command line:

$  mvn  –v

This command should output information similar to the following:

Apache Maven 3.1.0 (893ca28a1da9d5f51ac03827af98bb730128f9f2; 2013-06-27 20:15:32-0600)
Maven home: c: oolsmaven
Java version: 1.6.0_35, vendor: Sun Microsystems Inc.
Java home: C:Javajdk1.6.0_35jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 7", version: "6.1", arch: "x86", family: "windows"

Spring LDAP Archetypes

To jump-start Spring LDAP development, this book uses the following two archetypes:

  • practical-ldap-empty-archetype: This archetype can be used to create an empty Java project with all the required LDAP dependencies.
  • practical-ldap-archetype: Similar to the above archetype, this archetype creates a Java project with all the required LDAP dependencies. Additionally, it also includes Spring LDAP configuration files, sample code, and dependencies to run an in-memory LDAP server for testing purposes.

Before you can use the archetypes to create a project, you need to install them. If you have not already done so, download the accompanying source/download files from Apress. In the downloaded distribution, you will find practical-ldap-empty-archetype-1.0.0.jar and practical-ldap-archetype-1.0.0.jar archetypes. Once you have the jar files downloaded, run the following two commands at the command line:

mvn  install:install-file 
     -DgroupId=com.inflinx.book.ldap
     -DartifactId=practical-ldap-empty-archetype
     -Dversion=1.0.0
     -Dpackaging=jar
     -Dfile=<JAR_LOCATION_DOWNLOAD>/practical-ldap-empty-archetype-1.0.0.jar
 
mvn  install:install-file
     -DgroupId=com.inflinx.book.ldap
     -DartifactId=practical-ldap-archetype
     -Dversion=1.0.0
     -Dpackaging=jar
     -Dfile=< JAR_LOCATION_DOWNLOAD >/practical-ldap-archetype-1.0.0.jar

These maven install commands will install the two archetypes in your local maven repository. Creating a project using one of these archetypes simply involves running the following command:

C:practicalldapcode>mvn archetype:generate
-DarchetypeGroupId=com.inflinx.book.ldap
-DarchetypeArtifactId=practical-ldap-empty-archetype
-DarchetypeVersion=1.0.0
-DgroupId=com.inflinx.ldap
-DartifactId=chapter3
-DinteractiveMode=false

Notice that this command is executed inside the directory c:/practicalldap/code. The command instructs maven to use the archetype practical-ldap-empty-archetype and generate a project named chapter3. The generated project directory structure is shown in Figure 3-4.

9781430263975_Fig03-04.jpg

Figure 3-4. Maven-generated project structure

This directory structure has a src folder that holds all the code and any associated resources such as XML files. The target folder contains the generated classes and build artifacts. The main folder under src usually holds the code that eventually makes its way to production. The test folder contains the related test code. Each of these two folders contains java and resources subfolders. As name suggests, the java folder contains Java code and the resources folder usually contains configuration xml files.

The pom.xml file in the root folder holds the configuration information needed by Maven. For example, it contains information about all the dependent jar files that are required for compiling the code (see Listing 3-1).

Listing 3-1.

<dependencies>
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core</artifactId>
        <version>${org.springframework.ldap.version}</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

The pom.xml snippet in Listing 3-1 indicates that the project will need the spring-ldap-core.jar file during its compilation.

Maven requires a group id and artifact id to uniquely identify a dependency. A group id is usually unique to a project or organization and is similar to the concept of a Java package. The artifact id is usually the name of the project or a generated component of the project. The scope determines the phase during which the dependency should be included in the classpath. Here are few possible values:

  • test: A test scope indicates that the dependency should be included in the classpath only during testing process. JUnit is an example of such dependency.
  • provided: The provided scope indicates that the artifact should be included in the classpath during compilation only. Provided scope dependencies are usually available at runtime via JDK or application container.
  • compile: A compile scope indicates that the dependency should be included in the classpath at all times.

An additional section in the pom.xml file contains information about the plug-ins that Maven can use to compile and build the code. One such plug-in declaration is displayed in Listing 3-2. It instructs Maven to use the compiler plug-in of version 2.0.2 to compile Java code. The finalName indicates the name of the generated artifact. In this case, it would be chapter3.jar.

Listing 3-2.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin
            </artifactId>
            <version>2.0.2</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
     </plugins>
     <finalName>chapter3</finalName>
</build>

To build this generated application, simply run the following command from the command line. This command cleans the target folder, compiles the source files, and generates a jar file inside the target folder.

mvn  clean  compile package

This setup, along with a text editor, is enough to start developing and packaging Java-based LDAP applications. However, it is a no-brainer that you can be more productive developing and debugging applications using a graphical IDE. There are several IDEs, with Eclipse, NetBeans, and IntelliJ IDEA being the most popular. For this book you will be using Spring Tool Suite, an Eclipse-based IDE from Spring Source.

Setting Up Spring IDE

STS is a free, Eclipse-based development environment that provides the best tool support for developing Spring-based applications. The following are some of its features:

  • Wizards for creating Spring projects and Spring beans
  • Integrated support for Maven
  • Templates based on best practices for project and file creation
  • Spring bean and AOP pointcut visualization
  • Spring ROO shell integration for rapid prototyping
  • Task-based user interface that provides guided assistance through tutorials
  • Support for Groovy and Grails

In this section you will look at installing and setting up the STS IDE.

  1. Download and initiate the STS installer from the Spring Tool Suite web site at www.springsource.com/developer/sts. The installation file for Windows is spring-tool-suite-3.3.0.RELEASE-e4.3-win32-installer.exe. Double-click the install file to start the installation (Figure 3-5).

    9781430263975_Fig03-05.jpg

    Figure 3-5. Installer home screen

  2. Read and accept the License Agreement and click the Next button.
  3. On the Target Path screen, choose an installation directory.
  4. Leave the default selection and then click the Next button (see Figure 3-6).

    9781430263975_Fig03-06.jpg

    Figure 3-6. Installation packages

  5. On the following screen, provide the path to the JDK installation and click the Next button.
  6. This will begin the installation; wait for the file transfer to complete.
  7. Click the Next button on the following two screens to complete the installation.

Creating Projects Using STS

In the earlier “Spring LDAP Archetype” section you used the practical-ldap-empty-archetype archetype to generate a project from command line. Now let’s look at generating the same project using STS.

  1. From the File menu, select New arrow.jpg Project. It will launch the New Project wizard (see Figure 3-7). Select the Maven Project option and click the Next button.

    9781430263975_Fig03-07.jpg

    Figure 3-7. New Project wizard

  2. Uncheck “Use default Workspace location” and enter the path for the newly generated project, and then select the Next button (see Figure 3-8).

    9781430263975_Fig03-08.jpg

    Figure 3-8. Project path setup

  3. On the Select an Archetype screen (see Figure 3-9), click “Add Archetype.” This step assumes that you have already installed the archetype as mentioned in the earlier section. Fill the Add Archetype dialog with the details shown in Figure 3-9 and press OK. Do the same for the other archetype.

    9781430263975_Fig03-09.jpg

    Figure 3-9. Archetype details

  4. Enter ldap in the Filter field and select the practical-ldap-empty-archetype. Click the Next button (see Figure 3-10).

    9781430263975_Fig03-10.jpg

    Figure 3-10. Archetype selection

  5. On the following screen, provide the information about the newly created project and click the Finish button (see Figure 3-11).

9781430263975_Fig03-11.jpg

Figure 3-11. Project information

This will generate a project with the same directory structure that you saw earlier. However, it also creates all the IDE-specific files such as .project and .classpath and adds all the dependent Jars to the project’s classpath. The complete project structure is shown in Figure 3-12.

9781430263975_Fig03-12.jpg

Figure 3-12. Generated project structure

LDAP Server Setup

In this section you will look at installing an LDAP server to test your LDAP code. Among the available open source LDAP servers, I find OpenDJ very easy to install and configure.

image Note   Even if you already have a test LDAP server available, I highly recommend that you follow the steps below and install OpenDJ LDAP server. You will be heavily using this instance to test the code in this book.

Download the OpenDJ distribution file OpenDJ-2.4.6.zip from www.forgerock.org/opendj-archive.html. Unzip the distribution to a folder on your local system. On my Windows box, I placed the extracted files and folders under C:practicalldapopendj. Then follow these steps to complete the installation.

  1. Start the installation by clicking the setup.bat file for Windows. This will launch the install screen.

    image Note   When installing under Windows 8, make sure you run the installer as an administrator. Otherwise, you will run into an error when enabling the server as a Windows service.

  2. On the Server settings screen, enter the following values and press the Next button. I changed the Listener Port from 389 to 11389 and Administration Connector Port from 4444 to 4445. I also used opendj as the password. Please use these settings for running code examples used in this book (see Figure 3-13).

    9781430263975_Fig03-13.jpg

    Figure 3-13. LDAP server settings

  3. In the Topology Option screen, leave the “This will be a standalone server” option and click the Next button.
  4. In the Directory Data screen, enter the value “dc=inflinx,dc=com” as the Directory Base DN, leave the other options untouched, and continue.
  5. In the Review screen, confirm that “Run the server as a Windows Service” option is checked and click the Finish button.
  6. You will see a confirmation indicating a successful installation (see Figure 3-14).

9781430263975_Fig03-14.jpg

Figure 3-14. Successful OpenDJ confirmation

Since you have the OpenDJ installed as Windows Service, you can start the LDAP server by going to Control Panel arrow.jpg Administrative Tools arrow.jpg Services and selecting OpenDJ and clicking Start (Figure 3-15).

9781430263975_Fig03-15.jpg

Figure 3-15. Running OpenDJ as a Windows Service

image Note   If you have not installed the OpenDJ as a Windows Service you can start and stop the server using start-ds.bat and stop-ds.bat files under <OpenDJ_Install_Folder>/bat folder.

Installing Apache Directory Studio

The Apache Directory Studio is a popular, open source LDAP browser that can help you browse LDAP directories very easily. To install Apache Directory Studio, download the installer file from

http://directory.apache.org/studio/downloads.html.

The Studio installation can be done by following these steps.

  1. On Windows, start the installation by double-clicking the install file (this will bring up the install screen).
  2. Read and accept the license agreements to continue.
  3. Choose your preferred installation directory, and select “Install” (see Figure 3-16).

    9781430263975_Fig03-16.jpg

    Figure 3-16. Apache installation directory selection

  4. You will be shown the status of the installation and file transfer.
  5. After all the files have been transferred, click the Finish button to complete the installation.

Once the installation is complete, the next step is to create a connection to the newly installed OpenDJ LDAP server. Before you can proceed, make sure your OpenDJ server is running. Here are the steps to set up the new connection.

  1. Launch ApacheDS server. In Windows, click the Apache Directory Studio.exe file.
  2. Launch the New Connection wizard by right-clicking in the “Connections” section and selecting “New Connection.”

    9781430263975_Fig03-17.jpg

    Figure 3-17. Creating a new connection

  3. On the Network Parameter screen, enter the information displayed in Figure 3-18. This should match the OpenDJ information you entered during OpenDJ installation.

    9781430263975_Fig03-18.jpg

    Figure 3-18. LDAP connection network parameters

  4. On the Authentication screen, enter “cn=Directory Manager” as Bind DN or user and “opendj” as password (see Figure 3-19).

    9781430263975_Fig03-19.jpg

    Figure 3-19. LDAP connection authentication

  5. Accept the defaults in the Browser Options section and select the Finish button.

Loading Test Data

In the previous sections you installed the OpenDJ LDAP server and Apache Directory Studio for accessing the LDAP server. The final step in setting up your development/test environment is to load the LDAP server with test data.

image Note   The accompanying source code/downloads contains two LDIF files, patrons.ldif and employees.ldif. The patrons.ldif file contains test data that mimics your library’s patrons. The employees.ldif file contains test data that mimics your library’s employees. These two files are heavily used for testing the code used in this book. If you have not already done, please download these files before moving forward.

Here are the steps for loading the test data.

  1. Right-click “Root DSE” in the LDAP browser pane and select Import arrow.jpg LDIF Import (see Figure 3-20).

    9781430263975_Fig03-20.jpg

    Figure 3-20. LDIF import

  2. Browse for this patrons.ldif file (see Figure 3-21) and click the Finish button. Make sure that the “Update existing entries” checkbox is selected.

    9781430263975_Fig03-21.jpg

    Figure 3-21. LDIF import settings

  3. Upon a successful import you will see the data loaded under the dc=inflinx,dc=com entry (see Figure 3-22).

9781430263975_Fig03-22.jpg

Figure 3-22. LDIF successful import

Spring LDAP Hello World

With this information in hand let’s dive into the world of Spring LDAP. You will start by writing a simple search client that reads all the patron names in the ou=patrons LDAP branch. This is similar to the example you looked at in Chapter 2. Listing 3-3 shows the search client code.

Listing 3-3.

public class SearchClient {
 
   @SuppressWarnings("unchecked")
   public List<String> search() {
      LdapTemplate ldapTemplate = getLdapTemplate();
      List<String> nameList = ldapTemplate.search( "dc=inflinx,dc=com",
      "(objectclass=person)",

                new AttributesMapper() {
                   @Override
                   public Object mapFromAttributes(Attributes attributes)
                   throws NamingException {

                      return (String)attributes.get("cn").get();
                   }
                });
      return nameList;
   }
 
   private LdapTemplate getLdapTemplate() { ....... }
}

Central to Spring LDAP framework is the org.springframework.ldap.core.LdapTemplate class. Based on the Template Method design pattern (http://en.wikipedia.org/wiki/Template_method_pattern), the LdapTemplate class takes care of the unnecessary plumbing involved in LDAP programming. It provides a number of overloaded search, lookup, bind, authenticate, and unbind methods that makes LDAP development a breeze. The LdapTemplate is threadsafe and the same instance can be used by concurrent threads.

SIMPLELDAPTEMPLATE

Spring LDAP version 1.3 introduced a variation of LdapTemplate called SimpleLdapTemplate. This is a Java 5-based convenience wrapper for the classic LdapTemplate. The SimpleLdapTemplate adds Java 5 Generics support to lookup and search methods. These methods now take implementations of ParameterizedContextMapper<T> as parameter, allowing the search and lookup methods to return typed objects.

The SimpleLdapTemplate exposes only a subset of operations available in LdapTemplate. These operations, however, are the most commonly used ones and hence SpringLdapTemplate would be sufficient in a lot of situations. The SimpleLdapTemplate also provides the getLdapOperations() method that exposes the wrapped LdapOperations instance and can be used to invoke the less commonly used template methods.

In this book, you’ll use both LdapTemplate and SimpleLdapTemplate classes for implementing code.

You start the search method implementation by obtaining an instance of LdapTemplate class. Then you invoke a variation of the LdapTemplate’s search method. The first parameter to the search method is the LDAP base and the second parameter is the search filter. The search method uses the base and filter to perform search and each javax.naming.directory.SearchResult obtained is supplied to an implementation of org.springframework.ldap.core.AttributesMapper that is provided as the third parameter. In Listing 3-3, the AttributesMapper implementation is achieved via creating an anonymous class that reads each SearchResult entry and returns the common name of the entry.

In Listing 3-3, the getLdapTemplate method is empty. Now let’s look at implementing this method. For LdapTemplate to properly execute the search it needs an initial context on the LDAP server. Spring LDAP provides org.springframework.ldap.core.ContextSource interface abstraction and its implementation org.springframework.ldap.core.support.LdapContextSource for configuring and creating context instances. Listing 3-4 shows the complete method for getLdapTemplate implementation.

Listing 3-4.

private LdapTemplate getLdapTemplate() {
   LdapContextSource contextSource = new LdapContextSource();
   contextSource.setUrl("ldap://localhost:11389");
   contextSource.setUserDn("cn=Directory Manager");
   contextSource.setPassword("opendj");
   try {
      contextSource.afterPropertiesSet();
   }
   catch(Exception e) {
      e.printStackTrace();
   }
   LdapTemplate ldapTemplate = new LdapTemplate();
   ldapTemplate.setContextSource(contextSource);
   return ldapTemplate;
}

You start the method implementation by creating a new LdapContextSource and populating it with information about the LDAP server, such as the server URL and binding credentials. You then invoke the afterPropertiesSet method on the Context Source that allows Spring LDAP perform housekeeping operations. Finally, you create a new LdapTemplate instance and pass in the newly created context source.

This completes your search client example. Listing 3-5 shows the main method that invokes the search operation and prints the names to the console.

Listing 3-5.

public static void main(String[] args) {
   SearchClient client = new SearchClient();
   List<String> names = client.search();
   for(String name: names) {
      System.out.println(name);
   }
}

This search client implementation simply uses Spring LDAP API without any Spring Framework-specific paradigms. In the coming sections, you will look at springifying this application. But before you do that, let’s quickly look at Spring ApplicationContext.

Spring ApplicationContext

Central to every Spring Framework application is the notion of ApplicationContext. Implementations of this interface are responsible for creating and configuring Spring beans. The application context also acts as an IoC container and is responsible for performing the dependency injection. A Spring bean is simply a standard POJO with metadata needed to run inside the Spring container.

In a standard Spring application the ApplicationContext is configured via an XML file or Java annotations. Listing 3-6 shows a sample application context file with one bean declaration. The bean myBean is of type com.inflinx.book.ldap.SimplePojo. When the application loads the context, Spring creates an instance of SimplePojo and manages it.

Listing 3-6.

<?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"
        xsi:schemaLocation="http://www.springframework.org/schema/
beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
 
        <bean  id="myBean" class="com.inflinx.book.ldap.SimplePojo">
        </bean>
</beans>

Spring-Powered Search Client

Our conversion of the search client implementation begins with the applicationContext.xml file as shown in Listing 3-7.

Listing 3-7.

<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context
/spring-context.xsd
">

 
<bean id="contextSource"
class="org.springframework.ldap.core.support.LdapContextSource">
     <property  name="url" value="ldap://localhost:11389"  />
     <property name="userDn" value="cn=Directory  Manager" />
     <property name="password" value="opendj"  />
  </bean>
 
<bean id="ldapTemplate"
class="org.springframework.ldap.core.LdapTemplate">
     <constructor-arg ref="contextSource" />
</bean>
<context:component-scan base-package="com.inflinx.book.ldap"/>
</beans>

In the context file, you declare a contextSource bean to manage connections to LDAP server. For LdapContextSource to properly create instances of DirContext, you need to provide it with information about the LDAP server. The url property takes the fully qualified URL (ldap://server:port format) to the LDAP server. The base property can be used to specify the root suffix for all LDAP operations. The userDn and password properties are used to provide authentication information. Next, you configure a new LdapTemplate bean and inject the contextSource bean.

With all your dependencies declared in the context file, you can proceed to re-implementing the search client, as shown in Listing 3-8.

Listing 3-8.

package com.inflinx.book.ldap;
import java.util.List;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support. ClassPathXmlApplicationContext;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Component;
 
@Component
public class SpringSearchClient {
 
   @Autowired
   @Qualifier("ldapTemplate")
   private LdapTemplate ldapTemplate;
 
   @SuppressWarnings("unchecked")
   public List<String> search() {
      List<String> nameList = ldapTemplate.search("dc=inflinx,dc=com",
      "(objectclass=person)",

                new AttributesMapper() {
                  @Override
                  public Object mapFromAttributes(Attributes attributes)
                  throws NamingException {

                     return (String)attributes.get("cn").get();
                  }
                });
      return nameList;
   }
}

You will notice that this code is no different from the SearchClient code you saw in Listing 3-4. You just extracted the creation of LdapTemplate to an external configuration file. The @Autowired annotation instructs Spring to inject the ldapTemplate dependency. This simplifies the search client class very much and helps you focus on the search logic.

The code to run the new search client is shown in Listing 3-9. You start by creating a new instance of ClassPathXmlApplicationContext. The ClassPathXmlApplicationContext takes the applicationContext.xml file as its parameter. Then you retrieve an instance of SpringSearchClient from the context and invoke the search method.

Listing 3-9.

public static void main(String[] args){
   ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
   SpringSearchClient client = context.getBean(SpringSearchClient.class);
   List<String> names = client.search();
   for(String name: names) {
      System.out.println(name);
   }
}

Spring LdapTemplate Operations

In the previous section, you utilized LdapTemplate to implement search. Now, let’s look at using LdapTemplate for adding, removing, and modifying information in LDAP.

Add Operation

The LdapTemplate class provides several bind methods that allow you to create new LDAP entries. The simplest among those methods is as follows:

public void bind(String dn, Object obj,  Attributes  attributes)

The first parameter to this method is the unique distinguished name of the object that needs to be bound. The second parameter is the object to be bound and is usually an implementation of the DirContext interface. The third parameter is the attribute of the object to be bound. Among the three, only the first parameter is required and you can pass a null for the rest of the two.

Listing 3-10 shows the code involved in creating a new patron entry with minimal set of information. You start the method implementation by creating a new instance of BasicAttributes class to hold the patron attributes. Single-valued attributes are added by passing the attribute name and value to the put method. To add the multi-valued attribute objectclass, you create a new instance of BasicAttribute. You then add the entry’s objectClass values to the objectClassAttribute and add it to the attributes list. Finally, you invoke the bind method on the LdapTemplate with the patron information and patron’s fully qualified DN. This adds the patron entry to LDAP server.

Listing 3-10.

public void addPatron() {
   // Set the Patron attributes
   Attributes attributes = new BasicAttributes();
   attributes.put("sn", "Patron999");
   attributes.put("cn", "New Patron999");
   // Add the multi-valued attribute
   BasicAttribute objectClassAttribute = new BasicAttribute("objectclass");
   objectClassAttribute.add("top");
   objectClassAttribute.add("person");
   objectClassAttribute.add("organizationalperson");
   objectClassAttribute.add("inetorgperson");
   attributes.put(objectClassAttribute);
   ldapTemplate.bind("uid=patron999,ou=patrons,dc=inflinx,dc=com",null, attributes);
}

Modify Operation

Consider the scenario where you want to add a telephone number to the newly added patron. To do that, LdapTemplate provides a convenient modifyAttributes method with the following signature:

public void modifyAttributes(String dn, ModificationItem[]  mods)

This variation of modifyAttributes method takes the fully qualified unique DN of the entry to be modified as its first parameter. The second parameter takes an array of ModificationItems where each modification item holds the attribute information that needs to be modified.

Listing 3-11 shows the code that adds a new telephone number to the patron.

Listing 3-11.

public void addTelephoneNumber() {
   Attribute attribute = new BasicAttribute("telephoneNumber", "801 100 1000");
   ModificationItem item = new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute);
   ldapTemplate.modifyAttributes("uid=patron999," + "ou=patrons,dc=inflinx,dc=com", new ModificationItem[] {item});
}

In this implementation, you simply create a new BasicAttribute with telephone information. Then you create a new ModificationItem and pass in the ADD_ATTRIBUTE code, indicating that you are adding an attribute. Finally, you invoke the modifyAttributes method with the patron DN and the modification item. The DirContext has a REPLACE_ATTRIBUTE code that when used will replace an attribute’s value. Similarly, the REMOVE_ATTRIBUTE code will remove the specified value from the attribute.

Deleting Operation

Similar to addition and modification, LdapTemplate makes it easy to remove an entry with the unbind method. Listing 3-12 provides the code that implements the unbind method and removes a patron. As you can see, the unbind method takes the DN for the entry that needs to be removed.

Listing 3-12.

public void removePatron() {
   ldapTemplate.unbind("uid=patron999," + "ou=patrons,dc=inflinx,dc=com");
}

Summary

Spring LDAP Framework aims at simplifying LDAP programming in Java. In this chapter, you got a high-level overview of Spring LDAP and some of the concepts associated with Spring Framework. You also looked at the setup needed to get up and running with Spring LDAP. In the next chapter, you will focus on testing Spring LDAP applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset