Bericht:

"EJB’s mit WebSphere Application Developer"

 

Untertitel: Vereinfachung der Programmierung von verteilten Objekten

 

Einleitung:

In der Softwareentwicklung werden heute fast nur noch verteilte Anwendungen realisiert.

Hier haben sich so genannte „Enterprise Java Beans“ als Standardlösung etabliert. Da die Anwendung aus verschiedenen Schichten besteht, wird der Entwicklungsprozess wesentlich erschwert. Mithilfe von WebSphere Application Developer lässt sich diese Aufgabe jedoch bewältigen.

 

Fließtext:

Das Enterprise Java Beans-Komponentenmodell ist prädestiniert zur Entwicklung von funktionstüchtigen und leistungsfähigen Komponenten für den Server. Diese können auf eine Vielzahl von Servern verschiedenster Anbieter ablaufen. Der Entwickler kann plattform-neutrale, verteilte, transaktionsorientierte Anwendungen realisieren. Dabei definiert das Enterprise Java Beans-Modell eine strikte Trennung zwischen der anwendungsspezifischen Geschäftslogik und den einzelnen Systemfunktionen. So kann der Anwendungsentwickler sich auf die Entwicklung der Geschäftslogik eines bestimmten Anwendungsbereiches (EJB) konzentrieren. Die Realisierung von komplexen Systemfunktionen wie Transaktionsverwaltung, die Persistenz der Objekte und die Systemsicherheit bleibt außen vor. Die EJB-Architektur führt automatisch alle nötigen Systemoperationen aus, wovon der Entwickler nichts mitbekommt. Sie stellt alle Basisfunktionalitäten bereit. Mit dessen Hilfe lassen sich Komponenten endlich über die Grenzen der Hardware, Betriebssystem und der Middleware verwenden. Der Entwicklungsaufwand wird gleichzeitig in Grenzen gehalten und somit die Investitionen gesichert.

 

Die EJB-Architektur:

Die EJB-Architektur ermöglicht die Kommunikation mit jeglicher Clientanwendung, da sie protokollunabhängig implementiert wurde. Der EJB-Server stellt eine Reihe von Diensten bereit, um die Installation einer EJB-Komponente zu vereinfachen. Unter anderem sind dies die Systemdienste zur Verwaltung von verteilten Objekten und der Aufruf dieser EJB-Objekte. Natürlich gibt es auch noch andere Systemdienste. Hierzu ein Beispiel, welchen Nutzen die EJB-Architektur bietet. Als Beispiel-Szenario nehmen wir eine Bank-Anwendung. Ein Benutzer will zum Beispiel von zu Hause auf alle seine Bankkonten zugreifen. Dabei ist es unerheblich, wo die Daten „real“ vorliegen. Die EJB-Architektur greift über eine Schnittstelle auf die reale Implementierung der Bank zu. Die Finanzanwendung auf dem Client nutzt das entfernte Objekt. Über den Mechanismus „Introspektive“ ermittelt der Client, wozu das Objekt in der Lage ist. Dabei agiert die EJB-Komponente transaktionsorientiert. Der Client kann eine Reihe von Operationen auf das Konto durch eine einzige Transaktion durchführen lassen. Dabei kann die Transaktion bestätigt oder auch wieder zurückgenommen werden. In einer verteilten Welt ist dies ein kritischer Vorgang. Es muss auf jeden Fall sichergestellt sein, dass die Transaktion wirklich komplett abgeschlossen ist, bevor eine Auszahlung gewährt wird.  Der Transaktionsmechanismus stellt sicher, dass bei einem Verbindungsfehler ein Ausnahmefehler ausgelöst und die Transaktion zurückgeschrieben wird. Die EJB-Architektur erledigt diese Aufgabe ohne unser zutun.

 

Die EJB-Basics:

