Componentware/Zur Version 2.0 der Spezifikation von Enterprise Javabeans

EJB 2.0: Fortschritt mit Lücken

08.06.2001
Ende April 2001: Die Welt wartet auf die endgültige Version 2.0 der Spezifikation von Enterprise Javabeans (EJB 2.0). Da erscheint die zweite Version des "vorgeschlagenen endgültigen Entwurfs" (Proposed Final Draft 2) der Spezifikation, die noch signifikante Änderungen gegenüber dem ersten Entwurf enthält. Hier ein Überblick, was sich das EJB-Team hat einfallen lassen. Von Volker Koch*

Die Spezifikationen vor EJB 2.0 wiesen Mängel auf: So fanden Aspekte wie Beziehungen zwischen und Vererbung von Komponenten oder die Möglichkeiten für asynchrone Komponentenaufrufe keine oder eine nur unzureichende Berücksichtigung. Besonders im Bereich der Entity Beans waren immer wieder Vorbehalte zu hören, sie seien zu langsam, besäßen die Tendenz, zu feingranular entworfen zu werden, und hätten keine einheitliche Abfragesprache. Zudem seien die Möglichkeiten, ein Container-managed-Persistence (CMP) Entity Bean auf eine Datenbank abzubilden, zu eingeschränkt, da meist nur eine Eins-zu-Eins-Abbildung zwischen Entity Bean und Tabelle möglich war. EJB 2.0 hat sich dieser Probleme - bis auf die Vererbung - angenommen und Lösungen präsentiert.

Verzicht auf Dependant ObjectsDie signifikanten Veränderungen vom ersten zum zweiten Entwurf der Spezifikation stecken in der zusätzlichen Einführung von Local Interfaces in Ergänzung zu den Remote Interfaces sowie in dem Verzicht auf Dependant Objects, die seit der ersten, Anfang Juni 2000 veröffentlichten Version Bestandteil der Spezifikation waren. Die Dependant Objects stellten einfache persistente Java-Objekte dar, die einen ähnlichen Persistenzmechanismus wie Container-managed Entity Beans nutzen sollten, ohne jedoch deren Overhead zu besitzen. Ferner sollte es nur über ein Entity Bean möglich sein, diese Objekte zu manipulieren. Sie hatten dem Zweck zu dienen, die Performance der persistenten Objekte (bestehend aus Entity Beans und Dependant Objects) zu erhöhen sowie grobgranularere Komponenten zu ermöglichen.

Die Dependant Objects wurden mit dem zweiten Entwurf ersatzlos gestrichen. Dafür führte man das Konzept der Local Interfaces nicht nur für Entity Beans, sondern auch für Session Beans ein. Die Remote Interfaces bestehen aus dem bisherigen Remote Interface (man beachte die geschickt gewählte Namensgebung) und dem bisherigen Home Interface (künftig Remote Home Interface). Die Local Interfaces stellen Pendants dazu dar: das Local Interface ("Vaterinterface EJBLocalObject") und das Local Home Interface ("Vaterinterface EJBLocalHome"). Diese besitzen die jeweils identischen fachlichen Aufgaben und technischen Namenskonventionen wie ihre Remote-Pendants (siehe Abbildung oben).

Die Local Interfaces dienen als Schnittstelle zu einem EJB innerhalb derselben Virtual Machine und sind nicht von einem entfernten Client etwa über RMI ansprechbar. Im Gegensatz zu den Remote Interfaces, die von Servlets, Applets und EJBs im gleichen oder einem anderen EJB-Container angesprochen werden können, sind die Local Interfaces nur von EJBs ansprechbar, die sich physisch im selben EJB-Container befinden. Dies hat den Vorteil, dass beim Aufruf eines EJBs der RMI- beziehungsweise Corba-Call eingespart und durch einen direkten Methodenaufruf ersetzt wird. Ferner werden Objekte bei den Local Interfaces nicht per Kopie (serialisiert), sondern als Referenz übergeben, was den Serialisierungs-Overhead vermeidet.

