Nostalgia: Das JavaBeans Development Kit (BDK)

Das BDK ist (war) eine Testumgebung für anzeigeorientierte Beans und Komponenten ohne visuelle Repräsentation wie Datenstrukturen und Container. Es ist nicht mehr im Original, sondern nur noch in der Version unter https://java.net/projects/bean-builder erhältlich.

Die Bean-Box bietet eine Arbeitsfläche, auf der die Komponenten platziert und verbunden werden können. Wird in der Bean-Box eine Komponente auf dem Bildschirm gesetzt, so liest Java aus der Bean die Informationen (die Properties genannt werden) aus und stellt sie dar. Nun können mehrere Beans miteinander verbunden werden, sodass etwa eine Komponente ein Ereignis auslöst, auf das die zweite Komponente reagiert. Alle Aktionen können direkt ohne eine Zeile Programmcode entworfen werden. Wir entwerfen zunächst im Design-Modus die Verbindungen, um sie dann im Laufzeit-Modus zu testen. Damit reiht sich die Bean-Box in die Reihe der grafischen Entwicklungsumgebungen wie etwa IBMs Visual Age ein. Ganz so komfortabel ist die Bean-Box dann aber auch nicht. Sie ist von Sun lediglich zum Testen und Anzeigen von Beans entworfen worden. Dies zeigt sich auch daran, dass beim Verlassen der Umgebung nicht einmal nach dem Speichern gefragt wird.

Die Bean-Box starten

In der BDK-Version 1.1 wechseln wir in das bdk/beanbox/bin-Verzeichnis und rufen die Skripte run.bat (Windows) oder run.sh (Unix) auf. Dann startet die Umgebung.

Eine Beispielsitzung im BDK

Das BDK ist nach dem Start in drei Fenster unterteilt. Dies sind die ToolBox, die Bean-Box und das Eigenschaften-Feld. Das ToolBox-Fenster enthält einige Beispielkomponenten, die wir verwenden können. Die Beispiele werden zur Laufzeit aus dem bdk/jars/-Verzeichnis genommen. Eigene Komponenten können wir als Jar-Dateien einfach dort hineinkopieren. Die eigentliche Bean-Box stellt die Zeichenfläche dar. Sie ist der wichtigste Teil des Pakets, weil auf ihr Komponenten platziert und getestet werden können. Wir wollen dies anhand der Komponente Molecule zeigen. Wird sie in der ToolBox angeklickt, so verwandelt sich der Cursor in einen Positionszeiger. Klicken wir in der Bean-Box auf eine Stelle, wird ein Molekül angezeigt. Es lässt sich verschieben und interaktiv in der Größe ändern. Die Eigenschaften jeder Komponente lassen sich im Property-Sheet ändern. Sie bestimmen das Aussehen und das Verhalten. Ist das Molekül aktiviert, erscheint im Eigenschaften-Dialog eine Auswahlliste mit einigen Molekülen. Eine Auswahl wirkt sich direkt in der Anzeige aus.

Hinweis: Leider können selektierte Komponenten nicht mit der Entfernen-Taste von der Oberfläche beseitigt werden. Hier ist nur der Gang über das Edit-Menü erfolgversprechend.

Das Zusammenspiel der Komponenten lässt sich testen, indem wir den Design-Modus verlassen. Dazu aktivieren wir im Menüpunkt View den ersten Punkt Disable Design Mode (der sich dann in Enable Design Mode umbenennt). Jetzt kann das Molekül mit der Maus verschoben werden.

Verknüpfungen zwischen Komponenten

Die hervorragendste Eigenschaft der grafischen Programmierung ist das visuelle Setzen von Beziehungen zwischen Komponenten. Dabei werden Ereignisse an Methoden anderer Beans gebunden. Wir wollen das mit der Komponente JellyBean und dem Molekül testen. Wenn wir nun mit der Maus auf die JellyBean klicken (also ein Mouse-Event auslösen), dann soll eine bestimmte Methode des Bean-Moleküls aufgerufen werden, sodass es sich auf dem Bildschirm dreht. Wir verbinden hier also einfach eine Ereignisquelle mit einer Ereignisbehandlung einer anderen Komponente. Die Bedienung der Bean-Box ist dabei so intuitiv, dass sie zum Spielen und Ausprobieren einlädt. Wir aktivieren die erste Schaltfläche und wählen den Menüpunkt Edit > Events > mouse > mousePressed.

