> 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.
Ziel ist es, eine minimale 'Chat'-Anwendung zu implementieren
Dabei werden die Attribute (Erstellungs-Timestamp, TCP-IP-Adresse-Ersteller und Message-Text) für einen 'chat'-Beitrag, die auf der Datenbank-Tabelle gespeichert werden, in einer eigenen Klasse definiert. diese Klasse stellt dann ein 'Business-Object' dar.
Vorigerer Schritt: Einrichten des Projects
Vorbemerkung
und Funktion des Codes
Vorbedingungen
Klasse
für das Business-Object codieren
* Klasse
Chat_BO
eröffnen
* Quell-Code
für Chat_BO
Session-Bean
codieren
* Class
ChatManagementBean
eröffnen
* XDoclet
Anweisungen des ChatManagementBean
codieren
* Generierten
Code des ChatManagementBean
adaptieren
* Method
establishDBConnection
zum
Anfordern einer Verbindung zum Datenbanksystem
('Connection')
* Method
storeChatEntry
zum
Speichern eines Chat-Eintrags in der Datenbank-Tabelle
Möglichkeit,
mit dem nächsten Schritt fortzufahren
* Method
getChatEntryList
zum
Lesen einer definierten Anzahl der neuesten Chat-Einträge aus
der Datenbank-Tabelle
Kompletter
Code des Session Bean ohne Test-Ausgaben
Weitere
Schritte und verwandte Dokumentation
Nächster Schritt: XDoclet-Anweisungen
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.
Schritt 1: Einrichten des Projects ausgeführt – und dessen Vorbedingungen auch.
Wie
schon unter
Vorbemerkung
und Funktion des Codes
erläutert,
wird eine Klasse codiert, die alle zusammen gehörenden Werte für
einen 'Chat'-Eintrag auf der Datenbank-Tabelle repräsentiert.
Diese Klasse mit der 'Ansammlung' von Attributen wird als
'Business-Object' (frei übersetzt: Objekt mit den
Geschäfts-Daten) bezeichnet.
Klasse
Chat_BO
eröffnen
Um ein neues Interface zu eröffnen wird mit der rechten Maustaste das Project (Java_EJB_01) angeklickt und aus dem Kontext-Menu >New>Class ausgewählt. |
|
Im darauf hin erscheinenden Fenster (New Java Class) 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 Java-Klasse angelegt. |
|
Quell-Code
für
Chat_BO
package
js_ejb03.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@javascout.biz
*
@date 2008-01-14
*
* @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
{
/*
* 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
=
""
;
}
Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Erläuterungen
für spezielle Teile Codes
Damit
ein Objekt dieser Klasse zwischen einem Client-Programm und dem EJB
übertragen werden kann, muß das Objekt 'serialisiert'
werden können – das heißt in einen Strom einfacher
Bytes gebracht werden können.
Die Methoden für das
serialisieren eines Objekt der Klasse werden mit einer Interface (
implements
Serializeable
)
implementiert.
Wie
schon unter
Vorbemerkung
und Funktion des Codes
erläutert,
sind die erlaubten Werte für den Input des EJB in einem 'Set'
definiert.
Dieses Set wird in einem Interface codiert.
Class
ChatManagementBean
eröffnen
Um eine neues Java-Klasse zu eröffnen wird mit der rechten Maustaste das Project (Java_EJB_01) angeklickt und aus dem Kontext-Menu >New>Class ausgewählt. |
Keine Abbildung; eine Anleitung zum eröffnen von Java-Klassen finden Sie im Abschnitt Klasse Chat_BO eröffnen. |
Im darauf hin erscheinenden Fenster (New Java Class) 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. |
|
XDoclet
Anweisungen des
ChatManagementBean
codieren
Die
Anweisungen für den XDoclet-Generator sind umfangreicher als bei
einem einfachen Session Bean ohne Datenbank-Zugriff.
package
js_ejb03.ejb.bean;
..........
........../**
*
* @author kurt@javascout.biz
*
@date 2008-01-14
*
* Anweisungen für
XDoclet die das Session-Bean allgemein
beschreiben.
* ----------------------
* @ejb.bean
name = "ChatManagement"
* jndi-name
= "ejb/js_ejb03/ChatManagement"
* view-type
= "remote"
* display-name
= "ChatManagement EJB"
* description
= "EJB (Session Bean) aus EJB-Tutorial 03"
*
* Anweisungen
für XDoclet die die Verbindung zur Datenbank
beschreiben.
* ----------------------
* @ejb.resource-ref res-ref-name
= "jdbc/Chat_DS"
* res-type
= "javax.sql.Datasource"
* res-auth
= "Container"
*
* Anweisungen
für XDoclet die dem JBoss Java Application Server mitteilen,
* daß das vordefinierte Default-Dataset des in
JBoss integrierten
* Hypersonic Datenbank-Systems
verwendet werden
soll.
* ----------------------
* @jboss.resource-ref res-ref-name
= "jdbc/Chat_DS"
* jndi-name
= "java:/DefaultDS"
*
*
@description
* Klasse für das Session-Bean
mit Datenbank-Zugriff aus dem Tutorial Java_EJB_03.
* Das
Beispiel ist eine einfache Chat-Applikation.
* Nähere
Beschreibungen sind bei den Methoden zu finden.
*
*
@change-log
*
when who why
*
--------------------------------------------------------
*
*/public
class
ChatManagementBean
implements
SessionBean
{
..........
..........}
Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Erläuterungen
für spezielle Teile Codes
* Anweisungen
für Xdoclet
* @ejb.bean name =
"ShowTimeDate"
* jndi-name
= "ejb/js_ejb01/ShowTimeDate"
* view-type
= "remote"
* display-name
= "ShowTimeDate EJB"
* description
= "EJB (Session Bean) aus EJB-Tutorial 01"Anweisungen
für das Eclipse-Plugin XDoclet.
Mit XDoclet werden weitere
Klassen und XML-Dateien mit Beschreibungen des EJB für den Java
Application Server (JAS) generiert.
Die Parameter für die
Generierung werden im Schritt XDoclet-Anweisungen vorgestellt.
Die
Auswirkungen der folgenden Anweisungen sind bereits im Tutorial
Einfache Session
Bean (Java_EJB_01) - Codieren beschrieben..
* name
= "ShowTimeDate"
* jndi-name
= "ejb/js_ejb01/ShowTimeDate"
* view-type
= "remote"
* display-name
= "ShowTimeDate EJB"
und
description
= "EJB (Session Bean) aus EJB-Tutorial 01"
* Anweisungen
für XDoclet die die Verbindung zur Datenbank
beschreiben.
* ----------------------
* @ejb.resource-ref res-ref-name
= "jdbc/Chat_DS"
* res-type
= "javax.sql.Datasource"
* res-auth
= "Container"Parameter,
die in der XML-Datei 'ejb-jar.xml' beschreiben, unter welchem
symbolischen Namen die Verbindung zum Datenbanksystem aufgebaut
werden kann.
Hier eine kurze Beschreibung der
Auswirkungen.
* res-ref-name
= "jdbc/Chat_DS"
ist
der symbolische Name, unter dem ein Objekt der Java-Klasse für
die Verbindung zum Datenbank-System im Code des EJB erstellt werden
kann.
(Auch wenn das jetzt kompliziert geklungen hat – wie
das im Code aussieht wird weiter unten beschrieben.)
* res-type
= "javax.sql.Datasource"
ist
ein genormter Name der Java-Klasse, die die Verbindung zum
Datenbank-System herstellt.
Die Bibliothek mit dieser Klasse muß
mit dem jeweiligen Datenbanksystem mitgeliefert werden.
Für
dieses Tutorial wird das in JBoss integrierte Hyperlink
Datenbanksystem verwendet; die Bibliothek mit der Klasse
'javax.sql.Datasource' wurde bereits bei der Installation von JBoss
mit installiert..
* res-auth
= "Container"
ist
die Anweisung, wie die Anmeldung (Authentification) auf die
Datenbank verwaltet werden.
Durch die Spezifikation 'Container'
werden ein Benutzername und das dazu gehörende Passwort in
einer XML-Datei hinterlegt und müssen nicht durch das Programm
des EJB bei jedem Datenbank-Zugriff an das Datenbanksystem übergeben
werden.
Das Hypersonic Datenbanksystem – als einfach zu
handhabendes Werkzeug bei der Entwicklung gedacht –
funktioniert auch ohne Benutzername / Passwort.
Der Parameter
wird aber trotzdem definiert, weil durch Editieren der später
erzeugten JAR-Datei (die an den JAS übergeben wird) auch ein
anderes Datenbanksystem verwendet werden kann ohne daß die
XDoclet-Anweisungen editiert werden müssen.
* Anweisungen
für XDoclet die dem JBoss Java Application Server mitteilen,
* daß das vordefinierte Default-Dataset des in
JBoss integrierten
* Hypersonic Datenbank-Systems
verwendet werden
soll.
* ----------------------
* @jboss.resource-ref res-ref-name
= "jdbc/Chat_DS"
* jndi-name
= "java:/DefaultDS"Spezielle
Parameter für JBoss, die in der XML-Datei 'jboss.xml'
beschreiben, welche Datenbank dem symbolischen Namen, der im
Programm des EJB verwendet wird, zugeordnet werden soll.
Hier
eine kurze Beschreibung der Auswirkungen.
* res-ref-name
= "jdbc/Chat_DS"
ist
der symbolische Name, der auch unter
@ejb.resource-ref
verwendet
wird.
* jndi-name
= "java:/DefaultDS"
ist
der Name, unter dem die Hypersonic Datenbank verwendet werden
kann.
Bei Verwendung eines anderen Datenbanksystems (die auch
mehrere Datenbanken verwealten können) kann auch ein anderer
Namen für die Datenbank verwendet werden.
Um dieses Tutorial
möglichst einfach zu halten, wird bis auf weiteres der
vordefinierte Datenbankname von Hypersonic verwendet.
Generierten
Code des
ChatManagementBean
adaptieren
Scheinbar
verbergen sich im geerbten Code der implementierten Java-Interface
(
Session-Bean
)
Fehler.
* Die Methode public
void
ejbCreate()
....
fehlt
und muß eingefügt werden.
Diese
Methode ist aber Vorraussetzung, daß das EJB auf einem JAS
'deployed' werden kann.
* Die generierten Methoden (public
void
ejbActivate()..
usw.)
sind mit
@override
gekennzeichnet.
Das
bedeutet, daß der Compiler einen Fehler meldet wenn diese
Methoden keinen Code enthalten.
Ein 'override
'
ist aber nicht notwendig; deswegen muß
@override
entfernt
werden.
Möglicherweise
sind diese Fehler bereits behoben wenn Sie dieses Tutorial lesen –
dann überspringen Sie bitte diesen Abschnitt.
..........
..........
*
* @change-log
*
when who why
*
--------------------------------------------------------
*
*/public
class
ChatManagementBean
implements
SessionBean
{
/*
* Eindeutige
Identifikation der Klasse;
* Jahr (einstellig), Monat,
Tag, Stunde, Minute. */
static
final long
serialVersionUID
=
801151133;
/*
* Constructor-Methode;
wird aufgerufen wenn die Klasse erstellt wird. */
public
ChatManagementBean()
{
/*
* Kein
spezieller Code; nur jenen aus der geerbten Interface ausführen.
*/
super
();
};
public
void
ejbCreate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbActivate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbPassivate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbRemove()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
setSessionContext(SessionContext
arg0)
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
..........
..........}
Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Erläuterungen
für spezielle Teile Codes
static
final long
serialVersionUID
=
801151133;
Vergeben
einer eindeutigen Versions-Nummer für die Klasse.
Wird diese
Anweisung weggelassen, wird eine Versions-Nummer automatisch
vergeben – aber auch ein Compiler-Warning angezeigt.
/*
* Constructor-Methode;
wird aufgerufen wenn die Klasse erstellt wird. */
public
ChatManagementBean()
{
/*
* Kein
spezieller Code; nur jenen aus der geerbten Interface ausführen.
*/
super
();
};'Constructor'_Methode
für die Klasse.
Durch die Anweisung super
()
wird
der Code der 'Constructor'-Methode der implementierten
Java-Interface (
SessionBean
)
ausgeführt.
Das ist wichtig weil darin Code für die
korrekte Initialisierung eines Objekts der Klasse enthalten sein
kann..
public
void
ejbCreate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbActivate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
........
........Methoden,
die bei den jeweiligen Statusveränderungen des EJB aufgerufen
werden.
Diese Methoden könnten mit Code versehen werden, der
dann bei den Statusveränderungen ausgeführt wird.
Das
ist aber bei der einfachen Aufgabenstellung dieses Tutorials nicht
der Fall.
Method
establishDBConnection
zum
Anfordern einer Verbindung zum Datenbanksystem ('Connection')
Diese
Methode stellt die Verbindung zum Datenbanksystem her.
Bitte lesen
Sie bei den Kommentaren nach, welche Aufgaben die einzelne Teile des
Codes haben...........
..........import
javax.ejb.SessionContext;
/*
* 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 den Methoden für die Verwendung der JNDI (Java Naming and
Directory Interface). */import
javax.naming.*;
/**
*
* @author
kurt@javascout.biz..........
........../*
* Methode
zum Herstellen einer Verbindung zur Datenbank (Connection).
*/
/**
* Anweisungen für XDoclet.
* @return
Connection
* Datenbank-Connection wie im package
java.sql spezifiziert.
*
* @ejb.interface-method
view-type = "local"
* Diese Methode ist
'private' (nur von Methoden innerhalb dieser Klasse
aufrufbar);
* deswegen darf sie auch nicht als
Methode des EJB 'nach außen' sichtbar sein.
* "local"
(im Gegensatz zu "remote") weist XDoclet an, diese Methode
nicht in die 'interface'
* der EJB aufzunehmen.
*/
private
Connection
establishDBConnection() {
/*
* Variable
für die Abfrage des JNDI (Java Naming and Directory Index) des
JAS.
* Über das JNDI wird aus dem symbolischen
Namen der Datenbank (Chat_DS) die
* passende
Java-Klasse für den 'Treiber' für das verwendete
Datenbanksystem geholt. */
InitialContext
DBContext =
null
;
/*
* Variable
für die Java-Klasse mit dem 'Treiber' für die Verbindung
zur DB. */
DataSource
jdbcFactory =
null
;
/*
* Variable
für die Verbindung zum Datenbanksystem. */
Connection
DBConnection =
null
;
/*
* Java-Klasse
mit dem Treiber für das DB-System über das JNDI
ermitteln
* und ein Object dieser Klasse konstruieren.
*/
try
{
DBContext
= new
InitialContext();
System.out
.println(
"Über
'DBContext.lookup' die Java-Klasse für den DB-Treiber
holen."
);
jdbcFactory
= (DataSource)
DBContext.lookup("java:comp/env/jdbc/Chat_DS"
);
System.out
.println(
"'DBContext.lookup'
erfolgreich."
);
}
catch
(Exception
e) {
/* Construction
des Objects mit dem DB-Treiber fehlgeschlagen.
*/
System.
out
.println(
"Fehler
beim
'DBContext.lookup'"
);
e.printStackTrace();
}/*
* Verbindung
zur Datenbank aus dem Object mit dem DB-Treiber 'holen'. */
try
{
System.out
.println(
"Über
'jdbcFactory.getConnection' die Verbindung zum DB-System
herstellen."
);
DBConnection
=
jdbcFactory.getConnection();
System.out
.println(
"'jdbcFactory.getConnection'
erfolgreich."
);
}
catch
(Exception
e) {
/* Holen
der Verbindung zum DB-System fehlgeschlagen.
*/
System.
out
.println(
"Fehler
beim
'getConnection'"
);
e.printStackTrace();
}/*
* Zurückliefern
der Datenbank-Connection;
* diese ist 'null' wenn das
'Holen' nicht funktioniert hat. */
return
DBConnection;
}}
Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Erläuterungen
für spezielle Teile Codes
/**
* Anweisungen
für XDoclet.
* @return ConnectionSpezifikation,
welcher Datentyp der Wert ist, der von der Methode zurückgeliefert
wird.
Diese Anweisung hat bei dem einfachen Beispiel dieses
Tutorials keine weitere Auswirkung.
/**
* Anweisungen
für
XDoclet.
....................
....................
*
* @ejb.interface-method
view-type = "local"Anweisungen
an den XDoclet-Generator, daß die generierte Java-Interface
für das EJB (Name der Interface: 'ChatManagement') diese
Methode nicht enthält.
Damit kann diese Methode nicht von
Client-Programmen aufgerufen werden..
Bitte
beachten Sie auch den Kommentar in der Klasse. Dieser beschreibt den
Sinn der einzelnen Anweisungen und das erwartete Ergebnis.
Method
storeChatEntry
zum
Speichern eines Chat-Eintrags in der Datenbank-Tabelle
Diese
Methode wird vom Client-Programm aufgerufen wenn ein Chat-Text in die
Datenbank-Tabelle eingetragen werden
soll.
..........
..........import
javax.naming.*;
/*
* Package
mit der Methode zur Ermittlung der aktuellen Zeit (des Timestamps).
*/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_ejb03.bo.Chat_BO;
/**
*
* @author
kurt@javascout.biz..........
........../*
* 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.
*/
/**
* Anweisungen für XDoclet.
* @param
parmChatBO
* Object (Daten-Struktur) mit
Chat-Text und TCP/IP-Adresse des Clients
* auf
dem der Chat-Text erfaßt wurde.
* @return
String
* Zeichenkette mit eventuellen
Fehlermeldungen des Datenbanksystems.
*
* @ejb.interface-method
view-type = "remote"
* Diese Methode
muß von Client-Programmen aufgerufen werden können.
*/
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
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
""
;
}}
Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Erläuterungen
für spezielle Teile Codes
Bitte
beachten Sie die Kommentare in der Klasse. Diese beschreiben die
einzelnen Anweisungen und das erwartete Ergebnis.
Möglichkeit,
mit dem nächsten Schritt fortzufahren
An
diesem Punkt des Tutorials ist möglich, mit dem nächsten
Schritt (XDoclet-Anweisungen)
fortzufahren.
Ich
empfehle, jetzt zum nächsten Schritt zu gehen, dieses Tutorial
zu beenden und auch das Tutorial für die Entwicklung des
Client-Programmes auszuführen und erst dann die Methode
getChatEntryList(
int
parmNumberOfNewest)
zu
codieren.
Method
getChatEntryList
zum
Lesen einer definierten Anzahl der neuesten Chat-Einträge aus
der Datenbank-Tabelle
Diese
Methode wird vom Client-Programm aufgerufen um eine bestimmte Anzahl
der neuesten Chat-Einträge aus der Datenbank-Tabelle zu
lesen.
..........
..........
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. */
/**
* Anweisungen für
XDoclet.
* @param parmNumberOfNewest
* Integer-Wert
mit der Anzahl der angeforderten Datensätze.
* @return
Vector
* Vector mit den Business-Objects die die
Daten repräsentieren.
*
* @ejb.interface-method
view-type = "remote"
* Diese Methode
muß von Client-Programmen aufgerufen werden können.
*/
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;
}}
Anschließend
wird der Code durch Anklicken des Save-Symbols (
/ Diskette links oben) gespeichert.
Erläuterungen
für spezielle Teile Codes
Bitte
beachten Sie die Kommentare in der Klasse. Diese beschreiben die
einzelnen Anweisungen und das erwartete Ergebnis.
package
js_ejb03.ejb.bean;
/*
* Packages
die durch die Interface 'SessionBean' importiert werden.
* In
diesen Java-Packages ist die Funktionalität der Session-Bean
enthalten. */import
java.rmi.RemoteException;
import
javax.ejb.EJBException;
import
javax.ejb.SessionBean;
import
javax.ejb.SessionContext;
/*
* 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 den Methoden für die Verwendung der JNDI (Java Naming and
Directory Interface). */import
javax.naming.*;
/*
* 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_ejb03.bo.Chat_BO;
/**
*
* @author kurt(at)javascout[dot]biz
*
@date 2008-01-14
*
* Anweisungen für
XDoclet die das Session-Bean allgemein
beschreiben.
* ----------------------
* @ejb.bean
name = "ChatManagement"
* jndi-name
= "ejb/js_ejb03/ChatManagement"
* view-type
= "remote"
* display-name
= "ChatManagement EJB"
* description
= "EJB (Session Bean) aus EJB-Tutorial 03"
*
* Anweisungen
für XDoclet die die Verbindung zur Datenbank
beschreiben.
* ----------------------
* @ejb.resource-ref res-ref-name
= "jdbc/Chat_DS"
* res-type
= "javax.sql.Datasource"
* res-auth
= "Container"
*
* Anweisungen
für XDoclet die dem JBoss Java Application Server mitteilen,
* daß das vordefinierte Default-Dataset des in
JBoss integrierten
* Hypersonic Datenbank-Systems
verwendet werden
soll.
* ----------------------
* @jboss.resource-ref res-ref-name
= "jdbc/Chat_DS"
* jndi-name
= "java:/DefaultDS"
*
*
@description
* Klasse für das Session-Bean
mit Datenbank-Zugriff aus dem Tutorial Java_EJB_03.
* Das
Beispiel ist eine einfache Chat-Applikation.
* Nähere
Beschreibungen sind bei den Methoden zu finden.
*
*
@change-log
*
when who why
*
--------------------------------------------------------
*
*/public
class
ChatManagementBean
implements
SessionBean
{
/*
* Eindeutige
Identifikation der Klasse;
* Jahr (einstellig), Monat,
Tag, Stunde, Minute. */
static
final long
serialVersionUID
=
801151133;
/*
* Constructor-Methode;
wird aufgerufen wenn die Klasse erstellt wird. */
public
ChatManagementBean()
{
/*
* Kein
spezieller Code; nur jenen aus der geerbten Interface ausführen.
*/
super
();
};
public
void
ejbCreate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbActivate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbPassivate()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
ejbRemove()
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
public
void
setSessionContext(SessionContext
arg0)
throws
EJBException,
RemoteException {
//
TODO Auto-generated method stub
};
/*
* Methode
zum Herstellen einer Verbindung zur Datenbank (Connection).
*/
/**
* Anweisungen für XDoclet.
* @return
Connection
* Datenbank-Connection wie im package
java.sql spezifiziert.
*
* @ejb.interface-method
view-type = "local"
* Diese Methode ist
'private' (nur von Methoden innerhalb dieser Klasse
aufrufbar);
* deswegen darf sie auch nicht als
Methode des EJB 'nach außen' sichtbar sein.
* "local"
(im Gegensatz zu "remote") weist XDoclet an, diese Methode
nicht in die 'interface'
* der EJB aufzunehmen.
*/
private
Connection
establishDBConnection() {
/*
* Variable
für die Abfrage des JNDI (Java Naming and Directory Index) des
JAS.
* Über das JNDI wird aus dem symbolischen
Namen der Datenbank (Chat_DS) die
* passende
Java-Klasse für den 'Treiber' für das verwendete
Datenbanksystem geholt. */
InitialContext
DBContext =
null
;
/*
* Variable
für die Java-Klasse mit dem 'Treiber' für die Verbindung
zur DB. */
DataSource
jdbcFactory =
null
;
/*
* Variable
für die Verbindung zum Datenbanksystem. */
Connection
DBConnection =
null
;
/*
* Java-Klasse
mit dem Treiber für das DB-System über das JNDI
ermitteln
* und ein Object dieser Klasse konstruieren.
*/
try
{
DBContext
= new
InitialContext();
jdbcFactory
= (DataSource)
DBContext.lookup("java:comp/env/jdbc/Chat_DS"
);
}
catch
(Exception
e) {
/* Construction
des Objects mit dem DB-Treiber fehlgeschlagen.
*/
System.
out
.println(
"Fehler
beim
'DBContext.lookup'"
);
e.printStackTrace();
}/*
* Verbindung
zur Datenbank aus dem Object mit dem DB-Treiber 'holen'. */
try
{
DBConnection
= jdbcFactory.getConnection();
}
catch
(Exception
e) {
/* Holen
der Verbindung zum DB-System fehlgeschlagen.
*/
System.
out
.println(
"Fehler
beim
'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.
*/
/**
* Anweisungen für XDoclet.
* @param
parmChatBO
* Object (Daten-Struktur) mit
Chat-Text und TCP/IP-Adresse des Clients
* auf
dem der Chat-Text erfaßt wurde.
* @return
String
* Zeichenkette mit eventuellen
Fehlermeldungen des Datenbanksystems.
*
* @ejb.interface-method
view-type = "remote"
* Diese Methode
muß von Client-Programmen aufgerufen werden können.
*/
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. */
/**
* Anweisungen für
XDoclet.
* @param parmNumberOfNewest
* Integer-Wert
mit der Anzahl der angeforderten Datensätze.
* @return
Vector
* Vector mit den Business-Objects die die
Daten repräsentieren.
*
* @ejb.interface-method
view-type = "remote"
* Diese Methode
muß von Client-Programmen aufgerufen werden können.
*/
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 |
Tutorial: Session Bean mit Datenbank-Zugriff (Java_EJB_03) – XDoclet-Anweisungen |
Im nächsten Schritt des Tutorial werden die Parameter für das Generieren von weiteren Klassen und XML-Dateien mit Beschreibungen des EJB für den Java Application Server vorgestellt. |