Eine EJB-Komponente ist nichts anderes als ein  „serverseitiges Objekt“ mit einer konkret spezifizierten Aufgabe. Jede EJB läuft innerhalb einer Schutzzone einem so genannten Container ab. Der Container regelt dabei die Kommunikation mit anderen EJB-Objekten. Über die portable Schnittstelle wird der Außenwelt der Zugriff auf die EJB gewährt. Bei der Entwicklung von Internet-Anwendungen wird häufig eine Multi-Tier-Architektur verwendet. Hierbei übernimmt der Client nur die Aufgabe der Darstellung und einen kleinen Teil der Verarbeitung der Daten. Jedoch greift die Client-Anwendung für weitere Funktionalitäten auf einen Applikationsserver und für Daten auf einen Datenbankserver zu. Innerhalb der mittleren Schicht werden die EJB-Komponenten bereitgestellt, welche die  Verarbeitung der Geschäftslogik durchführt. Die EJB-Spezifikation engt die Komplexität einer verteilten Systemarchitektur ein und schafft auf einfachste Weise eine Schnittstelle zwischen EJB Server und den EJB-Komponenten.

 

Verschiedene Typen von EJBs:

Die Herausforderung bei der EJB-Entwicklung stellt die Komplexität der beiden Gruppen von möglichen EJB Komponenten dar. So genannte „Session Beans“ werden zur Behandlung von Geschäftslogiken verwendet und können daher nur einen statuslosen oder einen bestimmten Status besitzen. Die Session Beans mit einem speziellen Status existieren nur für die Laufzeit einer Client/Server Sitzung. Eine statuslose Session Bean hingegen wird in einem Container verwaltet, um mehrere Anfragen von den unterschiedlichsten Clients zu behandeln. Im Vergleich bestehen so genannte „Entity Beans“ aus individuellen Einheiten (Entities) und werden innerhalb einer Anwendung genutzt, um Datenpersistenz und Daten Modellierung zu regeln. Eine Entity Bean kann dabei entweder die Verwaltung der Persistenz einem Container überlassen oder die Persistenz über eine eigene Implementierung abwickeln. Daher werden diese entweder „CMP“ oder „BMP“ genannt. Eine CMP Entity Bean lässt die Datenpersistenz über einen Container verwalten. Eine BMP Entity Bean verwaltet diese selber.

 

WebSphere:

Da die EJB-Entwicklung recht komplex ist, sollte man den Prozess mithilfe von Werkzeugen automatisieren. WebSphere stellt verschiedene Wizards für die unterschiedlichsten Aufgaben zur Verfügung. Diese unterstützen konsequent den gesamten Entwicklungsprozess und reichen vom Anlegen der EJB und geht bis zur  Bereitstellung, Austesten und Zusammenpacken der EJBs.

Zu Demonstrationszwecke legen wir hier eine Konto-Bean an. Mithilfe dieser Bean lassen sich neue Konten anlegen oder dessen Konto-Nr, Konto-Inhaber oder Kontostand abfragen oder setzen. Entsprechende Methoden sind innerhalb der Bean zu implementieren. Nach dem Start der WebSphere Entwicklungsoberfläche wird eine individuelle Perspektive anzeigt. Sie bietet einen Überblick über den jeweiligen Projekttypus (Web, EJB, Server).

 

Im ersten Entwicklungsschritt ist ein EJB-Projekt anzulegen.

Der Entwickler ruft den entsprechenden Wizard (New Project) über den Menüpunkt „File->New->EJB Project“ auf. Im Folgedialog ist auf der linken Seite der Eintrag „EJB“ zu selektieren und kann darauf den Eintrag „EJB-Project“ auswählen. Über „Next“ wird die nächste Seite des Wizards angezeigt. Dort ist lediglich der Projektname (MyProject) einzugeben. Schon  kann der Wizard über „Finish“ wieder beendet werden. Innerhalb der WebSphere IDE wird jetzt automatisch die J2EE-Perspektive eingeblendet, wodurch eine optimale EJB-Entwicklung sichergestellt werden soll. Die Verwaltung der EJBs erfolgt laut J2EE-Spezifikation innerhalb so genannter Module. Das J2EE-Ansichtsfenster ist in folgende Module unterteilt:

 

1) Enterprise Applications

2) Application Client Modules

3) Web Modules

4) EJB Modules

5) Server Configurations

6) Server Instances

7) Databases

 

Innerhalb des Ordners „EJB Modules“ wird unser neues EJB-Projekt abgelegt. WebSphere legt parallel ein korrespondierendes EAR-Projekt innerhalb des Ordners „Enterprise Applications“ ab.

 

