Komponentenarchitekturen (Teil 2): Javabeans

Javabeans erlauben die flexible Entwicklung von Anwendungen

18.06.1999
Suns Komponentenmodell "Javabeans" bietet eine überschaubare Anzahl von Schnittstellen-Spezifikationen und Namenskonventionen. Dadurch läßt es sich flexibel bei der Entwicklung einsetzen, läuft aber auch immer Gefahr, proprietär unterwandert zu werden. Im Modell sind deshalb laut Frank Griffel* einige Vorkehrungen getroffen worden.

Mit den Spezifikationen von "Javabeans" bietet Sun Microsystems einen Standard für Java, der Microsofts Component Object Model (COM) Konkurrenz macht und wie jenes zunächst auf die Entwicklung von GUI-Komponenten ausgerichtet war. Der Hersteller legt dabei Wert auf eine solide, schrittweise und kontrollierte Entwicklung neuer Modelle. So erfordert eine Javabean-konforme Programmierung lediglich die Einhaltung bestimmter Namenskonventionen und Schnittstellen-Spezifikationen, ohne daß man an der Sprache Java selbst Veränderungen oder Ergänzungen vornehmen müßte. Auch die Verwendung vorgefertigter Klassen ist nicht zwingend beziehungsweise reduziert sich auf ein Minimum.

Eine Javabean ist eine Java-Klasse, die bestimmte Schnittstellen implementiert und vor allem eine vordefinierte Namensgebung der in ihr implementierten Methoden einhält. Dabei sieht Sun keine eigene Interface Definition Language (IDL) zur Beschreibung der bisher einzigen, explizit unterstützten Schnittstelle einer Bean vor, legt aber mit den Namenskonventionen "set" und "get" Methoden für alle zugreifbaren Attribute (properties) einer Klasse fest. Solche Eigenschaften zählen dann zu den Konfigurationspunkten einer Javabean, da sie von außen in einer definierten Weise gesetzt werden können.

Interessant daran ist, daß das Verändern einer Eigenschaft von anderen Beans überwacht werden kann. Grundlage hierfür ist ein Ereignismodell, das analog zum Microsoft-Modell eine Registrierung interessierter Empfänger (sogenannte Event Listener) bei potentiellen Sendern ermöglicht. Damit findet sich auch in diesem Modell die "lose" Kopplung per ausgetauschtes Ereignis und nur wenigen bekannten Call-Methoden. Eine Schwäche im Modelldesign ist dabei, daß nur der Empfänger ausdrücklich ein spezielles Interface implementieren muß und er daran sofort als solcher erkannt werden kann. Die Ereignisquelle läßt sich hingegen erst durch entsprechende Registrierungsfunktionen im Code deuten. In Kombination der Attributzugriffe mit dieser Ereignisbehandlung sind dann die "bound-" und die "constraint-properties" vorgesehen. Verändern sich erstere, ergeht lediglich eine entsprechende Nachricht an andere Komponenten. Letztere müssen sich hingegen jede Veränderung vorab von speziell für solche Aufgaben registrierten Komponenten, den sogenannten Veto Listeners, genehmigen lassen.

Auch das Thema Meta-Information wird im Bean-Modell auf elegante Weise behandelt. So stehen zur dynamischen Untersuchung einer Komponente die Programmiertechnik der Java-Reflection-Mechanismen zur Verfügung. Diese geben beispielsweise Auskunft über die eigenen Attribute oder die anderer Komponenten oder ermitteln deren Methodensignaturen. So lassen sich etwa dynamische Aufrufe generieren, die erst im konkreten Kopplungsfall benötigt werden und nicht vorherbestimmt werden konnten.

