> Inhalt: Einführung in das Programmieren mit Java > Inhalt: Einführung in das Programmieren von Enterprise Java Beans |
|
Letzte
Bearbeitung dieses Dokuments: |
Voraussetzungen für das Verständnis dieses Dokuments:Grundkenntnisse in der Programmierung von Java (Klassen, Methoden, Schleifen) oder anderer Objekt-Orientierter Programmiersprachen (z.B. C++, Modula-2, Pascal). Kenntnisse im Umgang mit Eclipse; empfohlen ist das Durcharbeiten der Einführungsbeispiele für das Programmieren mit Java. |
Ungefährer Zeitbedarf zum Durcharbeiten dieses Dokuments:Arbeitszeit:
|
Dieses
Dokument enthält die Anleitungen zum Codieren der Session Bean
mit Datenbank-Zugriff.
Die Struktur der Klassen mit dem Java-Code
und der Konfigurationsdateien ist gleich wie schon im Tutorial:
Einfache Session Bean, EJB3Standard (Java_EJB_05) – Codieren
beschrieben.
Zusätzlich
wird in diesem Tutorial die Verwendung einer 'Datasource' – in
diesem Fall die Verbindung zu einer Datenbank – erklärt.
Ziel ist, eine minimale 'Chat'-Anwendung zu implementieren; anschließend ist eine kurze Erklärung der Funktionalität.
Dabei
werden die Attribute für einen 'Chat'-Beitrag (Timestamp der
Erstellung, TCP/IP-Adresse des Erstellers und Text des Beitrags) in
einer eigenen Klasse definiert – diese Klasse stellt dann ein
'Business-Object' (BO) dar.
Dieses BO wird zwischen dem EJB und
den Client-Programmen übertragen.
Für
die Übertragung eines kompletten Objekts mit mehreren Variablen
– wo bei die Variablen wieder Objekte einer individuell
definierten Klasse sein können – wird das Java-eigene
Übertragungsprotokoll 'RMI' (Remote Management Invocation)
genützt.
Kommerzielle JAS (Java Application Server) bieten
auch eigene Übertragungsprotokolle mit integrierter
Verschlüsselung der übertragenen Daten.
Welches
Übertragungsprotokoll letztendlich verwendet wird ist beim
Entwickeln der Geschäftslogik nicht von Bedeutung weil auf der
Client-Seite durch eine Konfigurationsdatei festgelegt wird welche
Bibliothek (JAR-Datei die mit dem JAS ausgeliefert wird) für das
Übertragungsprotokoll verwendet wird.
Das wird detailliert im
Dokument Tutorial:
Client-Programm für Session Bean mit Datenbank-Zugriff,
EJB3-Standard (Java_EJB_08) beschrieben.
Die Werte in den Attributen des BO sind auch die Werte die auf der Datenbank gespeichert bzw. von der Datenbank gelesen werden.
Vorigerer Schritt: Einrichten des Projects
Entsprechender Tutorial-Schritt für die frühere Version (vor EJB3-Standard)
Vorbemerkung
und Funktion des Codes
Vorbedingungen
Class
Chat_BO
mit
den zu übertragenden Werten erstellen
Interface
ChatManagementBeanLocal
mit
den Methoden, für die ein Zugriff innerhalb des JAS erlaubt ist,
erstellen
Interface
ChatManagementBeanRemote
mit
den Methoden, für die ein Zugriff von Client-Programmen
außerhalb des JAS erlaubt ist, erstellen
Class
ChatManagementBean
mit
den Implementierungen der Methoden erstellen
Gesamter
Code am Ende des Schrittes
Datei
Chat_BO.java
Datei
ChatManagementBeanLocal.java
Datei
ChatManagementBeanRemote.java
Datei
ChatManagementBean.java
Weitere Schritte und verwandte Dokumentation
Nächster Schritt: Packen der Dateien in Java-Archive (JAR) und 'deploy'
Wenn
Sie vor der Aufgabe stehen, Code für ältere EJBs adaptieren
zu müssen und die passende Anleitung dafür suchen dann
beginnen Sie bitte mit
Tutorial:
Session Bean mit Datenbank-Zugriff (Java_EJB_03) – Einrichten
des Projects.
Das
äquivalente Dokument für Code-Muster ist Tutorial:
Session Bean mit Datenbank-Zugriff (Java_EJB_03) –
Codieren.
Zusätzlich
brauchen Sie noch die Kenntnisse aus dem Schritt Tutorial:
Session Bean mit Datenbank-Zugriff (Java_EJB_03) –
XDoclet-Anweisungen – die
Tätigkeiten dieses Schrittes entfallen bei der Entwicklung nach
EJB3-Standard
Ein
Session-Bean wird mit einer Methode ausgestattet, die eine Verbindung
zur Datenbank (Connection-Handler) aufbaut.
Über diese
Verbindung können SQL-Kommandos auf die Datenbank abgesetzt
werden.
Weitere Methoden des Session-Bean erlauben das Speichern eines Textes (gemeinsam mit Datum/Uhrzeit des Eintrages und der TCP/IP-Adresse des Client-Computers, auf dem der Text erfaßt wurde) und das Abrufen einer gewünschten Zahl der neuesten 'Chat'-Einträge in der Datenbank-Tabelle
In
diesem Tutorial wird:
* Eine Klasse erstellt, die das
Chat-Business-Object (Chat_BO) mit allen Attributen
darstellt.
Dieses Business-Object transferiert
die Daten zwischen dem EJB und dem Client-Programm.
* Eine
Klasse, die die Verbindung zur Datenbank herstellt und die
Datenbank-Operationen ausführt.
Diese
Klasse enthält folgende Methoden:
** Aufbau der
Verbindung zur Datenbank (Connection Handler).
** Übernahme
eines Business-Objects vom Client-Programm und speichern der Werte
auf der Datenbank-Tabelle.
** Lesen einer gewünschten
Anzahl der neuesten Einträge auf der Datenbank-Tabelle und
zurückliefern einer Liste mit
Business-Objects mit den gelesenen Einträgen.
Dieses
Beispiel wurde gewählt weil:
* Das Konzept des
'Business-Objects' in einfacher Form vorgestellt werden kann.
* Ein
Bean mit einer 'privaten' Methode (Datenbank-Verbindung herstellen)
vorgestellt wird.
* Die Methoden für die
Datenübertragung vom/zum Client-Programm das Business-Object
bzw. eine Liste von Business-Objects verwenden.
Wie
schon im Einfachen Session Bean (siehe Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren)
gezeigt sind die Methoden des EJB die von einer Methode eines
Client-Programms aufgerufen werden dürfen ist in einer
Java-Interface-Datei (in diesem Beispiel
ChatManagementBeanRemote.java)
festgelegt.
Falls Methoden in dem EJB nicht von einem
Client-Programm, aber von einer anderen Methode innerhalb des
gleichen Java Application Servers (JAS) aufgerufen werden dürfen,
sind diese erlaubten Methode ebenfalls in einer Java-Interface-Datei
(in diesem Beispiel ChatManagementBeanLocal.java)
definiert.
Schritt 1: Einrichten des Projects ausgeführt – und dessen Vorbedingungen auch.
Das
Eröffnen einer (Java-) Klasse wurde im Detail und mit
Abbildungen bereits unter
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren >
Class ShowTimeDateBean mit den Implementierungen der Methoden
erstellen
beschrieben.
Aus
diesem Grund beschränkt sich die folgende Anleitung auf
Stichworte.
Um eine neue Java-Klasse zu eröffnen wird mit der rechten Maustaste das Project (Java_EJB_07) angeklickt und aus dem Kontext-Menu >New >Class ausgewählt. |
|
Im darauf hin erscheinenden Fenster (New Java Class / Ohne Abbildung) wird
Die anderen bereits vorgegebenen Werte werden nicht verändert. Durch Anklicken der Schaltfläche [ Finish ] wird die Datei für den Quell-Code der Klasse angelegt. |
|
Der
Java-Code ist unter Gesamter
Code am Ende des Schrittes > Datei Chat_BO.java
dokumentiert
und kann in die geöffnete Datei kopiert werden. Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Es
folgt eine kurze Erklärung des Codes; wenn Ihre Zeit knapp ist
können Sie die Erklärung auch überspringen und gleich
mit dem Abschnitt
Interface
ChatManagementBeanLocal
mit
den Methoden, für die ein Zugriff innerhalb des JAS erlaubt ist,
erstellen
fortsetzen.
Eine
kurze Erklärung der einzelnen Teile des Codes:
import
java.sql.*;
Dieses
(Java-) Package enthält die Klassen mit den Datentypen die den
SQL-Datentypen entsprechen.
Daraus wird der 'Timestamp' als
Primärschlüssel für den Datensatz verwendet.
'Timestamp' wurde deswegen gewählt weil der Wert leicht zu
erzeugen ist und mindestens auf 1/1000 Sekunde genau ist.
Für
dieses Tutorial ist das als Primärschlüssel ausreichend
weil die Wahrscheinlichkeit, dass 2 verschiedene Client-Programme
genau den gleichen Wert erzeugen verschwindend gering ist.
import
java.io.Serializable;
Die
(Java-) Interface Serializable
enthält
einen Algorithmus, der die Klasse (die Serializable
implementiert)
für die Übertragung als 'Bitstream' geeignet macht.
Die
Aufbereitung als Kette von Bits ist notwendig wenn ein Objekt dieser
Klasse über ein TCP/IP-Netzwerk übertragen werden
soll.
Diese Anforderung ist bei diesem Tutorial gegeben weil die
Werte zwischen EJB und Client-Programm ausgetauscht werden.
public
class
Chat_BO
implements
Serializable
{
Definition
der Klasse mit der Implementierung von Serializable
.
static
final long
serialVersionUID
=
200902242039L;
Die
spezielle Variable serialVersionUID
vermeidet
ein 'Warning' des Compilers.
Zweck von serialVersionUID
ist,
Versionen von Klassen zu identifizieren wenn deren Objekte aus einem
'Bitstream' wieder 'zusammen gesetzt' werden.
Wird, zum Beispiel,
die Reihenfolge der Definition von Variablen geändert dann ist
der Aufbau der Klasse ein anderer und der serialVersionUID
muss
geändert werden.
Wird die geänderte Klasse nicht
gleichzeitig im EJB und Client-Programm eingebunden dann wird über
die verschiedenen Werte der serialVersionUID
erkannt,
dass die Werte aus dem 'Bitstream' nicht mehr passen.
Wird die
serialVersionUID
gleich
gelassen obwohl die Definition der Variablen geändert wurde
dann wird der Wert des 'Bitstream' falsch in die Variablen
übertragen weil nicht erkannt werden kann, dass der Aufbau des
'Bitstream' nach anderen Regeln erfolgt ist.
/*
* Zeitpunkt
der Eintragung in die Datenbank; gleichzeitig Primärschlüssel.
*/
public
Timestamp
Erstellt_Timestamp
=
new
Timestamp(0);
/*
* TCP/IP-Adresse
des Computers, auf dem das Client-Programm ausgeführt wurde.
*/
public
String
Erstellt_TCPIP_Adresse
=
""
;
/*
* Chat-Text;
vom Benutzer eingegeben. */
public
String
Message_Text
=
""
;
Variable
dieser Klasse; der Zweck ist bei den jeweiligen Kommentaren
beschrieben.
Das
Eröffnen einer (Java-) Interface wurde im Detail und mit
Abbildungen bereits unter
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren >
Interface
CountryConstants
mit
statischen Werten für den Input erstellen
beschrieben.
Aus
diesem Grund beschränkt sich die folgende Anleitung auf
Stichworte.
Um
ein neues Interface zu eröffnen wird mit der rechten Maustaste
das Project (Java_EJB_07) angeklickt und aus dem Kontext-Menu
>New
>Interface
ausgewählt.
Im darauf hin erscheinenden Fenster (New Java Interface) wird
Das 'Package' (js_ejb07.ejb.interfaces.local) festgelegt.
Der Name der Interface (ChatManagementBeanLocal) festgelegt.
Die anderen bereits vorgegebenen Werte werden nicht verändert.
Durch
Anklicken der Schaltfläche
[ Finish ]
wird
die Datei für den Quell-Code der Interface angelegt.
Die erstellte Datei (mit der Java-Interface) ist im 'Package Explorer' von Eclipse gelistet. |
|
Der
Java-Code ist unter Gesamter
Code am Ende des Schrittes > Datei ChatManagementBeanLocal.java
dokumentiert
und kann in die geöffnete Datei kopiert werden. Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Wenn
das importierte (Java-) Package und die 'Injection' @Local
vom
Compiler als fehlerhaft markiert werden |
Die
Struktur des Codes in dieser Interface ist gleich wie schon in
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren >
Interface
ShowTimeDateBeanLocal
mit
den Methoden, für die ein Zugriff innerhalb des JAS erlaubt ist,
erstellen
beschrieben
wurde.
Falls Sie durch Zufall auf dieses Dokument gestoßen
sind, empfehle ich zuerst mit dem Tutorial
für die Einfache Session Bean, EJB3-Standard (Java_EJB_05)
zu
beginnen.
Das
Eröffnen einer (Java-) Interface wurde im Detail und mit
Abbildungen bereits unter
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren >
Interface
CountryConstants
mit
statischen Werten für den Input erstellen
beschrieben.
Aus
diesem Grund beschränkt sich die folgende Anleitung auf
Stichworte.
Um
ein neues Interface zu eröffnen wird mit der rechten Maustaste
das Project (Java_EJB_07) angeklickt und aus dem Kontext-Menu
>New
>Interface
ausgewählt.
Im darauf hin erscheinenden Fenster (New Java Interface) wird
Das 'Package' (js_ejb07.ejb.interfaces.remote) festgelegt.
Der Name der Interface (ChatManagementBeanRemote) festgelegt.
Die anderen bereits vorgegebenen Werte werden nicht verändert.
Durch
Anklicken der Schaltfläche
[ Finish ]
wird
die Datei für den Quell-Code der Interface angelegt.
Die erstellte Datei (mit der Java-Interface) ist im 'Package Explorer' von Eclipse gelistet. |
|
Der
Java-Code ist unter Gesamter
Code am Ende des Schrittes > Datei ChatManagementBeanRemote.java
dokumentiert
und kann in die geöffnete Datei kopiert werden. Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Wenn
das importierte (Java-) Package und die 'Injection' @Remote
vom
Compiler als fehlerhaft markiert werden |
Die
Struktur des Codes in dieser Interface ist gleich wie schon in
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren >
Interface
ShowTimeDateBeanRemote
mit
den Methoden, für die ein Zugriff von Client-Programmen
außerhalb des JAS erlaubt ist, erstellen
beschrieben
wurde.
Falls Sie durch Zufall auf dieses Dokument gestoßen
sind, empfehle ich zuerst mit dem Tutorial
für die Einfache Session Bean, EJB3-Standard (Java_EJB_05)
zu
beginnen.
Class
ChatManagementBean
mit
den Implementierungen der Methoden erstellen
Das
Eröffnen einer (Java-) Klasse wurde im Detail und mit
Abbildungen bereits unter
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) – Codieren >
Class ShowTimeDateBean mit den Implementierungen der Methoden
erstellen
beschrieben.
Aus
diesem Grund beschränkt sich die folgende Anleitung auf
Stichworte.
Um
eine neue Java-Klasse zu eröffnen wird mit der rechten Maustaste
das Project (Java_EJB_07) angeklickt und aus dem Kontext-Menu
>New
>Class
ausgewählt.
Im darauf hin erscheinenden Fenster (New Java Class / Ohne Abbildung) wird
Das 'Package' (js_ejb07.ejb.beans) festgelegt.
Der Name der Klasse (ChatManagementBean) festgelegt.
Folgende
Auswahl-Möglichkeiten werden nicht markiert:
[ ] public
static void main(String[] args)
[ ] Constructors
from superclass
[ ] Inherited abstract
methods
Die anderen bereits vorgegebenen Werte werden nicht verändert.
Durch
Anklicken der Schaltfläche
[ Finish ]
wird
die Datei für den Quell-Code der Klasse angelegt.
Die erstellte Datei (mit der Java-Klasse) ist im 'Package Explorer' von Eclipse gelistet. |
|
Der
Java-Code ist unter Gesamter
Code am Ende des Schrittes > Datei ChatManagementBean.java
dokumentiert
und kann in die geöffnete Datei kopiert werden. Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Wenn
das importierte (Java-) Package und die 'Injectiron' @Stateless
vom
Compiler als fehlerhaft markiert werden |
Es
folgt eine kurze Erklärung des Codes mit dem eine 'Data-Source'
definiert wird und Abfragen auf die Datenbank abgesetzt werden.
Wenn
Ihre Zeit knapp ist können Sie die Erklärung auch
überspringen und gleich mit dem nächsten Schritt des
Tutorials (Konfigurationsdateien
erstellen und Packen in JAR-Dateien
)
fortsetzen.
Abgesehen
vom Algorithmus – der durch die Kommentare innerhalb des Codes
erklärt wird – unterscheidet sich das hier präsentierte
Session-Bean mit Datenbank-Zugriff nicht vom Session-Bean im
Tutorial:
Einfache Session Bean, EJB3-Standard (Java_EJB_05) - Codieren
.
Neue
Teile sind die 'Injection' für die 'Data-Source', der Code für
die Verbindung zur Datenbank und das Absetzen von SQL-Kommandos an
die Datenbank.
Die
Verbindung zur Datenbank erfolgt unter Verwendung des symbolischen
Namens der 'Data-Source':
/*
* Basisklasse
für eine Verbindung zu einer Datenquelle.
* Datenquelle
('data-source') ist ein Überbegriff für alle Verbindungen
des EJB,
* über die Daten ausgetauscht
werden.
* Üblicherweise erfolgt diese Verbindung
zu einem Datenbanksystem;
* möglich ist aber auch
jede andere Datenverbindung – z.B. eine Schnittstelle.
* Mit
welcher Datenquelle das EJB verbunden wird ist in
Konfigurationsdateien festgelegt.
* Eine davon ist
'ejb-jar.xml'; weitere hängen vom verwendeten JAS (Java
Application Server)
* und der Art der Datenquelle ab.
*/
import
javax.annotation.Resource;
Damit
wird die Programm-Bibliothek und die Klasse importiert, die die
Funktionalität enthält, mit der der JAS die im
EJB3-Standard neue 'Injection' @Resource
ausführen
kann.
/*
* 'Injection' für die Verbindung zu einer
'Datenquelle' – einer Datenbank.
*/@Resource(name=
"ds/Chat_DS"
,
mappedName=
"java:/DefaultDS"
)
Im
EJB3-Standard neue Anweisung der Art 'Injection' mit der dem JAS zur
Kenntnis gebracht wird, dass dieses EJB eine Verbindung zu einer
Datenquelle (in diesem Fall eine Datenbank) benötigt.
Der
JAS verbindet dann zu einem so genannten 'Connection Pool' –
im Falle dieses Tutorials zu einem Java-Objekt, das die Verbindungen
(Connections) zu der Datenbank verwaltet.
Nebenbemerkung:
Das
Öffnen und Schließen von Connections zu einer Datenbank
erfordert unverhältnismäßig viel Zeit –
verglichen mit SQL-Abfragen..
Durch die Verwendung eines
'Connection Pools' werden einmal geöffnete Verbindungen zur
Datenbank nicht geschlossen wenn die SQL-Abfrage beendet ist sondern
bei der nächsten Anforderung einer 'Connection' wieder
verwendet. Damit wird die Zeit für das Schließen und
Öffnen eingespart.
Die
Verbindung zur Datenbank wird über den Namen des EJB
(@Stateless(
name=
"Java_EJB_07_Tutorial"
,
mappedName=
"ejb/ChatManagementBeanJNDI"
)
)
und den Namen der Datasource (@Resource(
name=
"ds/Chat_DS"
,
mappedName=
"java:/DefaultDS"
)
)
in Konfigurationsdateien außerhalb der Java-Klassen des EJB
festgelegt.
Ein Beispiel dafür ist im Schritt Maßnahmen
für den Zugriff auf eine MySQL-Datenbank
beschrieben.
Eine
weitere Vereinfachung ist, dass in der @Resource
Injection
auch bereits ein JNDI-Name für die Datasource definiert werden
kann:@Resource(name=
"ds/Chat_DS"
,
mappedName=
"java:/DefaultDS"
)
Das
erleichtert die ersten Schritte der Entwicklung eines EJB wenn der
für die Tests verwendete JAS bereits mit einem integrierten und
vorkonfigurierten Datenbanksystem ausgestattet ist. In diesem Fall
ist es nicht notwendig, externe Konfigurationsdateien für die
Verbindung zur Datasource zu erstellen – es können gleich
SQL-Kommandos auf die Datenbank abgesetzt werden.
Das Beispiel
ist für den JBoss
JAS; die Anleitung für das Anlegen der Datenbank-Tabellen und
die Abfrage der aus dem EJB eingefügten Werte finden Sie im
Schritt Benutzen
der Hypersonic Datenbank von 'JBoss'.
/*
* Variable
für die Java-Klasse mit dem 'Treiber' für die Verbindung
zur 'Datasource'. */
private
DataSource
jdbcFactory =
null
;
Definition
der Variable für die Verbindung zur Datasource.
Auch wenn
diese Variable mit dem Initialwert null
definiert
ist wird, bedingt durch
@Resource(name=
"ds/Chat_DS"
,
mappedName=
"java:/DefaultDS"
)
,
die Verbindung zur Datasource hergestellt.
Aus dieser Variable
kann die Verbindung (Connection) der Datenbank ermittelt werden; das
ist im nächsten Punkt beschrieben.
/**
* Methode
zum Herstellen einer Verbindung (Connection) zur Datenbank.
* In
dieser Methode wird zentral für dieses EJB die Verbindung zur
Datenbank verwaltet. */
private
Connection
establishDBConnection() {
/*
* Variable für
die Verbindung zur 'Datasource'; hier eine Datenbank.
*/
Connection
DBConnection = null;
/*
* 'Holen'
der Verbindung zur Datenbank aus dem 'Treiber' für die
'Datasource' (jdbcFactory).
* jdbcFactory wurde durch
die 'Injection' @Resource initialisiert. */
try
{
DBConnection =
jdbcFactory
.getConnection();
}
catch(Exception
e) {/* Construction
des Objects mit dem DB-Treiber fehlgeschlagen.
*/
System.
out
.println("Fehler
beim
'jdbcFactory.getConnection'");
e.printStackTrace();
}
/*
* Zurückliefern
der Datenbank-Connection;
* diese ist 'null' wenn das
'Holen' nicht funktioniert hat. */
return
DBConnection;
}Der
Grund-Code besteht nur aus einem Kommando:
DBConnection
=
jdbcFactory
.getConnection();
Das
ist eine wesentliche Vereinfachung gegenüber dem Codier-Aufwand
vor EJB.
Die Fehlerbehandlung in diesem Tutorial ist einfach
gehalten:
Für den Echt-Betrieb kann aber davon ausgegangen
werden, dass eine einmal getestete Verbindung zur Datasource auch
nach vielen Wiederholungen einwandfrei wieder hergestellt werden
kann – oder sonst ein grober Fehler beim verwendeten JAS
vorhanden ist.
/*
* Methode
zum Lesen einer gewünschten Zahl der neuesten Einträge
* aus
der Datenbank-Tabelle.
* Hier ist die Implementierung
der in den Interfaces ChatManagementBeanLocal
* bzw.
ChatManagementBeanRemote definierten Methode. */
public
Vector
getChatEntryList(
int
parmNumberOfNewest)
{
/*
* Bei
0 oder einem negativen Wert im Parameter wird der Wert auf 9
gesetzt. */
if
(parmNumberOfNewest
< 1) parmNumberOfNewest = 9;
/*
* Vector
für das Set mit den Business-Objects, die 'return'ed werden,
definieren. */
Vector
vecReturnVector =
new
Vector();
/*
* Methode
zum 'Holen' der DB-Connection aufrufen. */
Connection
DBConnection = establishDBConnection();
/*
* Wenn
keine DB-Connection zurückgeliefert wurde,
* dann
den leeren Vector zurückliefern. */
if
(DBConnection
==
null
)
return
vecReturnVector;
/*
* Connection
zur Datenbank vorhanden;
* 'Prepared Statement'
welches das SQL-Kommando enthält definieren.
*/
PreparedStatement
PrepStatement =
null
;
/*
* 'Prepared
Statement' mit dem SQL-Kommando füllen und absetzen.
*/
try
{
PrepStatement
= DBConnection.prepareStatement(
"SELECT
* FROM Chat ORDER BY Erstellt_TS DESC LIMIT ?"
);
/*
* Attribute
mit dem Wert für die Anzahl der zu lesenden Datensätze
füllen. */
PrepStatement.setInt(1,
parmNumberOfNewest);
/*
* 'Prepared
Statement' ausführen; gelesene DB-Einträge sind im
SQLResultSet. */
ResultSet
SQLResultSet = PrepStatement.executeQuery();
/*
* Die
Einträge im SQLResultSet werden über eine 'for-loop'
ausgelesen. */
for
(;;)
{
/*
* Lesen
des nächsten Eintrages aus dem SQLResultSet und
* Abbrechen
der 'for-loop' wenn im SQLResultSet keine Datensätze mehr sind.
*/
if
(!SQLResultSet.next())
break
;
/*
* Definieren
einer Struktur für das BO.
* Diese Struktur wird
mit den Werten aus dem SQLResultSet gefüllt und
* dann
als ein Element in den Vector eingefügt. */
Chat_BO
locstructChat_BO =
new
Chat_BO();
/* */
locstructChat_BO.Erstellt_Timestamp
=
SQLResultSet.getTimestamp("Erstellt_TS"
);
locstructChat_BO.Erstellt_TCPIP_Adresse
=
SQLResultSet.getString("Erstellt_TCPIP_Adresse"
);
locstructChat_BO.Message_Text
=
SQLResultSet.getString("Message_Text"
);
/* */
vecReturnVector.addElement(locstructChat_BO);
}/*
* Wenn
das Programm bis hierher kam ist das SQL-Kommando korrekt ausgeführt
worden.
* 'Prepared Statement' und Verbindung zum
Datenbank-System ('DBConnection')
* ordnungsgemäß
schließen.
*/
PrepStatement.close();
DBConnection.close();
}
catch
(SQLException
SQLExc) {
/* Datenbank-Zugriff
fehlgeschlagen. */
System.
out
.println(
"Fehler
bei SQL; method
'getChatEntryList'"
);
SQLExc.printStackTrace();/* 'Leeren'
Vector an die aufrufende Methode zurückliefern.
*/
return
vecReturnVector;
}/*
* Datenbank-Zugriff
war erfolgreich; Vector mit dem Set der Chat-BO
* an
aufrufende Methode zurückliefern. */
return
vecReturnVector;
}Das
Absetzen eines SQL-Kommandos und das Auslesen der Ergebnisse der
Abfrage erfordert keine besondere Adaptierung an den Code eines EJB
- es ist gleich wie bei jedem anderen Java-Programm auch.
Eine
detaillierte Erklärung für das Verwenden von SQL-Kommandos
innerhalb des Java-Codes finden Sie im Tutorial:
Datenbank-Ladeprogramm mit Grahischer Benutzeroberflche
(Java_Intro_02) – SQL-Kommandos ausführen > Code für
die Methode
processDBOperation(.
. .)
zum
Ausführen der SQL-Kommandos / Klasse
DB_Load__Thread
.
Gesamter
Code am Ende des Schrittes
package
js_ejb07.bo;
/*
* Type
'Timestamp' ist in diesem Package enthalten. */ import
java.sql.*;
/*
* Methoden
für das 'Serialisieren' eine Objektes sind in diesem Package
enthalten. */ import
java.io.Serializable;
/**
*
* @author kurt(at)javascout[dot]biz
* @date
2009-08-19
*
* @description
* Klasse,
die das Business Object für einen Chat-Eintrag in
die
* Datenbank-Tabelle 'Chat' repräsentiert.
*
* @change-log
*
when who why
*
--------------------------------------------------------
*
*/public
class
Chat_BO
implements
Serializable
{
/*
* Eindeutige
Identifizierung der Klasse.
* Bei 'Serializable'
notwendig um ein 'Warning' des Compilers zu vermeiden. */
static
final long
serialVersionUID
=
200902242039L;
/*
* Zeitpunkt
der Eintragung in die Datenbank; gleichzeitig Primärschlüssel.
*/
public
Timestamp
Erstellt_Timestamp
=
new
Timestamp(0);
/*
* TCP/IP-Adresse
des Computers, auf dem das Client-Programm ausgeführt wurde.
*/
public
String
Erstellt_TCPIP_Adresse
=
""
;
/*
* Chat-Text;
vom Benutzer eingegeben. */
public
String
Message_Text
=
""
;
}
package
js_ejb07.ejb.interfaces.local;
/*
* Basisklasse
für die 'lokale' Funktionalität eines EJB gemäß
dem EJB3-Standard.
* 'Lokal' bedeutet, dass die
Methoden des EJB von einem anderen EJB innerhalb des
* Java-Application-Server (JAS) aufrufbar sind.
* Die
Funktionalität dieser Basisklasse wird nicht durch 'Vererbung'
übertragen
* sondern durch die (im EJB3-Standard
neue) 'Injection': @Local . */
import
javax.ejb.Local;
/*
* Package
mit der Klasse 'Vector'.
* Dieser wird für die
'Zurücklieferung' der gelesenen 'Chat'-Einträge verwendet.
*/
import
java.util.Vector;
/*
* Package
mit der Klasse des Business-Objects.
* Das ist die
'Datenstruktur' für einen Eintrag in die Chat-Tabelle der
Datenbank. */
import
js_ejb07.bo.Chat_BO;
/*
* 'Injection'
der Funktionalität für ein 'lokales' EJB */@Local
/**
*
* @author kurt(at)javascout[dot]biz
* @date
2009-08-19
*
* @description
* Interface
mit den Methoden die von anderen EJBs innerhalb des JAS aufrufbar
sind.
*
* @change-log
*
when who why
*
--------------------------------------------------------
*
*/public
interface
ChatManagementBeanLocal
{
/*
* Methode
zum Speichern eines Chat-Eintrags in die Datenbank-Tabelle.
* Die
Implementierung der Methode erfolgt in der Klasse
'ChatManagementBean'. */
public
String
storeChatEntry(Chat_BO parmChat_BO);
/*
* Methode
zum Lesen einer angeforderten Anzahl der jüngsten Chat-Einträge
von
* der Datenbank-Tabelle.
* Zur
Übertragung in Richtung aufrufende Methode werden die
Business-Objekte
* in einen 'Vector' verpackt weil ein
Objekt der Klasse 'Vector' eine unbestimmte
* Anzahl
von Objekten umfassen und übertragen kann.
* Die
Implementierung der Methode erfolgt in der Klasse
'ChatManagementBean'. */
public
Vector
getChatEntryList(
int
parmNumberOfNewest);
}
package
js_ejb07.ejb.interfaces.remote;
/*
* Basisklasse
für die 'entfernte' Funktionalität eines EJB gemäß
dem EJB3-Standard.
* 'Entfernt / remote' bedeutet, dass
die Methoden des EJB von einem Client-Programm
* außerhalb
des Java-Application-Server (JAS) aufrufbar sind.
* Die
Funktionalität dieser Basisklasse wird nicht durch 'Vererbung'
übertragen
* sondern durch die (im EJB3-Standard
neue) 'Injection': @Remote . */
import
javax.ejb.Remote;
/*
* Package
mit der Klasse 'Vector'.
* Dieser wird für die
'Zurücklieferung' der gelesenen 'Chat'-Einträge verwendet.
*/
import
java.util.Vector;
/*
* Package
mit der Klasse des Business-Objects.
* Das ist die
'Datenstruktur' für einen Eintrag in die Chat-Tabelle der
Datenbank. */
import
js_ejb07.bo.Chat_BO;
/*
* 'Injection'
der Funktionalität für ein 'remote' EJB */@Remote
/**
*
* @author kurt(at)javascout[dot]biz
* @date
2009-08-19
*
* @description
* Interface
mit den Methoden die von Client-Programmen außerhalb des JAS
aufrufbar sind.
*
* @change-log
*
when who why
*
--------------------------------------------------------
*
*/public
interface
ChatManagementBeanRemote
{
/*
* Methode
zum Speichern eines Chat-Eintrags in die Datenbank-Tabelle.
* Die
Implementierung der Methode erfolgt in der Klasse
'ChatManagementBean'. */
public
String
storeChatEntry(Chat_BO parmChat_BO);
/*
* Methode
zum Lesen einer angeforderten Anzahl der jüngsten Chat-Einträge
von
* der Datenbank-Tabelle.
* Zur
Übertragung in Richtung aufrufende Methode werden die
Business-Objekte
* in einen 'Vector' verpackt weil ein
Objekt der Klasse 'Vector' eine unbestimmte
* Anzahl
von Objekten umfassen und übertragen kann.
* Die
Implementierung der Methode erfolgt in der Klasse
'ChatManagementBean'. */
public
Vector
getChatEntryList(
int
parmNumberOfNewest);
}
package
js_ejb07.ejb.beans;
/*
* Basisklasse
für ein Stateless Session Bean.
* 'Stateless'
bedeutet, dass in einem Bean-Objekt keine Werte 'aufgehoben' werden.
* Durch die Anweisung 'Stateless' braucht der JAS
(Java Application Server) nicht ein
* neues Objekt der
Bean konstruieren wenn eine Anforderung eines anderen Clients
erfolgt
* sondern kann die angeforderte Methode des
bereits bestehenden Bean-Objekts ausführen.
* Die
Funktionalität dieser Basisklasse wird nicht durch 'Vererbung'
übertragen
* sondern durch die (im EJB3-Standard
neue) 'Injection': @Stateless . */
import
javax.ejb.Stateless;
/*
* Basisklasse
für eine Verbindung zu einer Datenquelle.
* Datenquelle
('data-source') ist ein Überbegriff für alle Verbindungen
des EJB,
* über die Daten ausgetauscht
werden.
* Üblicherweise erfolgt diese Verbindung
zu einem Datenbanksystem;
* möglich ist aber auch
jede andere Datenverbindung – z.B. eine Schnittstelle.
* Mit
welcher Datenquelle das EJB verbunden wird ist in
Konfigurationsdateien festgelegt.
* Eine davon ist
'ejb-jar.xml'; weitere hängen vom verwendeten JAS (Java
Application Server)
* und der Art der Datenquelle ab.
*/
import
javax.annotation.Resource;
/*
* Package
mit den 'klassischen' Methoden für Datenbank-Zugriff. */import
java.sql.*;
/*
* Package
mit den Methoden, wie eine Datenbank über die
* JNDI-Referenz
eingebunden werden kann. */import
javax.sql.*;
/*
* Package
mit der Methode zur Ermittlung der aktuellen Zeit (des
Timestamps)
* und für die Datenstruktur 'Vector'.
*/import
java.util.*;
/*
* Package
mit der Klasse des Business-Objects.
* Das ist die
'Datenstruktur' für einen Eintrag in die Chat-Tabelle der
Datenbank. */import
js_ejb07.bo.Chat_BO;
/*
* Interfaces
mit den Methoden die für 'lokalen' und 'entfernten / remote'
Aufruf freigegeben sind. */
import
js_ejb07.ejb.interfaces.local.*;
import
js_ejb07.ejb.interfaces.remote.*;
/*
* 'Injection' der Funktionalität für ein
'stateless' EJB. */@Stateless(name=
"Java_EJB_07_Tutorial"
,
mappedName=
"ejb/ChatManagementBeanJNDI"
)
/**
*
* @author kurt(at)javascout[dot]biz
* @date
2009-09-20
*
* @description
* Klasse
für das Session-Bean Java_EJB_07 – erstellt im
gleichnamigen Tutorial.
* Nähere
Beschreibungen der Funktionalität sind bei den Methoden zu
finden.
*
* @change-log
*
when who why
*
--------------------------------------------------------
*
*/public
class
ChatManagementBean
implements
ChatManagementBeanLocal,
ChatManagementBeanRemote
{
/*
* 'Injection'
und Variable zum Herstellen einer Verbindung zur Datenbank
(Connection).
* Als JNDI-Name (mappedName) ist die
Standard-Verbindung eines JBoss-JAS zu der in
* JBoss
integrierten HyperSonic-Datenbank festgelegt.
* Dieser
JNDI-Name kann bei Bedarf in externen Konfigurationsdateien verändert
werden. */@Resource(name=
"ds/Chat_DS"
,
mappedName=
"java:/DefaultDS"
)
/*
* Variable
für die Java-Klasse mit dem 'Treiber' für die Verbindung
zur 'Datasource'. */
private
DataSource
jdbcFactory
=
null
;
/**
* Methode
zum Herstellen einer Verbindung (Connection) zur Datenbank.
* In
dieser Methode wird zentral für dieses EJB die Verbindung zur
Datenbank verwaltet. */
private
Connection
establishDBConnection() {
/*
* Variable
für die Verbindung zur 'Datasource'; hier eine Datenbank.
*/
Connection
DBConnection =
null
;
/*
* 'Holen'
der Verbindung zur Datenbank aus dem 'Treiber' für die
'Datasource' (jdbcFactory).
* jdbcFactory wurde durch
die 'Injection' @Resource initialisiert. */
try
{
DBConnection
= jdbcFactory
.getConnection();
}
catch
(Exception
e) {
/* Construction
des Objects mit dem DB-Treiber fehlgeschlagen.
*/
System.
out
.println(
"Fehler
beim
'jdbcFactory.getConnection'"
);
e.printStackTrace();
}/*
* Zurückliefern
der Datenbank-Connection;
* diese ist 'null' wenn das
'Holen' nicht funktioniert hat. */
return
DBConnection;
}/*
* Methode
zum Speichern eines Chat-Eintrags in die Datenbank-Tabelle.
* Hier
ist die Implementierung der in den Interfaces
ChatManagementBeanLocal
* bzw. ChatManagementBeanRemote
definierten Methode. */
public
String
storeChatEntry(Chat_BO parmChat_BO) {
/*
* In
die im Parameter übergebene Daten-Struktur wird
* aktuelles
Datum und Uhrzeit gespeichert.
*/
parmChat_BO.
Erstellt_Timestamp
=
new
Timestamp(
new
java.util.Date().getTime());
/*
* Methode
zum 'Holen' der DB-Connection aufrufen. */
Connection
DBConnection = establishDBConnection();
/*
* Wenn
keine DB-Connection zurückgeliefert wurde,
* dann
Fehler an die aufrufende Methode melden. */
if
(DBConnection
==
null
)
return
"DBConnection
ist 'null'."
;
/*
* Connection
zur Datenbank vorhanden;
* 'Prepared Statement'
welches das SQL-Kommando enthält definieren.
*/
PreparedStatement
PrepStatement =
null
;
/*
* 'Prepared
Statement' mit dem SQL-Kommando füllen und absetzen.
*/
try
{
PrepStatement
= DBConnection.prepareStatement("INSERT
INTO Chat VALUES (?, ?, ?)"
);
/*
* Attribute
mit Werten aus der Datenstruktur (Parameter der Methode) füllen.
*/
PrepStatement.setTimestamp(1,
parmChat_BO.
Erstellt_Timestamp
);
PrepStatement.setString(2,
parmChat_BO.Erstellt_TCPIP_Adresse
);
PrepStatement.setString(3,
parmChat_BO.Message_Text
);
/*
* 'Prepared
Statement' ausführen.
*/
PrepStatement.executeUpdate();
/*
* Wenn
das Programm bis hierher kam ist das SQL-Kommando korrekt ausgeführt
worden.
* 'Prepared Statement' und Verbindung zum
Datenbank-System ('DBConnection')
* ordnungsgemäß
schließen damit das Datenbanksystem ein 'commit'
durchführt.
* Durch den 'commit' werden die
Änderungen erst gültig.
*/
PrepStatement.close();
DBConnection.close();
}
catch
(SQLException
SQLExc) {
/* Datenbank-Zugriff
fehlgeschlagen. */
System.
out
.println(
"Fehler
bei SQL; method
'storeChatEntry'"
);
SQLExc.printStackTrace();/* Fehler-Beschreibung
im return-value der Methode an die aufrufende
* Methode
zurückliefern. */
return
"Fehler
bei SQL; method 'storeChatEntry': "
+
SQLExc.getMessage();
}/*
* Datenbank-Zugriff
war erfolgreich; Leeren String an aufrufende Methode zurückliefern.
*/
return
""
;
}/*
* Methode
zum Lesen einer gewünschten Zahl der neuesten Einträge
* aus
der Datenbank-Tabelle.
* Hier ist die Implementierung
der in den Interfaces ChatManagementBeanLocal
* bzw.
ChatManagementBeanRemote definierten Methode. */
public
Vector
getChatEntryList(
int
parmNumberOfNewest)
{
/*
* Bei
0 oder einem negativen Wert im Parameter wird der Wert auf 9 gesetzt.
*/
if
(parmNumberOfNewest
< 1) parmNumberOfNewest = 9;
/*
* Vector
für das Set mit den Business-Objects, die 'return'ed werden,
definieren. */
Vector
vecReturnVector =
new
Vector();
/*
* Methode
zum 'Holen' der DB-Connection aufrufen. */
Connection
DBConnection = establishDBConnection();
/*
* Wenn
keine DB-Connection zurückgeliefert wurde,
* dann
den leeren Vector zurückliefern. */
if
(DBConnection
==
null
)
return
vecReturnVector;
/*
* Connection
zur Datenbank vorhanden;
* 'Prepared Statement'
welches das SQL-Kommando enthält definieren.
*/
PreparedStatement
PrepStatement =
null
;
/*
* 'Prepared
Statement' mit dem SQL-Kommando füllen und absetzen.
*/
try
{
PrepStatement
= DBConnection.prepareStatement(
"SELECT
* FROM Chat ORDER BY Erstellt_TS DESC LIMIT ?"
);
/*
* Attribute
mit dem Wert für die Anzahl der zu lesenden Datensätze
füllen. */
PrepStatement.setInt(1,
parmNumberOfNewest);
/*
* 'Prepared
Statement' ausführen; gelesene DB-Einträge sind im
SQLResultSet. */
ResultSet
SQLResultSet = PrepStatement.executeQuery();
/*
* Die
Einträge im SQLResultSet werden über eine 'for-loop'
ausgelesen. */
for
(;;)
{
/*
* Lesen
des nächsten Eintrages aus dem SQLResultSet und
* Abbrechen
der 'for-loop' wenn im SQLResultSet keine Datensätze mehr sind.
*/
if
(!SQLResultSet.next())
break
;
/*
* Definieren
einer Struktur für das BO.
* Diese Struktur wird
mit den Werten aus dem SQLResultSet gefüllt und
* dann
als ein Element in den Vector eingefügt. */
Chat_BO
locstructChat_BO =
new
Chat_BO();
/* */
locstructChat_BO.Erstellt_Timestamp
=
SQLResultSet.getTimestamp("Erstellt_TS"
);
locstructChat_BO.Erstellt_TCPIP_Adresse
=
SQLResultSet.getString("Erstellt_TCPIP_Adresse"
);
locstructChat_BO.Message_Text
=
SQLResultSet.getString("Message_Text"
);
/* */
vecReturnVector.addElement(locstructChat_BO);
}/*
* Wenn
das Programm bis hierher kam ist das SQL-Kommando korrekt ausgeführt
worden.
* 'Prepared Statement' und Verbindung zum
Datenbank-System ('DBConnection')
* ordnungsgemäß
schließen.
*/
PrepStatement.close();
DBConnection.close();
}
catch
(SQLException
SQLExc) {
/* Datenbank-Zugriff
fehlgeschlagen. */
System.
out
.println(
"Fehler
bei SQL; method
'getChatEntryList'"
);
SQLExc.printStackTrace();/* 'Leeren'
Vector an die aufrufende Methode zurückliefern.
*/
return
vecReturnVector;
}/*
* Datenbank-Zugriff
war erfolgreich; Vector mit dem Set der Chat-BO
* an
aufrufende Methode zurückliefern. */
return
vecReturnVector;
}}
Dokument |
Inhalt |
Im
nächsten Schritt des Tutorial wird beschrieben, wie die
Java-Archive-Datei (JAR) generiert wird, die an den
Java-Application-Server (JAS) übergeben ('deployed')
wird. |