Overhead deutlich abgebautDer Bean Provider hat nun die Wahl, ob er für sein EJB die Remote Interfaces, die Local Interfaces oder beide Arten zur Verfügung stellt. Man kann mit den Local Interfaces einen adäquaten Ersatz der Dependant Objects erreichen. Typische Anwendungsdesigns sehen ohnehin vor, dass die Schnittstelle, die einem Client (Servlet, Applet, Anwendung) zur Verfügung gestellt wird, durch Session Beans definiert wird. Diese Session Beans stellen dann üblicherweise eine Prozess-Schicht dar und kapseln den Zugriff auf die Entity Beans vollständig. Die Session Beans besitzen somit Remote Interfaces, während die Entity Beans lediglich Local Interfaces haben, die von den Session Beans benutzt werden.

Damit sind die Ziele des geringeren Overheads bei der Verwendung von Entity Beans sowie der höheren Performance und der Möglichkeit zu grobganulareren Komponenten ebenso - möglicherweise noch besser - erreichbar wie bei den Dependant Objects. Ein weiterer Vorteil gegenüber den Dependant Objects besteht darin, dass statt zwei lediglich ein Programmiermodell (Entity Beans) für persistente Objekte existiert, was die Arbeit für den Bean Provider erleichtert.

Grundlegend überarbeitetes PersistenzkonzeptDer erste Entwurf sah außerdem eine weitere Rolle im Entwicklungsprozess vor, welche die Implementierung der Persistenz von CMP Entity Beans übernehmen sollte: der Persistence Manager Provider. Diese Rolle wurde im zweiten Entwurf ebenfalls gestrichen. Seine Aufgaben nimmt nun im Wesentlichen der EJB Container Provider wahr. Die Grundidee des überarbeiteten Persistenzmechanismus ist jedoch erhalten geblieben und sieht die Unterbringung der fachlichen Funktionalität sowie der Persistenzabwicklung in zwei unterschiedlichen Klassen vor.

Zu diesem Zweck schreibt der Bean Provider eine abstrakte Bean-Klasse. Diese enthält entgegen der EJB-1.1-Version keine Attribute mehr, die den persistenten Zustand repräsentieren. Vielmehr existieren abstrakte "getter/setter"-Methoden für den Zugriff auf diese Attribute. Außerdem beinhaltet die Bean-Klasse den fachlichen Code.

Der Bean Deployer ist verantwortlich, dass eine konkrete Unterklasse der Bean-Klasse mit Hilfe der Werkzeuge des Container Providers erzeugt wird. Die Unterklasse kümmert sich ausschließlich um die Persistenz der Attribute durch die Implementierung der abstrakten getter/setter-Methoden.

Dadurch ist es theoretisch möglich, ein beliebiges Persistenz-Framework in den Application-Server zu integrieren, das ausgefeiltere und Performance-stärkere Mechanismen besitzt als beispielsweise das Eins-zu-Eins-Mapping von Entity Beans auf Tabellen. Diese Vorgehensweise lässt sich bereits auf einem Container simulieren, der nur EJB 1.1 unterstützt. Dazu erhebt man die generierte Unterklasse zur Bean-Klasse, kennzeichnet das Entity Bean als "bean-managed" und verwendet den EJB 1.1 Deployment Descriptor.

Behandlung von BeziehungenDurch die Einführung von automatisch verwalteten Beziehungen zwischen CMP Entity Beans wird der Bean Provider weitestgehend von dieser Aufgabe entlastet. Er muss dafür entsprechend abstrakte getter/setter-Methoden für die Beziehung in der Bean-Klasse definieren. Der Parameter beziehungsweise Rückgabewert besteht bei einer Zu-1-Beziehung aus dem Local Interface des referenzierten EJBs, bei Zu-n-Beziehungen hingegen aus einer vom Container zur Verfügung gestellten Implementierung der Interfaces "java.util.Set" oder "java.util.Collection".

