Componentware/Modellbasierende Generierung von EJBs

Komponentenentwicklung: Ganzheitlicher Prozess gefragt

15.12.2000
Beim Einsatz einer Komponententechnologie sieht man sich immer wieder mit der Frage konfrontiert, wie ein praktikabler Entwicklungsprozess aussieht und mit welcher Granularität Komponenten zu definieren sind. Steffen Müller* und Torsten Lodderstedt* zeigen am Beispiel der Technologie Enterprise Javabeans (EJB) einen Lösungsweg auf.

Objektorientierte Konzepte haben sich im Laufe des bald zu Ende gehenden Jahrzehnts in der Softwareindustrie erfolgreich etabliert. In zunehmendem Maße werden sie nun mit dem Prinzip der komponentenorientierten Softwareentwicklung verknüpft. Dafür gibt es mehrere Gründe: Zum einen sind Komponenten relativ unabhängige Bausteine, aus denen größere Systeme zusammengesetzt werden können, was wiederum die Wartbarkeit verbessert und die parallele Entwicklung in großen Teams erleichtert. Zum anderen können Komponenten mit Hilfe heutiger Techniken auf verschiedene Knoten in einem Netzwerk verteilt werden und so die Distribution von Anwendungen unterstützen mit dem Ziel, die Skalierbarkeit zu verbessern und die Ausfallsicherheit und effiziente Ausnutzung von Server-Ressourcen zu erhöhen.

Am Markt haben sich verschiedene Komponententechniken für die Verwendung in den unterschiedlichsten Anwendungskontexten etabliert, darunter COM+, Javabeans, EJB und Corba sowie Corba Components. Bei allen Unterschieden im Detail ist diesen Technologien ein generelles Komponentenkonzept gemein: Eine Komponente ist ein klar abgegrenzter, mit wohldefinierten Schnittstellen versehener Softwarebaustein, dessen Verwendung kein Wissen über sein Innenleben voraussetzt. Die verschiedenen Techniken haben sich in vielen Projekten für reale Systeme als tragfähig erwiesen.

Einige Fragen stellen sich jedoch in jedem Projekt aufs Neue, zum Beispiel: Woher kommen Komponenten beziehungsweise wie werden Kandidaten für Komponenten identifiziert? Welche Größe sollten Komponenten haben? Welche alternativen Mechanismen stehen dem Entwickler neben Komponenten zur Verfügung? Diese Fragen sind von grundlegender Bedeutung für den erfolgreichen und effizienten Einsatz der Technologie.

Generell gültige Antworten gibt es jedoch nicht, da jedes Komponentenmodell seine spezifischen Eigenschaften und Ziele hat. Um effiziente Anwendungen bauen zu können, müssen die technischen Eigenschaften eines Komponentenmodells und der beabsichtigte Einsatzzweck unbedingt berücksichtigt werden.

Diese Eigenschaften haben unter anderem Auswirkungen auf die empfehlenswerte Granularität einer Komponente und auf das Design ihrer Schnittstellen. Im Folgenden geht es um die Verwendung von Enterprise JavaBeans bei der Realisierung verteilter Systeme. Dabei wird ein ganzheitlicher Prozess für die Entwicklung von EJB-basierenden Anwendungen beschrieben, angefangen vom Business-Design über das Design der Komponenten bis hin zur Generierung von lauffähigen EJBs.

Am Anfang der Entwicklung steht das Business Object Model. Mit Hilfe der CRC-Technik (Classes, Responsibilities and Collaborationships) werden aus den vorhandenen Anwendungsfällen die relevanten Geschäftsobjekte herausgezogen und diesen Geschäftsobjekten Verantwortlichkeiten bei der Durchführung der Anwendungsfälle zugeordnet (siehe Abbildung 1 "CRC Modell"). Das CRC-Design wird in gemeinsamen Design-Sessions zwischen Fachleuten und Softwareingenieuren erstellt. Auf der Basis des Modells spielen die Teilnehmer die Anwendungsfälle durch und stellen sicher, dass alle notwendigen Objekte und Verantwortlichkeiten definiert worden sind. Ziel der Design-Session ist ein gemeinsames Verständnis über das fachliche Thema und das zu realisierende System.

