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


Inhalt:
Anlegen der Application
Anlegen der Entity Bean "Kuchen"
Anlegen der Entity Bean "Zutat"
Nachbearbeitung der KuchenBean
Nachbearbeitung der ZutatBean
Erstellen der 1:n-Relationship
Anlegen des Webclients
Ausführen des Clients
Ein Blick in die Datenbank

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 weitgehend dem Beispiel "KuchenZutat" für den SunAppServer. Die Deployanleitung bezieht sich auf IBM WebSphere.
Hier gibt es das WebSphere-Projekt zum Download (dies ist ein Project Interchange-Export, die Importanleitung findet man im Stateless-Beispiel): KuchenZutatExport.zip
Die verwendete Datenbank heißt hier "KnaufDB"

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 Webprojekt.
Erzeugen einer Application (Module)
Das Ergebnis sollte im Project Explorer so aussehen:
Project Explorer


Anlegen der Entity Bean "Kuchen"

Es wird eine neue Entity Bean angelegt. Dazu im Project Explorer "EJB Projects" -> "KuchenZutatEJB" -> "Deployment Descriptor: KuchenZutatEJB" -> "Entity Beans" wählen und im Contextmenü den Punkt "New" -> "Entity Bean" auswählen.
Bean-Name und Package-Name müssen angegeben werden. Beantyp, CMP-Version und Projekt sind bereits korrekt vorgewählt.
Kuchen Bean (1)
Im nächsten Schritt 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). Dankenswerterweise hat der Assistent bereits ein PrimaryKey-Feld "id" vom Typ "java.lang.Integer" zugefügt.
Das einzige weitere Datenfeld unserer Bean ist "Name". Dieses wird zugefügt.
Kuchen Bean, Felder (2)
Das Ergebnis dieses Schritts sollte so aussehen:
Kuchen Bean (2)
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.
Bean-Name und Package-Name müssen angegeben werden. Beantyp, CMP-Version und Projekt sind bereits korrekt vorgewählt.
Zutat Bean (1)
Im nächsten Schritt wird festgelegt, dass wir hier ein Local Interface haben wollen.
In der unteren Liste fügen wir die Container Managed Attribute zu. Das Primary-Key-Feld "id" wurde bereits vom Assistent erzeugt.
Das erste Datenfeld unserer Bean ist "ZutatName". Dieses wird ebenfalls zugefügt.
Zutat Bean, Felder (1)
Das zweite Datenfeld unserer Bean ist "Menge". Dieses wird ebenfalls zugefügt.
Zutat Bean, Felder (2)
Das Ergebnis dieses Schrittes sollte so aussehen:
Zutat Bean (2)
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 "Queries" 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 !):
Zuerst wird eine ejbSelect-Methode hinzufügt, um den bisherigen maximalen Primary Key-Wert der Tabelle zu ermitteln. Dazu zum EJB-Implementierungsdeskriptor der Bean wechseln (Doppelklick auf die Bean in der J2EE-Hierarchie), und unter "Queries" eine neue hinzufügen.
Wir fügen eine neue Methode namens "ejbSelectMaxId" zu, die den Rückgabetyp "Integer" hat. Kuchen Bean, ejbSelectMaxId-Methode (Schritt 1)
Die Query sieht so aus:
select max (o.id) from Kuchen o
Kuchen Bean, ejbSelectMaxId-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 "ejbHomeGetNextId" abgerufen (diese wiederum greift auf "ejbSelectMaxId" zu) und in der Bean gesetzt:
	this.setId (this.ejbHomeGetNextId() )
Alternativ hätten wir hier auch über das Home-Interface gehen können:
	this.setId ( ( (KuchenLocalHome) (this.getEntityContext().getEJBLocalHome())).getNextId() ); 
"ejbHomeGetNextId" muss auf das Home-Interface hochgestuft werden.

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 im EJB-Implementierungsdeskriptor unter "Queries" 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 !):
Es wird eine ejbSelect-Methode hinzufügt, um den bisherigen maximalen Primary Key-Wert der Tabelle zu ermitteln.
Dazu im EJB-Implementierungsdeskriptor der Bean unter "Queries" eine neue hinzufügen. Wir fügen eine neue Methode namens "ejbSelectMaxId" zu, die den Rückgabetyp "Integer" hat.
Zutat Bean, ejbSelectMaxId-Methode (Schritt 1)
Die Query sieht so aus:
select max (o.id) from Zutat o
Zutat Bean, ejbSelectMaxId-Methode (Schritt 2)
Das Ergebnis mit den beiden Methoden sollte so aussehen:
ZutatBean: Queries

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 "ejbHomeGetNextId" abgerufen (diese wiederum greift auf "ejbSelectMaxId" zu) und in der Bean gesetzt:
	this.setId (this.ejbHomeGetNextId() )
"ejbHomeGetNextId" muss auf das Home-Interface hochgestuft werden.

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-Deploymentdeskriptor wählt man die Kuchen-Bean und geht zu "Beziehungen".
Kuchen: Relationship, Schritt 1
Man klickt auf "Add". Im etwas verwirrenden Assistenten wählen wir links die Kuchen-Bean aus, rechts die ZutatBean.
Bei der ZutatBean ändern wir den Rollennamen von "zutat" auf "zutaten" (so soll unsere abstrakte Property heißen), wählen als "Multiplicity" "0..*" und setzen in dem Kasten "Role name" die Checkbox "Cascade delete".
Kuchen: Relationship, Schritt 2
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.
Achtung, Bug: Beim nachträglichen Öffnen des Dialogs kann es sein dass man die EJB-Relationship zerstört (siehe
hier).

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 Dynamic Web Projects "KuchenZutatWeb" wechseln und unter "Java JAR Dependencies" das EJB-JAR wählen.
EJB-Verweise festlegen:
Im Webimplementierungsdeskriptor auf die Registerkarte "References" wechseln und lokale Verweise "ejb/Kuchen" und "ejb/Zutat" auf Kuchen bzw. Zutat zufügen. Das Ergebnis sieht so aus:
EJB-Referenzen
Es müssen vier JSP-Seiten "Kuchen.jsp", "KuchenEdit.jsp", "KuchenZutaten.jsp", "KuchenZutatEdit.jsp" zugefügt werden (Rechtsklick auf "Dynamic Web Projects" -> "KuchenZutatWeb", im Contextmenü "New" -> "JSP File" wä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 "Run" -> "Run on Server..." starten. Wichtig ist, dass in Schritt 3 (nach der Auswahl des Servers und der auszuführenden Enterprise Application) 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.


Ein Blick in die Datenbank

Mittels des Tools Cview können wir einen Blick in die Datenbank werfen.
Die Tabelle KUCHEN sieht so aus:
Tabelle KUCHEN
Die Tabelle ZUTAT sieht so aus:
Tabelle ZUTAT
Man beachte das zusätzliche erzeugte Feld "KUCHEN_ID" mit dem Foreign Key auf den Kuchen. Der zugehörige Foreign Key heißt im Beispiel "C6103860".
Foreign Key



Version 1.0.1.3, Stand 06.12.2005
Historie:
1.0.0.0 (12.10.2005): Erstellt
1.0.1.0 (29.10.2005): Datenbank im Projekt auf "KnaufDB" geändert.
1.0.1.1 (10.11.2005): Code in KuchenZutat.jsp aufgeräumt, Verweis auf Bug mit EJB-Relationships.
1.0.1.2 (17.11.2005): Alle ejbCreate-Methoden geben jetzt (gemäß EJB-Spezifikation) null zurück.
1.0.1.3 (06.12.2005): Dateiname für Bildreferenz korrigiert.