Jetzt erscheint eine rote Linie, die mit der Maus bewegt wird. Nun klicken wir auf unser Molekül. Daraufhin erscheint eine Liste mit Funktionen, die bei der Mausbewegung ausgelöst werden können. Wir entscheiden uns für rotateOnX.

Beans speichern

In der Bean-Box lässt sich unter dem File-Menü die Bean in ein Jar-Archiv für ein Applet einwickeln. Der Speicherdialog schlägt standardmäßig ein Unterverzeichnis der Bean-Box vor. Zusätzlich zur serialisierten Klasse befinden sich im Archiv noch die vom BDK erstellten Metainformationen, die Quellcodes zu der Bean in einem Extra-Verzeichnis, eine HTML-Datei sowie eine Readme-Datei mit den Informationen darüber, welche Dateien zur Komponente gehören. Die HTML-Datei erhält eine Referenz auf die Klassendatei, sodass ein Applet-Viewer oder ein Browser direkt die Bean darstellen kann. Alte Browser unterstützen das Jar-Format im Applet-Tag der HTML-Datei nicht.

Die kleinste Bohne der Welt

Wir wollen uns nicht lange mit theoretischem Schnickschnack aufhalten – dafür bleibt noch genügend Zeit. Beginnen wir mit einer Komponente, die wir FirstBean nennen wollen.

package com.javatutor.insel.bean;

import java.applet.Applet;
import java.awt.*;

public class FirstBean extends Applet
{
 @Override
 public void paint( Graphics g )
 {
  g.drawString( "Hui; so kurz?", 20, 20 );
 }
}

Zweifellos wird die Kürze dieser Lösung verwundern. Das kommt daher, dass sich die Beans gut in die vorhandene Technologie einfügen und schon viele Komponenten als Beans gebaut sind.

Beginnen wir nun, das schon in der Einführung als einfaches Beispiel für Komponenten identifizierte Applet in unseren Application-Builder einzubauen. Dazu muss die Softwarekomponente in einem speziellen Format vorliegen: in Jar-Dateien.

Jar-Archive für Komponenten

Eine Jar-Datei ist ein Archivformat, das Sun zum Verbund von Klassen und Mediendateien einführte. Nach dem Compilieren der Klasse FirstBean wird die Datei mit einem zusätzlichen Manifest in eine Jar-Datei gepackt. Damit der Application-Builder erkennen kann, dass es sich dabei um eine Bean handelt, erwartet er eine bestimmte Information in einer Manifest-Datei, die automatisch beim Zusammenpacken erzeugt wird. Stünden diese Informationen nicht dabei, könnte der Application-Builder die Bean nicht erkennen.

Wir wollen die Jar-Datei mit dem Dienstprogramm jar von Hand erzeugen. Zunächst legen wir eine Manifest-Datei an, die wir nach der Komponente benennen.

FirstBean.mf

Manifest-Version: 1.0
Name: FirstBean.class
Java-Bean: True

Hinweis: Vor den Doppelpunkten dürfen keine Leerzeichen stehen, sonst erkennt Jar die erste Option nicht und bemängelt den fehlerhaften Header. Leider ist Jar nicht sehr fehlertolerant.

Befinden sich im Jar-Archiv mehrere Klassen, sollten ihre Dateinamen mit Return getrennt sein. Bei Paketnamen ist eine Trennung mit / vorgesehen, nicht mit dem Windows-\.

Im nächsten Schritt packen wir mit jar die Klassen sowie die Manifest-Datei zu einem Archiv zusammen. Hier müssen wir die Optionen cfm nutzen. Merken wir uns die Option im englischen Satz »Create a File with a Manifest«, übersetzt »Lege die Datei mit Manifest an« .

$ jar cfm FirstBean.jar FirstBean.mf FirstBean.class

Für eine genauere Beschreibung des Dienstprogramms jar sei auf Kapitel in der Insel verwiesen.