Ihre erste Bean:

Anschließend ist die Enterprise Bean anzulegen. Für diese Aufgabe nimmt man am besten den EJB-Wizard zur Hilfe. Der Entwickler selektiert das entsprechende EJB-Projekt mit der rechten Maustaste und kann über den Kontextmenüeintrag „File->New->Enterprise Bean“ den Wizard starten. Im Dialog ist der Name der Bean einzugeben und der Typ der Bean (Session, BMP Entity oder CMP Entity) zu bestimmen.

 

Soll wie bei uns eine CMP Entity Bean erzeugt werden, sind die einzelnen Datenfelder der Bean anzulegen. Die KontoBean benötigt die Felder KontoNr, Inhaber und Kontostand. Über die Schaltfläche „Add“ fügt man die einzelnen Felder der Bean hinzu.

Im Dialog (Create Persistence Field) ist der Feldname (KontoNr) und der Feldtyp (int) als erstes zu bestimmen. Daraufhin kann über die Checkbox „KeyField“ bestimmt werden, ob das Feld als Verwaltungsschlüssel dienen soll. Ob entsprechende Getter und Setter –Methoden für das Feld erzeugt werden, gibt man über die Checkbox „Access with Getter and Setter methods“ vor. Sollen diese Methoden ebenfalls in der entfernten Schnittstellen aufgenommen werden, ist die Checkbox „Promote Getter and Setter methods to remote interface“ anzuklicken. Auf Basis dieser Konfiguration legt der Wizard die einzelnen Dateibezeichnungen (Bean Class, Home Interface, Remote Interface)

fest. Nun kann der Wizard wieder über „Finish“ beendet werden.

Der Wizard generiert daraufhin automatisch eine Standard-Bean.

 

Innerhalb der J2EE-Ansicht wird das Ergebnis der Generierungsprozess deutlich. Ein Doppelklick auf die Bean und die generierten Dateien werden aufgelistet. Es wurde die Bean und die Home- und Remote Schnittstellen erzeugt. Selbstverständlich lässt sich die EJB noch modifizieren. WebSphere stellt für diese Aufgabe den leistungsstarken EJB-Editor zur Verfügung, welcher die Korrektheit des Codes automatisch prüft. Per Doppelklick auf ein EJB-Projekt, und der EJB-Editor wird aufgerufen. Der Editor verfügt über verschiedene Registerreiter (General, Bean, Security, Transaction, Environment)

zur Konfiguration der verschiedenen Aspekte einer Bean. Der Registerreiter „Bean“ listet alle Beans eines EJB-Projekts innerhalb der linken Seite auf. Jetzt ist eine Bean auszuwählen die konfiguriert werden soll. Daraufhin werden alle Informationen der Bean auf der rechten Seite angezeigt. Dies umfasst die:

 

1)Bean Klasse

2)Home Schnittstelle

3)Remote Schnittstelle

4)und die Attribute der Bean.

 

Per Schaltfläche "Edit" lässt sich jeder Eintrag beliebig editieren. Ebenso kann eine neue Bean erzeugt oder eine alte Bean gelöscht werden.

 

Implementierungsdetails:

Für jede EJB-Klasse ist eine entfernte (remote) und eine lokale (local) Schnittstelle anzulegen. Zur Arbeitserleichterung generiert der Wizard diese automatisch für uns. Die entfernte Schnittstelle nutzt die Clientschicht, um die Geschäftsmethoden der EJB auszuführen. Darüber kann bei der KontoBean erfragt werden, wer der Kontoinhaber ist oder wie der aktuelle Kontostand ist. Ebenso lassen sich die einzelnen Attribute einer Bean darüber setzen. Mittels öffentlicher Methoden set() und get() greifen wir auf die internen Attribute der Bean-Klasse zu. Die lokale Schnittstelle definiert für die Clientschicht die Lebensmöglichkeiten der EJB-Objekte. Dies kann das Anlegen oder Löschen einer EJB sein. Per Default sind alle Schnittstellenmethoden innerhalb der EJB-Klasse zu implementieren. Dies betrifft in unserem Fall die Methodensignaturen setKontoNr(), setKontoInhaber(), setKontoStand() und getKontoNr(), getKontoInhaber(), getKontoStand(). Sobald die EJB erschaffen wurde, übernimmt der Container die Verwaltung. Dies geschieht durch die Generierung der Implementierungsklasse für die entfernte und lokale Schnittstelle. Standardmäßig werden solche Schnittstellen innerhalb von Modulen organisiert. Die entfernte Schnittstelle der KontoBean hat folgenden Aufbau:

 

