Drucken

Tomcat, Jetty & LDAP

Wer eine Webanwendung auf Basis von Servlets erstellt hat und diese im Entwicklungszyklus mittles Jetty testet, wird unter Umständen beim Ausrollen auf Tomcat eine sehr böse Überraschung erleben, falls er über JNDI auf LDAP-Repositories zugreifen will. Der Grund dafür und die Möglichkeiten, den Code portabel für Jetty und Tomcat zu gestalten, wird hier erläutert.

 

JNDI und der initiale Context

Die Arbeit mit JNDI verlangt die Erzeugung eines initialen Contexts. Dies geschieht über eine Factoryklasse, die über eine HashMap - ein sogenanntes Environment - gesteuert wird:

Hashtable env = new Hashtable();
DirContext ctx = new InitialDirContext(env);

Hinter dem  javax.naming.directory.DirContext steckt eine Implementierung, die von verschiedenen Herstellern stammen kann. Die eigentlich benutzten Implementierungsklassen können vom Anwender über Einträge im Environment gesteuert werden. Gibt man dort keine Präferenz an, wird Java einfach diejenige benutzen, die es für richtig hält.

Servletcontainer

Servletcontainer wie Jetty oder Tomcat bringen eine eigene JNDI-Implementierung mit, da auch einige interne Vorgänge in diesen Komponenten auf JNDI aufbauen. Das hat zur Folge, daß diese Implementierungen als Standard eingestellt sind und benutzt werden, wenn der Anwender nichts anderes explizit über das Environment spezifiziert.

Und genau hier liegt das Problem bei Tomcat in seinen 5.5-er Versionen: Läßt man ihn gewähren, schlägt die Benutzung von JNDI-Komponenten fehl, weil er eine Klasse des JNDI-Stack nicht finden kann. Zu schwarzer Magie wird das vor dem Hintergrund, daß diese Klasse in einem der Standard-JAR-Dateien von Tomcat genau in dem Paket existiert, in dem Tomcat sucht. 

Anders bei Jetty: Auch dieser Servletcontainer bringt seine eigene JNDI -Implementation mit - allerdings funktioniert diese hier auch für Webanwendungen.

Tomcat 5.5x - und die Lösung des Problems

Die Lösung des Problems erscheint naheliegend: wenn es mit dem Tomcat-JNDI-Provider nicht geht, dann benutzt man einfach einen eigenen. Dann sind nur noch zwei Fragen zu beantworten:

  1. Welchen soll man benutzen?
  2. Was muß man wie konfigurieren, damit die Alternative benutzt wird?

Welchen soll man benutzen?

Wir schlagen vor, die Java-eigene Implementierung zu benutzen. Bei unseren Tests funktionierte der und man bringt dadurch keine neue zusätzliche Abhängigkeit ins Projekt.

Was muß man wie konfigurieren, damit die Alternative benutzt wird?

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL,cs.getLocation());
env.put("com.sun.jndi.ldap.connect.timeout", cs.getTimeout());
DirContext ctx = new InitialDirContext(env);

Wünschen Sie Unterstützung bei der Umsetzung Java-basierter Server-Anwendungen oder nähere Informationen zu unseren Java-Komponenten , freuen wir uns über eine Kontaktaufnahme. Wir setzen uns umgehend mit Ihnen in Verbindung.