<!DOCTYPE html> <!-- | Generated by Apache Maven Doxia Site Renderer 1.11.1 from src/site/xdoc/dev/ldap_testing.xml at 2025-02-23 | Rendered using Apache Maven Fluido Skin 1.12.0 --> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="generator" content="Apache Maven Doxia Site Renderer 1.11.1" /> <meta name="author" content="Emmanuel Hugonnet" /> <meta name="author" content="Miguel Moquillon" /> <title>Silverpeas Project Web Site – Testing your LDAP code with OpenDJ</title> <link rel="stylesheet" href="../css/apache-maven-fluido-1.12.0.min.css" /> <link rel="stylesheet" href="../css/site.css" /> <link rel="stylesheet" href="../css/print.css" media="print" /> <script src="../js/apache-maven-fluido-1.12.0.min.js"></script> <!-- Google Analytics --> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-2015926-3', 'auto'); ga('send', 'pageview'); ga('set', 'anonymizeIp', true); ga('set', 'forceSSL', true); </script> <style>.github-fork-ribbon:before { background-color: orange; }</style> </head> <body class="topBarEnabled"> <a class="github-fork-ribbon right-top" href="https://github.com/Silverpeas" data-ribbon="Fork me on GitHub" title="Fork me on GitHub">Fork me on GitHub</a> <header id="topbar" class="navbar navbar-fixed-top navbar-inverse"> <div class="navbar-inner"> <div class="container"> <a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a> <nav class="nav-collapse"> <ul class="nav"> <li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown">Silverpeas <b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="../intro.html" title="About">About</a></li> <li><a href="../product/features.html" title="Key Features">Key Features</a></li> <li class="dropdown-submenu"> <a href="../product/applications.html" title="Applications">Applications</a> <ul class="dropdown-menu"> <li><a href="../product/social_network.html" title="Social Network">Social Network</a></li> <li><a href="../product/documentation_management.html" title="Electronic Documentation Management">Electronic Documentation Management</a></li> <li><a href="../product/content_management.html" title="Content Management">Content Management</a></li> <li><a href="../product/data_collection.html" title="Data Collection">Data Collection</a></li> <li><a href="../product/gallery.html" title="Pictures Management">Pictures Management</a></li> <li><a href="../product/knowledge_management.html" title="Knowledge Management">Knowledge Management</a></li> <li><a href="../product/project_documentation.html" title="Project Documentation">Project Documentation</a></li> </ul> </li> <li><a href="../screenshots.html" title="Screenshots">Screenshots</a></li> <li class="dropdown-submenu"> <a href="../installation/index.html" title="Install Silverpeas">Install Silverpeas</a> <ul class="dropdown-menu"> <li><a href="../installation/installationV6.html" title="Installation of Silverpeas 6">Installation of Silverpeas 6</a></li> <li><a href="../installation/cloud.html" title="Silverpeas in the Cloud">Silverpeas in the Cloud</a></li> <li><a href="../installation/webdav.html" title="Online Edition of Documents">Online Edition of Documents</a></li> </ul> </li> <li class="dropdown-submenu"> <a href="../#" title="Our versions">Our versions</a> <ul class="dropdown-menu"> <li><a href="https://tracker.silverpeas.org/projects/silverpeas/roadmap" title="Roadmap">Roadmap</a></li> <li><a href="https://tracker.silverpeas.org/projects/silverpeas/roadmap?completed=1&with_subprojects=1" title="Changelog">Changelog</a></li> <li><a href="../releasenotes.html" title="Release Notes">Release Notes</a></li> </ul> </li> <li><a href="../scm.html" title="Source Code">Source Code</a></li> <li class="dropdown-submenu"> <a href="../#" title="Some Configuration Tips">Some Configuration Tips</a> <ul class="dropdown-menu"> <li><a href="../configuration/ldap.html" title="LDAP Synchronization">LDAP Synchronization</a></li> <li><a href="../configuration/proxy.html" title="Configuring a reverse-proxy">Configuring a reverse-proxy</a></li> </ul> </li> <li><a href="../faq.html" title="FAQ">FAQ</a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown">Silverpeas Projects <b class="caret"></b></a> <ul class="dropdown-menu"> <li class="dropdown-submenu"> <a href="../#" title="Global information">Global information</a> <ul class="dropdown-menu"> <li><a href="../intro.html" title="About Silverpeas">About Silverpeas</a></li> <li><a href="../team.html" title="Team">Team</a></li> <li><a href="../mailing-lists.html" title="Mailing List">Mailing List</a></li> <li><a href="../issue-management.html" title="Issue Tracking">Issue Tracking</a></li> <li><a href="../source-repository.html" title="Source Repository">Source Repository</a></li> <li><a href="../ci-management.html" title="Continuous Integration">Continuous Integration</a></li> </ul> </li> <li><a href="../docs/core/index.html" title="Silverpeas Core">Silverpeas Core</a></li> <li><a href="../docs/components/index.html" title="Silverpeas Applications">Silverpeas Applications</a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown">How to contribute <b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="../dev/collaboration.html" title="Contribution">Contribution</a></li> <li><a href="../dev/quality.html" title="Code Quality">Code Quality</a></li> <li><a title="Testing the LDAP code">Testing the LDAP code</a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown">Licensing <b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="../legal/licensing_gnu_affero.html" title="License">License</a></li> <li><a href="../legal/licensing_faq.html" title="Licensing FAQ">Licensing FAQ</a></li> <li><a href="../legal/floss_exception.html" title="FLOSS Exception">FLOSS Exception</a></li> <li><a href="../legal/trademark.html" title="Silverpeas Trade Mark">Silverpeas Trade Mark</a></li> </ul> </li> </ul> </nav> <div class="nav-collapse"> </div> </div> </div> </header> <div class="container container-top"> <header> <div id="banner"> <div class="pull-left"><a href="https://www.silverpeas.org/" id="bannerLeft"><img src="../images/logo-silverpeas.png" alt="Silverpeas" style="" /></a></div> <div class="pull-right"></div> <div class="clear"><hr/></div> </div> <div id="breadcrumbs"> <ul class="breadcrumb"> <li><a href="https://www.silverpeas.org" class="externalLink" title="Silverpeas">Silverpeas</a><span class="divider">/</span></li> <li class="active ">Testing your LDAP code with OpenDJ</li> <li id="publishDate" class="pull-right"><span class="divider">|</span> Last Published: 2025-02-23</li> <li id="projectVersion" class="pull-right">Version: 6.4.2</li> </ul> </div> </header> <main id="bodyColumn" > <section> <h2><a name="Testing_your_LDAP_code_with_OpenDJ"></a>Testing your LDAP code with OpenDJ</h2> <p>In the age of TDD and unit testing, you have to be able to test your code easily and fast. <br /> If testing with SQL databases is well documented, this is not the case for LDAP directories. Hopefully, with the current modern libre LDAP Java servers, this feature is becoming available. <br /> ApacheDS offers a JUnit runner, but we meet with problems trying to use it. Thus we decided to use OpenDJ which can be easily embedded and which can use an in-memory backend so performance should be acceptable for tests. <br /> Nevertheless, even if OpenDJ uses an in-memory backend, its configuration is managed with files. That's why you will have to add those files to your test environment. </p> <p>With JUnit, we have two ways to manage external resources: </p> <ul> <li>use a specific JUnit runner that will manage the reference to the embedded server (this is the choice of ApacheDS)</li> <li>use a JUnit rule that will start and stop the embedded server. This is our choice, using a <i>ClassRule</i>, a rule that is applied to a static variable of the test class. This feature is available since JUnit 4.10. </li> </ul> <p>In order to simplify the configuration of the OpenDJ server we have defined an annotation, <a class="externalLink" href="https://github.com/ehsavoie/embedded-ldap/blob/master/src/main/java/org/silverpeas/ldap/CreateLdapServer.java"><b>CreateLdapServer</b></a>, to pass some parameters to our instance: </p> <ul> <li>a ldif file containing the data to be inserted into the directory</li> <li>the path (relative or absolute) to the directory containing the minimum configuration of OpenDJ</li> <li>the in-memory backend id where the test data will be stored</li> <li>the Distinguished Name for the in-memory backend</li> </ul> <p>Now, we only need to write our rule class that implements <i>org.junit.rules.TestRule</i>.<br /> So let's write the required method: </p> <p> <code> </p> <div> <pre> @Override public Statement apply(Statement stmnt, Description d) { CreateLdapServer annotation = d.getAnnotation(CreateLdapServer.class); if (annotation != null) { return statement(stmnt, annotation.serverHome(), annotation.ldifConfig(), annotation. ldifFile(), annotation.backendID(), annotation.baseDN()); } return stmnt; } </pre></div> </code> <p>The first line is looking for our <code>CreateLdapServer</code> annotation, and if one is found then the execution statement for the test is wrapped so that we can start the LDAP server when the class is loaded and stop it after all the tests in the test class have run. This is what you can see in the following code: </p> <p> <code> </p> <div> <pre> private Statement statement(final Statement stmnt, final String serverHome, final String ldifConfigFile, final String ldifFile, final String backendId, final String dn) { return new Statement() { @Override public void evaluate() throws Throwable { before(); try { stmnt.evaluate(); } finally { after(); } } private void after() { stopLdapServer(); } private void before() { try { startLdapServer(serverHome, ldifConfigFile); loadLdif(ldifFile, backendId, DN.decode(dn)); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException("Could'nt start LDAP Server", ex); } } }; } </pre></div> </code> <p>You can see that we create an instance of <code>org.junit.Statement</code> wrapping the test statement with two methods: <code>before()</code> called before the test execution and <code>after()</code> when all the test has run, whatever its result is. These two methods are quite simple: </p> <ul> <li> <code>before()</code> starts the LDAP server and load the ldif file into it, </li> <li> <code>after()</code> stops the LDAP server. </li> </ul> <p>Since all the data are stored in an in-memory backed we don't need to clean them before stoping the server. Look into <a class="externalLink" href="https://github.com/ehsavoie/embedded-ldap/blob/master/src/main/java/org/silverpeas/ldap/OpenDJRule.java">the code</a> if you want to know exactly how we start the server and create the in-memory backend. </p> <p> If you want to use all of this in your test, this is how you should proceed. <br /> First, annotate your test code with the <i>CreateServer</i> annotation:</p> <p> <code> </p> <div> <pre> @CreateLdapServer(ldifConfig="opendj/config/config.ldif", serverHome="opendj", ldifFile="silverpeas-ldap.ldif") public class LDAPDriverTest { ... </pre></div> </code> <p>Then declare our rule:</p> <p> <code> </p> <div> <pre> @ClassRule public static OpenDJRule ldapRule = new OpenDJRule(); </pre></div> </code> <p>Now you are almmost ready to test your code. Add the OpenDJ required librairies to your test classpth. In the case of an Apache Maven project you will have to define the following dependencies: </p> <p> <code> </p> <div> <pre> ... org.forgerock.opendj opendj-server 2.4.5 test com.sleepycat je 1.4.7 test ... </pre></div> </code> <p>All you need now are some configuration files: </p> <ul> <li>the ldif file (<b>silverpeas-ldap.ldif</b>) that we have declared and should be in <i>src/test/resources</i>.</li> <li>the directory <b>opendj</b> which contains the minimum confiuration to run OpenDJ and should also be in<i>src/test/resources</i>.</li> </ul> <p> <b>Be careful not to filter the content of the opendi directory with Apache Maven.</b> <br />The source code with a sample is available on Github : <a class="externalLink" href="https://github.com/ehsavoie/embedded-ldap" hreflang="en">https://github.com/ehsavoie/embedded-ldap</a> <br /> <br />Many thanks to Ludovic Poitou for his kind help on how to configure and use OpenDJ. </p> </section> </main> </div> <hr/> <footer> <div class="container"> <div class="row"> <div class="license"> <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>. </div> </div> <p id="poweredBy" class="pull-right"><a href="https://netbeans.apache.org/download/index.html" title="IDEA IntelliJ" class="builtBy"><img class="builtBy" alt="IDEA IntelliJ" src="../images/logos/intellij-idea-logo.png" style="" /></a> <a href="https://www.eclipse.org" title="Eclipse" class="builtBy"><img class="builtBy" alt="Eclipse" src="../images/logos/logo_eclipse.png" style="" /></a> <a href="https://maven.apache.org/" title="Maven" class="builtBy"><img class="builtBy" alt="Maven" src="../images/logos/logo_maven.png" style="" /></a> <a href="https://izpack.org/" title="Izpack" class="builtBy"><img class="builtBy" alt="Izpack" src="../images/logos/logo_izPack.png" style="" /></a> </p> </div> </footer> <script> if(anchors) { anchors.add(); } </script> </body> </html>