Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

On the mailing list, people ask regularly on how to write a custom partition. Please note that this is not an easy task. Nevertheless I try to give you a starting point with some simple examples. If you simply plan to add another suffix to ApacheDS (besides dc=example.,dc=com, for instance) in order to store data, it is not necessary to write any code. You can simply add some lines to the configuration. The following is for those developers who plan to use implement another storage mechanism than the provided default.

...

Implementing your own partition is basically implementing the Partition interface from the org.apache.directory.server.core.partition package. Please note that this is not an easy task. Nevertheless I try to give you a starting point with some simple examples.

Hello world. A minimal partition

...

Currently, the sources are checked in here

In order to build it, simply check it out and type "mvn install".

Implementing the class HelloWorldPartition

The following UML class diagram depicts the structure of the little example.

Image Added

In order to be a partition, class HelloWorldPartition implements the corresponding interface from org.apache.directory.server.core.partition. It has an association to it's only entry (which will hold the "hello, world" method). This entry is created in the init life cycle method of the partition, which looks like this:

Code Block
java
java

...
public void init(DirectoryService core) throws Exception {
                        
  // Create LDAP DN
  suffixDn = new LdapDN(suffix);
  suffixDn.normalize(core.getRegistries().getAttributeTypeRegistry().getNormalizerMapping());
  Rdn rdn = suffixDn.getRdn();
        
  // Create the only entry in this partition
  ServerEntry entry = new DefaultServerEntry(core
          .getRegistries(), this.suffixDn);
  entry.put(SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
                SchemaConstants.ORGANIZATIONAL_UNIT_OC);        
  entry.put(SchemaConstants.OU_AT, rdn.getUpValue().toString());
  entry.put("description", "hello, world", "a minimal partition");
        
  this.helloEntry = entry;
}
...

We assume that the suffix starts with "ou=" in order to create an entry of object class organizational unit. If someone tries to set a suffix which starts with another attribute for the RDN, the setSuffix will throw an exception.

The Partition interface requires to implement many methods for all the operations a partition should support (adding, deleting, modifying entries ...). Due to the fact, that this is a read only partition, the implementation in our case is minimalistic. Here is the delete method as an example.

Code Block
java
java

...
public void delete(DeleteOperationContext opContext)
        throws LdapOperationNotSupportedException {
    throw new LdapOperationNotSupportedException(
            MODIFICATION_NOT_ALLOWED_MSG, ResultCodeEnum.UNWILLING_TO_PERFORM);
}
...

Although this example should be minimal, some methods need more attention. At least if we want to see the partitiion in an LDAP and not only in the error logs ...

The important methods are hasEntry, lookup and search. The following code is the search method. Please note that it ignores search scopes other than BASE and search filters completely in order to have simple code.

Code Block
java
java

public EntryFilteringCursor search(SearchOperationContext ctx)
        throws Exception {

    if (ctx.getDn().equals(this.suffixDn)) {
        switch (ctx.getScope()) {
        case OBJECT:
            // return a result with the only entry we have
            return new BaseEntryFilteringCursor(
                    new SingletonCursor<ServerEntry>(this.helloEntry), ctx);
        }
    }

    // return an empty result
    return new BaseEntryFilteringCursor(new EmptyCursor<ServerEntry>(), ctx);
}

For the other methods, take a look in the source code.

Using the partition

Embedded mode

Code Block
java
java
package org.apache.directory.samples.partition.hello;

import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.ldap.LdapService;


import org.apache.directory.server.protocol.shared.SocketAcceptor;

public class Main {

    public static void main(String[] args) throws Exception {
        DirectoryService directoryService;

        SocketAcceptor socketAcceptor;
        LdapService ldapService;

        directoryService = new DefaultDirectoryService();
        directoryService.setShutdownHookEnabled(true);

        socketAcceptor = new SocketAcceptor(null);
        ldapService = new LdapService();
        ldapService.setSocketAcceptor(socketAcceptor);
        ldapService.setDirectoryService(directoryService);
        ldapService.setIpPort(10389);

        HelloWorldPartition helloPartition = new HelloWorldPartition();
        helloPartition.setSuffix("ou=helloWorld");
        helloPartition.init(directoryService);
        
        directoryService.addPartition(helloPartition);       
        
        directoryService.startup();
        ldapService.start();
    }
}

...

Note that the class HelloWorldPartition has to be in the class path of the server. Withgout, starting the server leads to a ClassNotFoundException. You can copy the jar file which results from the build to the lib directory and adjust the command line parameters in the apacheds.sh script.

...

Verification

After adding the HelloWorldPartition to the directory service like above (embedded or via configuration in server.xml), you can browse it with an LDAP browser like the one from Apache Directory Studio. Here are some screen shots.

...

Code Block
none
none
$ ldapsearch -h localhost -p 10389 -D "uid=admin,ou=system" -w secret \\
    -b "" -s base "(objectclass=*)" namingContexts
version: 1
dn:
namingContexts: ou=system
namingContexts: ou=helloWorld
namingContexts: ou=schema
$
$ ldapsearch -h localhost -p 10389 -D "uid=admin,ou=system" -w secret \\
    -b "ou=helloWorld" -s base "(objectclass=*)"

version: 1
dn: ou=helloWorld
objectClass: organizationalUnit
objectClass: top
description: hello, world
description: a minimal partition
ou: helloWorld
$

...

Currently, the sources are checked in here

In order to build it, simply check it out and type "mvn install".

verification

After adding the SystemPropertyPartition to the directory service (embedded or via configuration in server.xml), you can browse it with an LDAP browser like the one from Apache Directory Studio. Here is a screen shot.

...