Tomcat und JNDI installieren #

JNDI ist eine Art "Objektverzeichnis". Damit kann man zentral für einen Tomcat-Server bestimmte Objekte oder Werte definieren, die dann allen Applikationen zur Verfügung stehen. Dies hat zwei praktische Anwendungen, die mir spontan einfallen: Zum einen kann man Konfigurationseinstellungen zentral angeben, über die dann alle Applikationen verfügen können. So kann man ihnen mitteilen, in welcher Umgebung sie laufen ohne jede Applikation einzeln konfigurieren zu müssen. Zum anderen kann man Datenbankverbindungen zentral verwalten.

JDBC-Verbindungen zentral verwalten #

Eine Datenbankverbindung ist relativ teuer, d.h. man benötigt relativ viel Zeit und Ressourcen, um eine Verbindung mit einem MySQL-Server aufzubauen und zu authentifizieren. Ist diese Verbindung einmal aufgebaut, benötigt eine normale Webanwendung jedoch oftmals nur die Daten eines einzigen Querys und schließt die Verbindung dann wieder (oder schlimmer noch: schliesst sie nicht). Um eine solche Applikation nun zu beschleunigen, benutzt man sogenannte "Connection Pools". Ein solcher Pool enthält Verbindungen zu einer Datenbank, die dann bei Bedarf einer Applikation zugeordnet werden. In einer normalen, praktischen Applikation, die im Intranet läuft, hat unser Tomcat sowieso meistens nicht mehr als einen oder vielleicht mal zwei Threads gleichzeitig zu bearbeiten. Das bedeutet dann, daß der Tomcat beim ersten Starten eine einzige Verbindung öffnet und diese dann immer wieder benutzt wird.

Schnell-Anleitung #

Die offizielle Doku zum Thema findet sich auf der Tomcat Webseite. Die Doku dort ist sehr gut und ausführlich, allerdings vielleicht ein wenig zu ausführlich. Deshalb habe ich hier direkt und kurz die nötigsten Schritte unter Debian Linux (siehe auch JavaUnterDebian) notiert, um loszulegen:

Pool- und JDBC-Treiber in den Tomcat installieren

  aptitude install libmysql-java libcommons-dbcp-java
  cd /usr/share/tomcat4/common/lib/
  ln -s ../../../java/mysql.jar .
  ln -s ../../../java/commons-dbcp.jar .
  ln -s ../../../java/commons-pool.jar .

JDBC-Ressourcen meiner Applikation definieren

In der WEB-INF/web.xml muss man folgendes eintragen. Man deklariert damit, welche Ressourcen das Programm benutzen will, welchen Typ diese Ressource hat und unter welchem Namen sie gesucht werden wird. Der Name fängt normalerweise mit jdbc/ an. In folgendem Beispiel geht es also um die banking-Datenbank.

    <resource-ref>
        <description>
            Ressource-Reference zu einer Factory, die
java.sql.Connection
            Instanzen erzeugen kann. Diese können (müssen) in der
server.xml
            eingerichtet werden.
        </description>
        <res-ref-name>
            jdbc/banking
        </res-ref-name>
        <res-type>
            javax.sql.DataSource
        </res-type>
        <res-auth>
            Container
        </res-auth>
    </resource-ref>

Java-Quelltext

Ein genaues Beispiel eines Servlets anzugeben, ist hier zu stark von der jeweiligen Applikation abhängig. Es ist jedoch definitiv so, daß jede datenbankgestützte Applikation irgendwo ein Connection-Objekt benötigt. Dieses zu bekommen ist nun etwas anders als bei einfachem JDBC-Aufruf. Sehr wichtig ist übrigens, daß die Connection auch wieder mit close() geschlossen wird (und zwar auch nur genau einmal), sonst funktioniert das Ganze natürlich nicht richtig...

  Context initCtx = new InitialContext();
  Context envCtx = (Context) initCtx.lookup("java:comp/env");
  DataSource ds = (DataSource) envCtx.lookup("jdbc/banking");
  Connection conn = ds.getConnection();
  ...
  conn.close();

Konfiguration der Datasource

In der Datei ../conf/server.xml des Tomcat trägt man nun die Daten ein, mit denen der Tomcat das Datasource-Objekt einrichten kann. Diesen Teil kann man z.B. im <GlobalNamingResources>-Bereich einfügen. Dann kann diese JNDI-Ressource global von allen Applikationen benutzt werden. Man kann den Teil jedoch auch innerhalb des Host- oder des Context-Tags benutzen, um die Ressource auf bestimmte Applikationen zu beschränken.

   <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
            maxActive="100" maxIdle="30" maxWait="10000"
            username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/javatest?autoReconnect=true"/>

Bei Tomcat 4.x und 5.0 war die Syntax wie folgt:

    <Resource name="jdbc/banking" auth="Container" type="javax.sql.DataSource"/>
    <ResourceParams name="jdbc/banking">
        <parameter>
            <name>factory</name>
            <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
        </parameter>
        <parameter>
            <name>username</name>
            <value>freibierweb</value>
        </parameter>
        <parameter>
            <name>password</name>
            <value>freibierwebpasswort</value>
        </parameter>
        <parameter>
            <name>driverClassName</name>
            <value>org.gjt.mm.mysql.Driver</value>
        </parameter>
        <parameter>
            <name>url</name>
            <value>jdbc:mysql://localhost:3306/banking16?autoReconnect=true</value>
        </parameter>
        <parameter>
            <name>maxActive</name>
            <value>8</value>
        </parameter>
        <parameter>
            <name>maxIdle</name>
            <value>4</value>
        </parameter>
    </ResourceParams>

Ergebnis #

Obwohl ich jetzt diese wunderbare, überlegene Technologie benutze :-), konnte ich beim Seitenaufruf übrigens keinen echten Geschwindigkeitsvorteil feststellen. Falls man jedoch einen Server hat, der viele parallele Anfragen beantworten muss, dürfte der Unterschied bemerkbar werden. -- ThomasBayen

Tags:  Java, Tomcat, JNDI, JDBC, Datenbank

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-9) was last changed on 19-Feb-2008 21:29 by PeterHormanns