Klassen dynamisch laden mit Class.forName()
Einführung
Mit Java ist das Erzeugen von Objekten einer dynamisch geladenen Klasse zur Laufzeit möglich.
Dieses Verfahren wird zum Beispiel angewandt, wenn mittels Java Database Connectivity (JDBC) auf eine relationale Datenbank zugegriffen wird. Zu den Aufgaben von JDBC gehört u.a. das Verwalten von Verbindungen zur Datenbank, das Weiterleiten von SQL-Befehlen und die Aufbereitung der Ergebnisse aus SQL-Befehlen, sodass sie in Java weiterverarbeitet werden können. Die JDBC-Schnittstelle bietet Zugriff auf Datenbanken verschiedener Hersteller und ist nicht an eine bestimmte Datenbankart gebunden. Damit ist der Hersteller in der Pflicht, Treiber für sein Datenbanksystem bereitzustellen, welche die JDBC-Spezifikation implementieren. Diese entsprechenden Treiber werden im Klassenpfad der Anwendung abgelegt und mit Class.forName() zur Laufzeit geladen.
Ein weiteres Beispiel wäre, eine Art „Plug-In“-System: Wenn die Klasse dynamisch geladen wird, besteht die Möglichkeit, deren entsprechende Funktionalität zu ändern und die neue Version im Klassenpfad abzulegen. Beim nächsten Laden der Klasse, wird die neue Version geladen, ohne dass die komplette Anwendung neu deployt werden musste.
Die Meta-Klasse „Class“ – Ein wenig Theorie
Objekte der Klasse Class können (eingeschränkt) als Meta-Objekte bezeichnet werden, denn sie stellen alle Informationen einer Klasse zur Verfügung, die sie repräsentieren. Jede Klasse ist innerhalb der Java Virtual Machine (JVM) eindeutig einem Class-Objekt zugeordnet. Diese Eindeutigkeit ist zum Beispiel wichtig für die Synchronisation von Threads. Class-Objekte können nicht durch den Entwickler erzeugt werden, sie werden automatisch von der JVM erstellt.
Mit Class-Objekten kann man
- Klassen dynamisch in die JVM laden
- Den vollständigen Klassennamen eines Objektes ermitteln (getName())
- Verschiedenste Informationen über das repräsentierte Objekt ermitteln (getMethods(), getFields(),…). Dieses Verhalten wird als Reflection bezeichnet.
- Ein neues Objekt des repräsentierten Objekts erstellen
- Oberklassen ermitteln
In diesem Artikel liegt der Fokus auf dem dynamischen Laden von Klassen. Daher soll an dieser Stelle die Methode forName() etwas näher erläutert werden.
Die Methode "Class.forName()"
Der Aufruf der Methode Class.forName("x") lädt die Klasse "X" dynamisch zur Laufzeit. Das heißt, die Klasse wird von der JVM geladen und der statische Initalisierer der Klasse wird aufgerufen. Ein Beispiel:
Klasse DynamicClass (wird dynamisch geladen)
package com.ulc.jnotes.demo;
class DynamicClass
{
public DynamicClass()
{
System.out.println("Constructor: DynamicClass");
}
static
{
System.out.println("Static: DynamicClass");
}
}
Hauptprogramm
public class Program
{
public static void main(String[] args)
{
try
{
Class c = Class.forName("com.ulc.demo.jnotes.DynamicClass");
DynamicClass dClass = (DynamicClass) c.newInstance();
}
catch (ClassNotFoundException e)
{
…
}
catch (InstantiationException e)
{
…
}
catch (IllegalAccessException e)
{
…
}
}
}
Ausgabe
Static: DynamicClass Constructor: DynamicClass
XPages mit JDBC verdrahten – Ein Beispiel
Um beispielsweise ein RepeatPanel auf einer XPage mit Daten aus einer relationalen Datenbank zu befüllen, sind folgende Schritte nötig:
Zunächst wird eine ManagedBean benötigt, die sich um den Datenbankzugriff und die Datenbindung an die XPage kümmert. Wie sie eine ManagedBean im Domino Designer erstellen erfahren Sie hier.
Neben der Datenbindung wird eine Methode zum Auslesen von Daten aus der SQL-Datenbank benötigt.
public void executeSqlQuery() throws SQLException
{
PreparedStatement stmt = null;
Connection conn = null;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@192.168.6.102:1521:xe";
String queryString = "SELECT username FROM usertable WHERE username = ?";
String username = "TestNutzername";
conn = DriverManager.getConnection(url, "DBUser", "123456");
stmt = conn.prepareStatement(queryString);
stmt.setString(1, username);
ResultSet rset = stmt.executeQuery();
while (rset.next())
{
// daten weiterverarbeiten
}
stmt.close();
conn.close();
}
catch (ClassNotFoundException cfEx)
{
cfEx.printStackTrace();
}
catch (SQLException sqlEx)
{
sqlEx.printStackTrace();
}
finally
{
if(stmt != null)
stmt.close();
if(conn != null)
conn.close();
}
}
Mit der Anweisung Class.forName("oracle.jdbc.driver.OracleDriver"); wird die JVM angewiesen, im Klassenpfad nach einem passenden Treiber (genauer: einer passenden Klasse) zu suchen und den statischen Initialisierungsteil auszuführen. In diesem Initialisierungsteil registriert sich der Treiber in der JVM. Es muss also kein eigenes Objekt erzeugt werden.
Der Rest ist reines JDBC. Eine Verbindung mit der Oracle-Datenbank wird hergestellt, eine SQL-Abfrage ausgeführt und das Ergebnis kann weiterverarbeitet werden und zum Beispiel innerhalb der Bean an eine Methode gebunden werden, die wiederum vom RepeatPanel aufgerufen wird.
Einige Klassen für Datenbanktreiber:
|
DB2/Derby
|
com.ibm.db2.jcc.DB2Driver
|
|
Oracle
|
oracle.jdbc.driver.OracleDriver
|
|
mSQL
|
com.imaginary.sql.msql.MsqlDriver
|
|
MySQL
|
com.mysql.jdbc.Driver4
|
|
Borland JDataStore
|
com.borland.datastore.jdbc.DataStoreDriver
|
|
Borland Interbase
|
interbase.interclient.Driver
|
|
Adabas D
|
de.sag.jdbc.adabasd.ADriver
|
|
SYBASE ASE
|
com.sybase.jdbc.SybDriver
|
|
IDS Server
|
ids.sql.IDSDriver
|
Dynamisches Laden von Klassen mit der JVM des Domino-Servers 8.5.2
Mit Domino 8.5.2 und höher hat IBM die Sicherheitsrichtlinien überarbeitet, so dass der vorliegende Code nicht mehr fehlerfrei funktioniert. Standardmäßig ist das dynamische Laden von Klassen am Domino Server deaktiviert. Sollten Sie folgende Fehlermeldung bekommen:
Müssen Sie in der Datei „...\Lotus\Domino\jvm\lib\security\java.policy“ folgenden Eintrag hinzufügen:
Abgelegt unter:
Bewerten Sie diesen Artikel:

Senden Sie einen Kommentar