Da dieser "Einblick" in eine Komponente aber sehr weitreichend ausfallen kann, sieht das Bean-Modell eine zweite Variante vor, um explizit Zusatzinformationen zu einer Komponente anzugeben beziehungsweise diese gezielt einzuschränken. Hierzu wird der Komponente eine "Bean-Info"-Klasse zur Seite gestellt, die spezifizierte Methoden für den Zugriff auf einzelne Informationen erlaubt, etwa auf vorhandene Attribute und deren Typen beziehungsweise ob diese nur gelesen oder auch geschrieben werden dürfen. Sun setzt hier auf den "freieren" Ansatz, eine Black-Box-Sicht zwar zu ermöglichen, sie aber nicht zu erzwingen. Entsprechende Entwicklungsumgebungen präsentieren einem Programmierer dann beispielsweise nur die tatsächlich über die als "Introspection" bezeichnetet Analyse der Bean Info-Daten ermittelten Informationen.

Zur raschen Etablierung einheitlicher Entwicklungsumgebungen sieht die Bean-Spezifikation zwei weitere wichtige Konzepte vor: die Property-Editoren und die Customizer. Beide dienen der (nachträglichen) Anpassung fertiger, vorkonfiguriert ausgelieferter Softwarekomponenten. Die Property-Editoren entsprechen im wesentlichen den etwa aus Visual-Basic-Umgebungen bekannten "Property Sheets", das heißt kleinen Konfigurationsfenstern, die jeweils die Auswahl einstellbarer Eigenschaften einer Komponente anzeigen und deren Veränderung erlauben. Da Komponentenhersteller solche Property-Editoren vordefiniert mitliefern, ist eine der jeweiligen Komponente angemessene Repräsentation von erlaubten Konfigurationspunkten möglich. Solche Editoren müssen dabei im Bean-Modell nicht komponentenspezifisch sein, sondern können sich auf den Typ der zu verändernden Attribute beziehen und dadurch auch automatisch von einer Entwicklungsumgebung ausgewählt und integriert werden.

Wichtig für die Akzeptanz von komponentenbasierter Software-Entwicklung ist, daß Anwendungsentwickler existierende Komponenten nicht mehr verändern können und keine "Variantenflut" entsteht. Das Bean-Modell will diese Probleme mit Hilfe der "Customizer" lösen. Die Idee ist, weitergehende Variationen gekaufter Komponenten durch einen Entwickler zuzulassen. Dabei sind theoretisch beliebige Veränderungen wie der Austausch eines intern verwendeten Algorithmus an der Komponente denkbar. Insofern ist der Umfang eines Bean-Customizers auch nicht genau spezifiziert. Er bietet in der Regel "Wizards", also eine grafisch geführte und angeleitete Form der Konfiguration, wenn dennoch konsistente und korrekte Komponenten zurückbleiben sollen.

Dauerhafte Speicherung von Komponenten

Ein letzter wichtiger Aspekt für ein Komponentenmodell ist, daß sich vorkonfiguriert ausgelieferte Komponenten persistent (dauerhaft) speichern lassen. Das Bean-Modell greift hierzu auf die in Java enthaltene Möglichkeit der "Serialisierung" zurück, das heißt die Überführung eines Java-Objekts (also einer aktiven Klasseninstanz) in einen Datenstrom, der sich beispielsweise in einer Datei oder Datenbank speichern läßt. Dabei werden die Zustände der zugehörigen Variablen (allerdings nur der nicht statischen) mitgesichert, so daß beim Wiedereinlesen eines solchen serialisierten Datenstroms ein fertig konfiguriertes Objekt vorliegt. Analoge Mechanismen finden sich in Microsofts COM-Modell in Form der "Ipersist-Stream"-Schnittstelle, die allerdings in der Regel deutlich aufwendiger implementiert werden muß.

Die so vorkonfigurierten Implementierungsteile einer Komponente sind in der Regel in einem "Archiv" zusammengefaßt, das bei Java "JAR"-Dateien, bei Microsoft "CAB"-Dateien heißt. Häufig wird dann auch von einer solchen Archivdatei als "Komponente" gesprochen, da erst sie alle zum Einsatz einer Komponente notwendigen Daten enthält. Als "Produktgarantie" lassen sich dann solche Archive beispielsweise elektronisch signieren, so daß ein Empfänger von korrekter "Ware" ausgehen kann.

Bean-Modell entwickelt sich weiter

