Der Zauberspruch zur Verbindung zur Datenbank besteht in Java aus drei Wörtern: Java Database Connectivity oder abgekürzt JDBC. Dieser Standardmechanismus ist so alt wie Java selbst, aber mit der Entwicklung von Java zur bevorzugten Umgebung für Server-Anwendungen haben sich die Möglichkeiten weiter entwickelt. Mit der Version 1.4 des JDK haben die Neuerungen, die zunächst für Server-Programme entwickelt wurden, Einzug in den Java-Standard auch für die Client-Programmierung genommen. Das optionale Erweiterungs-Package javax.sql, das die JDBC 2.0 Erweiterungen enthält, wird neuerdings mit dem normalen Java Development Kit ausgeliefert. Völlig neu sind diese Schnittstellen nicht; sie wurden vorher schon mit der Enterprise Edition gebündelt und waren auch separat als Erweiterung erhältlich. Aber mit der Aufnahme in die Standard-Version von Java sind diese Komponenten nun in jeder aktuellen Java-Umgebung vorhanden.

Die Datenbankverbindungen basieren weiterhin alle auf JDBCs. Hinzugekommen sind allerdings Objekte wie DataSource und ConnectionPoolDataSource. Damit werden Connection Pools für den Client verfügbar und ein Stichwort wie JNDI – das Java Naming and Dirctory Interface – gewinnt Aktualität auch für Java-Standardanwendungen.

Will man maximale Plattformunabhängigkeit für seine Anwendungen sicherstellen (gerade deshalb entscheidet man sich ja oft genug für Java), dann erfordert dies insbesondere im Bereich der Verbindung zur Datenbank sorgfältigen Umgang mit den Möglichkeiten der Programmiersprache.
Java stellt für die Verbindung zur Datenbank die Schnittstellen – so genannte Interfaces – zur Verfügung. Die zugehörigen Implementierungen – die Java-Klassen – werden von anderen, meist den Datenbankherstellern geliefert. Für die iSeries zum Beispiel ist das vor allem IBM mit dem Toolbox-Treiber und dem so genannten native Treiber. Die eigentliche Kunst des Programmierers besteht nun darin, den konkreten Treiber erst zur Laufzeit bekannt zu geben oder ihn in einer leicht zu verteilenden Konfiguration zu hinterlegen. Der Austausch eines Treibers soll keine Programm-Änderungen nötig machen.

Verwendung von DriverManager

Die elementarste Verbindung zur Datenbank mittels JDBC erfordert zwei Schritte. Die Registrierung des Treibers erfolgt bei selbst registrierenden Treibern (diese Fähigkeit besitzen fast alle Treiber) durch Aufruf von Class.forName(), wobei der Name des Treibers als Parameter übergeben wird. Die Methode forName der Klasse class erzeugt dabei per Reflection, wie man das in Java nennt, ein Objekt der Treiberklasse; dabei wird der Konstruktor des Treibers aufgerufen, der die Registrierung erledigt. Die Verbindung selber wird durch DriverManager mit dem Aufruf der Methode getConnection() hergestellt. Als Parameter reicht hier ebenfalls wieder eine Zeichenkette aus, der die URL – die Adresse der Datenbank – enthält.

	Connection con;
	private void connect() 
	{
		String url = "jdbc:as400://MyAs400/MyLib";
		try 
		{
			Class.forName("com.ibm.as400.access.AS400JDBCDriver");
			con = DriverManager.getConnection(url);
		}	
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}

Bei dieser Vorgehensweise können alle datenbankspezifischen Bestandteile extern in einer Property-Datei hinterlegt werden und von dort zur Laufzeit eingelesen werden. Die URL kann dann noch alle Treibereinstellungen als Erweiterungen enthalten. Details hierzu kann man der Dokumentation des jeweiligen Treibers entnehmen.

Dieses Verfahren ist auf einzelne Datenbankverbindungen ausgerichtet, die über einen längeren Zeitraum benötigt werden und über die in erster Linie gelesen werden soll. Für Web Anwendungen ist dies eher untypisch, hier werden häufig sehr viele Verbindungen immer nur für eine Benutzer-Transaktion benötigt. Auch beim Schreiben in Datenbanken vereinfacht sich das Transaktions-Handling entscheidend, wenn man für jede Datenbanktransaktion eine eigene Connection verwendet, womit man auch in diesem Fall bei sehr vielen Verbindungen sowie bei kurzer Dauer landet.