#Code1:#

package unixopen;

import java.rmi.RemoteException;

public interface Konto extends javax.ejb.EJBObject {

   public int getKontoNr() throws RemoteException;

   public float getKontostand() throws RemoteException;

   public String getKontoInhaber() throws RemoteException;

 

   public int setKontoNr() throws RemoteException;

   public float setKontostand() throws RemoteException;

   public String setKontoInhaber() throws RemoteException; }

 

Nachdem die entfernte Schnittstelle definiert ist, definieren wir die Sicht der realen Welt bzw. der Öffentlichkeit auf diese Entity Bean. Dazu definieren wir die Home-Schnittstelle für die Bean. Dies gibt an, wie die Bean angelegt werden kann, diese zu lokalisieren ist und auch wieder zerstört werden kann. Diese Methoden stellen das mögliche Verhalten einer Bean zur Laufzeit dar. Hier die Definition der Home-Schnittstelle für die KontoBean im Detail:

 

#Code2:#

package unixopen;

 

import java.rmi.RemoteException;

import java.ejb.CreateException;

import java.ejb.FinderException;

 

public interface KontoHome extends javax.ejb.EJBHome {

   public Konto create(int id) throws CreateException, RemoteException;

   public Konto findByPrimaryKey (KontoPK pk) throws FinderException, RemoteException; }

 

Die Schnittstelle „KontoHome“ wird von der Schnittstelle „EJBHome“ abgeleitet. Diese gibt eine Methode vor, um Beans zu löschen, so dass KontoHome diese automatisch erbt. Die Implementierung von KontoHome ist somit gezwungen, so eine Methode zu implementieren. Die KontoHome-Schnittstelle definiert die zwei Methoden create() und findByPrimeryKey(). Durch diese Methoden wird eine Bean angelegt oder lokalisiert. Damit die Schnittstelle auch gefunden wird, sollte diese sich im gleichen Projektverzeichnis befinden, wie die gewöhnlichen Klassen auch.

 

Die Entity Bean-Implementierung:

Nun die eigentliche Implementierung der Bean. Unsere KontoBean ist eine CMP EntityBean.

Die Persistenz der Datenfelder wird durch den Container sichergestellt. Somit fällt dessen Implementierung simpel aus. Zusätzlich zu den Methoden der EJB sind alle Methoden der entfernten und lokalen Schnittstelle zu implementieren. Hier der interne Aufbau unserer

KontoBean Klasse:

 

#Code3:#

package unixopen;

import javax.ejb.EntityContext;

 