Trotz all dieser Möglichkeiten gibt es bis heute einige Mängel im Bean-Modell. So ist es im Vergleich zu COM deutlich rudimentärer, daher aber auch einfacher konsistent zu halten. Insbesondere fehlen den Javabeans zur Zeit Container beziehungsweise Aggregationsmodelle. Auch Aspekte wie ein uniformer Datentransfer zur Ermöglichung von Drag-and-drop-Techniken zwischen Komponenten und deren verteilte Kommunikation waren zunächst nicht vorgesehen. Abhilfe sollen hier die Vorschläge im Rahmen der "Glasgow-Spezifikationen" (neuerdings auch "Edinburgh-Spezifikationen") bringen oder Ansätze wie der "Infobus", als neuartige datengesteuerte Kopplungsformen für Javabeans, die auch eine verteilte Kommunikation erlauben sollen. Allerdings droht an solchen Punkten die anfängliche Homogenität der Bean-Welt aufzuweichen.

Als Fortsetzung des Client-Modells bietet Sun das Modell der Enterprise Javabeans (EJB) für die Server-seitige Komponentensicht, dessen Konzept exakt auf die heute so beliebten Applikations-Server zielt. Es ermöglicht durch eine wiederum überschaubare und klare Menge an Schnittstellen-Spezifikationen den Entwurf von Server-seitigen Komponenten, die Anwendungslogik kapseln und sie einer Vielzahl von Klienten zugänglich werden lassen. Zugleich bietet EJB eine Kapselung der "dritten Schicht", also des Datenbankzugriffs, der dadurch komponentenoriertiert ist.

Zentrum dieses Komponentenmodells ist der "Container" (siehe Grafik). Das Javabeans-Basismodell lebt jedoch ungeschmälert fort, denn den Inhalt eines Containers bilden eben diese Java- beans-Komponenten. Sie müssen sich nun aber nicht mehr mit "allgemeinen" und im Basismodell gar nicht vorgesehenen Problemen beschäftigen, wie etwa dem eines transaktionalen Datenbankzugriffs, der Sicherheit ihrer Nutzung oder eben eines verteilten Zugriffs. Alles dies übernimmt der EJB-Container, der in einem Server-Prozeß angesiedelt wird. Zugleich herrscht auch hier wieder Liberalität: Ein Container kann einer Komponente die entsprechende Arbeit abnehmen oder diese einer Bean-managed-Komponente überlassen. Neben der technischen Spezifikation der EJB-Architektur liefert Sun bemerkenswerterweise auch ein passendes Rollenmodell für alle Beteiligten mit. Letztere sind der Entwickler der Anwendungskomponente, der Endanwender, derjenige, der sie anpaßt, und derjenige, der entsprechende Container entwickelt und anbietet. Unterstützt wird diese Einteilung durch die sogenannten Deployment-Descriptoren. Diese enthalten vergleichbar einer serialisierten Bean die Informationen über die Vorkonfiguration beziehungsweise die von einer konkreten Komponente erwarteten Umgebungsbedingungen.

Damit EJB diese breite Akzeptanz findet und unterschiedlichen Anwendungsszenarien die angemessene Lösung anbieten kann, unterscheidet die EJB-Spezifikation zum einen zwischen zustandslosen (stateless) und zustandsbehafteten (statefull) Komponenten, andererseits zwischen sogenannten Session- beziehungsweise Entity-Beans. Während eine Session-Bean individuell für eine Client-Kommunikation und auch nur während dieser zur Verfügung steht, stellt eine Entity-Bean eine dauerhaft, also auch über eine aktuelle Kommunikation hinaus bestehende Einheit dar, die von verschiedenen Klienten gleichzeitig genutzt werden kann. Für die entsprechende Synchronisation beziehungsweise Persistierung sorgt im Zweifelsfall wieder der Container, wobei zumindest der heutige Stand der Produkte dem Programmierer hier noch umfangreiche Aufgaben überläßt.

*Frank Griffel ist Mitarbeiter im Arbeitskreis "Verteilte Systeme" an der Universität Hamburg.