Verwendung eines Connection Pools

Die Erstellung einer Datenbankverbindung ist für den Datenbank-Server eine relativ aufwändige Operation – sowohl was die Verarbeitungszeit als auch die verbrauchten Ressourcen betreffen. Der Zeitbedarf zur Herstellung einer Datenbankverbindung liegt auf der iSeries im Bereich von Zehntelsekunden, während die Zugriffszeiten im bereich von Millisekunden liegen. Wird nur eine einzelne Benutzertransaktion über eine Verbindung bedient, dann ist der Verwaltungsaufwand für die Erstellung und Beendigung der Verbindung höher als die eigentlich geleistete Arbeit, was sogar die Skalierbarkeit einer Anwendung beeinträchtigen kann.

Der Lösungsweg, der hier in Java-Anwendungen eingeschlagen wurde, besteht im Offenhalten von nicht mehr benötigten Verbindungen zur Wiederverwendung – sozusagen Recycling unverbrauchter, bereits verwendeter Datenbankverbindungen. Diese Aufgabe wird von einem eigenen Spezialisten – einem Connection Pool – übernommen.

Solche Pools sind meist in Applikations-Servern wie WebSphere, Tomcat und JBoss enthalten, sind aber auch als Open Source-Komponenten verfügbar oder werden sogar schon mit manchem JDBC-Treibern angeboten.