public class KontoBean implements javax.ejb.EntityBean {

public int id;

public int kontonr;

public float kontostand;

public String kontoinhaber;

 

public void ejbCreate (int id)

{ this.id = id; }

public void ejbPostCreate (int id)

{ // hier ist nichts notwendig! }

 

public int getKontoNr()

{ return kontonr; }

public float getKontostand()

{ return kontostand; }

public String getKontoInhaber()

{ return kontoinhaber; }

 

public void setKontoNr(int nr)

{ kontonr = nr; }

public void setKontostand(float stand)

{ kontostand = stand; }

public setKontoInhaber(String name)

{ kontoinhaber = name; }

 

public void setEntityContext (EntityContext ctx)

{ // nicht implementiert! }

public void unsetEntityContext()

{ // nicht implementiert! }

public void ejbActivate()

{ // nicht implementiert! }

public void ejbPassive()

{ // nicht implementiert! }

public void ejbLoad()

{ // nicht implementiert! }

public void ejbStore()

{ // nicht implementiert! }

public void ejbRemove()

{ // nicht implementiert! }

 

Innerhalb des Pakets „unixopen“ wird die Klasse „KontoBean „abgelegt, wo alle anderen Dateien ebenso liegen.  Die Klasse „KontoBean“ wird von der Klasse „EntityBean“ abgeleitet, welche fünf Methoden vordefiniert. Dies sind im Einzelnen EjbActivate(), ejbPassivate(), ejbLoad() ejbStore() und ejbRemove(). Der Container nutzt diese Methoden um die KontoBean über verschiedene Ereignisse (Events) zur Laufzeit zu informieren. Da diese Methoden bereits implementiert sind, braucht man diese hier nicht implementieren und kann diese somit leer lassen. Da die KontoBean einfach gehalten ist, benötigen wir keine spezielle Prozeßbehandlung zur Laufzeit.

Im Fall unserer KontoBean gibt es nur eine create() Methode, so dass es auch nur eine korrespondierende ejbCreate() Methode und eine ejbPostCreate() geben kann. Wenn ein Client eine Methode der Home-Schnittstelle aufruft, wird dies an die betreffende ejbCreate() Methode einer Bean Instanz delegiert. Die ejbCreate() Methode initialisiert dann die Felder, in unserem Fall also die KontoBean und setzt das ID-Feld auf einen übergebenen Integer-Wert. Nachdem die ejbCreate() ausgeführt wurde, wird die ejbPostCreate() aufgerufen und führt zur Erzeugung der Bean.

Die ejbCreate und ejbPostCreate Methoden müssen eine Signatur aufweisen die mit den Parametern und gegebenenfalls mit den Exceptions der Home-Schnittstellenmethode create() übereinstimmt. Wie auch immer, die ejbCreate und ejbPostCreate sind nicht nötig, um RemoteException oder CreateException werfen zu können. Der EJB Container führt diese Exceptions nämlich automatisch zur Laufzeit aus, wenn irgendwelche Probleme bei der Kommunikation oder andere systemspezifischen Probleme auftauchen.

Die entityspezfischen Methoden sind verantwortlich für das Setzen und Holen von Entity Contexten. Die EntityContext ist eine Schnittstelle, welche vom EJB-Container implementiert wird. Dieser liefert die Bean Informationen über den Container, die Identität des Clients, Transaktionskontrolle und andere Umgebungsinformationen, wenn die Bean diese benötigt. Da unserer Bean sehr einfach gehalten ist, benötigen wir diese Funktion nicht.

 

Die Datenbankschicht:

Jede Entity Bean muss die Geschäftsdaten sichern. Die Daten existieren nur solange, wie das Objekt im Speicher vorhanden ist. Man kommt nicht herum, diese innerhalb einer Datenbank abzulegen. Eine Konto-Bean muss beispielsweise Daten für die Kontonummer, den Kontoinhaber und den aktuellen Kontostand sichern. Nur so kann die Anwendung mit diesen Daten arbeiten. Zum Glück automatisiert WebSphere diese Aufgabe für uns. Es generiert ein Datenbank-Schema auf Basis der Entity Bean. Für jede Entity Bean wird eine Datenbank-Tabelle angelegt. Jedes Datenfeld der Bean zeigt auf eine bestimmte Spalte der Tabelle. Der Entwickler selektiert mit der rechten Maustaste das betreffende EJB-Projekt. Im Kontextmenü wählt er dann den Eintrag "Generate->EJB to RDB Mapping" aus, was den Wizard startet. Jetzt ist im Dialog der Eintrag „Top Down“ für den Entwickungsprozess auszuwählen. Über „Next“ gelangt man dann auf die nächste Seite des Wizards. Dort ist „InstantDB“ als Ziel-Datenbank auszuwählen. Dann ist der Datenbankname (KontoDB) einzugeben. Der Eintrag „Schema Name“ ist hier leer zu lassen. Zum Schluss ist die Checkbox „Generate DDL“ auszuwählen. Nun kann über „Finish“ der Wizard beendet werden, wodurch der Generierungsprozess startet. Das EJB-RDB-Mapping Tool zeigt im linken Fensterbereich die CMP-Felder der Entity Bean und im rechten Bereich die Datenbank Tabellen mit ihren einzelnen Feldern an.

 

Der Auslieferungsprozess:

Nun ist der optimale Projektzeitpunkt, um die Korrektheit des Codes vor der Auslieferung zu prüfen. Der WebSphere EJB Validator prüft, ob die Enterprise Java Bean der EJB-Spezifikation entspricht. Dieser Vorgang ist nur erfolgreich, wenn vorher das komplette Projekt kompiliert wurde. Der Validator prüft dabei alle Aspekte des Projektes. Zur Prüfung wählt man ein EJB-Projekt mittels rechter Maustaste aus und kann über den Kontextmenüeintrag „Run Validation“ den Prozess starten. Bevor es zur Auslieferung kommt, muss der Deployment-Code generiert werden. WebSphere führt dies mithilfe des EJB-Deploy-Tools durch. Innerhalb der Workbench kann über den Menüpunkt "Generate->Deploy Code & RMIC Stub" der Prozess angestoßen werden. Eine entsprechende JAR-Datei mit dem Deploy-Code wird daraufhin erzeugt. Öffnet man diese Datei, findet man eine Reihe von Klassendateien vor.

 

Test the Rest:

Im Anschluss sollte ein Test gefahren werden, ob die Anwendung auch funktioniert. Der Prozess kann lokal oder auf einem entfernten Applikationsserver ausgeführt werden. Dazu stellt WebSphere die Single Server Testumgebung bereit. Hierzu selektiert man ein EJB-Projekt mittels rechter Maustaste und ruft den Kontextmenüeintrag "Run On Server" auf. Daraufhin wird das EAR-Projekt auf dem Server veröffentlicht und der Server gestartet. Zu Testzwecken wird ein webbasierter EJB-Testclient für EJBs zur Verfügung gestellt. Als Erstes muss die Enterprise Bean erstmal auf dem Server ausfindig gemacht werden. Der JNDI-Explorer hilft bei dieser Aufgabe. Es ist der JNDI-Name einzutippen und kann dann über die Lookup-Funktion nach EJBs suchen. Sobald die Bean gefunden wurde, wird die Home-Schnittstelle der Bean innerhalb der EJB-Seite angezeigt. Die EJB-Seite ist in drei Teilbereiche untergliedert. Der Erste enthält alle Referenzen auf EJB-Objekte. Diese sind in Gruppen unterteilt. Der Zweite listet die Parameter für die aktuell selektierte Methode auf. Der Dritte zeigt die Ergebnisse aller Methodenaufrufe an.

 

Schluss:

WebSphere Application Developer ermöglichen es besonders leicht moderne Multi-Tier-Systeme zu entwickeln. Entsprechende Wizards begleiten aktiv den Entwicklungsprozess. Die fertigen Anwendungen sind beliebig skalierbar, sehr sicher, portabel und sehr robust. Die EJB-Architektur befreit dabei von der Systemprogrammierung und alle Systemoperationen werden automatisiert ausgeführt. Man braucht kein Experte mehr zu sein, um solche komplexen Anwendungen zu realisieren. Da die heutigen Internet-Anwendungen quasi alle auf einer Multi-Tier-Architektur basieren, kommt den „Enterprise Java Beans“ einen bedeutende Stellung zu. Den Grundstein hat aber die Firma Sun mit der EJB-Spezifikation gelegt.

 

Bildunterschriften:

Bild1.tif:

Das ist die Entwicklungszentrale von WebSphere Application Developer. Dem Einsteiger wird eine umfassende Einführung geboten.

Bild2.tif:

Beliebige Projekttypen lassen sich mithilfe eines Wizards anlegen.

Bild3.tif:

Mithilfe des Wizards wird hier eine Standard-EJB generiert. Diese lässt sich individuell konfigurieren.

Bidl4.tif:

Über den EJB-Editor kann eine Bean flexibel editiert werden.

Anpassungen lassen sich leicht vornehmen.

Bidl5.tif:

Über die J2EE-Ansicht wird jederzeit der Überblick über ein Projekt gewahrt.

Bidl6.tif:

Innerhalb der Entwicklungsoberfläche lassen sich verschiedene Perspektiven einnehmen.

Bild7.tif:

WebSphere verfügt über ein vielseitiges Hilfesystem.

Fast alle Themengebiete werden umfassend erläutert.

Bild8.tif:

Das EJB-RDB-Mapping Tool erlaubt die Datenbankstruktur einzusehen, welche für eine Entity Bean erzeugt wurde.