= 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
[http://tomcat.apache.org 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.

<pre>
    <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>
</pre>

==== 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...

<pre>
  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();
</pre>

==== 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


[{Tag Java Tomcat JNDI JDBC Datenbank}]