CRC-Design verringert AbhängigkeitenDer Schwerpunkt des CRC-Designs liegt auf Objekten und den erforderlichen Protokollen für die Zusammenarbeit dieser Objekte bei der Realisierung von Anwendungsfällen. Es ist also ein verhaltensorientiertes Design, das im Gegensatz zu datenorientierten Ansätzen durch den Kommunikationsaspekt besser für die Entwicklung komponentenbasierender Systeme geeignet ist, da die Objekte schon mit Blick auf eine geringe Kopplung und Kapselung entworfen werden. Das konsolidierte fachliche CRC-Objektmodell wird anschließend nahtlos in Richtung eines Designmodells weiterentwickelt. Dazu wird für jedes Objekt regelbasierend definiert, wie seine Verantwortlichkeiten auf Attribute, Operationen oder Assoziationen verteilt sind.

Diese Elemente bestimmen das Protokoll, mit dem die fertige Komponente die entsprechende Verantwortlichkeit für andere Objekte und Anwendungen zur Verfügung stellt. Im nächsten Schritt wird auf Basis des verfeinerten fachlichen Modells ein komplettes technisches Designmodell entworfen. Ab diesem Zeitpunkt spielen die Möglichkeiten und Limitierungen der Zielplattform eine wichtige Rolle. Betrachtet man EJB 2.0 als Zielplattform, so lassen sich die verschiedenen Bausteine des EJB-Standards wie folgt skizzieren.

Kern der Technologie sind die EJBs. Diese Server-seitig ausgeführten instanziierbaren Komponenten existieren in drei Ausprägungen:

-Entity-Beans sind langlebige persistente Komponenten, auf die Anwendungen parallel und transaktionsgesichert zugreifen können.

-Session-Beans beinhalten den Teil der Anwendungslogik oder Unterstützungslogik, der auf dem Server ausgeführt wird. Sie sind einem Client eindeutig zugeordnet und nicht persistent, können aber während einer Sitzung vorübergehend persistent gespeichert werden.

-Message-Beans sind Komponenten, mit denen eine Anwendung oder ein anderer Client asynchron unter Nutzung des Java Messaging Service (JMS) kommunizieren kann.

Ein EJB-Container, die Ablaufumgebung für EJB-Komponenten, ist für ihr Lifecycle-Management, das Messaging, die Persistenz von Entity-Beans, die Sicherheit, das Pooling von Datenbank-Verbindungen sowie die Steuerung und Verwaltung von Transaktionen zuständig. Diese Dienstleistungen erleichtern die Entwicklung von komponentenbasierenden verteilten Systemen in hohem Maße, haben aber auch ihren Preis, etwa durch Laufzeitkosten, die durch die Kommunikation mit den Komponenten über ein Netzwerk entstehen, wobei Aspekte wie Marshalling und De-Marshalling (Versenden von Parametern und Ergebnissen in einem plattformunabhängigen Datenformat) ebenso eine Rolle spielen wie die Aktivierung der Komponenten.

Aber auch der erforderliche Speicherplatz und die Rechenleistung am Server sind nicht zu vernachlässigen. Zum Beispiel wird jeder Aufruf zu einer EJB vom Container unterbrochen, um die Security-Policy durchzusetzen und gegebenenfalls Transaktionen zu beeinflussen. Dies muss beim Design einer EJB-Anwendung unbedingt berücksichtigt werden. Der Kommunikationsaufwand kann allerdings durch die Verwendung einiger Designmuster oder durch ein durchdachtes Clustering der Komponenten verringert werden. Ab Version 2.0 definiert der EJB-Standard als Ergänzung zu den EJBs die so genannten Dependent Values und Dependent Objects. Die Erstgenannten sind ein Objekt, das sowohl über die Schnittstelle einer Komponente zwischen Client und Server übertragen als auch im Kontext einer Entity-Bean mit einfachen Mitteln persistent gespeichert werden kann. Dependent Values werden beispielsweise genutzt, um den kompletten Zustand einer Komponente mit einem einzigen Aufruf zum Client zu übertragen. Dependent Objects sind Objekte, die im Kontext einer Entity-Bean mit ausgefeilten Datenbank-Mechanismen persistent gespeichert werden und Assoziationen zu anderen Objekten oder Komponenten eingehen können. Mit Verfügbarkeit dieser neuartigen Bausteine kann der Entwickler bei der Realisierung jedes Aspektes seines Systems jetzt zwischen serverbasierenden Komponenten und einfachen Objekten wählen und für jeden Anwendungsfall die optimale Umsetzung finden.

