> Inhalt: Einführung in das Programmieren mit Java > Inhalt: Einführung in das Programmieren von Enterprise Java Beans 

Tutorial: Session Bean mit Datenbank-Zugriff (Java_EJB_03) – Codieren

* Bitte beachten Sie die Hinweise und Bestimmungen bezüglich Urheberrecht, Haftungsausschluß und geschützte Marken oder Warenzeichen die für dieses Web-Dokument und möglicherweise auch für 'verlinkte' Dokumente gelten.

  • Der Betreiber dieser Web-Site (www.javascout.biz) ist nicht verantwortlich für den Inhalt von Web-Sites, die innerhalb dieses Web-Dokumentes oder anderer Dokumente von www.javascout.biz verlinkt sind.

  • Wenn dieses Web-Dokument oder andere Dokumente dieser Web-Site (www.javascout.biz) Rechte von Ihnen verletzen, oder sie glauben, daß Rechte Anderer (Dritter Personen) dadurch verletzt werden, informieren Sie bitte den Betreiber dieser Web-Site.
    Eine E-Mail können Sie ganz einfach durch anklicken des Symbols oder Textes im Frame rechts oben senden.

Dieses Dokument drucken.

 Letzte Bearbeitung dieses  Dokuments:
2008-01-17



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:
Ca.
.

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.

Inhaltsverzeichnis:

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 

Vorbemerkung und Funktion des Codes

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.

Vorbedingungen

zum Inhaltsverzeichnis

Klasse für das Business-Object codieren

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.

zum Inhaltsverzeichnis

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

  • Das 'Package' (js_ejb03.bo) festgelegt.

  • Der Name der Klasse (Chat_BO) 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 Java-Klasse angelegt.

zum Inhaltsverzeichnis

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.

zum Inhaltsverzeichnis

Session Bean codieren

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.

zum Inhaltsverzeichnis

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

  • Das 'Package' (js_ejb03.ejb.bean) festgelegt.

  • Der Name der Klasse (ChatManagementBean) festgelegt.

  • Die Interface (javax.ejb.SessionBean) wird durch Anklicken der Schaltfläche [ Add... ] hinzugefügt.

  • Die Auswahl '[X] Constructors from superclass' wird markiert.

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.

zum Inhaltsverzeichnis

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

zum Inhaltsverzeichnis

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

zum Inhaltsverzeichnis

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

zum Inhaltsverzeichnis

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

zum Inhaltsverzeichnis

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.

zum Inhaltsverzeichnis

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

zum Inhaltsverzeichnis

Kompletter Code des Session-Bean ohne Test-Ausgaben

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;
    }
}

zum Inhaltsverzeichnis

Weitere Schritte und verwandte Dokumentation

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.

zum Inhaltsverzeichnis