Beispiel: Container Managed Relationship zweier Entity Beans (IBM WebSphere)


Beispiel für zwei Container Managed Entity Bean, auf die per Webclient zugegriffen wird. Zwischen den beiden Beans besteht eine Container Managed Relationship.
Dieses Beispiel entspricht (mit Modifikationen) dem Beispiel "KuchenZutat" für den SunAppServer. "KuchenZutatAutoPK" entfällt, da WebSphere keine automatisch generierten Primary Keys unterstützt. Die Deployanleitung bezieht sich auf IBM WebSphere.
Hier gibt es das WebSphere-Projekt zum Download (dies ist ein Projektaustausch-Export, die Importanleitung findet man im Stateless-Beispiel): KuchenZutatExport.zip

Aufbau des Beispieles


a) Entity Bean-Klasse für Kuchen mit Local-Interfaces.
b) Entity Bean-Klasse für Zutat mit Local-Interfaces.
c) Webclient


Anlegen der Application

Ein Unternehmensanwendungsprojekt mit dem Namen "KuchenZutat" erstellen.
Zu erzeugende Module definieren. Dieses Beispiel benötigt ein EJB-Projekt und ein Anwendungsclientprojekt.
Erzeugen einer Application (Module)
Die J2EE-Hierarchie sollte so aussehen:
Erzeugte J2EE-Hierarchie


Anlegen der Entity Bean "Kuchen"

Es wird eine neue Entity Bean angelegt. Dazu in der J2EE-Hierarchie "EJB-Module" -> "KuchenZutatEJB" -> "Entity Beans" wählen und im Contextmenü den Punkt "Neu" -> "CMP-Bean" auswählen.
Im ersten Schritt wird das EJB-Projekt gewählt, in dem die Bean erstellt werden soll.
In Schritt 2 wird der Typ der Bean festgelegt: Es handelt sich um eine Bean mit Container Managed Felder, und zwar nach CMP-Version 2. Bean-Name und Package-Name müssen angegeben werden.
Kuchen Bean, Step 2
In Schritt 3 wird festgelegt, dass wir hier ein Local Interface haben wollen. In der unteren Liste fügen wir die Container Managed Attribute zu.
Da IBM WebSphere keine automatisch generierten Primary Keys kennt, müssen wir den Primary Key manuell erzeugen (siehe letztes Beispiel KuchenSingle). Wir fügen also ein Feld "id" von Typ "java.lang.Integer" zu.
Kuchen Bean, Felder (1)
Das einzige Datenfeld unserer Bean ist "Name". Dieses wird ebenfalls zugefügt.
Kuchen Bean, Felder (2)
Das Ergebnis von Schritt 3 sollte so aussehen:
Kuchen Bean, Step 3
Damit haben wir das Erstellen der Bean abgeschlossen. Die weiteren Schritte erfolgen, sobald wir die zweite Bean "Zutat" angelegt haben.


Anlegen der Entity Bean "Zutat"

Es wird eine neue Entity Bean namens "Zutat" angelegt.
In Schritt 2 wird der Typ der Bean festgelegt: Es handelt sich um eine Bean mit Container Managed Felder, und zwar nach CMP-Version 2. Bean-Name und Package-Name müssen angegeben werden.
Zutat Bean, Step 2
In Schritt 3 wird festgelegt, dass wir hier ein Local Interface haben wollen.
In der unteren Liste fügen wir die Container Managed Attribute zu.
Da IBM WebSphere keine automatisch generierten Primary Keys kennt, müssen wir den Primary Key manuell erzeugen (siehe letztes Beispiel KuchenSingle). Wir fügen also ein Feld "id" von Typ "java.lang.Integer" zu.
Zutat Bean, Felder (1)
Das erste Datenfeld unserer Bean ist "ZutatName". Dieses wird ebenfalls zugefügt.
Zutat Bean, Felder (2)
Das zweite Datenfeld unserer Bean ist "Menge". Dieses wird ebenfalls zugefügt.
Zutat Bean, Felder (3)
Das Ergebnis von Schritt 3 sollte so aussehen:
Zutat Bean, Step 3
Damit haben wir das Erstellen der Bean abgeschlossen. Jetzt können wir uns an die Nachbearbeitung der Beans machen.