EJBs, Dependent Values und Dependent Objects werden ihrerseits zu größeren Einheiten, den EJB-Archiven, zusammengefasst und zur Auslieferung gebracht. Die Zusammenstellung und Konfiguration der EJB-Archive sollte im Design aus folgenden Gründen beachtet werden: Ein EJB-Archiv ist die kleinste Komponente, die in einen EJB-Container installiert werden kann. Auf dieser Ebene kann damit auf das Load-Balancing und die Fehlerdomänen Einfluss genommen werden. Viele Container bieten zudem Optimierungsmöglichkeiten für die Kommunikation zwischen Komponenten innerhalb eines Containers, was dafür spricht, Komponenten mit engen Kommunikationsbeziehungen im gleichen Container zu betreiben. Außerdem verwenden die Komponenten in einem EJB-Archiv im Allgemeinen denselben Persistence-Manager und ein gemeinsames Datenbankschema. Dieses interne Wissen ermöglicht eine Optimierung des Datenbankzugriffs, zum Beispiel bei der Traversierung von Beziehungen zwischen Entity-Beans.

Zwei Klassen von KomponentenIn einer EJB-Anwendung unterscheidet man zwei Klassen von Komponenten: Modellkomponenten und Anwendungskomponenten. Erstgenannte sind die direkte Repräsentation des Business Object Models. Bei ihrem Design liegt das Hauptaugenmerk auf der Flexibilität, da sie von verschiedenen Anwendungen genutzt werden können. Anwendungskomponenten hingegen führen anwendungsspezifische Logik auf dem Server aus. Bei ihrem Design geht es um die effiziente Verteilung der Verarbeitung zwischen Client und Server. Aktionen, die ein hohes Maß an Interaktionen mit Serverkomponenten oder viel Rechenleistung erfordern, werden auf dem Server ausgeführt, alle anderen Aktivitäten auf dem Client. Außerdem können Anwendungskomponenten das Protokoll zwischen Client und Server unter dem Gesichtspunkt der Netzwerkbelastung optimieren.

Im ersten Designschritt wird nun entschieden, welche Objekte als Komponenten und welche als abhängige Objekte realisiert werden. Dafür gibt es zwar kein Patentrezept, aber einige Entscheidungskriterien: Objekte können in unterschiedlichem Kontext einmal als Komponente und einmal als Klasse realisiert werden. Eine wichtige Grundlage für Designentscheidungen sind Erfahrungswerte im Umgang mit der Technologie. Ein Anhaltspunkt ist, ob aus Sicht der Anwendung der Wert oder die Identität des Objektes von Interesse ist. Bei einem Datum etwa interessiert vor allem der Wert, dagegen ist bei einem Kunden im Allgemeinen das Objekt als solches interessant, unabhängig vom Wert einzelner Attribute. Alle Objekte, die per se identifizierbar sein müssen, werden als Komponenten realisiert.

Einstiegspunkte und NavigationspfadeEin weiterer Anhaltspunkt sind die Einstiegspunkte und Navigationspfade im Objektgeflecht. Solche Objekte werden immer als Komponenten realisiert. Nur dann stehen die notwendigen Query-Mechanismen und die Unterstützung für die Implementierung von Assoziationen zur Verfügung. Ein Grenzfall sind oft Objekte, die sich an den Enden der Navigationspfade befinden, beispielsweise die Adresse. Solche Objekte werden meist als Dependent Objects realisiert. In jedem Fall sollte man sich bei der Entscheidung vor Augen halten, worin der Nutzen einer Komponente besteht und was ihre Verwendung kostet.