Die entsprechenden Methoden sind Bestandteil des Local Interface, das bei der Verwendung von Beziehungen zwingend vorgesehen, aber nicht Bestandteil des Remote Interface ist. Um die Beziehung zu manipulieren oder zu lesen, sind entweder die abstrakten Methoden (aus der Bean-Klasse selbst) oder die Methoden des Local Interface (andere EJBs im selben Container) zu verwenden. Als Beziehungstypen sind sowohl bidirektionale als auch unidirektionale sowie 1:1-, 1:n-, m:1- und m:n-Beziehungen möglich. Diese können - bis auf die m:n-Beziehung - über den Deployment Descriptor mit einem Mechanismus für kaskadierendes Löschen versehen werden. Der Container Provider sorgt für die Implementierung der abstrakten Methoden in der generierten Unterklasse. Dies bietet die Möglichkeit, Beziehungen erst beim direkten Zugriff von der Datenbank nachzuladen.

Message Driven BeansDurch EJB 2.0 wird eine neue, dritte Bean-Art neben Session und Entity Beans eingeführt: die Message Driven Beans. Diese Beans besitzen weder Local noch Remote Interfaces. Sie stellen Empfänger von Nachrichten aus einer JMS Queue oder einer JMS Topic dar. Mit dem Java Messaging Service (JMS) lassen sich Nachrichten asynchron verschicken. Eine JMS Queue ist eine Warteschlange, in der es genau einen Empfänger der Nachricht gibt (Beispiel: Mail). Hingegen ist eine JMS Topic am ehesten mit einem Chatroom vergleichbar, da sie beliebig viele Empfänger haben kann. Ein Client verschickt eine Nachricht über JMS, die asynchron an einen - bei Topic - oder mehrere dort registrierten Message Listener ausgeliefert wird. Ein Message Driven Bean ist ein solcher Message Listener.

Die Verwendung des Message Driven Beans hat gegenüber dem herkömmlichen Message Listener den Vorteil, dass eingehende Nachrichten parallel von mehreren Bean-Instanzen bearbeitet werden können, was üblicherweise nur durch Eigenimplementierung zu realisieren wäre. Der EJB-Container hält zu diesem Zweck einen Pool von Instanzen der Bean-Klasse. Dabei ist zu beachten, dass ein Message Driven Bean wie ein Stateless Session Bean keinen Status besitzt.

Erweiterte SucheMit EJB 2.0 wird ein weiteres Hindernis für die Übertragbarkeit von CMP-EJB-Komponenten auf andere Application-Server beseitigt. Bisher besitzt jeder Application-Server eine eigene Abfragesprache für die Beschreibung der Finder-Methoden von CMP Entity Beans. Die EJB Query Language (EJB QL) standardisiert diese Abfragesprache. Die Entity Beans sowie die Beziehungen und persistenten Attribute definieren über den Deployment Descriptor ein abstraktes Persistenzschema, ähnlich einem Datenbankschema. Mit dem an SQL-92 orientierten EJB QL ist es möglich, über das Persistenzschema Suchen auszuführen, von Objekt zu Objekt zu navigieren, Parameter von Finder-Methoden in die Anfrage zu integrieren und Finder-Methoden aufzurufen. Da es sich um eine reine Abfragesprache handelt, können nicht wie bei OQL (Object Query Language) beliebige Methoden der Objekte aufgerufen oder Datenbank-Änderungen vorgenommen werden. Über den Deployment Descriptor wird jeder Finder-Methode eines CMP Entity Beans ein EJB-QL-Ausdruck zugeordnet. Dieser wird vom Container Provider beim Erzeugen der entsprechenden "ejbFindXXX(...)"-Methode in der Bean-Unterklasse ausgewertet.

Finder-Methoden werden üblicherweise von Clients eines Entity Beans aufgerufen. Für CMP Entity Beans werden zusätzlich Select-Methoden eingeführt, die von der Bean-Klasse intern aus der Business-Logik heraus aufgerufen werden. Im Gegensatz zu den Finder-Methoden, bei denen das Ergebnis immer ein EJB des jeweiligen EJB-Typs ist (beziehungsweise eine Menge davon), kann das Ergebnis einer Select-Methode ein einzelnes Attribut eines EJBs sein. Der Bean Provider definiert zu diesem Zweck eine abstrakte "ejbSelectXXX(...)"-Methode, die nach Auswertung des im Deployment Descriptor definierten EJB-QL-Ausdrucks wiederum in der generierten Unterklasse implementiert wird.