Wurde das Jar-Archiv erfolgreich erstellt, muss dem Application-Builder die Bean bekannt gemacht werden. Hier unterscheiden sich die Produkte der einzelnen Hersteller voneinander. Im BDK von Sun müssen alle Beans im Unterverzeichnis jars liegen, damit sie das BDK automatisch erkennt. Kopieren wir unsere Bean dort hinein. Unter Windows schreiben wir:

$ copy FirstBean.jar c:\bdk\jars

Wenn wir jetzt die Bean-Box starten, erscheint unsere Komponente mit in der Liste. Im jars-Verzeichnis stehen auch die anderen Beans.

Tipp: Eine etwas schnellere Vorgehensweise besteht darin, die Jar-Datei nicht in das jars-Verzeichnis, sondern in ein eigenes Verzeichnis zu legen. Das hat den Vorteil, dass die Bean-Box schneller startet, weil sie dann nicht die zusätzliche Bean auswerten muss, was immer Zeit kostet. Wenn wir Beans nicht benötigen, können wir sie auch verschieben oder löschen, was die Ladezeit zusätzlich erhöht. Damit in diesem Fall das eigene Jar-Archiv eingebunden wird, laden wir es unter dem Menüpunkt File > Load Jar.

Wenn wir wiederholt Beans in ein Archiv packen und keine integrierte Entwicklungsumgebung diese Arbeit erledigt, kann uns ein kleines Skript helfen. Ein Beispiel für Windows wäre:

a.bat

javac zzz.java
jar cfm zzz.jar zzz.mf zzz.class
copy zzz.jar c:\bdk\jars

Bean-Eigenschaften anpassen

In einem visuellen Entwicklungswerkzeug lassen sich alle ausgezeichneten Eigenschaften einer Bean anpassen. Dazu bietet die Umgebung oft ein zweigeteiltes Fenster an. Auf der einen Seite befinden sich die Eigenschaften und auf der anderen Seite die Editoren für jede Eigenschaft. Die folgende Abbildung zeigt einige Properties und deren Anzeigen.

Haben wir zum Beispiel als Eigenschaft eine Zeichenkette (wie der angezeigte Text eines Label-Objekts), können wir diese einfach in das Feld eintragen. Mit einem eigenen Property-Editor sind wir jedoch nicht auf die einfachen Datentypen beschränkt. Was ist, wenn etwa eine Komponente die Auswahl zwischen DM und Euro anbieten will? Wir können dem Benutzer nicht zumuten, dies in Zahlen einzugeben. Auch bei einem Label gibt es zum Beispiel die Möglichkeit, einen Cursor aus einer Liste auszuwählen.

Für ungewöhnliche Eigenschaften können wir einen eigenen Property-Editor definieren. Dazu kann der Editor den Anzeigebereich als Grafikfläche beschreiben.

Customizer

Reicht auch der Editor nicht aus, zum Beispiel bei einer Farbe, die wir gerne aus einem Farbkreis auswählen wollen, lässt sich zudem ein Customizer definieren, der noch einen Schritt weiter geht, denn für einen Customizer ist ein eigenes Fenster vorgesehen. Er soll mit einer einfachen Benutzerführung den internen Zustand ändern. IBM sieht für seine Beans zum Beispiel ein Hilfe-Feld vor. In WebGain wird dieser Customizer durch eine Schaltfläche mit drei Punkten angezeigt.

Property-Editoren

Für jede sichtbare Eigenschaft einer Bean gibt es einen Property-Editor, der den Wert darstellen und ihn bei einer veränderbaren Eigenschaft auch editieren kann. Bekommt die Eigenschaft den Fokus, wird automatisch der passende Editor ausgewählt. Für alle primitiven Datentypen gibt es standardmäßig Editoren, und zusätzlich kommen Auswahlmöglichkeiten für String, Color und Font hinzu. Ein Editor gilt für jeweils eine Property. Die Editoren werden an einer zentralen Stelle, dem Property-Editor-Manager, registriert und dann beim Fokus ausgewählt und aktiviert. Das ist Aufgabe der Entwicklungsumgebung.