Ein Baukasten für einen einfachen, leicht einzusetzender Connection Pool ist als Open Source bei SourceForge (http://sourceforge.net/projects/c3p0) erhältlich.

Am einfachsten lässt sich so ein Connection Pool über eine eigene Klasse verwenden, die dann eine Methode getConnection() enthält, die immer dann aufgerufen wird, wenn in der Applikation eine Verbindung zur Datenbank benötigt wird. In Java nennt man so was dann eine Factory – also eine Fabrik zur Herstellung von Datenbankverbindungen. Damit man nicht für jede Datenbankverbindung eine neue Fabrik baut, sorgt man dafür, dass es nur eine Fabrik geben kann und macht aus dieser Klasse einen Single-Ton. Besonders einfach geht das, indem man alles “static” macht.

Unsere kleine Datenbankfabrik bedient sich nun des Open Source Frameworks, um die Datenbankverbindungen in einem Pool zu verwalten. Wir erstellen uns eine ComboPooledDataSource, geben dieser dann unseren Treiber und die URL der Datenbank bekannt. Anschließend werden lediglich ein paar Einstellungen an dem Pooling-Mechanismus vorgenommen und kurz darauf ist die eigentliche Arbeit bereits erledigt.

import javax.sql.*;
import com.mchange.v2.c3p0.*; 

public class Pool
{
	private static DataSource ds;
	static
	{
		String url = "jdbc:as400://MyAs400/MyLib" 
			+ "user=MyUser; password=MyPassW;"
			+ "extended dynamic=true;"
			+ "package=MyPkg;package library=Mylib;"
			+ "package criteria=SELECT;"
			+ "package cache=true";
		ComboPooledDataSource cpds = new ComboPooledDataSource(); 
		try
		{
			cpds.setDriverClass(DRIVER);
			cpds.setJdbcUrl(url);
			cpds.setUser(USER);
			cpds.setPassword(PASSWORD);
			cpds.setMaxPoolSize(30);
			cpds.setMaxStatements(180);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		ds = cpds;
	}
	public static Connection getConnection()
	throws SQLException
	{
		return ds.getConnection();
	}
}

Die kompletten benötigten Komponenten des Pools sind in einem einzigen Java-Archiv enthalten, das im Classpath gefunden werden muss. Die Erstellung von Connections mit diesem Pool reduziert sich anschließend auf den Aufruf der statischen Methode getConnection() des Pools.
Wird die Connection von der Applikation nicht mehr benötigt, wird einfach die close()-Methode der Connection aufgerufen, die aber die Verbindung dann nicht wirklich schließt, sondern die Connection an den Pool zurückgibt, der diese dann zur Wiederverwendung aufrecht erhält. Der Pool hält auch preparedStatements in seinem Cache, so dass sogar reine Client-Anwendungen von dem Einsatz dieses Pools profitieren können, selbst wenn sie nur eine Verbindung benötigen. Selbstverständlich müssen beim Einsatz eines Pools alle Datenbankverbindungen mit demselben Benutzer an die Datenbank verbinden.

Im obigen Beispiel ist auch zu sehen, dass die eigentliche Verbindung zur Datenbank über eine DataSource und nicht über DriverManager hergestellt wird. Dieses Interface gehört auch zu den Neuerungen in Java bezüglich JDBC.

DataSource zur Erstellung von Datenbankverbindungen

Unangenehm und fehlerträchtig war bisher die Einstellung des Treibers über Erweiterungen der URL. Zudem gibt es hier viele Unterschiede von Treiber zu Treiber. Mit der Einführung des Interfaces DataSource – zunächst nur für die Java Enterprise Edition – wurde dann für die Erstellung von Connections ein eigener Standard für ein Factory-Objekt definiert, sozusagen einem Spezialisten, der die Verbindung zur Datenbank übernimmt.

Seit dem JDBC-Standard 2.0 werden Implementierungen für das Interface DataSource von den Treiber-Lieferanten angeboten. Für den Toolbox-Treiber wird diese Erweiterung universell angeboten. Die Erstellung und Verwendung einer DataSource erfolgt nun minimal mit wenigen Anweisungen.

	AS400JDBCDataSource ds = new AS400JDBCDataSource(SYSTEM);
	ds.setUser(USER);
	ds.setPassword(PASSWORD);
	Connection con = ds.getConnection();

Nun lassen sich zwar alle gewünschten Einstellungen des Treibers komfortabel und sicher mit spezifischen Methoden vornehmen, aber die Treiber-Unabhängigkeit ist verloren gegangen, wenn man dies in die Anwendung selbst verlagert. Man hat also mit der Lösung eines Problems ein neues erkauft.

Im Bereich von Server Java hat man dieses Problem mit der Verlagerung der Tätigkeit der Erstellung einer DataSource in die Konfiguration des Applikations-Servers gelöst und mittlerweile lassen sich diese Einstellungen auch relativ handhabbar in dem jar-Archiv der Applikation mitverteilen.
Für Client-Anwendungen und alle anderen, die keinen Applikations-Server verwenden, lassen sich allerdings dieselben Mechanismen benutzen, die hier für die Applikations-Server in den Java-Standard aufgenommen wurden. Hier lassen sich zwar auch Einstellungen für die JVM konfigurieren, allerdings nicht so leicht automatisch verteilen. Und beim Wechsel der Java-Version müssten diese Einstellungen dann angepasst werden.

Es gibt aber auch weitere Möglichkeiten, diese Probleme zu lösen. Wenn man denn nun auch dort DataSources benutzen will (das wird in Zukunft unumgänglich werden) und wenn man alle Möglichkeiten des Treibers weiter ausschöpfen will, dann muss man sich mit den erforderlichen Techniken vertraut machen.

Das Java Naming und Directory Interface

JNDI ist seit Java Version 1.4.1 ebenfalls im Standard verfügbar und war bis dahin der Server-Variante Enterprise Edition vorbehalten. Wie bei einigen anderen javax Erweiterungs-Packages müssen die entsprechenden Implementierungen anderweitig zur Verfügung gestellt werden. Diese Lücke schließen die entsprechenden Applikations-Server. Für unsere Zwecke reicht aber bereits die Unterstützung von Java 1.4.1 plus das frei verfügbare Paket JNDI 1.2.1 & More von Sun aus, das die beiden Archive fscontext.jar und provideutil.jar liefert, die im Classpath mit enthalten sein müssen.

JNDI stellt einen standardisierten Weg bereit, in Java-Applikationen Ressourcen beinahe jeglicher Art zur Verfügung zu stellen und darauf zuzugreifen. JNDI setzt auf den unterschiedlichsten Schichten auf und stellt damit eine Brücke zu LDAP, CORBA, aber auch zu dem lokalen File-System und anderen Diensten dar.

Unsere verwendeten und oben erwähnten Klassen gehen den einfachsten Weg und setzen auf dem lokalen File-System auf. Wir erstellen uns in einem kleinen Java-Programm eine DataSource aus unserer Toolbox-Implementierung und legen diese anschließend über JNDI lokal ab. Die entsprechenden Voraussetzungen – nämlich die Implementerung der beiden Schnittstellen Referenceable und Serializable – bringt die AS400JDBCDataSource mit.

Zur Verwendung von JNDI-Funktionen muss vorbereitend ein so genanntes Context-Objekt erstellt werden, dem dann mitgeteilt wird, wer später die Klasse erstellen soll, die das Ablegen und Holen von Objekten erledigt. In unserem Fall ist das dann die RefFSContextFactory aus dem package com.sun.jndi.fsciontext.

import com.ibm.as400.access.*;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;

public class SetupJndiJDBC 
{
	public static void main(String[] args) 
	{
		try
		{
			Hashtable env = new Hashtable();
			env.put(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.fscontext.RefFSContextFactory"); 
			Context ctx = new InitialContext(env);
			
			AS400JDBCDataSource ds = new AS400JDBCDataSource(”MySystem”);
			ds.setUser(“MyUser”);
			ds.setPassword(“MyPassW”);
			ds.setSavePasswordWhenSerialized(true);

			ctx.rebind("jdbc/myAS400DS", ds);
			System.out.println("rebind myAS400DS success");
		}
		catch(Exception e)
		{
			System.out.println(e);
		}
	}	
}

Nachdem die Erstellung des Context erledigt ist, wird die gewünschte DataSource erstellt. Ich beschränke mich hier auf das Minimum und stelle für die DataSource nur den Datenbank-Server, den Benutzer und das Kennwort ein und belasse es ansonsten bei den Default-Werten. Im richtigen Leben wird man dies dann um die spezifischen Einstellungen des Treibers ergänzen, die man der Javadoc der DataSource entnehmen kann.

Die letzte Einstellung mittels setSavePasswordWhenSerialized() verhindert, dass bei späterer Verwendung der DataSource eine Kennwortabfrage irgendwo ins Nirwana gesendet wird.
Mit dem Aufruf der Context-Methode rebind wird die soeben erstellte DataSource über JNDI unter dem Namen jdbc/myAS400DS abgelegt. In diesem Programm sind nun alle Treiber-Abhängigkeiten gekapselt, und die einmalige Ausführung dieses Programms stellt diese DataSource dann zur späteren Verwendung bereit.

import java.sql.*;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class TestConnectDs 
{
	public static void main(String[] args) 
	{
		try
		{					
			Hashtable env = new Hashtable();
			env.put(Context.INITIAL_CONTEXT_FACTORY,
			 "com.sun.jndi.fscontext.RefFSContextFactory"); 
			Context ctx = new InitialContext(env);
			
			DataSource ds = (DataSource) ctx.lookup("jdbc/myAS400DS");

			Connection con = ds.getConnection();
			// snip
			}
		}
		catch(Exception e)
		{
			System.out.println(e);
		}
	}	
}

Braucht man nun in einem Java-Programm eine Connection, so erstellt man sich wieder einen entsprechenden Context, holt sich die auf Platte gespeicherte DataSource über JNDI und lässt sich von dieser Factory nun eine Connection erstellen. Selbstverständlich muss das über JNDI geholte Objekt anschließend noch passend gecasted werden. In unserem Fall ist es wichtig, nur auf das Standard-Interface DataSource zu casten und nicht in den ebenfalls möglichen Originaltyp zu wandeln, dann hätten wir ja wieder die Treiber-Abhängigkeit im Programm.

In der Applikation wird nun, wie im Beispiel zu sehen, auf die Datenbank nur über den JNDI-Namen zugegriffen und alle Treiber-Abhängigkeiten sind in der DataSource gekapselt. Zum Wechsel des Treibers oder der Einstellung muss eine neue oder geänderte DataSource erstellt werden, die dann wieder über JNDI unter einem Namen abgelegt wird.

Auf diese Art lässt sich auch die im Connection Pool-Beispiel verwendete DataSource über JNDI ablegen. Hierzu werden lediglich die Statements zur Erstellung der DataSource gegen die entsprechenden Statements aus dem Beispiel mit dem Pool ausgetauscht und die Importe entsprechend abgeändert.
Bei der Verwendung dieser DataSource wird dann ein Connection Pool verwendet, ohne dass die Applikation dies überhaupt bemerkt. Legt man diese DataSource mit JNDI unter einem eigenen Namen ab, so kann man je nach Anforderung verschiedene Treiber und Einstellungen ansprechen.

Der Apache Connection Pool

Der bereits vorgestellte Connection Pool von Steve Waldmann ist konkurrenzlos einfach zu verwenden und hat eigentlich alles, was man braucht – inklusive Statement Cache für prepared Statements. Er liegt aber bisher leider erst als Beta Release vor und das, obwohl dieses bereits einen gut ausgereiften und stabilen Eindruck macht. Weiter in der Entwicklung, sicher auch weiter verbreitet und mit mehr Entwickler-Unterstützung versehen, dürfte der ebenfalls als Open Source angebotene Connection Pool von Apache sein. Apache ist wohl jedem ein Begriff – angefangen vom gleichnamigen Web Server, von Tomcat sowie von weiteren Open Source-Bausteinen höchster Qualität.

Der Pool DBCP gehört zur Abteilung Commons des Apache-Projekts jakarta (http://jakarta.apache.org/commons/dbcp) und erfordert zwei weitere Open Source-Pakete von Apache – ebenfalls aus der Abteilung Commons. Der Pool (http://jakarta.apache.org/commons/pool) stellt die Grundlagen für allgemeine Object Pools bereit und Collections (http://jakarta.apache.org/commons/collections) liefert ein paar Hilfsklassen. Mit den Internas dieser Pakete muss man sich nicht befassen, lediglich die Archive commons-collections-3.0.jar, commons-dbcp-1.1.jar und commons-pool-1.1.jar werden im Classpath benötigt.

Der Apache Connection Pool kann in alle gängigen Applikations-Server eingebunden werden; zu den Konfigurationseinträgen in den Dateien server.xml und web.xml befinden sich Hinweise in der Dokumentation des Treibers. Die manuelle Einbindung in JNDI ist etwas problematisch, es bleibt aber noch der Weg über ein eigenes Connection Pool-Objekt mit einer statischen getConnection()-Methode übrig – ähnlich wie in einem vorhergehenden Beispiel.

An dieser Stelle zeigt sich, dass der vorher besprochene Open Source Pool durchaus sogar Vorteile gegenüber dem Pool von Apache hat und im Bereich von Client Java erste Wahl sein könnte.

import javax.sql.DataSource;
import java.sql.*;
import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS;
import org.apache.commons.dbcp.datasources.SharedPoolDataSource;

public class PoolStatement
{
	private static DataSource ds;

	static
	{
		String url = "jdbc:as400://MySystem/MyLib;"
			+ "user=MyUser;password=MyPaasW;”
			+ "extended dynamic=true;"
			+ "package=MyPac;package library=MyLib;"
			+ "package criteria=SELECT;"package cache=true";

		DriverAdapterCPDS cpds = new DriverAdapterCPDS();
		cpds.setUrl(url);
		cpds.setPoolPreparedStatements(true);
		cpds.setMaxActive(100);
		try
		{
			cpds.setDriver(DRIVER); 
		}
		catch(ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		SharedPoolDataSource tds = new SharedPoolDataSource();
		tds.setConnectionPoolDataSource(cpds);
		tds.setMaxActive(0);
		tds.setMaxWait(50);

		ds = tds;
	}

	public static Connection getConnection()
	throws SQLException
	{
		return ds.getConnection();
	} 
}

Im ersten Schritt wird der eigentlich verwendete Treiber in eine Adapterklasse eingepackt, die als wesentliche Eigenschaft das Interface ConnectionPoolDataSource implementiert. Diese Zwischenschicht hat in erster Linie die Aufgabe, dafür zu sorgen, dass ein Aufruf von close() für die Connection diese nicht wirklich schließt, sondern lediglich an den Pool zurückgibt.

Diesen Zweck würde auch die entsprechende Toolbox-Klasse AS400JDBCConnectionPoolDataSource erfüllen. Ich habe mich aber hier gegen die Toolbox entschieden, da das hier verwendete Objekt aus dem Apache Framework nicht nur universeller verwendbar, sondern auch leistungsfähiger ist. Hierdurch werden Treiber-Abhängigkeiten umgangen und Pooling von preparedStatements ermöglicht.
Im nächsten Schritt des static-Abschnitts wird dann eine SharedPoolDataSource erstellt, die als wesentliche Eigenschaft das Interface DataSource umfasst. Dieses Objekt kapselt nunmehr über die erste erstellte ConnectionPoolDataSource den eigentlich verwendeten JDBC-Treiber. Die einzige Methode der Connection Pool-Klasse ist static, und getConnection() liefert eine Verbindung aus dem systemweiten Connection Pool zurück.

Vorteile eines Connection Pools

Für welchen der skizzierten Wege man sich auch immer entscheidet, man sollte einem Connection Pool in der Regel den Vorzug geben gegenüber den mit DriverManager erstellten Datenbankverbindungen. Phänomenale Geschwindigkeitsvorteile, wie sie manchmal genannt werden, sollte man allerdings nicht erwarten.

Wenn die Datenbankzugriffsschicht zu langsam ist, hat das so gut wie immer andere Ursachen. Hauptsächlich verantwortlich ist hier, dass die Anzahl der Lesezugriffe unnötig groß ist, dass im Datenbank-Design Mängel vorhanden sind oder dass Zugriffspfade fehlen. Der Wechsel der Technik der Datenbankverbindung oder des Connection Pools wirkt sich stärker auf die Skalierbarkeit aus als auf die Geschwindigkeit. Es wird schneller, bleibt aber zumeist unter der direkten Messbarkeit durch den Endanwender.

Bei der Verwendung eines Applikations-Servers ist die Verwendung einer DataSource, die ihrerseits die Connections in einem Pool verwaltet, vorzuziehen. Die DataSource wird dann in der server.xml und in der web.xml konfiguriert und in der Anwendung über JNDI lokalisiert.

Für reine Java Anwendungen, die keinen Applikations-Server benötigen, kann man die JNDI-Variante wählen, wenn der Pool dies ermöglicht oder wenn eine eigene Pool-Klasse verwendet wird. In jedem Fall sollte man alle Abhängigkeiten von Pool und Treiber in eine einzige Klasse kapseln. Die Datenbankzugriffsschicht, geschweige denn die Anwendung darf nicht sehen, wie und an welche Datenbank verbunden wird.

	String prep = "INSERT INTO TEST VALUES( ?, ?, ?, ?)";
	Connection con = Pool.getConnection();
	PreparedStatement stmt = con.prepareStatement(prep);
	stmt.setInt(1, 1);
	stmt.setString(2, "Hugo");
	stmt.setString(3, "Hühnerkopf");
	stmt.setString(4, "Frankfurt");
	if(stmt.execute())
		con.commit();
	else
		con.rollback();
	stmt.close();
	con.close();

Bei der Verwendung eines Pools wird jetzt für jede Transaktion eine eigene Connection vom Pool geholt. Nach der Verwendung werden die close()-Methoden aufgerufen, um die Objekte an den Pool zurückzugeben. Dieser kümmert sich dann darum, die Datenbankverbindungen zu überprüfen, gegebenenfalls zu erneuern und auf Anforderung wieder zur Verfügung zu stellen. Die Details sind für die einzelnen Pools einstellbar über Methodenaufrufe und Konfigurationen.

Zu achten ist bei der Verwendung eines Connection Pools auch noch, nichts an den Connections zu ändern, was für andere Verwender schädlich wäre – d. h. also, nicht das Sperrverhalten ändern, nicht den Benutzer oder das Default-Schema wechseln. Dies sind allerdings alles Dinge, die in Java-Anwendungen ohnehin fehl am Platze sind.

In einigen exotischen Fällen kann die Verwendung eines Connection Pools sogar schädlich sein. Wenn man zum Beispiel für eine JVM nur einen Datenbank Connect benötigt, dann ist ein Pool in jedem Fall schädlich. Das kann zum Beispiel bei Batch-artigem Workload der Fall sein. Zu überlegen ist in solchen Fällen allerdings, die Anwendung in einen Server-Dienst umzustrukturieren, wie dies für Java eher typisch ist.

Werden auf einer iSeries zahlreiche JVMs gestartet, was bei der Verwendung von direkten Java-Aufrufen aus RPG keine Seltenheit ist, dann ist von einem Connection Pool ebenso abzuraten. Aber auch hier gilt, dass die eigentliche Ursache in einem Design liegt, das sich nicht an den Möglichkeiten von Java orientiert, sondern altes (prozedurales) Denken widerspiegelt.

Bei Java Web-Anwendungen geht an der Verwendung eines Connection Pools kein Weg mehr vorbei, nicht nur weil das in allen Empfehlungen so steht. Die Programmierung der Datenbankschicht wird einfacher und die Einrichtung eines Pools und die Verteilung der Konfiguration werden von allen Applikations-Servern unterstützt.

Den Autor Dieter Bender erreichen Sie unter dieter.bender@midrangemagazin.de