Nachbearbeitung der KuchenBean

Die Methode "findAll" muss implementiert werden. Dazu zum EJB-Implementierungsdeskriptor unter "Abfragen" eine neue hinzufügen.
findAll: Schritt 1
Die Query lautet
select object(o) from Kuchen o order by o.name
findAll: Schritt 2
Das Ergebnis sollte so aussehen:
findAll: Schritt 3

Die Logik für das Verwalten des Primary Keys muss implementiert werden (manuell zu erzeugen !):
Wir definieren eine finder-Methode, die den Datensatz mit der Maximalen Id zurückliefert (mittels einem Subselect). Dies geschieht an der gleichen Stelle im "EJB-Implementierungsdeskriptor" wie die findAll-Methode. Die Finder-Methode hat den Namen "findByMaxId", sie steckt im Local-Interface, und hat als Rückgabewert eine einzelne Kuchen-Bean.
Kuchen Bean, Finder-Methode (Schritt 1)
Die Query sieht so aus:
select object(o) from Kuchen o where o.id in (select max (oInner.id) from Kuchen oInner)
Es wird also in einer inneren Abfrage die maximale ID geholt, dann wird der Datensatz zu dieser ID geholt. (Dies führt zu FinderExceptions, wenn noch keine Beans in der Datenbank vorhanden sind).
Kuchen Bean, Finder-Methode (Schritt 2)

Weitere Nachbearbeitung:
In der Methode "ejbCreate" entfernen wir den Parameter "id" (im Home-Interface nachziehen !) sowie den Aufruf von "setId(id)". Stattdessen wird die ID mittels einer einzufügenden Methode "getNextId" abgerufen (diese wiederum greift auf "findByMaxId" zu) und in der Bean gesetzt: "this.setId (this.getNextId() )".

Die Methode "ejbCreateByName" (Rückgabewert: Integer !) muss zugefügt werden. Natürlich muss auch "ejbPostCreateByName" implementiert werden. Diese neue Create-Methode muss auf das LocalHome-Interface hochgestuft werden.

Nachbearbeitung der ZutatBean

Die Methode "findAll" muss implementiert werden. Dazu zum EJB-Implementierungsdeskriptor unter "Abfragen" eine neue hinzufügen.
findAll: Schritt 1
Die Query lautet
select object(o) from Zutat o order by o.zutatName
findAll: Schritt 2

Die Logik für das Verwalten des Primary Keys muss implementiert werden (manuell zu erzeugen !):
Wir definieren eine finder-Methode, die den Datensatz mit der Maximalen Id zurückliefert (mittels einem Subselect). Dies geschieht an der gleichen Stelle im "EJB-Implementierungsdeskriptor" wie die findAll-Methode. Die Finder-Methode hat den Namen "findByMaxId", sie steckt im Local-Interface, und hat als Rückgabewert eine einzelne Zutat-Bean.
Kuchen Bean, Finder-Methode (Schritt 1)
Die Query sieht so aus:
select object(o) from Zutat o where o.id in (select max (oInner.id) from Zutat oInner)
Es wird also in einer inneren Abfrage die maximale ID geholt, dann wird der Datensatz zu dieser ID geholt. (Dies führt zu FinderExceptions, wenn noch keine Beans in der Datenbank vorhanden sind).
Kuchen Bean, Finder-Methode (Schritt 2)
Das Ergebnis mit den beiden Find-Methoden sollte so aussehen:
findAll: Schritt 3