Damit die Einstellmöglichkeit nicht auf diese einfachen Typen beschränkt bleibt, können wir für eine Eigenschaft einen eigenen Property-Editor konstruieren. Der kann eine ganz einfache Textzeile darstellen oder auch eine eindrucksvolle Multimedia-Komponente. Der Editor übernimmt die Anzeige und ist gleichzeitig das Modell (also gibt es keine Trennung von Daten und Visualisierung an dieser Stelle). Der Wert ist als Object in unserem Editor gespeichert. Außerdem muss der Editor die Schnittstelle java.beans.PropertyEditor implementieren oder alternativ die Klasse java.beans.PropertyEditorSupport erweitern, was meist einfacher ist.

BeanInfo

Durch Introspection/Reflection existiert ein leistungsfähiger Mechanismus, um die Eigenschaften und Ereignisse zur Laufzeit auszulesen. In der Regel nimmt die Entwicklungsumgebung dafür Methoden, die sich an die Namenskonvention halten. Es gibt aber noch eine zweite Möglichkeit, und die lässt sich über eine Bean-Information-Klasse nutzen. Sie bietet folgende Funktionalität:

  • explizites Auflisten der freigegebenen Leistungen, die nach außen sichtbar sein sollen
  • Zuordnung eines mit der Bean verwendeten Icons
  • Anmeldung einer Customizer-Klasse

Sind die freigegebenen Leistungen aufgelistet, wird damit eine Untersuchung der Bean-Klassen auf die Namensgebung verhindert. Es gibt daher zur Freigabe der Eigenschaften und Ereignisse spezielle Methoden, die von uns gefüllt werden, indem wir jede Eigenschaft auflisten. Jede Methode nutzt zur Beschreibung der Leistungen so genannte Deskriptoren. Gibt es keinen Deskriptor, wird die jeweilige Eigenschaft, Methode oder das Ereignis nicht veröffentlicht. Gibt die Anfrage-Methode aus der Bean-Information-Klasse null zurück, wird für die jeweilige Eigenschaft/Event/Methode Reflection genutzt. Der Java-Code für dieses Doktor-Spielchen liegt in java.beans.Introspection. Ein kleines Beispiel, das alle get-Methoden der Klasse Point ausgibt:

BeanInfo beanInfo = Introspector.getBeanInfo( Point.class );
for ( PropertyDescriptor p : beanInfo.getPropertyDescriptors() )
System.out.println( p.getReadMethod() );

Die Ausgabe liefert vier Zeilen:

public final native java.lang.Class java.lang.Object.getClass()
public java.awt.Point java.awt.Point.getLocation()
public double java.awt.Point.getX()
public double java.awt.Point.getY()

Beliebte Fehler

Das Programmieren von Beans ist zwar einfach, doch schleichen sich immer wieder Fehler ein. Dieser Abschnitt soll auflisten, welche Fehler für eine Bean letal sind, sodass sie von einer Umgebung nicht erkannt werden kann.

  • Die Klasse muss öffentlich (public) und darf nicht abstrakt sein. Abstrakte Klassen können keine Exemplare bilden, was für eine Bean-Box aber unumgänglich ist.
  • Die Klasse muss vom Klassenlader ohne Folgefehler geladen werden können. Der Vorgang wird während des Ladens durch Fehler im static-Block oder durch fehlende Klassen möglicherweise abgebrochen.
  • Die Bean muss einen öffentlichen Standard-Konstruktor anbieten.
  • Die Klasse muss Serializable implementieren, muss also serialisierbar sein. Das hat zur Konsequenz, dass alle Attribute, die nicht transient sind, ebenso serialisierbar sein müssen. Eine Verletzung dieser Regel liegt beispielsweise vor, wenn eine grafische Komponente eine Referenz auf ein Image-Objekt hält, denn Image-Objekte sind nicht serialisierbar. Wir müssen daher entweder ImageIcon nutzen oder eigene Methoden wie writeObject(), readObject() implementieren. Wenn schon eine Oberklasse serialisierbar ist, dann muss unsere Klasse nicht noch einmal Serializable implementieren, weil wir dann selbst automatisch instanceof Serializable durch die Oberklasse sind. Es bietet sich jedoch zum Zweck der Lesbarkeit an, implements Serializable zu schreiben, damit das auf den ersten Blick sichtbar ist.

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert