Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
{scrollbar}

Embedding Apache Directory Server into an application

Tipnote
titleWork in progressApacheDS 1.5.5

This site is in the process of being reviewed and updated.

Warning

This page describes how to embed the server, using the trunk. It won't work with 1.5.4 as there is a problem in the way we built the apacheds-all-1.5.4.jar. A workaround is to load all the included jars, but it's a bit painful, as there are 32 jars to define (this list will be given at the end of this page}

Code for this sample :
EmbeddedADS.java
pom.xml

Embedding Apache Directory Server into an application

The idea is to use the server directly without having to communicate with a remote server, eliminating all the network layer. This is one of the reason ADS has been developed in Java : to allow such usage.

We will go through a very simple example step by step to show you how this can be done.

Setting up the environment

We first need to define a base for our project. Here is the structure we will use :

was updated for ApacheDS 1.5.5.

The idea is to use the server directly without having to communicate with a remote server, eliminating all the network layer. This is one of the reason ADS has been developed in Java: to allow such usage.

We will go through a very simple example step by step to show you how this can be done.

Setting up the environment

We first need to define a base for our project. We use Maven (2.0.9 or above) to build our project, so the structure we will use looks like this:

Code Block

.
|-- pom.xml
`-- src
    `-- main
        `-- java
     
Code Block

/
|
+--src
    |
    +--main
       `-- |
org
                +`--java apache
            : we will put all the sources into this directory
Note

You will need some jars file in order to compile and run this sample when used with 1.5.4. If you are using the trunk, don't worry, a pom.xml with all the needed dependencies is attached.

* antlr-2.7.7.jar
* apacheds-bootstrap-extract-1.5.4.jar
* apacheds-bootstrap-partition-1.5.4.jar
* apacheds-core-1.5.4-sources.jar
* apacheds-core-avl-1.5.4.jar
* apacheds-core-cursor-1.5.4.jar
* apacheds-core-entry-1.5.4.jar
* apacheds-core-integ-1.5.4.jar
* apacheds-core-shared-1.5.4.jar
* apacheds-jdbm-1.5.4.jar
* apacheds-jdbm-store-1.5.4.jar
* apacheds-protocol-ldap-1.5.4-sources.jar
* apacheds-protocol-shared-1.5.4.jar
* apacheds-schema-bootstrap-1.5.4.jar
* apacheds-schema-registries-1.5.4.jar
* apacheds-server-integ-1.5.4.jar
* apacheds-utils-1.5.4.jar
* apacheds-xdbm-base-1.5.4.jar
* apacheds-xdbm-search-1.5.4.jar
* bcprov-jdk15-140.jar
* commons-collections-3.2.1.jar
* commons-io-1.3.2.jar
* commons-lang-2.4.jar
* junit-4.4-sources.jar
* log4j-1.2.14-sources.jar
* mina-core-1.1.7.jar
* mina-filter-ssl-1.1.7.jar
* shared-asn1-0.9.13.jar
* shared-asn1-codec-0.9.13.jar
* shared-ldap-0.9.13.jar
* shared-ldap-constants-0.9.13.jar
* slf4j-api-1.5.2-sources.jar
* slf4j-log4j12-1.5.2-sources.jar

We will also build the project using Maven 2.0.9. So we need a pom.xml to build the project. It has been attached.

Creating the application

So let's start with the code. It's quite simple : we define a class, add a main() method, and initialize the server, before using it. In the code snippet below, we have removed all the initialization part to keep only the main() method.

`-- directory
                        `-- EmbeddedADS.java

You could download both files here:
EmbeddedADS.java
pom.xml

Note

If you don't want to use Maven you need to add the following dependencies to your classpath in order to compile and run this sample.
* apacheds-all-1.5.5.jar
* slf4j-api-1.5.6.jar
* slf4j-log4j12-1.5.6.jar
* log4j-1.2.14.jar

Creating the application

So let's start with the code. It's quite simple: we define a class, add a main() method, and initialize the server, before using it. In the code snippet below, we have removed all the initialization part to keep only the main() method.

Code Block

package org.apache.directory;

/**
 * A simple example exposing how to embed Apache Directory Server
 * into an application.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$, $Date$
 */
public class EmbeddedADS
{
    /** The directory service */
    private DirectoryService service;

    ...

    /**
     * Creates a new instance of EmbeddedADS. It initializes the directory service.
     *
     * @throws Exception If something went wrong
     */
    public EmbeddedADS() throws Exception
    {
        init();
    }

    /**
     * Main class. We just do a lookup on the server to check that it's available.
     *
     * @param args Not used. 
     */
    public static void main( String[] args ) //throws Exception 
    {
        try
        {
            // Create the server
            EmbeddedADS ads = new EmbeddedADS();
            
            // Read an entry
            Entry result = ads.service.getAdminSession().lookup( new LdapDN( "dc=apache,dc=org" ) );
            
            // And print it if available
            System.out.println( "Found entry : " + result );
        }
        catch ( Exception e )
        {
            // Ok, we have something wrong going on ...
            e.printStackTrace();
        }
    }
}

As you can see, we first initialize the server, and immediately do a lookup to check that we can read an entry from it.

Let's focus on the initialization part now.

Initializing the server

This is done in the init() method. It will create the DirectoryService global object (service), and create a partition in which we will store the entries.

Note

A partition is a storage point, associated with a DN, root point for this partition. It's a bit like a mounting point on Unix.
We also need a context entry associated to this DN.

Here, we will create the apache partition, associated with the 'dc=apache,dc=org' DN.

Here is the code for this method :

Code Block

    ...

    /**
     * Initialize the server. It creates the partition, adds the index, and
     * injects the context entries for the created partitions.
     *
     * @throws Exception if there were some problems while initializing the system
     */
    private void init() throws Exception
    {
Code Block

package org.apache.directory;

/**
 * A simple exemple exposing how to embed Apache Directory Server
 * inot an application.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$, $Date$
 */
public class EmbeddedADS
{
    /** The directory service */
    private DirectoryService service;
    
    /**
     * Creates a new instance of EmbeddedADS. It initializes the directory service.
     *
     * @throws Exception If something went wrong
     */
    public EmbeddedADS() throws Exception
    {
        init();
    }

    /**
     * Main class. We just do a lookup on the server to check that it's available.
     *
     * @param args Not used. 
     */
    public static void main( String[] args ) //throws Exception 
    {
        try
        {
            // Create the server
            EmbeddedADS ads = new EmbeddedADS();
            
            // Read an entry
            Entry result = ads.service.getAdminSession().lookup( new LdapDN( "dc=apache,dc=org" ) );
            
            // And print it if available
        // Initialize the LDAP service
    System.out.println( "Found entry : "service += resultnew DefaultDirectoryService();
        }
        catch// (Disable Exceptionthe eChangeLog )system
        {
    service.getChangeLog().setEnabled( false );

        // Ok,Create wea havenew somethingpartition wrong going on ..named 'apache'.
        Partition apachePartition =  e.printStackTrace();
    addPartition( "apache", "dc=apache,dc=org" );
        }
    }
}

As you can see, we first initialize the server, and immediately do a lookup to check that we can read an entry from it.

Let's focus on the initialization part now.

Initializing the server

This is done in the init() method. It will create the DirectoryService global object (service), and create a partition in which we will store the entries.

Note

A partition is a storage point, associated with a DN, root point for this partition. It's a bit like a mounting point on Unix.

We also need a context entry associated to this DN.

Here, we will create the apache partition, associated with the 'dc=apache,dc=org' DN.

Here is the code for this method :

Code Block

    /**
        // Index some attributes on the apache partition
        addIndex( apachePartition, "objectClass", "ou", "uid" );
        
        // And start the service
        service.startup();
        
        // Inject the apache root entry if it does not already exist
     * Initialize the server.if It creates the partition, add the index, and
( !service.getAdminSession().exists( apachePartition.getSuffixDn() ) )
       * inject{
 the context entries for the created partitions.
     *
LdapDN dnApache = new  * @throws Exception if there were some problems why initializing the system
     */
    private void init() throws Exception
    {
        // Initialize the LDAP service
LdapDN( "dc=Apache,dc=Org" );
            ServerEntry entryApache = service.newEntry( dnApache );
            entryApache.add( "objectClass", "top", "domain", "extensibleObject" );
             service = new DefaultDirectoryService();
        
        // Disable the ChangeLog system
entryApache.add( "dc", "Apache" );
              service.getChangeLoggetAdminSession().setEnabledadd( falseentryApache );

        }
        //
 Create a new partition named 'apache'.
  // We are all done !
 Partition apachePartition = addPartition( "apache", "dc=apache,dc=org" ); }

       ...

We disabled the ChangeLog service because it's useless in our case. As you can see, the steps to initialize the server are:

  • create a new DirectoryService instance
  • add a partition
  • add some index
  • start the service
  • add the context entry

One important point: as the data are remanent, we have to check that the added context entry does not exist already before adding it.

Some helper methods have been used : addPartition and addIndex. Here they are :

Code Block

    ...

    /**
     * Add a new partition to the server 
        // Index some attributes on the apache partition
        addIndex( apachePartition, "objectClass", "ou", "uid" );
        
        // And start the service
        service.startup();
     *
   
  * @param partitionId The partition Id
 // Inject the apache root* entry@param ifpartitionDn itThe does not already existpartition DN
     * @return The try
newly added partition
     * {
@throws Exception If the partition can't be added
     service.getAdminSession().lookup( apachePartition.getSuffixDn() );*/
    private Partition addPartition( String }
partitionId, String partitionDn ) throws Exception
   catch ( LdapNameNotFoundException lnnfe ) {
        {
    // Create a new partition named 'foo'.
        LdapDNPartition dnApachepartition = new LdapDN( "dc=Apache,dc=Org" JdbmPartition();
        partition.setId( partitionId );
     ServerEntry entryApache = servicepartition.newEntrysetSuffix( dnApachepartitionDn );
        service.addPartition( partition );
  entryApache.add( "objectClass", "top", "domain", "extensibleObject" );      
        return partition;
   entryApache.add( "dc", "Apache" ); }
    
    
    service.getAdminSession().add( entryApache );
/**
     * Add a new  }
        set of index on the given attributes
     *
     * @param partition The partition on which we want to add index
     * @param attrs //The Welist areof allattributes doneto !index
    }

We disabled the ChangeLog service because it's useless in our case. As you can see, the steps to initialize the server are :

  • create a new DirectoryService instance
  • add a partition
  • add some index
  • start the service
  • add the context entry

One important point : as the data are remanent, we have to check that the added context entry does not exist already before adding it. Here, we simply assume it does exist, and if not, we catch the exception we got, and create the entry.

Some helper methods have been used : addPartition and addIndex. Here they are :

Code Block

    /**
     * Add a new partition to the server
     *
     * @param partitionId The partition Id */
    private void addIndex( Partition partition, String... attrs )
    {
        // Index some attributes on the apache partition
        HashSet<Index<?, ServerEntry>> indexedAttributes = new HashSet<Index<?, ServerEntry>>();
        
        for ( String attribute:attrs )
        {
     * @param partitionDn The partition DN
  indexedAttributes.add( new  * @return The newly added partition
JdbmIndex<String,ServerEntry>( attribute ) );
         *}
 @throws Exception If the partition can't be added
     */
    private Partition addPartition( String partitionId, String partitionDn ) throws Exception((JdbmPartition)partition).setIndexedAttributes( indexedAttributes );
    {}

        // Create a new partition named 'foo'.
        Partition partition = new JdbmPartition();
        partition.setId( partitionId );
        partition.setSuffix( partitionDn );
        service.addPartition( partition );
        
        return partition;
    }
    
    
    /**
     * Add a new set of index on the given attributes
     *
     * @param partition The partition on which we want to add index
     * @param attrs The list of attributes to index
     */
    private void addIndex( Partition partition, String... attrs )
    {
        // Index some attributes on the apache partition
        HashSet<Index<?, ServerEntry>> indexedAttributes = new HashSet<Index<?, ServerEntry>>();
        
        for ( String attribute:attrs )
        {
            indexedAttributes.add( new JdbmIndex<String,ServerEntry>( attribute ) );
        }
        
        ((JdbmPartition)partition).setIndexedAttributes( indexedAttributes );
    }

That's it ! (the attached code will contain the needed imports)

Building the sample

Using Maven 2.0.9, this is easy :

...

That's it! (the attached code will contain the needed imports)

Building the sample

Using Maven this is easy:

Code Block

$ mvn clean compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building ApacheDS embedded sample
[INFO]    task-segment: [clean, compile]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory /tmp/EmbeddedADS/target
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /tmp/EmbeddedADS/src/main/resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Compiling 1 source file to /tmp/EmbeddedADS/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Sat Nov 28 20:02:23 CET 2009
[INFO] Final Memory: 17M/76M
[INFO] --------
Code Block

elecharny@elecharny-laptop:~/ws-ads-1.5.4/EmbeddedADS$ mvn clean install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building ApacheDS Server Embedded sample
[INFO]    task-segment: [clean, install]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory /home/elecharny/ws-ads-1.5.4/EmbeddedADS/target
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to /home/elecharny/ws-ads-1.5.4/EmbeddedADS/target/classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [jar:jar]
[INFO] Building jar: /home/elecharny/ws-ads-1.5.4/EmbeddedADS/target/apacheds-embedded-sample-1.5.4.jar
[INFO] [install:install]
[INFO] Installing /home/elecharny/ws-ads-1.5.4/EmbeddedADS/target/apacheds-embedded-sample-1.5.4.jar to /home/elecharny/.m2/repository/org/apache/directory/server/apacheds-embedded-sample/1.5.4/apacheds-embedded-sample-1.5.4.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL

The resulting jar can be found in the target directory.

Running the sample

Using Maven this is easy:

Code Block

$ mvn exec:java -Dexec.mainClass=org.apache.directory.EmbeddedADS
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9 seconds
[INFO] Finished at: Fri Dec 05 19:31:24 CET 2008Building ApacheDS embedded sample
[INFO]   Final Memorytask-segment: 18M/82M[exec:java]
[INFO] ------------------------------------------------------------------------
elecharny@elecharny-laptop:~/ws-ads-1.5.4/EmbeddedADS$ 

The resulting jar can be found in the target directory.

...


[INFO] Preparing exec:java
[INFO] No goals needed for project - skipping
[INFO] [exec:java {execution: default-cli}]

When the main method is run, you should obtain something like :

Code Block
log4j:WARN No appenders could be found for logger (org.apache.directory.server.schema.registries.DefaultNormalizerRegistry).
log4j:WARN Please initialize the log4j system properly.
Found entry : ServerEntry
    dn[n]: 0.9.2342.19200300.100.1.25=apache,0.9.2342.19200300.100.1.25=orgdc=Apache,dc=Org
    objectClass: extensibleObject
    objectClass: domain
    objectClass: top
    dc: Apache

That's it!