Eine weitere Neuerung hat in beide Home-Interfaces von Entity Beans Einzug gehalten: die Home-Business-Methoden. Diese Methoden sind keine Create-, Finder- oder Remove-Methoden und keiner konkreten Instanz eines Entity Beans zuordenbar. Stark vereinfacht ausgedrückt handelt es sich dabei um quasi-statische EJB-Methoden, auch wenn diese Methoden in Java nicht statisch implementiert werden. Beispielweise könnte eine Bank über eine Home-Methode die Zinsgutschrift für alle ihrer Festgeldkonten ausführen oder ein Unternehmen seinen Mitarbeitern die jährliche Prämie ausbezahlen. Die Implementierung der Home-Methode (ejbHome<Method>(...)) wird in der Bean-Klasse durch den Bean Provider vorgenommen. Bei der Ausführung dieser Methode wird, ähnlich wie bei den Finder-Methoden, eine Instanz der Bean-Klasse aus dem Instanzen-Pool verwendet, der aktuell keine Identität im Sinne eines Primärschlüssels zugeordnet wird.

Es gibt also einige wesentliche Verbesserungen in der Spezifikation 2.0. Umso unverständlicher ist die Tatsache, dass das Problem der Vererbung von Entity Beans in der neuen Version nicht gelöst wurde. Die primäre Problematik besteht nicht darin, dass keine Vererbung der jeweiligen Klassen und Interfaces auf Ebene der Programmiersprache durchgeführt werden kann, sie liegt vielmehr im Verhältnis der Primärschlüssel von Ober- und Untertyp. Zudem ist aus einem Primärschlüssel nicht erkennbar, zu welchem EJB-Typ er gehört.

Nicht nachvollziehbar ist auch, weshalb die Rolle des Persistence Manager Providers gestrichen und dessen Aufgaben dem Container Provider zugeschlagen wurde. Dadurch wird die Integration von Persistenz-Frameworks von Fremdherstellern in einen Application-Server erschwert, da der Anbieter des Application-Servers nun nicht mehr gezwungen ist, bestimmte Schnittstellen für eine nahtlose Integration zur Verfügung zu stellen. Vielleicht war genau das der Sinn dieser Maßnahme.

Ein weiteres Problem der bisherigen EJB-Entwicklung stellt der Deployment-Vorgang dar. Es ist sehr häufig zu beobachten, dass gängige Application-Server-Hersteller davon ausgehen, EJB sei fehlerfrei und vor allem auf Anhieb zu entwickeln. Dies ist jedoch bei der Komplexität der EJB-Spezifikation nicht möglich. Hier sollte hinsichtlich der Spezifikation über Lösungsmöglichkeiten hinsichtlich der Spezifikation nachgedacht werden.

Fazit: Bei der Entwicklung der neuen Spezifikation wurden viele Probleme der ersten berücksichtigt und überzeugende Lösungsansätze präsentiert. Inwieweit diese in der Praxis zu positiven Ergebnissen führen, lässt sich erst durch die Verfügbarkeit entsprechender Implementierungen beurteilen.

*Diplominformatiker Volker Koch ist Seniorberater bei der IBL Ingenieurbüro Letters GmbH, ein Unternehmen der Plenum AG.

Links

EJB-Homepage

http://java.sun.com/products/ejb

J2EE Referenzimplementierung

http://java.sun.com/j2ee

EJB-2.0-BewertungVorteile:

+ asynchrone Kommunikation,

+ Local Interfaces,

+ grundlegend renovierte Persistenz,

+ grobgranularere Komponenten,

+ automatisches Beziehungs-Management,

+ einheitliche Abfragesprache,

+ quasi-statische Bean-Methoden.

Nachteile:

- Komponentenvererbung,

- Verzicht auf die Rolle des Persistenz- Managers,

- Bindung der Hersteller an Deployment- Standards.

Abb.1: Remote und Local Interfaces

Quelle: Plenum

Abb.2: Message Driven Beans

Beispiele für den Gebrauch von Message Driven Beans im Zusammenpiel mit JMS Queues beziehungsweise Topics. Quelle: Plenum