Weitere Nachbearbeitung:
In der Methode "ejbCreate" entfernen wir den Parameter "id" (im Home-Interface nachziehen !) sowie den Aufruf von "setId(id)". Stattdessen wird die ID mittels einer einzufügenden Methode "getNextId" abgerufen (diese wiederum greift auf "findByMaxId" zu) und in der Bean gesetzt: "this.setId (this.getNextId() )".

Die Methode "ejbCreateByNameMenge" (Rückgabewert: Integer) muss zugefügt werden. Natürlich muss auch "ejbPostCreateByNameMenge" implementiert werden. Diese neue Create-Methode muss auf das LocalHome-Interface hochgestuft werden.

Erstellen der 1:n-Relationship

Im EJB-Implementierungsdeskriptor wählt man die Kuchen-Bean und geht zu "Beziehungen".
Kuchen: Relationship, Schritt 1
Man klickt auf "Hinzufügen". Im ersten Schritt des Assistenten wählt man die beiden zu verknüpfenden Beans aus.
Kuchen: Relationship, Schritt 2
Im nächsten Schritt gibt man die Kardinalität der Beziehung an und definiert die Feldnamen der Properties. Als einzige Änderungen sind hier vorzunehmen:
Den Namen der Property "zutat" ändern wir in "zutaten", da ein Kuchen eine Liste von Zutaten zurückliefert.
Auf der Zutat-Seite wird als Multiplizität "Many" gewählt, da ein Kuchen aus 0 bis n Zutaten besteht.
Außerdem wird mehrstufiges Löschen ("on delete cascade") aktiviert.
Kuchen: Relationship, Schritt 3
Es werden automatisch in der Kuchen-Bean die Methoden "getZutaten" und "setZutaten" angelegt. In der ZutatBean wird "getKuchen" und "setKuchen" angelegt. Die Properties erkennt man auch in der J2EE-Hierarchie.

Nachbearbeitung:
In der KuchenBean werden die beiden Methoden "addZutat" und "getZutatenListe" (umwandeln der Zutaten-Collection aus "getZutaten" in eine ArrayList, damit Clients sie verwenden können) zugefügt. Beide Methoden müssen auf das Local Interface hochgestuft werden.


Anlegen des Webclients

Der Webclient muss die EJB-JARs referenzieren. Dazu in die Eigenschaften des Webmoduls "KuchenZutatWeb" wechseln und unter "Java-JAR-Abhängigkeiten" das EJB-JAR wählen.
EJB-Verweise festlegen:
Im Webimplementierungsdeskriptor auf die Registerkarte "Verweise" wechseln und lokale Verweise "ejb/Kuchen" und "ejb/Zutat" auf Kuchen bzw. Zutat zufügen. Das Ergebnis sieht so aus:
EJB-Referenzen (Schritt 2)
Es müssen vier JSP-Seiten "Kuchen.jsp", "KuchenEdit.jsp", "KuchenZutaten.jsp", "KuchenZutatEdit.jsp" zugefügt werden (Rechtsklick auf "Webmodule" \ "KuchenZutatWeb", im Contextmenü "Neu" -> "Andere..." wählen und in der Auswahlliste links auf "Web" gehen. Dann rechts "JSP-Seite" auswählen.). Die Einstellungen für "Kuchen.jsp" sieht man im folgenden Screenshot:
Webclient: Kuchen.jsp zufügen

Ausführen des Clients

Der Client wird per Rechtsklick und "Auf Server ausführen" gestartet.
Zu beachten ist, dass vorher die Beans auf dem Server laufen. Dazu das EJB-Projekt per Rechtsklick und "Auf Server ausführen" starten. Wichtig ist, dass in Schritt 2 (nach der Auswahl des Servers) die Option "Tabellen und Datenquellen erstellen" gewählt wird (zumindest beim ersten Aufruf und nach jeder Änderung).
Webclient: Tabellen erstellen
Die Anwendung ist unter http://localhost:9080/KuchenZutatWeb/Kuchen.jsp zu erreichen.