Versions Compared

Key

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

...

The method contextDestroyed simply stops the protocol and shuts down the service.

Code Block
java
java
titleStartStopListener.javajava
package org.apache.directory.samples.embed.webapp;

import java.io.File;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;

/**
 * A Servlet context listener to start and stop ApacheDS.
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class StartStopListener implements ServletContextListener
{
    private DirectoryService directoryService;

    private LdapServer ldapServer;

    /**
     * Startup ApacheDS embedded.
     */
    public void contextInitialized( ServletContextEvent evt )
    {
        try
        {
            directoryService = new DefaultDirectoryService();
            directoryService.setShutdownHookEnabled( true );

            ldapServer = new LdapServer();
            ldapServer.setDirectoryService( directoryService );
            ldapServer.setAllowAnonymousAccess( true );

            // Set LDAP port to 10389
            TcpTransport ldapTransport = new TcpTransport( 10389 );
            ldapServer.setTransports( ldapTransport );

            // Determine an appropriate working directory
            ServletContext servletContext = evt.getServletContext();
            File workingDir = ( File ) servletContext.getAttribute( "javax.servlet.context.tempdir" );
            directoryService.setWorkingDirectory( workingDir );

            directoryService.startup();
            ldapServer.start();

            // Store directoryService in context to provide it to servlets etc.
            servletContext.setAttribute( DirectoryService.JNDI_KEY, directoryService );
        }
        catch ( Exception e )
        {
            throw new RuntimeException( e );
        }
    }

    /**
     * Shutdown ApacheDS embedded.
     */
    public void contextDestroyed( ServletContextEvent evt )
    {
        try
        {
            ldapServer.stop();
            directoryService.shutdown();
        }
        catch ( Exception e )
        {
            throw new RuntimeException( e );
        }
    }
}

...

In order to execute the listener code, the class has to be defined in the deployment descriptor of a web application, as depicted below:

Code Block
xml
xml
titleweb.xmlxml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <display-name>ApacheDS embedded in a WebApp</display-name>
  <description>
    A simple yet portable way to run ApacheDS within a servlet
    container
  </description>

  <listener>
    <listener-class>
      org.apache.directory.samples.embed.webapp.StartStopListener
    </listener-class>
  </listener>
</web-app>

...

The following servlet, which will be deployed together with the other class in the web archive, connects to ApacheDS directly, i.e. via the internal JNDI provider. No network access is needed. In the doGet method it performs a search operation against the Root DSE of the server, as the examples above do.

Code Block
java
java
titleRootDseServlet.javajava
package org.apache.directory.samples.embed.webapp;

import java.io.PrintWriter;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.jndi.CoreContextFactory;

/**
 * A servlet which displays the Root DSE of the embedded server.
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory
 *         Project</a>
 */
public class RootDseServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException {

        try {
            resp.setContentType("text/plain");
            PrintWriter out = resp.getWriter();

            out.println("*** ApacheDS RootDSE ***\n");

            DirContext ctx = new InitialDirContext(this.createEnv());

            SearchControls ctls = new SearchControls();
            ctls.setReturningAttributes(new String[] { "*", "+" });
            ctls.setSearchScope(SearchControls.OBJECT_SCOPE);

            NamingEnumeration<SearchResult> result = ctx.search("",
                    "(objectClass=*)", ctls);
            if (result.hasMore()) {
                SearchResult entry = result.next();
                Attributes as = entry.getAttributes();

                NamingEnumeration<String> ids = as.getIDs();
                while (ids.hasMore()) {
                    String id = ids.next();
                    Attribute attr = as.get(id);
                    for (int i = 0; i < attr.size(); ++i) {
                        out.println(id + ": " + attr.get(i));
                    }
                }
            }
            ctx.close();

            out.flush();
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    /**
     * Creates an environment configuration for JNDI access.
     */
    protected Hashtable<Object, Object> createEnv() {

        // Fetch directory servive from servlet context
        ServletContext servletContext = this.getServletContext();
        DirectoryService directoryService = (DirectoryService) servletContext
                .getAttribute(DirectoryService.JNDI_KEY);

        Hashtable<Object, Object> env = new Hashtable<Object, Object>();
        env.put(DirectoryService.JNDI_KEY, directoryService);
        env.put(Context.PROVIDER_URL, "");
        env.put(Context.INITIAL_CONTEXT_FACTORY, CoreContextFactory.class
                .getName());

        env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
        env.put(Context.SECURITY_CREDENTIALS, "secret");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");

        return env;
    }
}

In order to make the servlet available to clients, it has to be declared in the deployment descriptor web.xml, here are the additions (a servlet named RootDseServlet for the class above, and a URL mapping)

Code Block
xml
xml
titleweb.xml, extendedxml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  ...
  <servlet>
    <servlet-name>RootDseServlet</servlet-name>
    <servlet-class>
      org.apache.directory.samples.embed.webapp.RootDseServlet
    </servlet-class>
  </servlet>

   <servlet-mapping>
     <servlet-name>RootDseServlet</servlet-name>
     <url-pattern>/RootDse</url-pattern>
   </servlet-mapping>
</web-app>

...