Für jede identifizierte Komponente wird anschließend der EJB-Typ festgelegt:

-Komponenten, die langlebige und persistente Objekte des Business Object Model repräsentieren und als geteilte Ressourcen von vielen Anwendungen oder Benutzern gleichzeitig verwendet werden, werden als Entity-Beans realisiert.

-Geschäftsprozesse werden in Entity-Beans abgebildet, wenn sie von anderen persistenten Komponenten referenziert werden beziehungsweise nach ihrer Ausführung noch als Ressource des Informationssystems zur Verfügung stehen sollen, etwa um den Ablauf des Prozesses zu erfassen und Statistiken darauf anzuwenden. Ansonsten sind Stateful-Session-Beans eine angemessene Umsetzung.

-Alle Arten von Anwendungs- und Hilfskomponenten (Utilities), die nicht notwendigerweise über einen langen Zeitraum persistent gespeichert werden müssen, werden als Session-Beans realisiert.

-Für die lose Kopplung von verschiedenen Informationssystemen auf der Basis asynchroner Nachrichten bietet sich die Verwendung von Message-Beans an.

Für die anschließende Implementierung der Komponenten empfiehlt sich ein generativer Ansatz. Wer schon einmal EJBs von Hand kodiert hat, wird dies bestätigen. Der Vorteil einer modellbasierenden Generierung besteht neben der hohen Produktivität auch in dem enormen Potenzial für die Erstellung von qualitativ hochwertigem Quellcode. Es ist durchaus möglich, aus einem Modell ablauffähige und auf den konkreten EJB-Container optimierte Komponenten zu generieren, die alle Aspekte der technischen Infrastruktur, wie Persistenz und Transaktionen, abdecken. Dazu werden neben dem Quellcode auch diverse Deployment-Deskriptoren erzeugt. Darüber hinaus kann eine komplette Umgebung für Abbildung und Test der Komponenten generiert werden. Die Hauptaufgabe der Entwickler besteht dann in der Implementierung der eigentlichen Business-Logik innerhalb der Komponenten und des zugehörigen Testcodes.

Trotz der großen Vorteile, die eine modellbasierende Generierung bietet, sollte man sich nicht dazu verleiten lassen, die Auswirkungen von zuvor getroffenen Designentscheidungen auf das zu erstellende System zu vernachlässigen. Vielmehr muss man sich um die spezifischen Eigenschaften der Zielplattform sowie um Performanz, Skalierbarkeit und Wartbarkeit genauso viele Gedanken machen wie um die fachlichen Anforderungen des Systems. Ansonsten kann es passieren, dass das System bedingt durch die hohe Produktivität des Generators "degeneriert".

*Steffen Müller und Torsten Lodderstedt sind Berater und Entwickler beim Freiburger IT-Architekturhaus Interactive Objects Software GmbH.

ANGEKLICKTFür die erfolgreiche Entwicklung eines komponentenbasierenden Systems empfiehlt sich der Einsatz eines ganzheitlichen Entwicklungsprozesses. Er leitet und unterstützt den Entwickler zielgerichtet auf dem kritischen Pfad von der fachlichen Anforderung bis hin zur laufenden EJB-Anwendung. Die Produktivität der Entwicklung und die Qualität der Resultate werden durch eine modellbasierende Generierung wesentlich erhöht. Bei der Entwicklung von effizienten komponentenbasierten Anwendungen ist es notwendig, die technischen Eigenschaften der konkreten Zielplattform sowie die angebotenen Mechanismen zu kennen und im Design zu berücksichtigen. Um die Risiken bei der Entwicklung zu minimieren, empfiehlt es sich, inkrementell Teile der Anwendung vom fachlichen Modell bis zur Technologie zu realisieren. Nur so können frühzeitig Risiken erkannt und entsprechende Maßnahmen ergriffen werden, um das Projekt zu einem erfolgreichen Abschluss zu bringen.