– die Plattform
Enterprise-Java mit Eclipse 3.1
eclipse_v01.book Seite 4 Montag, 30. Januar 2006 12:02 12
© 2006 entwickler.press, ein Imprint der Software & Support Verlag GmbH
http://www.entwickler-press.de
http://www.software-support.biz
Inhaltsverzeichnis
1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.1 Was ist Eclipse? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.2 Warum ein Buch über Eclipse?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3 An wen richtet sich dieses Buch? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4 Was erwartet Sie in diesem Buch? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5 Was benötigen Sie?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.6 Anforderungen an eine moderne IDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7 Open Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2 Wegweiser durch Eclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1 Perspektiven und Views von Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1.1 Perspektiven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1.2 Perspektiven auswählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1.3 Die Java-Perspektive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.1.4 Neues Java-Projekt erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.5 Package Explorer und View-Funktionen . . . . . . . . . . . . . . . . . . 21
2.1.6 Das Eclipse-Editorfenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.7 Outline View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.8 Tasks/Problems View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.9 To be done – Arbeiten mit Tasks. . . . . . . . . . . . . . . . . . . . . . . . . 25
2.1.10 Eigene Tasks definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2 Hilfe in Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.3 Eclipse-Projekte individuell konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . 31
2.3.1 Vorhandenen Sourcecode ins Projekt Link to Source . . . . . . . . . 35
2.3.2 Projekteigenschaften definieren . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.4 Sourcecode-Editor-Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.4.1 Quick Fix auf Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.4.2 Automatische Getter/Setter-Erzeugung . . . . . . . . . . . . . . . . . . . 43
2.4.3 Sourcecode-Vervollständigung (Code completion) . . . . . . . . . . 44
2.4.4 Try-Catch-Block-Generierung . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.4.5 Sourcecode-Templates verwenden . . . . . . . . . . . . . . . . . . . . . . . 48
2.4.6 Gimmicks des Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.4.7 Immer ein Undo für die Vergangenheit. . . . . . . . . . . . . . . . . . . . 51
2.5 Refactoring mit Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.5.1 Überschreiben/Implementieren von Methoden. . . . . . . . . . . . . . 56
2.5.2 Auslagern von Zeichenketten/Mehrsprachigkeit . . . . . . . . . . . . 57
2.6 Erstellung eines JUnit-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5
eclipse_v01.book Seite 6 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
6
eclipse_v01.book Seite 7 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
7
eclipse_v01.book Seite 8 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
8
eclipse_v01.book Seite 9 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
9
eclipse_v01.book Seite 10 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
10
eclipse_v01.book Seite 11 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
11
eclipse_v01.book Seite 12 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
12
eclipse_v01.book Seite 13 Montag, 30. Januar 2006 12:02 12
1 Einleitung
13
eclipse_v01.book Seite 14 Montag, 30. Januar 2006 12:02 12
Kostengesichtspunkten nicht nutzen kann. In diesem Buch liegt der Fokus auf Tools und
Plug-Ins, die als Open Source-Produkte sowohl beruflich als auch privat genutzt werden
können. Viele dieser Werkzeuge lassen sich im Bereich der Evaluation, als reine Entwick-
lungsplattform, aber auch im produktiven Umfeld einsetzen. Manchmal werden auch kom-
merzielle Produkte vorgestellt. In diesen Fällen muss entschieden werden, ob der zusätzli-
che Nutzen die entsprechenden Kosten rechtfertigt.
1. http://www.eclipse.org
14
eclipse_v01.book Seite 15 Montag, 30. Januar 2006 12:02 12
1 – Einleitung
Teil 1 – führt in die grundsätzliche Verwendung von Eclipse ein. Es wird die IDE vor-
gestellt. Dies ist erforderlich, um sich die Unterstützung von Eclipse für ein bestimmtes
Themengebiet in den nachfolgenden Kapiteln genauer erarbeiten zu können.
Teil 2 – geht speziell auf Aufgabenstellungen in verschiedenen Arbeitsfeldern wie UML-
Modellierung, Model Driven Architecture, Versionsverwaltung, Konfigurations- und
Buildmanagement, GUI-Design oder J2EE-Features ein.
Teil 3 – rundet das Buch ab, indem wir von der Entwicklung mit Eclipse zur Eigenentwick-
lung an Eclipse kommen. Wir untersuchen, wie man Eclipse als „Startframework“ für ei-
gene Clients benutzen kann oder eigene Plug-Ins für Eclipse zur Verfügung stellt.
15
eclipse_v01.book Seite 16 Montag, 30. Januar 2006 12:02 12
Open Source
wicklungsumgebungen ist recht groß, angefangen von kommerziellen Produkten bis hin zu
reinen Open Source-Produkten wie Eclipse.
Den Ansatz der individuellen Anpassbarkeit für die Bedürfnisse (z.B. durch ein Plug-In-
Konzept) hat vermutlich Eclipse bisher als einziges Produkt vervollständigt. Viele Produkte
lassen sich mehr oder minder durch Plug-Ins erweitern. Im Vordergrund stehen aber oft
Produktlinien wie „Personal“-, „Professional“- und „Enterprise“-Versionen. Jemand, der
beispielsweise bei der Entwicklung einer Java EE-Anwendung Unterstützung sucht, soll
mehr bezahlen als derjenige, der ausschließlich Standalone-Anwendungen erstellt. Open
Source-Produkte verwenden diese Form der Marktsegmentierung in der Regel nicht.
Der Ansatz bei der Entwicklung von Eclipse durch OTI/IBM im Gegensatz zu anderen
IDEs war, das Gesamtprodukt als Bausteinsystem zu konzipieren, in das sich alle Funktio-
nen als Komponenten integrieren lassen (siehe Kapitel „Eclipse-Architektur“).
Wer eine Entscheidung über die Auswahl der zukünftigen Entwicklungsumgebung treffen
möchte, sollte stets die Wahl der Architektur und der Werkzeuge, die er dafür benötigt, be-
rücksichtigen. Eclipse wandelte sich mit der Zeit auch immer mehr zur IDE für weitere
Sprachen wie C/C++, COBOL, Fortran, Groovy, Nice, LISP, C#, Jython/Python usw., um
nur einige zu nennen. Die am besten unterstützte Sprache bleibt derzeit aber noch Java.
Wenn es also um Java geht und wenn sich Komponenten und Funktionen der IDE an die je-
weiligen Bedürfnisse anpassen lassen sollen, ist Eclipse sicherlich ein Kandidat der enge-
ren Wahl.
Die Anforderungen an eine moderne IDE hängen primär von den ganz persönlichen Be-
dürfnissen ab und ob ein Produkt alles können soll oder ob Medienbrüche (Wechsel zwi-
schen mehreren Produkten bei der Entwicklung) vom Benutzer als akzeptabel empfunden
werden oder nicht. Am vorteilhaftesten ist es vermutlich, wenn man selbst entscheiden
kann, welche Funktionen über den Basisrhythmus wie Programmierung-Compile-Deploy-
ment hinaus für das eigene Vorgehen noch benötigt werden. Wenn dies mit einer kosten-
losen IDE (wie Eclipse) funktioniert, umso besser.
1. http://jakarta.apache.org
16
eclipse_v01.book Seite 17 Montag, 30. Januar 2006 12:02 12
1 – Einleitung
Probleme mit Open Source-Produkten können dadurch entstehen, dass sie im frühen Sta-
dium ihres Lebenszyklus noch nicht ausgereift sind. Das Risiko besteht dabei, dass die Wei-
terentwicklung nicht oder nur langsam erfolgt. Außerdem kann es vorkommen, dass ein
Open Source-Produkt nach dem Erreichen eines Stadiums, in dem es schließlich effektiv
eingesetzt werden kann, nur noch kommerziell vertrieben wird.
Letztendlich muss jeder selbst entscheiden, welches Framework oder Produkt für ihn am
sinnvollsten erscheint. Die Mächtigkeit von Open Source-Produkten (auch professionellen)
im Java-Sektor ist allerdings schon recht beeindruckend.
Lassen Sie sich nun mitnehmen auf die Reise durch eine weltweit prämierte Open Source-
Entwicklungsumgebung, durch die Tools und Utilities, die dafür geschrieben wurden,
durch die Welt von objektorientierter Softwareentwicklung und Enterprise-Technologien.
Viel Spaß beim Kennenlernen von Eclipse und beim Erobern neuer Horizonte!
Lars Wunderlich
17
eclipse_v01.book Seite 18 Montag, 30. Januar 2006 12:02 12
eclipse_v01.book Seite 19 Montag, 30. Januar 2006 12:02 12
Zur besseren Orientierung auf der Oberfläche von Eclipse wollen wir in diesem Kapitel mit
einem Quickstart beginnen. Dieser Überblick über Eclipse beinhaltet im Gegensatz zu einer
Referenz nicht jede Funktion, sondern nur jene, die bei der Arbeit vorrangig wichtig er-
scheinen.
Nach dem Start von Eclipse fragt dieses nach einem Workspace-Verzeichnis für seine eige-
nen Dateien. Wir klicken die Checkbox an, um das vorgeschlagene Verzeichnis zum De-
faultdirectory zu erklären, und wählen danach OK. Sollten Sie eine alte Eclipse-Version in-
stalliert haben oder die Daten mit einer anderen Eclipse-Version teilen wollen (z.B. wenn
Eclipse-Metadaten in einem Source-Control-System liegen), empfiehlt sich die Wahl eines
entsprechenden, anderen Verzeichnisses.
Eclipse begrüßt uns daraufhin mit dem Welcome-Bildschirm. Für Neueinsteiger empfiehlt
sich hier grundsätzlich die Führung durch die einzelnen Tutorials, um die Oberfläche ken-
nen zu lernen. Wir möchten allerdings gleich in medias res gehen und klicken daher im
Menü WINDOW den Menüpunkt OPEN PERSPECTIVE | JAVA an, um in die Java-Perspektive zu
wechseln. Gegebenenfalls müssen Sie das Welcome-Fenster auch schließen.
Aus jeder beliebigen Ansicht lässt sich über diese Menüpunkte zurück in die Java-Perspek-
tive wechseln.
2.1.1 Perspektiven
Das Aussehen von Eclipse bzw. dessen Erscheinungsbild bei der Arbeit hängt im Wesent-
lichen von der Perspektive ab, die jeweils aktiviert ist. Eine Perspektive ist eine Sammlung
von Fenstern (im Eclipse-Kontext als Views bezeichnet) und Menüpunkten, die gemeinsam
ein Themengebiet behandeln. Solche Themengebiete könnten das Editieren des Source-
codes, das Debuggen, aber auch das Installieren von weiteren Plug-Ins sein.
Grundsätzlich können eigene Perspektiven wie in einer Art Baukasten zusammengestellt, an-
geordnet und für weitere Verwendungszwecke gespeichert werden (siehe Abschnitt 2.11.1).
19
eclipse_v01.book Seite 20 Montag, 30. Januar 2006 12:02 12
Die so genannte Shortcut-Bar, die Leiste der Schnellzugriffe, ist am rechten oberen Rand
des Eclipse-Fensters angeordnet. In ihr befinden sich alle auswählbaren und bereits einmal
aktivierten Perspektiven. In der linken unteren Ecke sehen Sie Icons für alle Views, die vom
Benutzer in die Leiste gelegt wurden, um schnell zugreifbar zu sein.
In Abb. 2.1 sehen wir oben die aus vielen Programmen bekannte Menüzeile. Auf die ein-
zelnen Funktionen wollen wir hier noch nicht eingehen. Wenn bereits Erfahrungen mit
Eclipse vorliegen, sollte Ihnen bekannt sein, wie man die Such- und Startfunktionen für
Java-Programme aufruft und neue Klassen anlegt. Daneben finden sich hier alle wesentli-
chen Funktionen – die Arbeit mit Projekten, Sourcecode-Modifikationen, Suchalgorith-
men, die Konfiguration der kompletten Oberfläche, das Hilfesystem und der Welcome-
Bildschirm, den wir bereits sahen.
20
eclipse_v01.book Seite 21 Montag, 30. Januar 2006 12:02 12
Viele Funktionen aus den Menüs kommen im Beispielprojekt zum Einsatz. Eine ganze Rei-
he von ihnen sind auch über entsprechende Kontextmenüs oder eine spezielle Tastenkom-
bination, die neben dem Namen des Menüpunkts steht, verfügbar.
Viele Views verfügen über eine eigene Toolbar (wie beispielsweise Package Explorer und
Outline View), die sich direkt unter der Fenster-Namenszeile befindet und zumeist das Aus-
21
eclipse_v01.book Seite 22 Montag, 30. Januar 2006 12:02 12
sehen und den Inhalt der jeweiligen View beeinflusst. Die Package Explorer View erlaubt
dabei beispielsweise – wie dargestellt – die nachfolgenden Aktionen:
BACK – zeigt die Hierarchie, so wie sie direkt vor der aktuellen Anzeige ausgesehen hat.
FORWARD – zeigt die Hierarchie, wie sie direkt nach der aktuellen Anzeige ausgesehen hat.
UP – zeigt die Hierarchie des Elternobjekts der aktuell höchsten Resourcestufe.
COLLAPSE ALL – schließt die aktuelle Baumansicht, indem der Baum in sich „zusammen-
fällt“.
LINK WITH EDITOR – aktiviert die Synchronisation zwischen dieser View und dem aktiven
Editorfenster.
Einzelne ausgesuchte Views besitzen zusätzlich ein eigenes Funktionsmenü, das über den
kleinen nach unten weisenden schwarzen Pfeil aktiviert wird. In diesen Menüs befinden
sich zumeist jene Aktionen, die es erlauben, die Anzeige dieser View weiter an die persön-
lichen Bedürfnisse anzupassen (Ein/Ausblenden bestimmter Inhalte, Wechsel der Struktur-
darstellungen, ...).
Mit einem Rechtsklick auf das Fenster-Icon können die Fensterfunktionen angezeigt wer-
den (Abb. 2.3), wobei die Features (egal ob View oder nicht) stets gleichbleibend sind. Ne-
ben den klassischen Funktionen wie Minimierung (MINIMIZE), Maximierung (MAXIMIZE),
Größenänderung (SIZE) oder Schließen (CLOSE) verfügen die Fenster zusätzlich über die Fä-
higkeit, sich mit anderen in einem so genannten Stack zusammenfassen zu lassen. Ein
Stack ist dabei eine Art Blattsammlung mit Registern (siehe Abb. 2.4).
Per Drag&Drop kann entschieden werden, auf welchem Stack eine View abgelegt werden
soll (docking). Neu geöffnete Views werden automatisch einem Stack zugeordnet. Die Re-
gister der Views im Stack erscheinen am oberen Rand der jeweiligen View. Durch Klicken
auf den Namen des entsprechenden Registers öffnet sich die zugehörige View. Views, die
22
eclipse_v01.book Seite 23 Montag, 30. Januar 2006 12:02 12
nicht mehr in den Stack passen, können über die Doppelpfeile am rechten Rand ausgewählt
und über das Eingabefeld am oberen Rand sogar namentlich gesucht werden.
Als so genannte Fast Views werden View-Fenster bezeichnet, die über den Menüpunkt FAST
VIEW in die Shortcut Bar auf der unteren linken Seite des Eclipse Fensters verbannt wurden.
Beim Klicken auf deren Icon wird vorübergehend die entsprechende View eingeblendet.
Durch Klicken in einen anderen Fensterbereich verschwindet sie wieder. Über die rechte
Maustaste auf dem View-Icon kann die Fast-View-Anzeige wieder deaktiviert werden. Für
die Navigation zwischen Views und ihren Funktionen finden sich entsprechende Menü-
punkte und Tastatur-Shortcuts im Menü WINDOW | NAVIGATION.
23
eclipse_v01.book Seite 24 Montag, 30. Januar 2006 12:02 12
Hilfreich ist es, wenn alle Views einen in sich geschlossenen, konsistenten
Zustand zeigen. Damit Outline View, Editor und Package Explorer dabei
Bezug nehmen auf die gleichen Methoden und Klassen, aktiviert man in
den beiden Views das doppelte File-Icon (link to editor). Danach führen
——
Klicks in einem der Fenster zur Synchronisation der Ansicht mit den ver-
bleibenden.
Wie in jeder View kann auch in diesen beiden die Darstellung gefiltert werden. Durch Klick
auf das Filternsymbol (die drei nach rechts weisenden Pfeile auf der Tasks/Problems View)
erscheint ein Dialog, in dem individuell bestimmt werden kann, welche Informationsele-
mente wichtig sind.
24
eclipse_v01.book Seite 25 Montag, 30. Januar 2006 12:02 12
Eclipse erlaubt die Erfassung von so genannten Tasks. Hierzu wird im linken schraffierten
Bereich des Editors die rechte Maustaste gedrückt, ADD TASK gewählt und dann die noch
auszuführende Aufgabe beschrieben. Die neue Task befindet sich daraufhin in der Tasks
View (siehe Abb. 2.7). Abgeschlossene Arbeiten können später gelöscht werden.
Sollte die Taskview noch nicht angezeigt werden, lässt sie sich über WINDOW | SHOW VIEW |
OTHER... | BASIC | TASKS schnell herbeizaubern.
Alternativ zu Standardkommentaren bietet Eclipse die Möglichkeit, durch Inline-Kommen-
tare im Sourcecode solche Tasks selbst zu definieren und zu erzeugen. Diese Variante hat
den Vorteil, dass die komplette Information im Sourcecode bereits enthalten ist und nicht
verloren geht, wenn die Eclipse-Informationen nicht mit weitergegeben werden (z.B. zwi-
schen Entwicklern). Dafür sind diese ToDo’s auch gleich projektweit für alle sichtbar.
25
eclipse_v01.book Seite 26 Montag, 30. Januar 2006 12:02 12
Hierzu wird einfach der Begriff TODO und dahinter die Beschreibung, was zu tun ist, in
den Sourcecode-Kommentar geschrieben. Beim nächsten Speichern der Datei (Ÿ+S)
wird der Kommentar automatisch zu einer Task in der Taskliste. Dort kann er gegebenen-
falls auch modifiziert werden, was sich gleich wieder auf den Sourcecode auswirkt.
Eclipse selbst bedient sich dieser Funktionalität auch gerne und erzeugt künstlich Kom-
mentare mit dem Hinweis „To do“, wenn es beispielsweise Methoden automatisch gene-
riert und daher Javadoc und Implementierung nicht vollständig sein können.
Neben dem TODO-Tag sind andere Tags wie „to be reviewed“ oder „to be
optimized“ in ihrem jeweiligen Kontext sinnvoll. Sehr interessant ist auch
immer mitanzusehen, wenn ein Projekt beispielsweise aus dem Jakarta-
Umfeld importiert wird, an welchen Hotspots die dortigen Autoren noch
——
26
eclipse_v01.book Seite 27 Montag, 30. Januar 2006 12:02 12
1. http://jakarta.apache.org/oro
27
eclipse_v01.book Seite 28 Montag, 30. Januar 2006 12:02 12
Hilfe in Eclipse
Die Beschreibung einer Regular Expression setzt sich zumeist aus der Kombination eines
Wertebereichs (z.B. [0-9]) und einer Mengenangabe ({5}) zusammen. Tabelle 2.1 zeigt ei-
nige Beispiele.
[0-9]{2} zwei Ziffern – Beispiel: 05, 76, 65, 54, 29, 99, ...
Für unser Beispiel legen wir jetzt als Erstes über das Menü FILE | NEW | PROJECT | JAVA | JAVA
PROJECT | NEXT ein neues Java-Projekt mit dem Namen RegExTest an. Nach der Eingabe
des Namens im Feld PROJECT NAME drücken wir den Button FINISH, um das Projekt zu er-
zeugen. Dann drücken wir auf dem Projektnamen die rechte Maustaste, wählen aus dem
Kontextmenü den Menüpunkt NEW | PACKAGE, tippen als Package-Namen com.entwick-
ler.eclipsebuch.kapitel2.analyzer ein und klicken auf FINISH. Auf dem erzeug-
ten Package wählen wir wiederum aus dem Kontextmenü den Menüpunkt NEW | CLASS, als
Klassennamen geben wir ExpressionAnalyzer im Wizard ein und drücken auf FINISH.
Sollte automatisch eine Main-Methode erzeugt worden sein, können Sie diese getrost erst
einmal löschen.
Damit ist die erste Beispielklasse com.entwickler.eclipsebuch.kapitel2.analy-
zer.ExpressionAnalyzer erzeugt, wenn auch bisher mit wenig Sourcecode. Diesen
kann man sich in einem Editor ansehen. Ein Doppelklick auf den Dateinamen öffnet stets
ein entsprechendes Editorfenster. Eine gegebenenfalls generierte Main-Methode können
wir vorerst löschen.
Wir schreiben jetzt eine Methode, die alle Vorkommnisse eines Pattern innerhalb eines
Strings heraussucht und die Menge dieser gefundenen Ergebnisse in einem Vektor zurück-
liefert. Zunächst erzeugen wir die Methodensignatur. Hierzu tippen wir den folgenden
Sourcecode in die ExpressionAnalyzer-Klasse ein:
Bereits jetzt meldet Eclipse, dass es die Begriffe Vector und den Listentyp String nicht
kennt, da wir in den Importstatements die Klasse Vector auch noch nicht bekannt gemacht
haben. Lassen wir die Maus über den Begriff Vector fahren, zeigt uns Eclipse die Begrün-
dung in einem so genannten Hover an. Eclipse benutzt Hovers an vielen Stellen zur Anzei-
ge von Problemen, für Vorschläge, wie man diese lösen kann, oder zur Kenntlichmachung
von Dokumentationen.
28
eclipse_v01.book Seite 29 Montag, 30. Januar 2006 12:02 12
Haben wir bereits gespeichert (Tastenkombination: Ÿ+S) und dadurch implizit den
Compile-Lauf ausgelöst, finden wir eine ganze Reihe von Hinweisen auf einen Fehler. Zu-
nächst einmal ist der Begriff Vector unterstrichen. Das kleine Lämpchen mit dem X links
vom Sourcecode zeigt den Fehler an, auf der rechten Seite vom Sourcecode-Fenster findet
sich ein kleiner Balken, der anzeigt, dass sich an dieser Stelle vom Gesamtdokument ein
Fehler befindet. Ein kleiner roter Kasten in der rechten oberen Ecke des Editorfensters
weist auf einen Fehler hin und der Editorreiter mit dem Namen ExpressionAnalyzer.java
besitzt ebenfalls ein rotes X (siehe Abb. 2.9).
Dies setzt sich in der Package Explorer View auf der linken Seite fort. Die Klasse, das
Package und auch das komplette Projekt bekommen ein X als Kennzeichnung eines Com-
pile-Fehlers und schließlich finden sich in der Problems View darunter noch einmal die
Fehler mit Beschreibung, Resource, Ordner und Angabe der Zeilennummer. Ein Dop-
pelklick auf den Fehler in der Problems View führt ebenfalls zum Compile-Fehler. Dass der
Fehler auch in der Outline View rechts angezeigt wird, dürfte schon fast selbstverständlich
erscheinen.
Eclipse bietet zur Problemlösung mehrere Möglichkeiten an. Bei keiner davon muss das
Importstatement allerdings per Hand ergänzt werden.
29
eclipse_v01.book Seite 30 Montag, 30. Januar 2006 12:02 12
Hilfe in Eclipse
Das Klicken auf das kleine Lämpchen links vom Sourcecode (oder Ÿ-1 auf dem se-
lektierten Vector-Begriff) ermöglicht es, sich die Lösungsmöglichkeiten (Quick Fix) für
das Problem anzeigen zu lassen. Eclipse bietet u.a. an, die Klasse Vector aus java.util
zu importieren, eine Vector-Klasse zu erzeugen oder ein entsprechendes Interface zu ge-
nerieren, und zwar jeweils im Hover daneben unter Erläuterung der Aktivitäten, die es
durchführen würde. Wir entscheiden uns für den Import der Klasse Vector. Nach einem
weiteren Compile mit Ÿ+S bleiben Vector und String aber markiert. Grund ist dafür
der Compliance Level. In Java 1.4 waren getypte Listen noch nicht erlaubt. Wir klicken nun
mit dem Cursor auf den Begriff „String“ und drücken erneut Ÿ-1. Aus der Auswahl
wählen wir CHANGE WORKSPACE COMPLIANCE AND JRE TO 5.0. Hiermit wird der gesamte
Workspace Java-5.0-fähig gemacht. Wir speichern erneut mit Ÿ-S. Vector und
String sind jetzt nicht mehr unterstrichen. Dieser Fehler scheint behoben.
Eclipse 3.1 ist grundsätzlich in der Lage, neben 5.0 auch mit JRE 1.3 und
1.4 umzugehen. Die Eclipse-Version 3.2 bringt zusätzlich Unterstützung
für Java 6 mit. Da sich die Java-5-Sprachfeatures deutlich von denen von
Java 1.4 unterscheiden, müssen sie entweder pro Projekt oder für das
——
ganze Eclipse aktiviert werden. Die Installation eines Java-5-JDKs ist hier-
für Voraussetzung. Haben Sie dies noch nicht getan, können Sie weitere
JREs über das Menü WINDOW | PREFERENCES | JAVA | INSTALLED JREs nach-
holen. In den Beispielen kam ein Sun JDK 5.0_05 zum Einsatz. Wählen
Sie zum Ändern der Compile-Einstellungen entweder im Menü WINDOW |
PREFERENCES | JAVA | COMPILER | JAVA COMPLIANCE LEVEL aus oder wählen Sie
über das Kontextmenü auf einem Java-Projekt im Menüpunkt PROPERTIES
den Unterpunkt JAVA COMPILER | ENABLE PROJECT SPECIFIC SETTINGS und stel-
len Sie den JAVA COMPLIANCE LEVEL entsprechend ein.
Dafür weist Eclipse nun darauf hin, dass wir zwar ein getyptes Vector-Objekt zurückge-
ben wollten, aber kein return-Statement haben. Auch hier können wir den Fehler auf die
gleiche Art und Weise beheben, indem wir uns die Lösungsvarianten durch Klick auf das
Lämpchen anzeigen lassen (siehe Abb. 2.11).
30
eclipse_v01.book Seite 31 Montag, 30. Januar 2006 12:02 12
Die Entscheidung fällt erneut auf die erste Lösungsalternative: das Erzeugen des return-
Statement.
31
eclipse_v01.book Seite 32 Montag, 30. Januar 2006 12:02 12
Eclipse erkennt anhand seines Scans über das Verzeichnis, in welchen Unterverzeichnissen
sich Java-Klassen befinden (kann versionsbedingt leicht abweichen) und dass zum Beispiel
ein Compile des /doc-Verzeichnisses keinen Sinn macht (siehe Abb. 2.13). Eclipse erkennt
dabei auch die unterschiedlichen Packagestatements und dass bei den Hauptklassen die
Package-Struktur bereits bei /src/java beginnt. Es bietet ein entsprechendes Projektlayout
zur Erstellung in Form einer Baumdarstellung an.
Da wir die Tools und Examples nicht mitkompilieren möchten, löschen wir deren Einträge
heraus, so dass nur noch /src/java übrig bleibt. Hierfür klicken wir auf dem /src/java-Zweig
mit der rechten Maustaste den Menüpunkt CONFIGURE INCLUSION/ EXCLUSION FILTERS an. Er
definiert, welche Verzeichnisse unterhalb von /src/java nicht in den Compile mit einbezo-
gen werden sollen. Um die gegebenenfalls unerwünschten Packages examples und tools
auszuschließen, fügen wir nun im Fenster EXCLUSION PATTERN über den Button ADD MUL-
TIPLE die Verzeichnisse examples und tools (siehe Abb. 2.14) hinzu.
32
eclipse_v01.book Seite 33 Montag, 30. Januar 2006 12:02 12
33
eclipse_v01.book Seite 34 Montag, 30. Januar 2006 12:02 12
keine Vorteile.
Möglicherweise (je nach Version, die von ORO vorliegt) erscheinen eine Reihe von Warn-
dreiecken, die in der Problems View von Eclipse als nicht verwendete Importstatements in
diversen Klassen ausgewiesen werden. Diese Warnings können wir wie im vorhergehenden
Kapitel beschrieben wegfiltern. Sie würden allerdings als Warndreiecke weiterhin zu sehen
sein. Alternativ lassen sich auch die Compile-Einstellungen so ändern, dass diese Fehler
keine Warnungen erzeugen.
34
eclipse_v01.book Seite 35 Montag, 30. Januar 2006 12:02 12
Import Source
Würde die normale Importfunktionalität von Eclipse benutzt werden (Menü FILE | IMPORT
|FILE SYSTEM), würde im Normalfall ein Projekt im Eclipse-Workspace-Verzeichnis ange-
legt werden und alle bereits vorhandenen Dateien müssten noch einmal dort hineinkopiert
werden. Das ist z.B. dann sinnvoll, wenn der Sourcecode nicht in einzelnen Dateien vor-
liegt, sondern in einem Jar-File, er aber trotzdem gesehen werden soll, oder wenn die ur-
sprünglichen Dateien durch Modifikationen in Eclipse nicht verändert werden sollen.
Attach Source
Eclipse bietet die Möglichkeit wie auch beim Sourcecode des Java Runtime Environments,
Sourcecode nachträglich zu „attachen“. Wenn also neben dem Sourcecode auch der zustän-
dige Bytecode bereits vorliegt, werden in das Projekt die entsprechenden Class- bzw. Jar-
Files importiert und Eclipse wird durch Doppelklick auf dem entsprechenden Classfile mit-
geteilt, den Sourcecode hierzu anzuzeigen.
35
eclipse_v01.book Seite 36 Montag, 30. Januar 2006 12:02 12
Als ratsam hat sich erwiesen, unter bestimmten Umständen entgegen dem
obigen Beispiel Sourcecode und das fertig kompilierte Jar-File mit den
Classfiles gleichzeitig zu importieren. In diesem Fall wird der Sourcecode
quasi doppelt importiert. Wenn man überlegt, dass die JVM streng nach
——
36
eclipse_v01.book Seite 37 Montag, 30. Januar 2006 12:02 12
Über die integrierte Combobox können Sie in den Properties nach Schlagwörtern suchen,
was bei umfangreichen Einstellungen und vielen installierten Plug-Ins sehr hilfreich sein
kann, um den Überblick nicht zu verlieren. Mittels der Pfeile in der rechten oberen Bild-
hälfte ist es möglich zwischen einzelnen Eigenschaftsseiten und deren Konfigurationen
hin- und herzublättern.
Compiler-Einstellungen
Im Unterpunkt JAVA COMPILER nehmen wir die Einstellungen für die individuelle Konfigu-
ration des Compile-Vorgangs bezogen auf dieses einzelne ORO-Projekt vor. Wir aktivieren
die Checkbox für USE PROJECT SETTINGS, um das Projekt separat zu konfigurieren. Hier kön-
nen Sie nun auch nochmals – falls noch nicht geschehen – den Compiler-Level auf 5.0-Un-
terstützung umschalten. Neben der separaten Einzeleinstellung der generierten Class-File-
Versionen findet sich darunter auch die sehr wichtige Konfiguration der zu generierenden
Attribute der Class-Files. Wer sicher gehen möchte, dass keine Probleme während des De-
buggens auftreten, sollte an diesen Einstellungen möglichst wenige Modifikationen vor-
nehmen.
Auf der linken Seite finden Sie im Baum unterhalb der Basis-Compiler-Einstellung auch
weitere Eigenschaftsseiten für den Build-Prozess und die erzeugten Warnungen und Fehler,
die der Compiler dabei ausgibt. Wir klicken nun den Unterpunkt ERRORS/WARNINGS an, ak-
tivieren die Checkbox USE PROJECT SETTINGS und klicken das Element UNNECESSARY CODE
an. Wir finden hier eine ganze Reihe von Prüfroutinen, darunter auch auf nicht verwendete
Importstatements, die u.a. schuld an den Build-Warnungen bei ORO sind. Hier stellen wir
die Combobox UNUSED IMPORTS von WARNING auf IGNORE um. Dies führt beim Kompilieren
zum Ignorieren der unbenutzten Importstatements im Sourcecode.
Grundsätzlich sollte im Projekt vereinbart werden, wie streng der Compile bei der Arbeit
vorgeht, für welche Classfile-Version kompiliert wird und wie der Build-Path (welche Lib-
raries verwendet werden) aussehen soll. Für die projektübergreifende Dokumentation der
Compiler-Einstellungen siehe Abschnitt 2.12.
In diesem ERRORS/WARNINGS-Abschnitt finden sich sehr unterschiedliche Elemente, die den
Build-Prozess beeinflussen können. Die Einstellungen für POTENTIAL PROGRAMMING PRO-
BLEMS und NAME SHADOWING AND CONFLICTS helfen schnell und einfach, bereits bei der Ko-
dierung mögliche Unstimmigkeiten im Sourcecode aufzudecken. Eclipses Fähigkeit, dabei
jede Java-Klasse sofort beim Speichern kompilieren zu können (inkrementelle Updates),
hilft beim schnellen Aufdecken von Fehlern.
Unter diesen Einstellungen findet sich auch eine, die serialisierbare Klassen auf das Vor-
handensein eines serialVersionUID-Felds prüft. Da diese Prüfung nur bedingt sinnvoll ist,
sei an dieser Stelle für das ORO-Projekt empfohlen, den Punkt SERIALIZABLE CLASS WITHOUT
SERIALVERSIONUID auf die Prüfung IGNORE zu schalten.
Auch für die Java 5-Version wurden hier zahlreiche eigene Einstellungen integriert, die sich
um Prüfungen bezüglich der neuen Sprachfeatures ranken. Darunter finden sich sowohl
Checks für generische Typen als auch Autoboxing (J2SE 5.0 OPTIONS). Da dieses ORO-Pro-
jekt noch Java-1.4-kompatibel ist, zielen zahlreiche Warnungen des Compilers auf unge-
37
eclipse_v01.book Seite 38 Montag, 30. Januar 2006 12:02 12
typte List-Elemente ab, die sich darin finden. Um diese Probleme zu umgehen, wählen Sie
in der Combobox UNCHECKED GENERIC TYPE OPERATIONS den Checkbox-Punkt IGNORE aus.
Im Unterelement BUILDING der Java-Compiler-Einstellung lassen sich auf die Projekte im
Workspace bezogene weitere Build-Einstellungen vornehmen, die nur indirekt zum Java-
Compiler in Beziehung stehen.
Pfade (z.B. Jar-Files, die tatsächlich derzeit nicht verfügbar sind) reagieren
soll und ob zirkuläre Abhängigkeiten zwischen Verzeichnissen erlaubt
sind. In letzterem Fall wird Eclipse nur schwer handhabbar, wenn man
nicht gleichzeitig Einfluss nimmt, wann die IDE auch die Ausgabeverzeich-
nisse für einen Recompile löscht (Scrub output folders when cleaning pro-
jects). Diese Einstellungen sind sehr mächtig, Änderungen an diesen
können aber auch zu sehr unangenehmen Nebeneffekten führen (z.B.
existierende Class-Files ohne zugehörige Java-Dateien).
Der Unterpunkt JAVA TASK TAGS ermöglicht es, das bereits definierte Tag TODO (siehe Ab-
schnitt 2.1.10) von der Liste der geprüften Tags zu entfernen. Wenn nicht großes Interesse
an der Dokumentation von Alpha- oder Betaversionskommentaren besteht, ist es hin und
wieder vorteilhaft, sich von diesem Ballast zu befreien. Wir löschen den TODO-Tag heraus.
Javadoc Location
Der Dialogpunkt JAVADOC LOCATION bietet die Möglichkeit, die aus dem Javadoc durch die
Entwickler erzeugte API-Dokumentation in das Projekt einzubringen. Da wir bereits in
dem Beispiel den fertigen Sourcecode importiert haben, ist die Javadoc-Dokumentation
quasi schon inklusive. Aber besonders bei Klassen von Drittanbietern, deren Sourcecode
nicht vorliegt, ist das Hinzufügen der API-Dokumentation sinnvoll.
38
eclipse_v01.book Seite 39 Montag, 30. Januar 2006 12:02 12
Die in dieser Kurzvorstellung präsentierten Einstellungen für das ORO-Projekt lassen sich
selbstverständlich auch für die gesamte Workbench, sprich alle Projekte, gleichzeitig
durchführen. Sie finden diese stets über das WINDOW | PREFERENCES-Menü oder den Link
CONFIGURE WORKSPACE SETTINGS in diesem Eigenschaftendialog.
Schließen Sie nun den Eigenschaftsdialog des ORO-Projekts mit dem Klick auf den Button
OK. Haben Sie einige oder sogar alle der oben empfohlenen Einstellungen vorgenommen,
werden Sie nun gefragt, ob das Projekt sinnvoller neu kompiliert werden sollte, um diese
auch zu aktivieren. Wir bestätigen in diesem Fall mit OK. Haben Sie alle Einstellungen vor-
genommen, sollte das Projekt selbst jetzt fehlerfrei kompilieren.
Für das RegExTest-Projekt erscheinen die Klassen aus ORO wie in einem einzigen großen
Projekt, während ORO umgekehrt von RegExTest gar nichts weiß.
den Compile und zur Laufzeit zu bilden ist. Dennoch sind sie grundsätzlich
möglich, wie wir bereits gesehen haben. Besonders wenn Fremd-Plug-Ins
oder unterschiedliche Library-Versionen oder Implementierungen benutzt
werden (was z.B. bei XML-Parser-Verwendung leicht passieren kann), ist
das Chaos schnell sehr groß. ClassNotFound-Exceptions, MethodNot-
Found-Probleme usw. können leicht durch unerwartete Bibliotheken und
Projektreferenzen entstehen.
39
eclipse_v01.book Seite 40 Montag, 30. Januar 2006 12:02 12
Sourcecode-Editor-Features
2.4 Sourcecode-Editor-Features
Der Sourcecode-Editor hat eine große Fülle an Features zu bieten, die nun anhand des Bei-
spiels betrachtet werden sollen. Grundsätzlich kann der Sourcecode vollkommen ohne wei-
tere Unterstützung über die üblichen Tastenkombinationen, wie z.B. Cut and Paste, bear-
beitet werden. Eclipse 3.2 bietet zusätzlich über die Cut and Paste-Funktionalität auch an,
Klassen, die sich in der Zwischenablage als Sourcecode befinden, automatisch ohne Anle-
gen expliziter Java-Dateien in Eclipse zu integrieren und zu kompilieren.
Wir ergänzen den Sourcecode der ExpressionAnalyzer-Klasse, so dass er wie folgt aus-
sieht (die Kommentare können dabei wahlweise ignoriert werden, die Fehler im Source-
code werden wir im Folgenden beseitigen):
package com.entwickler.eclipsebuch.kapitel2.analyzer;
import java.util.Vector;
/**
* ExpressionAnalyzer Test-Klasse
*/
Sourcecode Folding
Seit Version 3.0 beherrscht Eclipse nach Vorlage aus dem Microsoft .NET Visual Studio
und NetBeans nun auch das Sourcecode Folding. Über die kreisförmig umrahmten +- und
–-Zeichen links des Sourcecodes können einzelne Methoden oder ganze Klassen „zusam-
mengefaltet“ werden, um Überblick im Sourcecode zu erlangen.
40
eclipse_v01.book Seite 41 Montag, 30. Januar 2006 12:02 12
Neben dieser kleinen „Schönheits-OP“ verbirgt das Source-Menü aber eine ganze Reihe
weiterer Features. Bevor wir diese betrachten, fügen wir für die unbekannten Klassen die
entsprechenden Importstatements hinzu, die derzeit einen fehlerlosen Compile verhindern.
Dazu wählen wir ebenfalls im Untermenü SOURCE den Punkt ORGANIZE IMPORTS und drü-
cken nach dem automatischen Einfügen der Imports durch Eclipse Ÿ+S zum Spei-
chern.
Jetzt führt nur noch die Variable regexpCompiler zu einem Fehler. Falls weitere Fehler
auftreten, könnte es daran liegen, dass das ORO-Projekt vom RegExTest-Projekt aus nicht
korrekt – wie oben beschrieben – referenziert wurde (siehe Abschnitt 2.3.1).
Hinweis: Teilweise beherrscht Eclipse ein automatisches Organize Import. Wenn zwischen
zwei Klassen Sourcecode kopiert wird und sich die Referenzen auf Klassen des eigenen
Projekts beziehen, wird das Organize Imports unter Umständen von der IDE bereits ohne
weiteres Zutun durchgeführt.
Die Indentation, also die Einrückung des Sourcecodes, kann per Hand mit der Å-Taste
vorgenommen werden, wobei Á+Å die Einrückungen rückgängig macht. Der Wert
für die Anzahl der Leerzeichen pro Å-Tastendruck lässt sich in den PREFERENCES (siehe
Abschnitt 2.12) einstellen. Über den Menüpunkt CORRECT INDENTATION im Source-Kontext-
menü lässt sich zudem die Einrückung automatisch korrigieren.
Die nachfolgenden Funktionen erreicht man über das Untermenü SOURCE mit der rechten
Maustaste im geöffneten Editorfenster:
Kommentare
Mit dem Menüpunkt TOGGLE COMMENT (Ÿ+/) lässt sich für einen mit der Maus mar-
kierten Bereich ein Kommentar (//) erzeugen bzw. löschen. Mit den darunter folgenden
Aktionen ADD BLOCK COMMENT (Ÿ+Á+/) und REMOVE BLOCK COMMENT
(Ÿ+Á+\) ist selbiges auch im C++-Kommentarstil (/*) möglich.
41
eclipse_v01.book Seite 42 Montag, 30. Januar 2006 12:02 12
Sourcecode-Editor-Features
Wenn Sie jetzt korrekterweise noch den Javadoc-Kommentar vermissen: Dieser lässt sich
über den Unterpunkt ADD JAVADOC COMMENT (Ç+Á+J) anlegen. Der Javadoc-Kom-
mentar bezieht sich dabei immer auf das jeweilige Java-Element, das zurzeit im Source
markiert ist.
durchführ- bzw. anwendbar ist bzw. ob die Datei nicht schreibgeschützt ist
oder der Sourcecode nur attacht wurde und nicht geändert werden kann.
Importstatements
Das Ändern aller Importstatements gleichzeitig haben wir oben bereits gesehen. Ist ein
Klassenname im Kontext aller Libraries, die sich in einem Build-Path befinden, nicht ein-
deutig, bietet Eclipse eine entsprechende Dialogauswahl an. Über den Untermenüpunkt
ADD IMPORT (Ÿ+Á+M) kann im Gegensatz zu ORGANIZE IMPORTS (Ÿ+Á+O)
nur ein einzelnes Importstatement angelegt werden, und zwar für die Klasse, auf der sich
der Cursor zurzeit befindet.
Der Vollständigkeit halber sollten wir die Features in Bezug auf Imports auch abrunden.
Wenn der Cursor auf einer unbekannten Klasse steht, zeigt Eclipse an, dass es die Klasse
nicht kennt. Lassen wir den Cursor stehen und bewegen die Maus hinter den Namen der
Klasse, zeigt Eclipse an, welche Klasse es hinter dem Klassennamen vermutet. Gehen wir
mit dem Cursor direkt hinter den Klassennamen und drücken Ÿ+Leertaste, generiert
Eclipse (soweit es die Klasse im Build-Path findet) das Importstatement automatisch.
In Abschnitt 2.12 ist beschrieben, wie die Reihenfolge der Importstatements beeinflusst
werden kann.
42
eclipse_v01.book Seite 43 Montag, 30. Januar 2006 12:02 12
Eclipse bietet eine ganze Reihe an Lösungsmöglichkeiten an (siehe Abb. 2.18), angefangen
vom einfachen Anlegen einer lokalen Methodenvariablen, über eine Instanzvariable, einen
neuen Methodenparameter bis zur Generierung von nicht ganz Java-Style-like Klassen und
Interfaces mit kleinem führenden Anfangsbuchstaben.
Wir entscheiden uns für die Erstellung des privaten Felds (zweiter QuickFix-Punkt).
Da Eclipse den Typ der Variablen, die danach gecastet wird, innerhalb des Methodenauf-
rufs nicht erraten kann, erzeugt es ein relativ unspektakuläres Feld:
Wir werden den Typen modifizieren und für dieses Feld, das private deklariert worden
ist, noch eine Setter-Methode definieren.
43
eclipse_v01.book Seite 44 Montag, 30. Januar 2006 12:02 12
Sourcecode-Editor-Features
code die neue Methode platziert werden soll, und die SORT BY-Optionen, die die Reihenfolge
der angelegten Methoden kontrollieren.
Über die Checkbox GENERATE METHOD COMMENT lassen sich die typischen Methodenkom-
mentare erzeugen. In den Generierungsschritt von Kommentar und Methodenname können
Sie allerdings über entsprechende CODE TEMPLATES separat eingreifen. Klicken Sie zur Kon-
figuration hier auf den Link für die Code Templates. Sie werden aus den Workbench Pre-
ferences bedient, die wir später noch näher kennen lernen.
In Abb. 2.19 ist der Dialog für die Erzeugung von Getter- und Setter-Methoden dargestellt.
Wir klicken dabei die Get-Methode aus und wählen anschließend OK zur Generierung des
Setters.
44
eclipse_v01.book Seite 45 Montag, 30. Januar 2006 12:02 12
an. Über die Cursortasten lässt sich eine auswählen oder der Begriff manuell vervollständi-
gen. Zu bekannten Klassen zeigt Eclipse gleichzeitig daneben den Javadoc-Kommentar zur
Hilfestellung an. Die Auswahl einer Klasse führt implizit auch zur Generierung eines zu-
gehörigen Importstatements.
Eclipse unterscheidet sich bei der Code completion von den meisten anderen IDEs durch
die umfangreiche Liste der Vervollständigungsangebote. Während andere IDEs teilweise
noch die Klassen- und Methodensignaturen umständlich neu ermitteln müssen, macht
Eclipse dies intern automatisch – genauso wie die Auswahl des zugehörigen Javadoc-Kom-
mentars.
Was für die Vervollständigung von Klassennamen gilt, gilt genauso für die Vervollständi-
gung von Methoden- oder Variablennamen – bei den Variablen sogar bezogen auf Instanz-
oder lokale Variablen, die in der jeweiligen Methode verfügbar sind. Wurde noch keine Ein-
gabe getätigt, bietet Eclipse bei Ÿ+Leertaste eine Auswahl der vorhandenen Felder,
Methoden und Variablen der Klasse an.
Mittlerweile sieht der Sourcecode unseres Beispiels in etwa so aus (die Kommentare sind
der Einfachheit halber weggelassen, die noch vorhandenen Fehler sind markiert):
package com.entwickler.eclipsebuch.kapitel2.analyzer;
import java.util.Vector;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcherInput;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.Perl5Pattern;
45
eclipse_v01.book Seite 46 Montag, 30. Januar 2006 12:02 12
Sourcecode-Editor-Features
2.4.4 Try-Catch-Block-Generierung
Im Beispiel-Sourcecode muss die MalformedException abgefangen werden. Dazu mar-
kieren wir alle bisher kodierten Zeilen der gesamten Methode mit der Maus und wählen
dann über das Menü hinter der rechten Maustaste SOURCE | SURROUND WITH TRY/CATCH
BLOCK. Eclipse scannt die einzelnen Zeilen ab, um herauszufinden, welche unterschiedli-
chen Exception-Typen generiert werden können. Kann Eclipse keine finden, bietet es die
Möglichkeit, RuntimeExceptions im Catch-Block abzufangen. Die Generierung schlägt bei
unvollständig markierten Blöcken und anderen vorhandenen Compile-Fehlern im markier-
ten Bereich fehl (siehe Abb. 2.20).
46
eclipse_v01.book Seite 47 Montag, 30. Januar 2006 12:02 12
Grundsätzlich bezieht sich die Generierung von Try-Catch-Blöcken nur auf von ja-
va.lang.Exception abgeleitete Exception-Klassen. RuntimeException, Error und
Throwable bleiben außen vor.
Den von Eclipse erzeugten Catch-Block füllen wir mit der Zeile:
Hierbei erzeugt die Erstellung des Try-Catch-Blocks auch eine TODO-Task. Damit infor-
miert Eclipse über den noch zu füllenden Bereich und schreibt den Inhalt der Exception
über e.printStackTrace() in den Outputstream. Die BusinessException ist Eclipse
unbekannt, so dass es nach dem Compile zu entsprechenden Fehlermeldungen kommt. Mit
einem Klick auf das Fehlerlämpchen kann die Generierung einer neuen BusinessExcep-
tion-Klasse forciert werden. Eclipse geht dabei davon aus, dass die neue BusinessEx-
ception-Klasse von der java.lang.Exception-Klasse erbt und in das gleiche Package
gehört.
Wir lassen uns also über den Quick Fix eine entsprechende Exception-Klasse erzeugen.
Hierbei müssen wir darauf achten, die Checkbox CONSTRUCTORS FROM SUPERCLASS anzukli-
cken, um einen entsprechenden Konstruktor für die Klasse zu generieren, der auch den
String als Parameter entgegennehmen kann.
Es bleibt schließlich noch die fehlende throws-Information in der Methodensignatur der
getAllOccurrencesOfPattern-Methode. Wir können über einen Quick Fix das ge-
wünschte Ergebnis erzielen, indem wir das kleine Lämpchen auf der linken Seite anklicken
und CREATE CLASS 'BUSINESSEXCEPTION' wählen.
Eclipse öffnet jetzt einen Wizard zur weiteren Definition der Klasse. Wir belassen einfach
die Standardeinstellungen wie sie sind und klicken den OK-Button an.
Die neu generierte Exception wird erzeugt. Die Signatur der Methode hat allerdings noch
keine throws-Erweiterung. Daher klicken wir nach dem Speichern der Klasse erneut auf das
Lämpchen links vom Compile-Fehler und wählen ADD THROWS DECLARATION. Eclipse möch-
te schließlich noch wissen, welchen Exception-Typ die Methode werfen soll. Hier wählen
wir die BusinessException aus (siehe Abb. 2.21).
47
eclipse_v01.book Seite 48 Montag, 30. Januar 2006 12:02 12
Sourcecode-Editor-Features
Wir beginnen die Zeile hinter dem PatternMatcherInput und vor dem return-
Statement mit der Eingabe des Befehls while. Danach drücken wir Ÿ+Leertaste, um
die Kontexthilfe aufzurufen. Eclipse bietet drei verschiedene While-Schleifen an. Wir be-
gnügen uns mit der einfachsten (WHILE LOOP WITH CONDITION) und wählen diese aus (siehe
Abb. 2.22).
Der Editor vervollständigt die Schleife und markiert den noch undefinierten Condition-
Ausdruck. Wir geben als logischen Ausdruck die Buchstaben occ ein und drücken
Ÿ+Leertaste. Der Begriff wird auf occurrencesMatcher automatisch vervollstän-
digt. Anschließend tippen wir einen Punkt ein und drücken erneut Ÿ+Leertaste, um die
Menge aller Methoden zu sehen, die diese Objektinstanz anbietet.
Wenn wir c als ersten Buchstaben der zu suchenden Methode eingeben, filtert Eclipse auf
alle Methoden im occurrencesMatcher-Objekt, die mit c beginnen. Wir wählen die
zweite Methodensignatur (PatternMatcherInput, Pattern) aus, um diese zu erstellen
(siehe Abb. 2.23).
48
eclipse_v01.book Seite 49 Montag, 30. Januar 2006 12:02 12
Der Editor hilft bei langen Methodensignaturen, dass Sie nicht den Überblick über die Pa-
rameterreihenfolge verlieren, indem jeweils der gerade eingegebene Parameter im Tooltip
über der Methode fett markiert wird. Der Editor kann auch so konfiguriert werden, dass er
die Variablennamen, die in der Methodensignatur existieren, automatisch in die Code com-
pletion übernimmt. Allerdings ist dies nur selten nützlich. Wir ergänzen die While-Condi-
tion um die Parameter input und pattern. Selbstverständlich können wir auch hierbei
die Code-Vervollständigung ganz nach den eigenen Wünschen anwenden oder weitertip-
pen (siehe Abb. 2.24).
Semantisch haben wir festgelegt, dass die Schleife so lange durchgeführt wird, bis der
Matcher (quasi das Suchprogramm) im Input (in den Daten, die ihm übergeben worden
sind) das Pattern (das Suchmuster) findet.
Wir vervollständigen nun die Methode getAllOccurrencesOfPattern so, dass der
Sourcecode in der Methode wie folgt erscheint (Kommentare sind entfernt):
49
eclipse_v01.book Seite 50 Montag, 30. Januar 2006 12:02 12
Sourcecode-Editor-Features
Prüfen Sie bitte auch, ob die Erzeugung des results-Elements und das return-State-
ment wie im Beispielcode außerhalb des Try-Catch-Blocks sind, um die Übung problemlos
fortsetzen zu können. Sollten Sie erstmals die Code Completion-Funktionen von Eclipse
ausprobiert haben, wird dies vermutlich ohne Erfolg verlaufen sein. Grundsätzlich ist
Eclipse bei der Editierung nur dann behilflich, wenn es über genügend Wissen bezüglich
Klassen und Referenzen verfügt. Da Eclipse die Klasse MatchResult noch nicht kennt,
ergänzen wir das Importstatement entsprechend, indem wir hinter dem Begriff Match-
Result den Cursor setzen und Ÿ+Leertaste betätigen.
Wie im Beispiel-Source zu sehen, holen wir uns aus dem Matcher-Objekt die gefundenen
Results und daraus die erste Gruppe (group(0)). Bei einfachen Regular Expressions ent-
spricht dies dem gesuchten Ergebnisstring. Diesen fügen wir in unseren Result-Vektor re-
sult ein und erhalten so die fertige Ergebnismenge.
Smart Insert
Der Editor unterscheidet selbstverständlich auch zwischen Overwrite (Überschreiben) und
Insert (Einfügen), erreichbar über die ¡-Taste. Dabei kennt er aber auch eine Java-spe-
zifische Variante Smart Insert, deren Verhalten über die Preferences steuerbar ist.
50
eclipse_v01.book Seite 51 Montag, 30. Januar 2006 12:02 12
Kleiner Tipp für Löschexperten: Wenn Sie versehentlich einmal eine Java-
Klasse gelöscht haben sollten, was ohne Source Control Management-
System einer Vernichtung der Datei entspricht, erzeugen Sie eine neue
Java-Klasse mit dem exakt gleichen vollqualifizierten Namen und suchen
—
Sie mit REPLACE WITH FROM LOCATION HISTORY den letzten noch im Speicher
vorhandenen Stand. So lassen sich oft auch gelöschte Klassen recht ein-
fach wieder rekonstruieren.
1. Fowler, Martin – Refactoring – Wie Sie das Design vorhandener Software verbessern, 1. Auflage 15.03.2000,
Verlag Addison-Wesley, ISBN 3827316308
51
eclipse_v01.book Seite 52 Montag, 30. Januar 2006 12:02 12
Spricht man von Design, so ist nicht das Einrücken des Sourcecodes gemeint, sondern die
Art und Weise, wie Klassen und Objekte miteinander in Beziehung stehen und interagieren
(siehe auch Themenstellung Modellierung im Kapitel 3).
„Jeder Dummkopf kann Code schreiben, den ein Computer versteht. Gute Programmierer
schreiben Code, den Menschen verstehen.“1
Normalerweise bemüht sich der Entwickler um ein sauberes Design bei seiner Modellie-
rung, macht sich Gedanken über abstrakte Inhaltsbeschreibungen, konkrete Implementie-
rungen, Komponenten oder Interaktionen. Irgendwann, wenn das fertige Produkt dann an
den Kunden ausgeliefert ist, gibt es dennoch etliche Stellen, wo man von der Schönheit der
ersten Modellierungsstunde abgekommen ist, wo es Redundanzen im Sourcecode gibt, wo
Dokumentation vernachlässigt worden ist oder wo unnötige Abhängigkeiten von Kompo-
nenten untereinander entstanden sind. Meist sind Gründe dafür mangelndes Wissen über
die Ziele des Architekten/Designers, der das Design entwarf, oder Kompromisse, die man
aus Zeitgründen eingegangen ist, um schnell am Markt zu sein. Solche Strategien rächen
sich oft später beim Bugfixing oder in der Wartung.
Refactoring versucht, eine Antwort auf diese Probleme zu liefern, indem es beschreibt, wie
Sourcecode angepasst werden kann, damit er leichter verständlich und gleichzeitig leichter
wartbar wird.
Eclipse bietet eine Reihe von Refactoring-Mechanismen. Selbst wenn nur eine Variable
umbenannt oder eine Klasse von einem Package in ein anderes verschoben werden soll, ist
dies streng genommen eine Art von Refactoring.
Bei der Durchführung einer Refactoring-Maßnahme ergeben sich in der Regel eine Viel-
zahl unerwarteter Abhängigkeiten. Wird z.B. einer Methode ein anderer Name gegeben, ist
es sinnvoll, zu wissen, wer diese Methode aufruft, um an all diesen Stellen entsprechende
Änderungen vorzunehmen.
Wir wählen in unserem Beispiel im Package Explorer im Kontextmenü zur Methode set-
RegExpCompiler den Menüpunkt REFACTOR | CHANGE METHOD SIGNATURE. Als neuen
Parametertyp tragen wir im Register PARAMETERS (siehe Abb. 2.25) PatternCompiler ein
und bestätigen die Eingabe mit Æ. Im Register EXCEPTIONS können wir auch die Ausnah-
men beeinflussen.
Tipp: Das kleine Lämpchen neben der Tabellenzeile zeigt an, dass Ihnen die Vervollständi-
gungsfunktion von Eclipse zur Verfügung steht, so dass man mittels Ÿ-Leertaste un-
vollständige Klassennamen vervollständigen lassen kann.
Interessant ist die PREVIEW-Möglichkeit, bei der Eclipse anzeigt, an welchen Klassen Ände-
rungen vorgenommen werden. Müssen größere Refactoring-Aktionen durchgeführt wer-
den, sind solche Mechanismen unerlässlich.
52
eclipse_v01.book Seite 53 Montag, 30. Januar 2006 12:02 12
Als weiteres Beispiel markieren wir die ersten zwei Zeilen des While-Schleifenblocks in
der Methode getAllOccurrencesOfPattern und wählen im Kontextmenü REFACTOR |
EXTRACT METHOD.
Zur Erinnerung hier die beiden im Editor zu markierenden Zeilen:
Eclipse bietet daraufhin an, die Zeilen aus der Methode zu extrahieren und in eine neue
private-Methode zu schreiben (siehe Abb. 2.26).
Als neuen Methodennamen geben wir getMatchingTextFromMatcher ein und belassen
den private-Gültigkeitsbereich. Anschließend aktivieren wir die Checkbox ADD THROWN
RUNTIME EXCEPTIONS TO METHOD SIGNATURE und schauen uns im Preview-Modus das fertige
Ergebnis an. Um die Extrahierung durchzuführen, klicken wir auf OK.
Die Extrahierung findet über diesen Wizard bei Bedarf auch Duplikate im Sourcecode (RE-
PLACE X DUPLICATE CODE FRAGMENTS) und hilft so, mehrere Codestellen gleichzeitig zu refac-
toren.
53
eclipse_v01.book Seite 54 Montag, 30. Januar 2006 12:02 12
Convert Anonymous Class Wandelt eine anonyme innere Klasse in eine eingebettete,
to Nested benannte Subklasse um
54
eclipse_v01.book Seite 55 Montag, 30. Januar 2006 12:02 12
Pull Up Verschiebt eine Methode oder ein Feld von einer Unter-
klasse in die Oberklasse
Extract Interface Erzeugt ein neues Interface und entzieht der aktuellen
Klasse dafür alle Instanzmethodensignaturen. Die alte
Klasse implementiert ab jetzt das Interface als eine (von
theoretisch mehreren) möglichen Implementierungen.
Generalize Type Erlaubt es, den aktuellen Typ durch einen der geerbten
Supertypen zu ersetzen, soweit dies möglich ist
Use Supertype Where Ersetzt das Auftreten einer Klasse im Sourcecode durch
Possible dessen Superklasse, wo immer dieser Austausch syntak-
tisch möglich ist
Infer Generic Type Ersetzt Raw types durch generische Typen ab Java 5
Arguments
Extract Local Variable Ersetzt die selektierte Variable durch eine andere mit
anderem Namen unter Zuweisung der ersten an die zweite
Introduce factory Nach Selektion eines Konstruktors und Wahl dieser Aktion
wird eine statische Fabrikmethode für den nun privaten
Konstruktor erzeugt. Alle Aufrufe des Konstruktors werden
ersetzt.
55
eclipse_v01.book Seite 56 Montag, 30. Januar 2006 12:02 12
Die durch Eclipse abgedeckten Refactoring-Mechanismen sind sicher noch nicht vollstän-
dig. Andere IDEs bieten unter Umständen noch mehr Möglichkeiten. Betrachtet man je-
doch die Geschwindigkeit, in der die Fortentwicklung bei Eclipse in Bezug auf den Editor
betrieben wird, scheint dieses allerdings nur eine Frage der Zeit zu sein.
Nicht alle der oben genannten Refactoring-Maßnahmen stehen dem Benutzer zu jedem
Zeitpunkt zur Verfügung. Dies hängt vom Kontext ab (welcher Sourcecode ist markiert, wo
steht der Cursor, welches Element wurde angeklickt etc.).
56
eclipse_v01.book Seite 57 Montag, 30. Januar 2006 12:02 12
Über die rechte Maustaste SOURCE | OVERRIDE/IMPLEMENT METHODS bekommt man in einem
Dialog alle Methoden angezeigt (siehe Abb. 2.27), die überschrieben werden können. Da-
bei werden alle Superklassen der Hierarchie samt implementierten Interfaces aufgelistet.
Auch hier (wie in bereits vorangegangenen Beispielen) lassen wir uns den Methodenkom-
mentar mitgenerieren und schauen uns das Ergebnis an.
Auch in diesem Dialog sei auf die Wechselmöglichkeit in die CODE TEMPLATES verwiesen,
die es erlauben, die so generierten Methoden individuell anzupassen. Dies gilt speziell für
die generierten Javadoc-Kommentare.
Eclipse erzeugt hier nach Klick auf OK im Standardfall folgende Statements:
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
// TODO Auto-generated method stub
return super.toString();
}
Im automatisch erzeugten Source finden wir sowohl ein @see-Tag für die toString()-
Methode der Superklasse als auch die Java-5-Annotation für eine überschriebene Methode
(@Override) vor.
Das erzeugte return-Statement in der toString-Methode ersetzen wir jetzt beispielhaft
durch die folgende Zeile:
return "{ExpAnalyzer:"+String.valueOf(this.regexpCompiler)+"}";
57
eclipse_v01.book Seite 58 Montag, 30. Januar 2006 12:02 12
Eclipse durchsucht daraufhin die Klasse nach Zeichenketten und zeigt jede einzelne von ih-
nen als zu externalisieren an. Dabei würde sie durch eine entsprechende Variable ersetzt,
um diese in eine eigene Datei zu verlagern.
Da die Auslagerung innerhalb der toString-Methode nur begrenzten Nutzen hat, wählen
wir die beiden unteren Einträge und lassen den Ausdruck „Error in pattern...“ stehen (siehe
Abb. 2.28).
Eclipse zeigt zu jedem Key auch die Stelle im Sourcecode, wo dieser vorkommt. Wir erset-
zen die Key-Namen der ersten beiden Values durch ERROR_PATTERN_COMPILE1 bzw.
ERROR_PATTERN_COMPILE2. Die Namen dürfen hierbei keine Leerzeichen aufwei-
sen. Anschließend deaktivieren wir die Übersetzung für die beiden unteren Zeichenketten
durch Klick auf das Häkchensymbol und klicken auf CONFIGURE.
Dann vergeben wir als Property-Dateinamen language.properties und lassen die
weiteren Einstellungen unangetastet. Anschließend klicken wir, zurück im EXTERNALIZE
STRINGS Dialog angekommen, zweimal auf NEXT.
Ist bereits ein Accessor, also ein Default-Objekt, vorhanden, das z.B. Übersetzungen vor-
nimmt, werden die Einstellungen entsprechend angepasst. Eclipse informiert nach Klick
auf NEXT, dass das Property-File neu angelegt wird, und zeigt in einer Vorschau nochmals
die durchzuführenden Ergänzungen.
58
eclipse_v01.book Seite 59 Montag, 30. Januar 2006 12:02 12
Nach Klick auf FINISH hat Eclipse die Fehlermeldung in eine eigene Property-Datei ausge-
lagert und eine neue Message-Klasse erzeugt, über die die Fehlermeldungen eingelesen
werden können.
Die Einbindung im Sourcecode sieht nunmehr wie folgt aus:
Wir erstellen einen JUnit-Test-Case. Hierfür klicken wir mit der rechten Maustaste auf die
Klasse ExpressionAnalyzer und wählen den Menüpunkt NEW | JUNIT TESTCASE.
Da JUnit selbst ein in Java implementiertes Framework ist, fragt Eclipse den Entwickler, ob
es sinnvoll wäre, das notwendige junit.jar mit in den Build-Pfad aufzunehmen. Das können
wir mit YES bestätigen.
1. http://www.junit.org
59
eclipse_v01.book Seite 60 Montag, 30. Januar 2006 12:02 12
Eclipse sollte jetzt den Namen der zu testenden Klasse kennen. Der Name der Testklasse ist
der der Originalklasse, ergänzt um das Postfix „Test“. Wir tragen als Package-Namen
test ein und klicken die Checkbox SETUP an. Wenn der Test Case ohne Test Suite laufen
soll, müssen wir die Checkbox zur Erzeugung von main-Methode und TESTRUNNER aktivie-
ren. Für unseren Fall brauchen wir das allerdings nicht, da Eclipse mit JUnit-Test-Cases
auch so zurechtkommt (siehe Abb. 2.29).
Wir klicken auf NEXT und wählen die Checkbox neben der ExpressionAnalyzer-Klasse
und die zur Generierung von Tasks an.
In der Baumansicht entscheiden Sie sich, welche Methoden Sie testen möchten. Darunter
können auch Methoden der Superklassen fallen, wenn diese von Relevanz sind. Die Check-
box mit den Tasks erzeugt für jede Methode eine solche Task, was hilfreich sein kann, wenn
wir sehr viele Methoden testen und den Überblick nicht verlieren möchten. Mit FINISH wird
die neue Testklasse erzeugt.
Wir ergänzen den nachfolgenden Sourcecode. Der Einfachheit halber wird das Testen der
toString-Methode unterlassen und die Importstatements sind entsprechend selbstständig
zu ergänzen (z.B. über Ÿ-Leertaste hinter dem jeweiligen Klassennamen).
60
eclipse_v01.book Seite 61 Montag, 30. Januar 2006 12:02 12
[Importstatements]
public class ExpressionAnalyzerTest extends TestCase {
/** zu testender Content innerhalb des Tests */
public static final String CONTENT = "Willkommen im "
+ "Eclipse-3.1-Buch!";
/**
* regular expression-Pattern, das auf Kleinbuchstaben
* zwischen a und e reagiert
*/
public static final String PATTERN ="[a-e]";
/** Expression-Analyzerreferenz */
private ExpressionAnalyzer analyzer = null;
protected void setUp() throws Exception {
analyzer = new ExpressionAnalyzer();
analyzer.setRegexpCompiler(new Perl5Compiler());
}
public void testGetAllOccurrencesOfPattern() throws
BusinessException {
List <String> result =
analyzer.getAllOccurrencesOfPattern
(CONTENT, PATTERN);
Assert.assertNotNull("Ergebnisobjekt ist leer",
result);
Assert.assertEquals("Anzahl der Ergebnisse ist"
+ " falsch",result.size(),4);
Assert.assertTrue("Inhalt des Ergebnisses ist"
+ " falsch",result.get(0).equals("e"));
}
public void testSetRegexpCompiler() {
analyzer.setRegexpCompiler(null);
try {
analyzer.getAllOccurrencesOfPattern
(CONTENT,PATTERN);
throw new AssertionFailedError("Business"
+ "Exception did not occur.");
} catch (BusinessException e) {
// erwarteter Fehler
}
}
}
Über so genannte Assert-Aufrufe definiert man Annahmen über den Zustand und den In-
halt von Objekten zur Laufzeit. Treffen diese Annahmen nicht zu, ist entweder der Testfall
falsch definiert oder das zu testende Objekt arbeitet falsch. Hier haben wir sehr einfache
Assertions verwendet.
61
eclipse_v01.book Seite 62 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Die setUp-Methode initialisiert den Test. Für jede aufgerufene Testmethode (alle beginnen
mit dem Präfix test) wird die Methode setUp einmal aufgerufen. So bekommen wir je-
weils eine neue ExpressionAnalyzer-Instanz.
In der testGetAllOccurrences-Methode rufen wir den Analyzer mit dem Inhalt
„Willkommen im Eclipse-3.1-Buch!“ auf. Das Suchmuster lautet a-e. Wir su-
chen also alle Kleinbuchstaben, die a, b, c, d oder e lauten. Davon gibt es in diesem Text
vier.
Wir speichern jetzt die Klasse mit Ÿ+S, starten diese über die Toolbar oder das Menü
RUN | RUN AS | JUNIT TEST und erwarten das Ergebnis des Tests.
JUnit liefert Fehler, einen Error und einen Failure. Der Error ist derjenige, den wir bereits
erwartet haben. Der zweite ist eine NullpointerException, die vorauszuahnen war,
nachdem der Analyzer ohne Zuordnung eines Compilers gestartet worden ist (siehe Abb.
2.30).
Das Ergebnis entspricht voll und ganz den Erwartungen, aber es soll mal so getan werden,
als wäre dies nicht der Fall. Wir werden uns jetzt mit dem Debugging beschäftigen, um den
ersten der beiden Bugs zu „finden“ und zu „fixen“. ;-)
2.7.1 Breakpoints
Wir wechseln in die fehlgeschlagene testGetAllOccurrencesOfPattern-Methode
und doppelklicken auf den schraffierten Bereich links vom Sourcecode in der ersten
Sourcecode-Zeile der Methode, um einen Breakpoint zu setzen.
Grundsätzlich können Breakpoints nur sinnvoll gesetzt werden, wenn Sourcecode und
Classfile übereinstimmen. Dazu kommt, dass manche Stellen einer Klasse (wie Kommen-
62
eclipse_v01.book Seite 63 Montag, 30. Januar 2006 12:02 12
tare oder Importstatements) während eines Debug-Laufs nicht angesprungen werden kön-
nen, da dies technisch nicht abgebildet werden kann.
Breakpoints, die mit einem kleinen Häkchen versehen sind, sind solche, die erfolgreich im
Classfile hinterlegt und von der virtuellen Maschine angesprungen werden können. Zum
Debug-Zeitpunkt wird daher der gesetzte Breakpoint vermutlich mit einem Häkchen ver-
sehen sein, wenn der Classloader der VM die Klasse geladen hat.
Über die Breakpoint-Properties, die über die rechte Maustaste auf einem Breakpoint er-
reicht werden können, können wir die Aktivierung des Breakpoints mit zusätzlichen Eigen-
schaften einschränken (siehe Abb. 2.31) und beispielsweise vorgeben, wie viele Male der
Breakpoint übersprungen wird, bevor er greifen soll. Bei Breakpoints innerhalb von Schlei-
fenkonstrukten ist das von Vorteil, aber auch die Vorgabe einer expliziten zusätzlichen Be-
dingung kann in den Properties erfasst werden. Für unsere Zwecke können wir z.B. erfas-
sen, dass das Result leer sein soll.
Zwei interessante Properties sind in Bezug auf größere Projekte oder den Einsatz von
Multithreading-Anwendungen wie Application Server oder Webserver erwähnenswert.
Über den Baumast FILTERING kann eingeschränkt werden, in welchen Threads der Break-
point aktiv werden soll. Da erst zur Laufzeit eine Menge von Threads entsteht, kann erst
dann entschieden werden, welche Threads gefiltert werden sollen.
Eine andere wichtige Eigenschaft ist die SUSPEND POLICY. Unangenehmerweise kann es vor-
kommen, dass genau ein Thread angehalten wird und die anderen in Dead Locks verfallen
63
eclipse_v01.book Seite 64 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
oder sich ungewohnt verhalten. Dadurch kann der Test beeinträchtigt werden. In diesem
Fall wird mit SUSPEND VM die virtuelle Maschine angehalten, um einen konsistenten Zu-
stand zu gewährleisten.
Wir verlassen den Dialog mit CANCEL, um bei einem „Standard“-Breakpoint zu bleiben.
64
eclipse_v01.book Seite 65 Montag, 30. Januar 2006 12:02 12
der Konfiguration sehr aufgepasst werden, weil eine Klasse n-fach vorkom-
men kann und durch Löschung von Projekten Konfigurationsleichen
zurückgelassen werden.
Die verfügbaren Aktionen in den jeweiligen Registern der Launch configuration, die wir
hier erstellen, richten sich nach dem jeweiligen Debug-Typus. Wir wollen uns auf JUnit und
Java Application beschränken.
Bei JUNIT-Tests kann der Test als Einzeltest definiert werden oder es können alle Tests in ei-
nem Projekt bzw. Package oder Source-Verzeichnis gestartet werden (siehe Radiobutton).
Mittels des Punkts REMOTE JAVA APPLICATION können wir uns an entfernte, virtuelle Maschi-
nen „attachen“. Das heißt, wir sind potenziell in der Lage, auch produktive Java-Applika-
tionen, so diese im Debug-Modus gestartet wurden, über eine TCP/IP-Verbindung und ei-
nen auf dem Server geöffneten Socket zu debuggen. Die dafür notwendigen Startparameter
lernen wir im Debug-Abschnitt kennen. Grundsätzlich heißt es vor Remote Debugging kei-
ne Angst zu haben, denn Eclipse nutzt diese Funktion faktisch bei jedem Debug-Durchlauf
selbst, nur dass hierbei beide Applikationen auf ein und demselben Rechner laufen.
Wichtig ist: Wer Remote Debugging einsetzen möchte, muss darauf achten, entsprechende
VMs auf beiden Seiten (am besten gleiche Version des gleichen Herstellers) einzusetzen
und die zu debuggende Applikation auch im Debug-Modus zu starten bzw. beim Compile
mit Debug-Informationen zu durchsetzen. Weitere essenzielle Voraussetzung: Die zu de-
buggenden Sourcecode-Stellen müssen auf beiden Seiten den gleichen Versionsstand auf-
weisen, um vernünftig debuggen zu können.
Bei einer JAVA APPLICATION findet sich im vordersten Register die Benennung von Projekt
und zu startender Klasse.
Es kann automatisch in der Mainklasse gestoppt werden, selbst wenn kein Sourcecode exis-
tiert. Wenn beispielsweise ein Webserver debuggt werden soll, kann es Sinn machen, dass
die main-Methode aus einem „external jar“ kommt, also aus einer Library, für die kein
Sourcecode vorhanden ist.
Arguments
Im Register ARGUMENTS werden die Parameter eingetragen, die an das Testprogramm über-
geben werden sollen. Dabei wird zwischen Parametern an die main-Methode und weiteren
Parametern für die startende VM unterschieden. Dieses erlaubt es, z.B. weitere Java-
Umgebungsvariablen zu übergeben (-Dproperty=<wert>) oder den zur Verfügung
stehenden Prozessspeicher der Anwendung zu vergrößern (-Xmx512m). Eclipse erlaubt
dabei jetzt auch die Verwendung und Übergabe von definierten Variablenwerten wie Pro-
jektname, Projektpfad, Workspace-Lokation etc.
65
eclipse_v01.book Seite 66 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Classpath
Hier wird der Klassenpfad zusammengestellt und die Libraries werden gewählt, die dem
Klassenpfad hinzugefügt oder von ihm entfernt werden sollen. Hierbei ist zu beachten, dass
sich der Klassenpfad um jene Libraries vergrößert, die aus fremden Projekten, mit denen
das Projekt verbunden ist, kommen. Außerdem spielt die Reihenfolge der Libraries für den
Classloader eine Rolle.
Eclipse lässt es dem Benutzer dabei auch offen, über den Button ADVANCED weitere Lib-
raries oder Library-Sets (eine Menge zusammengehöriger Libraries, z.B. wie Struts und
Jakarta Commons Libraries, die nur zusammen lauffähig sind) einzubinden. Über den
Button RESTORE DEFAULT ENTRIES lassen sich die ursprünglichen Originaleinstellungen je-
derzeit wieder aufrufen.
In der Classpath-Ansicht wird zwischen den USER ENTRIES und den BOOTSTRAP ENTRIES un-
terschieden. Grundsätzlich entspricht der Classpath der Kombination von Libraries und
Projekten, die auch zum Build-Zeitpunkt verwendet wurden, um die Classfiles zu erzeugen.
Im Register USER ENTRIES wird der Classpath angegeben, den wir der VM zum Start einer
Klasse mitgeben (was wir per Hand mit dem Argument -cp der Java-VM übergeben).
Hierbei erlaubt Eclipse das Hinzufügen weiterer Projekte oder externer Jars. Im Baum
BOOTSTRAP ENTRIES wird die Menge aller Klassen festgelegt , die zum Startzeitpunkt der vir-
tuellen Maschine (nicht des eigentlichen Programms) herangezogen werden. Diese ergeben
sich im Standardfall aus den Libraries, die der JRE-Hersteller mitliefert.
JRE
In diesem Register wird das Java Runtime Environment gewählt, das beim Starten der An-
wendung genutzt werden soll. Weitere JREs werden über das Menü WINDOW | PREFERENCES
oder den Button INSTALLED JRES eingerichtet und können hier wahlweise das Projekt-JRE
ersetzen. Zusätzlich lässt sich nach der Auswahl definieren, ob mit dem Standard javaw
Executable gestartet werden soll oder nicht.
Source
Im Register SOURCE, das bei reinen Java-Applikationen zur Konfiguration zur Verfügung
steht, können wir selbst vorgeben, ob wir noch irgendwo zu den eingesetzten Libraries für
den Classpath weiteren Sourcecode besitzen. So lässt sich eine Gesamtapplikation aus
66
eclipse_v01.book Seite 67 Montag, 30. Januar 2006 12:02 12
Die Checkbox SEARCH FOR DUPLICATE SOURCE FILES ON THE PATH kann einem manchen Ärger
mit Sourcen ersparen, besonders, wenn unterschiedliche Source-Versionen existieren und
Eclipse nicht mehr weiß, welchen der generierten Classfiles es eigentlich entsprechen soll.
Environment
Über das Register ENVIRONMENT können in Eclipse für die zu startende Klasse weitere Um-
gebungsvariablen definiert werden. Diese ergänzen oder ersetzen dann je nach Wunsch die
„nativen“ Umgebungsvariablen des JRE.
Common
Wenn mühselig eine Launch Configuration aufgesetzt worden ist, ist es ärgerlich, dass
Eclipse bei jeder neuen Startklasse mit einer neuen Launch Configuration aufwartet. In die-
sem Fall kann die erarbeitete Variante in einer Datei gespeichert und wiederverwendet
(shared) werden und es lässt sich gleichzeitig vorgeben, welche Perspektive zum Startzeit-
punkt dieser Launch Configuration geöffnet werden soll. Es empfiehlt sich hier, die ent-
sprechende Checkbox aktiviert zu belassen.
Launch Perspectives
Klicken wir auf den Konfigurationstypen selbst (also z.B. JAVA APPLICATION oder JUNIT im
Konfigurationsbaum), können wir die Default-Einstellungen für den jeweiligen Typ vorge-
ben.
Grundsätzlich erscheint es sinnvoll, die Debug-Perspektive zu öffnen, wenn wir debuggen
wollen. Wenn wir aber eine eigene Debug-Perspektive zusammengestellt und gespeichert
haben, sollten wir diese beim Start aktivieren. Gleiches gilt für die Perspektive beim nor-
malen Start der Anwendung. NONE lässt die bereits laufende Perspektive dabei unberührt.
67
eclipse_v01.book Seite 68 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
es die Perspektive wechseln und in die Debug-Ansicht wechseln darf. Wir klicken die
Checkbox REMEMBER MY DECISION an und wählen den YES-Button.
Die unterschiedlichen Views stellen die wesentlichen Debug-Informationen zusammen.
Drei alte Bekannte begegnen uns dabei: der Editor (in verkleinerter Form), die Outline
View und die Tasks.
Die Console View ist für Outputs eines Programms gedacht, die an System.out oder
System.err geschickt werden (farblich unterscheidbar) und die nicht anderweitig um-
gelenkt wurden (z.B. in eine Datei).
68
eclipse_v01.book Seite 69 Montag, 30. Januar 2006 12:02 12
rechte Maustaste auf der aktuellen Methode im Stack, die Toolbar des Debugviews oder
über das RUN-Menü ausführen (siehe Tabelle 2.3).
Open Declaration Type Öffnen des Sourcecode-Abschnitts, in dem das aktuell mar-
kierte Objekt deklariert ist
Step Return – Ï Den Thread bis zum Erreichen des Verlassens der aktuellen
Methode (Return) laufen lassen
Terminate and Remove Wie Terminate mit Löschen des toten Eintrags der VM aus der
Debug View
Use Step Filter / Mit Step Filtering lassen sich einzelne Klassen oder Packages
Edit Step Filter / beim Debug-Durchlauf ausblenden. Diese Funktion kann ein-
Filter Type / und ausgeschaltet werden. Filter Type/Package beziehen den
Filter Package aktuellen Typ und das aktuelle Package in den Filter mit ein.
69
eclipse_v01.book Seite 70 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Fehler, den er erkannte, auch gleichzeitig fixen und musste sich nicht in mühevoller Arbeit
nach dem Build wieder bis zum Breakpoint vortasten, um seine Änderungen auf Korrekt-
heit zu prüfen.
Leider hatten diese Funktionen den Nachteil, dass IBM stets eine eigene VM entwickeln
musste – Inkompatibilitäten zu anderen VMs waren daher nicht ausgeschlossen.
Mit der früheren Java Plattform Debugging Architecture1 (JPDA) brach ein ganz neues
Zeitalter für virtuelle Maschinen an. Man definierte einen festen Einsprungpunkt in eine
laufende VM, um Entwicklungsumgebungen und virtuellen Maschinen eine definierte
Schnittstelle zu schaffen. Heute trägt diese Plattformfunktionalität auch den Namen JVMTI
(Java Virtual Machine Tool Interface), eine Zusammenfassung der Funktionalitäten JVMPI
und JVMDI (Profiling und Debug Interface).
So kann heute über Parameter ein Java-Programm bereits auf einen Debug-Lauf vorbereitet
und über einen geöffneten Port mit dem laufenden Programm Kontakt aufgenommen wer-
den (remote debugging). Dies wird in Eclipse dadurch realisiert, dass Eclipse per Zufall ei-
nen TCP/IP-Port ermittelt und diesen einer virtuellen Maschineninstanz mitgibt, um sich
selbst (als weiterer Java-Prozess) mit diesem Port zu verbinden. Deshalb läuft Eclipse kom-
plett autark von den Java-Programmen, die über Eclipse gestartet und debuggt werden. Es
kann sogar passieren, dass Eclipse abstürzt und das Programm unbeeindruckt weiterläuft.
Aus dieser klaren Trennung zwischen den zwei Prozessen (Eclipse und dem Debug-Pro-
zess) ergeben sich aber auch Konsequenzen, und zwar durch den Einsatz unterschiedlicher
virtueller Maschinen. So kann es passieren, dass viele Debug-Abläufe in Abstürzen enden,
während der gleiche Sourcecode in einer anderen VM vollkommen unproblematisch läuft.
Eclipse muss über die JVMTI-Schnittstelle den Quellcode und die Daten aus den Classfiles
in der Fremd-VM synchronisieren. Wenn die Classfiles ohne Debug-Informationen erstellt
worden sind, erschwert sich dieser Prozess für Eclipse. Noch schlimmer ist, wenn Source-
code- und Classfiles komplett unterschiedlich sind. Dann beginnt Eclipse im Sourcecode zu
springen, hält sich nicht mehr an gesetzte Breakpoints und der Überblick geht verloren.
Sollten also einige der nachfolgenden Erläuterungen nicht funktionieren, zum Absturz füh-
ren oder gar nicht erst verfügbar sein, liegt dies zumeist an der Auswahl der VMs, in der
Eclipse oder ein Programm läuft.
Da den alten VMs, wie Version 1.1.8 oder 1.2.2, aber auch 1.3.1, eine Reihe von Funktio-
nen fehlen, startet man die Debugsession häufig mit einer moderneren. Zu beachten ist hier-
bei die Zielplattform [VM-Version, JRE-Version, Ziel-VM-Hersteller, VM-Typ (Client-/
Server-VM), Optimierungsverhalten (Hotspot, Debug ...) und Classfile-Version]. Ein Trick
kann sein, eine 1.4-VM mit einer JRE-Library von 1.3.x zu kombinieren, was sich aller-
dings auch als kompliziert herausstellen kann. Es könnte auch beispielsweise ein 1.3.1er in
den Projekt-Properties als Build-VM bestimmt werden und in der Debug-Launch-Configu-
ration dann eine 1.4.2er zum Debuggen benutzt werden. Es besteht also eine große Freiheit
der Zusammenstellung von Eclipse-VM, Build-VM und Debug-VM und es existieren die
1. http://java.sun.com/products/jpda/
70
eclipse_v01.book Seite 71 Montag, 30. Januar 2006 12:02 12
verschiedensten Variationsmöglichkeiten, die dies extrem flexibel, aber auch anfällig für
Fehlkonfigurationen macht.
Grundsätzlich nicht empfehlenswert ist das Mischen von Java 1.x VMs mit Java 5.0/6.0
Compile-Ständen oder VMs. Auch die für Java 7 angekündigten Bytecode-Erweiterungen
zeigen auf, dass man in den unterschiedlichen Majorrelease-Versionen von Java besser
nicht mischen sollte.
Darunter befindet sich die Liste der parallel laufenden Threads in der VM und deren Typ
(SYSTEM THREAD oder nicht) sowie deren Name und Status (RUNNING, SUSPENDED ...). Wei-
tere System-Threads können über den Zusatzmenüpunkt in der Toolbar SHOW SYSTEM
THREADS eingeblendet werden.
Der Main-Thread wird am Breakpoint angehalten, der Stack ist zu sehen, wobei die Ver-
schachtelung wie immer im Stack von unten nach oben gelesen tiefer geht. Dort, wo der
Sourcecode zu dem entsprechenden Frame im Stack zugeordnet werden kann, gibt es eine
Zeilenangabe (z.B. Line: 31). Dort, wo er nicht vorhanden ist oder es sich um eine native
Methode handelt, die nicht in Java implementiert ist, finden wir ein NOT AVAILABLE. Am
Ende steht ein Eintrag für die virtuelle Maschine, in der dieser Test läuft und die Startzeit
der VM.
71
eclipse_v01.book Seite 72 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Über einen Doppelklick auf dem entsprechenden Frame wird dieser (soweit der Source-
code vorhanden ist) im Editor angezeigt. Über die rechte Maustaste können die oben be-
schriebenen Grundfunktionen zum Navigieren durch den Sourcecode benutzt werden.
Drop to frame
Die Menüfunktion DROP TO FRAME über die rechte Maustaste auf dem Stack ermöglicht es,
in der aktuellen Methode, die im Stack zurzeit selektiert ist, an den Anfang zurückzusprin-
gen. Allerdings ist dies mit der Einschränkung verbunden, dass Variableninhalte nicht die
Werte erhalten, die sie beim ersten Einsprung besaßen. Ob DROP TO FRAME angeboten wird
und funktioniert, hängt vom Kontext und der verwendeten VM ab. Es funktioniert z.B.
nicht in nativen oder main-Methoden.
Grundsätzlich ist es kein Problem, jenen Sourcecode bzw. jene Klassen zu modifizieren, die
von der VM noch nicht über die jeweiligen Classloader-Instanzen in die virtuelle Maschine
geladen wurden. Hier ist die Modifikation recht einfach. Beachten Sie auch, dass nur jene
Sourcecode-Stellen debuggt werden können, die keine Compile-Fehler aufweisen. Da
Eclipse einen inkrementellen Compile vorsieht, ist es ohne weiteres möglich, eine Klasse
zu laden, die fehlerhafte Methoden enthält. Die Ausführung dieser Methoden wird aller-
dings nicht erfolgreich sein, wohl aber von Teilen, die sich konsistent kompilieren ließen.
Startup-Parameter einsehen
Ist durch eine sehr komplexe Launch Configuration der Überblick darüber verloren gegan-
gen, welche Parameter in welcher Reihenfolge übergeben wurden und wie Eclipse den
Klassenpfad zusammengebaut hat, dann empfiehlt sich ein Blick zu den Startup-Parame-
tern. Hierzu wird mit der rechten Maustaste auf den Namen der Startklasse in der Debug
View geklickt und PROPERTIES gewählt. Im sich öffnenden Fenster kann daraufhin die Start-
konfiguration eingesehen werden.
Über Cut and Paste kann der Inhalt aus der Process Information in ein
Command- bzw. Shellfile kopiert werden, um die Java-Klasse standalone
ohne Eclipse zu starten und von der fertigen Konfiguration zu profitieren.
Damit dies zum Erfolg führt, müssen die JVMTI-bezogenen Parameter
—
Variables View
In der Variables View (rechts oben in der Debug-Perspektive) können die Inhalte von loka-
len Instanz- und Klassenvariablen eingesehen werden. Anhand der aus der Outline View
bekannten Symbole lässt sich entnehmen, welche Modifier die Variable besitzt. Dahinter
erscheint der Typ (wenn das kleine Toolbar-Symbol mit dem X aktiviert ist) sowie die Na-
men und der Inhalt der Objekte. Bei komplexen Objekten können diese in der Baumansicht
aufgefächert werden. Die darunter liegende Detailanzeige (Details) zeigt standardmäßig
72
eclipse_v01.book Seite 73 Montag, 30. Januar 2006 12:02 12
bei primitiven Datenelementen deren Inhalte. Bei komplexen wird im Default-Modus die
toString()-Methode aufgerufen.
Wenn man sich streng an das Beispielprojekt gehalten hat, findet man in der Detailansicht
tatsächlich den toString()-Inhalt wieder. Ansonsten sieht man hier den Namen der Ob-
jektklasse und die Hashcode-Adresse.
In den PREFERENCES können die Inhalte typartig einzeln konfiguriert werden. Bei allen kom-
plexen und zusammengesetzten Objekten (Arrays) findet sich ein ID-Wert hinter dem Na-
73
eclipse_v01.book Seite 74 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
men. Der ID-Wert stellt eine logische Speicheradresse innerhalb der virtuellen Maschine
dar (ID A == ID B => Objekt A == Objekt B).
Über das Menü des Debug-Fensters lässt sich die Ansicht der View steuern. Abgesehen von
der Steuerung der Anordnung der Fensterelemente und der Ausblendung einzelner Typen
ist der Menüpunkt JAVA PRIMITIVES interessant. Hier wird vorgegeben, in welcher Repräsen-
tation primitive Java-Typen ausgegeben werden sollen. Neben der Anzeige eines Character
in Form seines Unicode-Zeichens könnte die Anzeige als hexadezimaler Wert von Interesse
sein.
Eine Reihe weiterer Funktionen in der Variables View sind über die rechte Maustaste auf
den entsprechenden Baumeinträgen verfügbar (siehe Abb. 2.35). Diese sind in Tabelle 2.4
beschrieben.
Menüpunkt Aktion
Copy Variables Kopiert die Informationen der geöffneten und selektierten Baum-
elemente in die Zwischenablage z.B. zum Anzeigen in einem Editor.
Change Variable Öffnet ein Fenster zum Ändern des Variableninhalts. Dies geht nur
Value bei primitiven Datentypen nicht jedoch bei komplexen. Um kom-
plexe Objekte zu beeinflussen, z.B. auf null zu setzen oder neu zu
initialisieren, siehe Abschnitt „Display View – Execute“.
Find Variable Listet alle Variablen innerhalb des aktuellen Scope mit ihrem
Namen auf. Nach ihnen kann jeweils durch Teileingabe des
Namens gesucht werden.
New Detail Öffnet einen Dialog, in dem durch einen Code Snippet vorgegeben
Formatter werden kann, wie der Inhalt des Objekts in der Detailanzeige ange-
zeigt werden soll. Dies ist dann hilfreich, wenn die toString-
Methode nicht implementiert wurde bzw. werden konnte (fremder
Bytecode) und kurzfristig die Ansicht geändert werden soll.
Open Declared Öffnet ein Fenster mit dem Sourcecode des Objekttyps.
Type
Open Declared Öffnet ein Fenster mit der Vererbungshierarchieansicht des Objekt-
Type Hierarchy typs.
Instance Zeigt alle Breakpoints innerhalb des selektierten Objekts an, die
Breakpoints definiert sind, und erlaubt es, diese zu begrenzen.
Toggle Fügt einem Objekt einen Watchpoint hinzu oder entfernt diesen.
Watchpoint Zum Thema Watchpoints empfiehlt sich ein Blick in den anschlie-
ßenden Abschnitt über Breakpoints (2.7.7).
74
eclipse_v01.book Seite 75 Montag, 30. Januar 2006 12:02 12
Menüpunkt Aktion
Watch Mit Watch wird ein Beobachter auf das selektierte Objekt gesetzt,
das ab jetzt in der Expression View wiederzufinden ist und das die
ganze Zeit beobachtet wird. Siehe Expression View-Abschnitt.
Inspect Über Inspect kann das aktuell selektierte Objekt als eigenständige
Baumanzeige in der Expression View geöffnet und dessen Inhalte
separat betrachtet werden.
Geänderte Variablenwerte werden jeweils farbig markiert. Dies hilft auch beim Debuggen
durch den Sourcecode. So ist zur Laufzeit erkennbar, welche Werte durch den Sourcecode
manipuliert worden sind.
In der Abb. sind vier Breakpoint-Typen zu sehen, die von Eclipse unterstützt werden. Der
erste Breakpoint ist ein Classloader-Breakpoint. Beim Lesen und Laden der Klasse wird in
diesem Fall der Haltepunkt aktiv.
Der zweite Breakpoint ist ein Exceptionbreakpoint. Er wird aktiv, wenn eine NullPoin-
terException geworfen bzw. gefangen wird (CAUGHT AND UNCAUGHT). In diesem Fall ist
er zusätzlich auf eine konkrete Instanz (instance=(id=36)) fixiert, d.h., er greift nur,
wenn die NullPointerException exakt in dieser Objektinstanz geworfen wird.
75
eclipse_v01.book Seite 76 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Der dritte Breakpoint ist der typische Standardhaltepunkt. Er unterbricht den Fortlauf des
Programms in Zeile 31, in der testGetAllOccurrencesOfPattern()-Methode.
Der vierte und letzte Breakpoint in der Auflistung ist ein Watchpoint auf der Variablen
regexpCompiler.
Wenn in der VARIABLES VIEW auf dem ExpressionAnalyzer ein TOGGLE WATCHPOINT
aufgerufen worden ist, erscheint dieser hier unter den Breakpoints (vierter Breakpoint in
der Abbildung). Dahinter ist dann zu erkennen, dass es ein Watchpoint aus dem Objekt
regexpCompiler ist.
Wichtig ist der Eintrag in Klammern: ACCESS AND MODIFICATION. Wie beim Breakpoint kann
man Bedingungen angeben, unter denen die virtuelle Maschine im Debug-Modus anhalten
soll. In diesem Fall geschieht das beim Zugriff auf das Objekt (z.B. Lesen des Werts) und
bei der Modifikation des Objekts.
Oft reicht ein Watchpoint auf die Modifikation der Instanz vollkommen aus.
Watchpoints auf häufig vorhandene Typen wie z.B. java.lang.String sollten
möglichst vermieden werden, um nicht im Breakpoint-Dickicht die Über-
sicht zu verlieren, oder erst über die Checkbox vor dem Breakpoint-Ein-
—
Programmierer nach Klick mit der Maus direkt an die Stelle, wo der Fehler
aufgetreten ist. Beim Klicken auf den Namen einer Exception öffnet sich
automatisch der Dialog zum Exception Catchen als Breakpoints.
76
eclipse_v01.book Seite 77 Montag, 30. Januar 2006 12:02 12
Exception-Catching
Bei einer Nullpointerexception kann es passieren, dass im Log nur null oder nichts er-
scheint, je nachdem, wie viel Bemühungen in ein aussagekräftiges Log gesteckt worden
sind. In diesem Fall (und in einer ganzen Reihe von weiteren Fällen) ist es vorteilhaft, die
Nullpointerexception schon in dem Moment abzufangen, in dem sie auftritt. Um dies zu
tun, wählen wir das kleine „J“ mit dem Ausrufezeichen in der Toolbar der Breakpoint View,
das mit der Unterschrift JAVA EXCEPTION BREAKPOINT gekennzeichnet ist. Der Name be-
deutet nicht, dass nur java.lang.Exception oder alle davon abgeleiteten Klassen zum
Breakpoint definiert werden können, auch Throwable bzw. alle Error und Runtimeexcep-
tions können auf diese Art und Weise abgefangen werden.
Im sich öffnenden Dialog ist der gewünschte Exception-Typ auszuwählen und zu konfigu-
rieren, ob nur bei nicht abgefangenen oder bei abgefangenen Exceptions angehalten werden
soll. Die VM nur im ersten Fall anzuhalten, macht in der Regel keinen Sinn, da sie sowieso
nicht weiterlaufen kann.
Im Menü RUN finden wir den Menüpunkt ADD CLASS LOAD BREAKPOINT. Wir
können diese Breakpoints aber auch in jeder View (z.B. Package Explorer)
über die rechte Maustaste erreichen. In Eclipse 3 können so zu den „nor-
malen“ Breakpoints die VM bzw. Threads angehalten werden, wenn eine
—
Method Breakpoint
Beim Aufruf von Methoden lässt sich ebenfalls ein separater Breakpoint
definieren. Dieser wird in Eclipse als Method Breakpoint bezeichnet und
kann in einer View über die rechte Maustaste und TOGGLE METHOD BREAK-
POINT aktiviert werden.
—
77
eclipse_v01.book Seite 78 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Breakpoints organisieren
reich ist hierbei die Menüfunktion SHOW, erreichbar über das Kontextmenü
der Variables View. Wählen Sie dort die Organisation in Working Sets oder
über Sortierkriterien (z.B. in welchem Projekt sich die Breakpoints
befinden).
Expression View
Als Nächstes sehen wir uns die Expression View an. Dazu selektieren wir den Menüpunkt
WINDOW | SHOW VIEW | EXPRESSIONS.
Variablen bzw. Objekte, die in der Variables View über WATCH in die Expression View ko-
piert worden sind, können über Expressions ausgewertet werden. Um eine neue Expression
für das zu überwachende Element zu erfassen, wählen wir im Kontextmenü der Expression
View mit ADD bzw. EDIT WATCH EXPRESSION ein neues Element aus und geben im Dialog die
Watch-Expression ein, die evaluiert werden soll. Eine Reevaluierung dieser Bedingung
kann ebenfalls über das Kontextmenü vorgenommen werden.
Display View
Um die Display View zu aktivieren, wählen wir im Menü WINDOW den Menüpunkt SHOW
VIEW | DISPLAY.
Eine der meist unterschätzten Views ist die Display View. Hinter dem unscheinbaren Na-
men und dem leeren Eingabefeld verbirgt sich eine sehr mächtige Debug-Funktionalität.
Die Display View erlaubt die Anzeige, aber auch die Auswertung und Ausführung von
Sourcecodeteilen auf Objekten, die sich aktiv in der Variables View, also im Stack befinden.
Die Display View verfügt sogar über die Fähigkeit, diese Objekte nicht nur zu benennen,
sondern Code Completion bei der Eingabe zu bieten (siehe Abb. 2.37).
Im Folgenden sind kurz die Aktionen aufgelistet, die auf einem Sourcecode-Schnipsel
(snippet) über die rechte Maustaste ausgeführt werden können.
78
eclipse_v01.book Seite 79 Montag, 30. Januar 2006 12:02 12
Display
Lautet der Sourcecode z.B. analyzer.toString(), so kann dies unterschiedlich ausge-
wertet werden. Zum einen ist es sinnvoll, sich den Inhalt beim Aufruf anzusehen (originäres
Display). Hierzu wird der Sourcecode-Teil markiert, der in der Display View angesehen
werden soll, und dann über die rechte Maustaste DISPLAY angeklickt.
Das Ergebnis sieht folgendermaßen aus:
analyzer.toString()
(java.lang.String)
{ExpAnalyzer:org.apache.oro.text.regex.Perl5Compiler
@1edc073}
Eclipse liefert den Typ und den Inhalt zurück. Zu beachten ist, dass ein Display sinnvoller-
weise nur für Methoden, die nicht vom Typ void sind, erfolgen sollte. Bei allen anderen
Rückgabetypen wird das zurückgegebene Element in seine String-Repräsentation transfor-
miert.
Execute
Die zuletzt genannten Optionen auf der Display View sind nützlich, aber keine echten Neu-
erungen gegenüber den Funktionalitäten, die die Expression View bereits zur Verfügung
stellt.
Die mächtigste Aktion ist das Aufrufen des Execute-Befehls auf einem Code Snippet der
Display View. Was einem die Variables View verwehrt, nämlich das einfache Bearbeiten
komplexer Objekte, lässt sich mit der Display View bewerkstelligen. Es ist dort möglich,
jede beliebige Methode auf jedem durch die VM erreichbaren Objekt aufzurufen.
Als Beispiel verwenden wir das Objekt analyzer vom Typ Analyzer und ordnen diesem
eine null-Referenz zu (analyzer=null). Nach Aufruf von EXECUTE verweist die Objekt-
variable auf null. Stattdessen kann auch jede andere beliebige public-Methode darauf
ausgeführt werden – so, als sei sie an dieser Stelle im Sourcecode vorgekommen.
79
eclipse_v01.book Seite 80 Montag, 30. Januar 2006 12:02 12
Debuggen in Eclipse
Content Assist
Content Assist ist behilflich bei der Suche von Objekten. Die weitere Dokumentation kann
aber, wie auch bei den Befehlen CUT, PASTE und CLEAR, entfallen, da es aus dem Zusam-
menhang deutlich wird.
80
eclipse_v01.book Seite 81 Montag, 30. Januar 2006 12:02 12
Es kommt – wie bereits kurz in diesem Kapitel anklang – vor, dass Entwickler sogar im pro-
duktiven Application Server Fehler während der Laufzeit über Hotswap behoben und so
den Sourcecode korrigiert haben. Hiervon ist abzuraten, denn der Application Server muss
auf einer entsprechenden VM laufen, die Classfiles sollten am besten mit Debug-Attributen
versehen sein und schließlich muss die Anwendung Hotswap-Fehler abfedern können.
Je nachdem, wie atomar die Methoden sind und wie das Design einer Anwendung aussieht,
kann Hotswap mehr oder minder gut genutzt werden. Es sollte versucht werden, die Me-
thoden überschaubar zu halten und überflüssige Instanzvariablen als globalen Datenpool
der Klasse zu vermeiden. Dies vereinfacht die Arbeit mit dem Debugger.
81
eclipse_v01.book Seite 82 Montag, 30. Januar 2006 12:02 12
Navigation im Sourcecode
Die hier vorgestellten Funktionen sind zumeist sowohl über die Toolbar (siehe Abb. 2.38;
bei entsprechender Aktivierung über das Menü WINDOW | CUSTOMIZE PERSPECTIVE), über ei-
nen entsprechenden Menüeintrag (im Menü NAVIGATE) oder eine Tastenkombination er-
reichbar. Da die meisten Tastenkombinationen absolut frei vergebbar sind, wird auf deren
Aufzählung weitgehend verzichtet.
Die Links- und Rechtspfeile helfen dabei, in der Historie vor- bzw. zurückzugehen. Zu-
meist ist man als Entwickler aber weniger daran interessiert, alle Schritte, die man bei sei-
ner „Forschungsreise“ durch den Sourcecode gemacht hat, noch einmal zu durchlaufen,
sondern man möchte gleich an der letzten Stelle, an der man editiert hat, weitermachen.
Dafür dient der Linkspfeil mit dem kleinen Sternchen, der einen genau an diese Position
zurückbringt.
Die zwei nach oben und unten verweisenden Pfeile (Ÿ+., Ÿ+,) führen durch
die Annotations der Klasse. Die Annotations sind jene Stellen, die durch den Compile mar-
kiert wurden, an denen es Probleme gibt – sei es, dass ein Compile- bzw. Syntaxfehler vor-
liegt oder durch den Build-Vorgang eine Warnung erzeugt wurde. Welche Arten von Feh-
lern (Errors, Warnings, Infos, Tasks, ...) sie anzeigen, kann über den kleinen schwarzen
Pfeil rechts von ihnen konfiguriert werden.
82
eclipse_v01.book Seite 83 Montag, 30. Januar 2006 12:02 12
File Search
In CONTAINING TEXT wählen wir den zu suchenden Text (gerne auch mit Wildcards oder als
Regular Expression) und in FILE NAME PATTERNS den Dateinamen oder Typ an (sofern dieser
bekannt ist). Diese Suche entspricht der typischen Volltextsuche über eine Menge von Da-
teien. Erwartungsgemäß steigt die Ergebnisanzahl mit der Größe des Suchbereichs (hier als
Scope bezeichnet). Der Scope kann neben der selektierten Ressource oder dem Working-
Set auch die durch dieses Projekt eingeschlossenen Projekte (siehe Abschnitt 2.3.1) umfas-
sen. Maximal durchsucht Eclipse alle Dateien, die sich im Workspace befinden, wobei der
Workspace alle Projekte umfasst, die zurzeit in Eclipse aktiv sind.
Wenn man genauer abschätzen kann, in welchem Projekt oder sogar in welchem Verzeich-
nis gesucht werden soll, kann im Scope auch ein so genanntes Working Set definiert wer-
den. Über den CHOOSE-Button wird mittels eines logischen Namens konfiguriert, welche
Projekttypen, welche Verzeichnisse und welche Projekte durchsucht werden sollen. Gleich-
zeitig lassen sich Inhalte auch sofort ersetzen, dazu dient der REPLACE-Button bei der Datei-
suche.
Java Search
Die Java Search versucht dem logischen Suchstring einen Suchtyp zu assoziieren (TYPE,
CONSTRUCTOR, METHOD, ...), um das Element genauer zu beschreiben. Die Suche kann wei-
ter auf die Deklaration des entsprechenden Typs, auf Referenzen der Objekte dieses Typs,
auf Implementierungen oder auf alle Vorkommnisse begrenzt werden. Im Gegensatz zur
reinen Volltextsuche können die Ergebnisse also auch logische Ergebnisse sein, die durch
die Semantik der Java-Sprache der Suche entsprechen. Auch bei dieser Suche lässt sich der
Suchbereich einschränken.
83
eclipse_v01.book Seite 84 Montag, 30. Januar 2006 12:02 12
Navigation im Sourcecode
Die Ergebnisse der Suche werden in der Search View angezeigt, durch die mit den entspre-
chenden Pfeilen im View-Fenster navigiert werden kann. Eclipse passt die Menge der
Suchergebnisse zur Laufzeit an. Wird also ein Suchergebnis durch Modifikation einer Datei
aus der Ansicht eliminiert, aktualisiert sich die Search View entsprechend.
Sehr hilfreich in diesem Zusammenhang ist die Search History, die über das Toolbar-Icon
mit Lampe und kleinem Textfile erreichbar ist. So müssen bei erneuter Durchführung einer
alten Suche die damaligen Suchparameter nicht neu spezifiziert werden.
Alle gefundenen Sourcecode-Stellen werden nach einer Suche in Eclipse übrigens norma-
lerweise mit einem kleinen Pfeil am linken Editorrand markiert.
Find/Replace
Neben den Suchmethoden, die sich im Wesentlichen auf eine größere Menge von Dateien
beziehen und diese auf Suchergebnisse einzuschränken versuchen, gibt es die klassische
Aktion des FIND AND REPLACE-Mechanismus. Dieser greift allerdings nur im Editor auf einer
aktuellen Datei und lässt sich mit der Tastenkombination Ÿ-F aufrufen.
Es existieren hier die normalen Dialogelemente wie FIND und REPLACE-Buttons, die Mög-
lichkeit von Vorwärts- und Rückwärtssuche (von der Cursorposition aus gesehen) oder die
CASE SENSITIVE-Suche, also die Unterscheidung von Groß- und Kleinschreibung.
Seltenere Funktionen sind die Suche nur im markierten Textbereich (SCOPE – SELECTED
LINES), die Suche nur nach vollständigen Wörtern (WHOLE WORD), der WRAP SEARCH (Neu-
beginn der Suche am Anfang der Datei nach dem Erreichen von dessen Ende) und INCRE-
MENTAL SEARCH.
Bei der Suche nach einem Begriff stehen auch Regular Expressions zur Verfügung. Über
die Tastenkombination Ÿ+Leertaste kann man sich dabei Hilfe suchen.
Die Incremental Search ist ein sehr interessantes Feature. Während der Eingabe des zu su-
chenden Begriffs im FIND-Textfeld wird im Hintergrund ab der Cursorposition in der Datei
nach dem ersten Element gesucht, das der Suche entspricht, so dass zu dem Zeitpunkt, wo
der Suchbegriff eingetippt worden ist, dessen erstes Vorkommen schon angezeigt wird, be-
vor der FIND-Button angeklickt wird.
2.8.4 Open-Funktionen
Die folgenden Aktionen sind zumeist nach Selektion des Elements über einen entsprechen-
den Menüeintrag im Menü NAVIGATE, eine Tastenkombination oder durch Markierung eines
entsprechenden Begriffs im Sourcecode und Auswahl eines Kontextmenüpunkts über die
rechte Maustaste erreichbar.
Zu beachten ist, dass Eclipse bei allen nun folgenden Ausführungen nur jene Objekte bzw.
Elemente finden kann, die sich im Sourcecode befinden. Das heißt, all jene Bereiche von
Projekten, die zwecks Vereinfachung nicht in den Build-Pfad der Projekte einbezogen
wurden (dies betrifft auch nicht zum Klassenpfad hinzugezogene Libraries), werden von
Eclipse nur als reine Dateien erkannt. Auf der Suche nach Abhängigkeiten oder Verbin-
dungen kann nur die Volltextsuche helfen.
84
eclipse_v01.book Seite 85 Montag, 30. Januar 2006 12:02 12
85
eclipse_v01.book Seite 86 Montag, 30. Januar 2006 12:02 12
Navigation im Sourcecode
Bei einem sauberen Design sollte von einer möglichst kleinen Schnittstelle
zwischen Klassen und vor allem Komponenten ausgegangen werden. Da
das automatische Generieren von Accessor-Methoden (Javabeans-Kon-
vention) oft dazu verleitet, alles public zu deklarieren und sich auch nicht
—
86
eclipse_v01.book Seite 87 Montag, 30. Januar 2006 12:02 12
Die Darstellung des aktuell ausgewählten Typs als Baum-Wurzelobjekt kann dabei etwas
verwirrend sein. Sie stellt nicht immer die Hierarchie nach oben oder nach unten dar.
Im darunter liegenden Teil der Hierarchy View zeigt Eclipse die Variablen und Methoden
an, die durch die einzelne Klasse bzw. das jeweilige Interface zusätzlich definiert werden.
Über die Toolbar dieses Anzeigebaums ist konfigurierbar, ob zusätzlich alle geerbten
Member ebenfalls angezeigt werden sollen, ob statische und final Member ausgeblendet
und ob die Reihenfolge der Anzeige sortiert sein soll.
87
eclipse_v01.book Seite 88 Montag, 30. Januar 2006 12:02 12
Weitere Views
88
eclipse_v01.book Seite 89 Montag, 30. Januar 2006 12:02 12
89
eclipse_v01.book Seite 90 Montag, 30. Januar 2006 12:02 12
Java 5 – Features
Tatsache ist aber: Wenn man mit Java 5 umgehen möchte, wird bereits eine große Runtime-
Bibliothek – eben die von JRE-Hersteller – mitgeliefert, in der diese Konzepte umfangreich
angewandt werden. Insofern ist es ratsam, die hier von Eclipse vorgeschlagenen Warning-
Meldungen zumindest nicht zu unterschreiten.
Wer übrigens mehr über Java 5 als Sprache insgesamt erfahren möchte, dem sei ein Blick
in die inzwischen umfassende Reihe der Java-5-Bücher empfohlen1.
Zur Konfiguration der Compile-Einstellungen gehört auch die inzwischen angepasste For-
matierung des Sourcecodes, der sich zumindest inhaltlich leicht von seinem Vorgänger ab-
hebt.
In den Preferences der Workbench oder pro Java-Projekt finden sich die individuellen Ein-
stellungen des Code Formatters. Wir kommen später noch auf ihn zu sprechen. Sie können
unter JAVA | CODE STYLE | FORMATTER gefunden und eingestellt werden. Dort sehen wir bei-
spielsweise auch die Anpassbarkeit parametrisierter Typen (siehe Abb. 2.44).
1. z.B. Java 5 Programmierhandbuch, Ulrike Böttcher, Dirk Frischalowski, Software & Support,
ISBN 3935042639
90
eclipse_v01.book Seite 91 Montag, 30. Januar 2006 12:02 12
Wie man ein neues Java-Projekt anlegt, Klassen darin erzeugt und kompiliert, haben wir in
diesem Kapitel bereits ausführlich behandelt. Deshalb erstellen wir über das Menü NEW |
PROJECT | JAVA PROJECT ein Java-Projekt mit dem Namen „Java5“, um von der Konfiguration
weg hin zur Arbeit mit dem Sourcecode an dieser Stelle zu kommen.
Nach der Erstellung des Projekts bietet Eclipse für die Java-Elemente Enumeration und An-
notation spezielle Wizards an, die die Erstellung beschleunigen sollen (siehe Abb. 2.45).
Wir wollen hier testhalber eine Enumeration, eine Annotation und eine normale Java-Klas-
se zum Testen verwenden.
91
eclipse_v01.book Seite 92 Montag, 30. Januar 2006 12:02 12
Java 5 – Features
Zunächst legen wir dazu ein Package mit dem Namen com.entwickler.eclipse-
buch.kapitel2.examples an. Darin erzeugen wir eine Standard-Java-Klasse über
NEW | CLASS mit dem Namen JavaExamples.
Die Klasse ist zunächst rein Java-1.4-lastig gehalten. Sie nimmt alle Eingabeparameter und
erzeugt pro Wert ein Kundenobjekt mit dem Namen des Eingabewerts.
In der Main-Methode der Examples-Klasse wollen wir anschließend einen beliebigen Kun-
den herausgreifen und prüfen, ob er der erste Kunde ist1.
Hierfür benötigen wir zwei Klassen. Zum einen die JavaExamples-Klasse und eine „dum-
me“ Value-Klasse, die der Einfachheit halber sogar ohne Accessor-Methoden daherkommt.
Hier die JavaExamples-Klasse:
package com.entwickler.eclipsebuch.kapitel2.examples;
import java.util.ArrayList;
import java.util.List;
92
eclipse_v01.book Seite 93 Montag, 30. Januar 2006 12:02 12
package com.entwickler.eclipsebuch.kapitel2.examples;
Wir finden hier im Sourcecode die typischen Java-Probleme eines 1.4er Sourcecodes. Die
ungetypte Verwendung von Listen und das übermäßige explizite Typecasting lassen die
Main-Methode, die später zur Laufzeit fehlschlagen wird, im Compile trotzdem sauber er-
scheinen.
Die Customer-Klasse selbst, durchsetzt mit zahlreichen Konstanten, kann keine weiteren
Informationen aufnehmen. Da wir die Customer-Instanzen später persistent in die Daten-
bank schreiben wollen, fehlen uns hier Metainformationen über Tabellennamen und Spal-
ten, die wir zu den Customer-Attributen speichern könnten.
Im Editor erscheint in der Zeile des Hinzufügens des Kunden zur Liste bereits ein erster
Warnhinweis, dass der Listenzugriff ungetypt erfolgt (siehe Abb. 2.46). Leider gibt es hier-
zu keinen QuickFix, der das Problem lösen könnte. Aber wir können mit der rechten Maus-
taste auf der Kundenliste und durch die Wahl des Menüpunkts REFACTOR | INFER GENERIC
TYPE ARGUMENTS von Eclipse ermitteln lassen, welcher Listentyp für die customer variable
93
eclipse_v01.book Seite 94 Montag, 30. Januar 2006 12:02 12
Java 5 – Features
der richtige wäre. Klicken Sie auf den Button PREVIEW, um die Auswirkungen dieses Re-
factoring in Eclipse zu prüfen. Die Auswirkungen sind in Abb. 2.47 zu sehen.
Nach der Bestätigung des Refactoring mit OK ist der Warnhinweis verschwunden, dafür
bekommen wir jetzt den erwarteten Compile-Fehler, der in der Java-1.4-Variante zur
ClassCastException geführt hätte (siehe Abb. 2.48)
Wir ändern die Zeile entsprechend und ersparen uns ab jetzt das Casting, womit der Com-
pile-Fehler behoben wäre.
Um den Sourcecode nun noch etwas Java-5-konformer zu machen, ändern wir das Argu-
menten-Array der main-Methode auf die varargs-Variante, ersetzen den Integer-Kon-
struktor durch einen Autoboxing-Aufruf und den Zugriff auf die random()-Methode über
einen statischen Import.
94
eclipse_v01.book Seite 95 Montag, 30. Januar 2006 12:02 12
package com.entwickler.eclipsebuch.kapitel2.examples;
import java.util.ArrayList;
import java.util.List;
// statt Math.random()
import static java.lang.Math.random;
Ebenfalls als neues Sprachfeature dürfte die foreach-Schleife von Java 5 bekannt sein. Für
sie gibt es selbstverständlich entsprechende Wizards für ihre Erzeugung. Was aber, wenn
man bereits eine „altmodische“ For-Schleife wie in unserem Beispiel besitzt?
Klicken Sie mit der Maus auf das Schlüsselwort for und klicken Sie Ÿ-1 an. Eclipse
bietet uns daraufhin eine Umwandlung an. Wir wählen CONVERT TO ENHANCED FOR LOOP aus
und Eclipse refactored den Source entsprechend zu:
95
eclipse_v01.book Seite 96 Montag, 30. Januar 2006 12:02 12
Java 5 – Features
Nehmen wir uns nun der Typzuweisungszeile an. Wir wechseln in die Customer-Klasse
und ersetzen die Typdefinition durch folgendes Statement:
Eclipse kritisiert nun zu Recht, dass die Klasse CustomerState vollkommen unbekannt
ist. Über den QuickFix (Ÿ-1 oder Klick auf das gelbe Lämpchen) wählen wir nun die
Erzeugung einer Enumeration (CREATE ENUM CUSTOMERSTATE). Nach Bestätigung des
Enumeration-Wizard erzeugt Eclipse eine entsprechende Aufzählung. Wir wechseln in die
Enumeration und ergänzen weitere mögliche Status.
package com.entwickler.eclipsebuch.kapitel2.examples;
Wechseln Sie schließlich in die Customer-Klasse. Sie sollte später – so war die Vorgabe zu
Beginn – zu Persistenzzwecken verwendet werden. Hierfür ist es sinnvoll entsprechende
Annotations als Aspektbeschreibungen der Persistenz einzuführen. Wir tun dies durch Er-
gänzung entsprechender Annotationstatements im Source, der danach wie folgt aussieht:
package com.entwickler.eclipsebuch.kapitel2.examples;
@Persistent(tableName="customer", columnName="id")
public String id = null;
@Persistent(tableName="customer", columnName="name")
public String name = "";
96
eclipse_v01.book Seite 97 Montag, 30. Januar 2006 12:02 12
@Persistent(tableName="customer", columnName="age")
public Integer age = 0;
Da die hier eingeführte Annotation mit dem Namen @Persistent grundsätzlich im JRE
nicht definiert ist, markiert Eclipse sie korrekterweise als fehlerhaft. Auch hier hilft uns
wieder der QuickFix mit Ÿ-1 auf dem @Persistent-Marker weiter.
Wir erzeugen über CREATE ANNOTATION 'PERSISTENT' die neue Annotation. Den Annotation-
Wizard-Dialog bestätigen wir mit OK. Beim Erzeugen der Attribute ist Eclipse allerdings
noch weniger hilfreich, hier müssen wir die neuen Annotationelemente per Hand anlegen.
Die fertige Annotation sieht wie folgt aus:
package com.entwickler.eclipsebuch.kapitel2.examples;
97
eclipse_v01.book Seite 98 Montag, 30. Januar 2006 12:02 12
Customizing Eclipse
98
eclipse_v01.book Seite 99 Montag, 30. Januar 2006 12:02 12
99
eclipse_v01.book Seite 100 Montag, 30. Januar 2006 12:02 12
Customizing Eclipse
-data workspacePath
Pfad zum Workspace, dem Ort, an dem Eclipse neue Projekte standardmäßig erzeugt und
deren Einstellungen abspeichert. Normalerweise unterhalb des Eclipse-Verzeichnisses.
-debug [optionsFile]
Startet Eclipse im Debug-Modus und lädt Optionen dafür über den Dateinamen.
-dev [classpathEntries]
Startet Eclipse im Entwicklungsmodus. Die mit Kommas separierte Liste von Klassenpfad-
einträgen wird jedem Plug-In übergeben.
-keyring keyringFilePath
Zusammen mit der Passwortoption kann hier eine Autorisationsdatenbank angesprochen
werden.
-nl locale
Übergabe der Locale-Information, die Plug-Ins über den Aufruf BootLoader.getNL()
zur Verfügung steht. Für Deutsch ist das Standard-Locale de_DE.
-nolazyregistrycacheloading
Deaktiviert die Ladeoptimierung der Plug-In-Registry. Standardmäßig werden Extension-
Konfigurationselemente nur auf Anforderung vom Registry Cache geladen, diese Option
initiiert das vollständige Laden beim Startup von Eclipse.
-noregistrycache
Umgeht die Benutzung des internen Plug-In Registry Cache.
-nosplash
Startet Eclipse ohne Splash Screen.
-os operatingSystem
Definiert das Ziel-Betriebssystem, auf dem Eclipse läuft. Normalerweise kommt dies aus
der os.name-Umgebungsvariablen, z.B.: win32, linux, hpux, solaris, aix.
-password password
Passwort der Autorisationsdatenbank, benutzt in Verbindung mit der –keyring-Funktion.
-perspective perspectiveId
Perspektive, die beim Starten geladen werden soll.
-plugincustomization propertiesFile
Lokation des Property File mit den Default-Einstellungen für die Plug-Ins.
-refresh
Kompletten Workspace-Refresh beim Starten von Eclipse durchführen.
-showlocation
Option zur Anzeige der Lokation des Workspace in der Fenstertitelzeile.
-vm vmPath
Lokation des JRE (java.exe), mit dem diese Eclipse-Instanz gestartet wird.
100
eclipse_v01.book Seite 101 Montag, 30. Januar 2006 12:02 12
101
eclipse_v01.book Seite 102 Montag, 30. Januar 2006 12:02 12
Eclipse Preferences
In großen Projekten mit vielen Entwicklern kommt es häufig vor, dass The-
men wie „wie ist zu dokumentieren“ oder „wie ist der Sourcecode zu forma-
tieren“ und „wie sieht Eclipse beim Öffnen aus“ zu Grundsatzentscheidun-
gen beim Umgang mit der Entwicklungsumgebung werden. In diesem Fall
—
General-Properties
Unter dem Oberpunkt GENERAL verbergen sich alle für die Eclipse-Oberfläche relevanten
Einstellungen.
Property Eigenschaften/Funktionen
Capabilities Capabilities beschreiben die GUI-Elemente, die ein Benutzer für eine
bestimmte Aufgabe sehen soll. Über den Advance-Button können ein-
zelne Elemente aktiviert und deaktiviert werden.
Content Types Zuordnung von Dateiinhalten (versus Dateiendungen, siehe Unter-
punkt EDITORS | FILE ASSOCIATIONS) zu entsprechenden Editoren.
Editors In diesem Unterpunkt werden die Editoren, d.h. die gleichzeitig geöff-
neten Sourcecode-Fenster, konfiguriert.
Hilfreich, um den Überblick über die Masse an offenen Fenstern nicht
zu verlieren, ist das Feature CLOSE EDITORS AUTOMATICALLY. Ansonsten
öffnet Eclipse für jede Klasse ein neues Fenster, was schnell unüber-
sichtlich wird.
Die Funktion TEXT FILE ENCODING ist für Entwickler gedacht, die an ein
bestimmtes Encoding bei der Dateibearbeitung gebunden sind, bei-
spielsweise in Zusammenhang mit der Entwicklung von JSPs oder
XML.
Über den Unterpunkt SPELLING können Sie zusätzliche Wörterbuchprü-
fungen einschalten, um z.B. Ihre Kommentare prüfen zu lassen.
102
eclipse_v01.book Seite 103 Montag, 30. Januar 2006 12:02 12
Property Eigenschaften/Funktionen
Startup and Einstellung, welche Plug-Ins beim Start von Eclipse automatisch akti-
Shutdown viert werden sollen. Besonders, wenn mehrere ähnliche Plug-Ins
benutzt werden, die sich gegenseitig in der Arbeit behindern oder
überschreiben könnten, ist zu überlegen, welche für die Arbeit wirklich
benötigt werden.
Ant-Properties
Eclipse stellt mit Ant, einem Subprojekt von der Jakarta Apache Group1, eine Erweiterung
zur Verfügung, die Sie in Routinearbeiten wie Buildmanagement, also dem Erstellen von
auszuliefernden Java-Archiven (jar-Files), Web-Archiven (war-Files) oder EJB-Archiven
(ear-Files), unterstützt.
1. http://ant.apache.org/
103
eclipse_v01.book Seite 104 Montag, 30. Januar 2006 12:02 12
Eclipse Preferences
In vielen Unternehmen gehört der Einsatz von Ant als Teil des Build- und Deployment-Pro-
zesses nach der Entwicklung des fertigen Sourcecodes zum Standardrepertoire. Eclipse 3.1
unterstützt dabei mittlerweile sogar das Debuggen in solchen Ant-Skripts.
Innerhalb der Ant-Properties in den Preferences von Eclipse kann Ant individuell konfi-
guriert werden, angefangen von den jar-Files, die beim Start von Ant einbezogen werden,
bis hin zu der Reihenfolge der so genannten Tasks und Targets, also der Sequenzfolge der
Aktionen, die in XML definiert werden. Zusätzlich gibt es Möglichkeiten, das Syntaxhigh-
lighting und die Formatierung des XML zu beeinflussen.
Property Eigenschaften/Funktionen
Editor Einstellungen des Editors, mit dem das Build-XML-File, in dem die
Aktionsdefinitionen erfolgen, erstellt wird. Zusätzlich werden Vorlagen für
Ant-Tasks in Form von Templates mitgeliefert und können selbst definiert
werden.
Runtime Konfiguration des Ant selbst, welche Libraries einbezogen werden und
welche Aktionen (Tasks) im Build-Prozess mit welchen Umgebungsvariab-
len verfügbar sind. Eclipse bringt selbst eine ganze Reihe eigener Tasks
mit, die eng mit der Oberfläche zusammenarbeiten und Eclipse-Besonder-
heiten per Ant zugreifbar machen.
Help-Properties
Einstellung, wie die interne Online-Hilfe dargestellt werden soll. Hier kann man entschei-
den, ob die Hilfe intern oder im externen Browser zum Vorschein kommt.
Install/Update-Properties
Die Install- und Update-Möglichkeiten sind oft weitreichender, als man glaubt. Eclipse
bringt selbst ein Updatemanagement mit, das es erlaubt, Versionssprünge von Softwaretei-
len von Eclipse oder seinen Plug-Ins übers Internet quasi automatisch zu vollziehen, ohne
jedes Mal alles von Neuem herunterzuladen und zu installieren. Eclipse unterstützt sowohl
automatische Updates als auch die im Unternehmen öfter notwendige Proxy-Konfigura-
tion. Für die damit verbundene Konfiguration dienen die Unterpunkte in diesem Zweig des
Preferences-Baums.
In größeren Teams, die vielleicht sogar über entsprechende Entfernung an einem gemein-
samen Sourcecode arbeiten und eigenentwickelte Plug-Ins benutzen, kann die Definition
und Bereitstellung von neuen Versionen in einem zentralen Webserver reizvoll sein, um alle
Entwickler in Richtung Softwareumgebung auf dem gleichen Stand zu haben und Diskus-
sionen um unterschiedliche Eclipse- und Plug-In-Versionen zu vermeiden.
104
eclipse_v01.book Seite 105 Montag, 30. Januar 2006 12:02 12
Java-Preferences
Den Unterpunkt JAVA-PREFERENCES wollen wir an einigen Stellen genauer beleuchten, be-
sonders dort, wo es um Codegenerierung und -formatierung geht, aber auch dort, wo die
Compile-Einstellungen teilweise über „Leben und Tod“ der lauffähigen Software entschei-
den können.
Property Eigenschaften/Funktionen
Build path Wer nativ gerne mit der Java Runtime umgeht, der weiß, dass man ent-
weder über die Variable CLASSPATH oder den Parameter -cp der Java-
VM die notwendigen Libraries und Pfade definiert. Eclipse schert sich
allerdings intern um extern definierte Umgebungsvariablen wie
JAVA_HOME wenig. Für diesen Zweck können hier logische Namen
erfasst werden, die auf Pfade oder Dateien außerhalb verweisen und in
einem Eclipse-Projekt genutzt werden sollen. Dies ähnelt sehr den linked
resources aus dem Workbench-Abschnitt. Nicht selten vermischt Eclipse
auch beide Begrifflichkeiten.
Eclipse unterstützt die Definition eigener User Libraries. Damit sind
Sammlungen von Bibliotheken (JAR/ZIP-Files) gemeint, die immer
gemeinsam verwendet werden und daher zu einer Benutzerbibliothek
gehören. Diese Bibliotheken können dann z.B. in Launch configs schnel-
ler eingebunden werden, als alle Jar-Files von Hand zusammenzusam-
meln.
In der Registerleiste NEW PROJECT lässt sich entscheiden, mit welcher
Sourcecode/Bytecode-Trennung und welchem JRE für ein neues Projekt
als Standard begonnen werden soll. Die Möglichkeit der Trennung von
Sourcecode und generierten Classfiles sollte genutzt werden, da so die
Übersicht und das Deployment von Classfiles stark vereinfacht werden.
Hierzu wird unter SOURCE AND OUTPUT FOLDERS der Punkt FOLDERS aktiviert.
Ob als Output-Verzeichnis bin akzeptiert wird und class oder classes
gewählt wird, ist Geschmackssache.
105
eclipse_v01.book Seite 106 Montag, 30. Januar 2006 12:02 12
Eclipse Preferences
Property Eigenschaften/Funktionen
Code Style Eclipse besitzt seit Version 3 einen komplett überarbeiteten Code format-
ter. Die Komplexität der Code-Formatierungsoptionen hat damit zuge-
nommen. Es lassen sich eigene Profile für Code-Formatierungen abspei-
chern und die häufig verwendeten Sun Conventions werden als Build-In
ebenfalls unterstützt. Hier steht die Tür für teamübergreifende Codie-
rungsvorgaben offen. Wie man diese z.B. prüfen kann, beschreibt der
Abschnitt über Checkstyle im Kapitel über Qualitätssicherung.
Code Style/ Die Generierung von Sourcecode ist ähnlich wichtig wie die Formatie-
Code rung in größeren Projekten. Oft muss ein Copyrighthinweis am Anfang
Templates jeder Klasse erscheinen, der Kommentar von Methoden muss jeweils in
der gleichen Form aufgebaut sein oder aus dem Namen der Variablen
muss deren Typ erkennbar sein. Wer projekt- oder unternehmensweite
Vorschriften hat, kann diese hier niederlegen. Darunter fallen auch Logi-
ken, wie z.B. Getter-/Setter-Methoden oder andere Methodenrümpfe
generiert werden müssen.
Code Style/ Hier wird eingestellt, in welcher Reihenfolge Eclipse die Importstate-
Organize ments im Sourcecode organisieren soll.
Imports
Compiler/ Hier verbergen sich umfangreiche Einstellungen für die Prüfung des
Building, erzeugten Codes. Dazu zählen einfache „Schönheitsprüfungen“, poten-
Errors and zielle Fehlerkonstellationen bis hin zu überflüssigem Code und Java
Warnings Standard Edition 5-Compile-Konfigurationen.
Debug Die Funktionen zum Thema Debuggen sind begrenzt. Trotzdem macht
z.B. ein Ausschalten der Sourcecode-Teile, für die man keinen Source-
code besitzt, beim Debuggen (STEP FILTERING) oft Sinn, besonders wenn
Sourcecode-Teile native vorliegen, also gar nicht in Java geschrieben
sind. Da Eclipse normalerweise bei komplexen Datentypen Schwierig-
keiten hat, den Inhalt von Objekten sinnvoll anzuzeigen, empfiehlt sich
auch die Einstellung von DETAIL FORMATTERS. Ebenso ist es möglich, für
den Debugger die logischen Strukturbäume (logical structure) einzelner
Klassen zu definieren, was die Anzeige in der Variables View deutlich
vereinfacht.
Interessant sind in den Debug-Einstellungen auch die aktivierten Debug-
Informationen, die Sie beim Build besser nicht deaktivieren sollten, wenn
Ihnen an einem reibungslosen Testen etwas liegt.
106
eclipse_v01.book Seite 107 Montag, 30. Januar 2006 12:02 12
Property Eigenschaften/Funktionen
Editor Der Editor ist sicherlich die mächtigste Funktion bei der Codeerzeugung
im herkömmlichen Sinne. Die Entwickler von Eclipse haben sich große
Mühe gegeben, dem Editor viel Intelligenz beizubringen, angefangen
von automatischen Zeilenumbrüchen, über das automatische Auffinden
von Variablen und Methoden bis hin zu impliziter Javadoc-Kommentar-
generierung, der automatischen Erzeugung von öffnenden und schlie-
ßenden Klammern sowie Java-Syntaxhighlighting. Daneben gibt es
einfachere Entscheidungen z.B. über Schriftart und Schriftfarbe von
Java-Elementen im Sourcecode und ob Zeilennummern eingeblendet
werden sollen.
Besonders die Definition von eigenen Templates, also Vorlagen für
bestimmte Codeabschnitte, kann die Entwicklung beschleunigen. Einfa-
che For-Schleifen oder If-Konstrukte sind bereits definiert und können
über den entsprechenden Template-Namen mit anschließender Tastatur-
kombination Ÿ+Leertaste aufgerufen werden. Aber auch komplexere
Strukturen in Richtung Pattern lassen sich erzeugen, indem sie über den
Button NEW im Unterpunkt TEMPLATES selbst anlegt werden.
Unter der Registerkarte FOLDING können Standardeinstellungen für das
neue Sourcecodefolding-Feature definiert werden. Ebenfalls integriert in
Eclipse ist die Funktion, durch Klick auf Source-Elemente das Auftau-
chen bestimmter Syntaxelemente (Typen, lokale Variablen, Konstanten,
Methoden-Exits – sehr hilfreich bei mehreren Returnstatements pro
Methode) markieren zu lassen (MARK OCCURRENCES). Eclipse nimmt
sogar Wörterbücher entgegen und kann so neben dem Source auch die
Kommentare auf Rechtschreibung prüfen (SPELLING).
JUnit In diesem Dialog wird JUnit konfiguriert. Stack Trace-Filter für JUnit-
Klassen sind hier standardmäßig aktiv.
107
eclipse_v01.book Seite 108 Montag, 30. Januar 2006 12:02 12
Eclipse Preferences
Run-/Debug-Preferences
In den Run- und Debug-Preferences wird das Verhalten von Eclipse beim Start von Java-
Anwendungen im Run- oder Debug-Modus und die Arbeit mit den Launch Configurations
(siehe Abschnitt 2.7) konfiguriert.
Auf zwei Unterpunkte des Run/Debug-Baums soll dabei noch kurz eingegangen werden,
da die anderen eigentlich selbst erklärend sein sollten.
Console-Optionen
Obwohl die Console als View nicht mehr als ein Outputmedium zu sein scheint, lassen sich
hier sehr schöne Effekte erzielen.
FIXED WIDTH CONSOLE, also eine feste Konsolenbreite, macht je nach Output, der dort er-
scheint, Sinn, wenn im Output keine Zeilenumbrüche erzeugt werden. Zum Beispiel ist
eine feste Breite zumeist hilfreich (80 Zeichen ist Default).
Wird hingegen viel in die Konsole rausgeschrieben, wird einen LIMIT CONSOLE OUTPUT sehr
schnell behindern. Hierdurch kann es passieren, dass eine Anwendung wie abgestürtzt er-
scheint, in Wirklichkeit aber nur der Buffer der Konsole voll war. Jeder muss für sich ent-
scheiden, wohin er loggen will. Wenn man ein Framework wie LOG4J oder Apaches Com-
mons Logging benutzt, wird man auf die Konsole vielleicht sowieso nicht angewiesen sein
und parallel noch in eine Datei schreiben, wenn nicht, muss man sich Gedanken machen, ob
80000 Zeichen ausreichen und in welcher Farbe welcher Outputstream angezeigt werden
soll.
Andere Preferences
Es wurden hier die wichtigsten Einstellungen nur kurz angesprochen und von Milestone zu
Milestone, den sich Eclipse in den letzten Jahren weiterentwickelte, kamen neue Check-
boxen und Features hinzu. Für die einen mag es Spielerei sein, für die anderen eine riesige
Maschinerie aus kleinen Schräubchen, an denen man drehen kann. Mit einigen sinnvollen
davon kann man sich sicherlich das Leben und die Arbeit bei der Erzeugung von Java-
Sourcecode wesentlich erleichtern.
108
eclipse_v01.book Seite 109 Montag, 30. Januar 2006 12:02 12
Produkt Adresse
109
eclipse_v01.book Seite 110 Montag, 30. Januar 2006 12:02 12
OMONDO EclipseUML
110
eclipse_v01.book Seite 111 Montag, 30. Januar 2006 12:02 12
EclipseUML ist bereits seit längerem ein häufig verwendetes UML Plug-In für Eclipse. In
diesem Abschnitt konzentrieren wir uns auf die primären UML-Modellierungsfunktiona-
litäten und sehen von den erweiterten Features der Studio-Version ab. Wenn Sie einen
Feature-Überblick über die verschiedenen Versionen wünschen, können Sie diesen in der
Funktionsübersicht erhalten1.
1. http://www.omondo.com/features.html
2. http://www.omondo.com
3. http://www.eclipse.org/emf/
4. http://www.eclipse.org/gef/
5. http://www.eclipse.org/uml2/
111
eclipse_v01.book Seite 112 Montag, 30. Januar 2006 12:02 12
OMONDO EclipseUML
EclipseUML legt für jedes neu erzeugte Diagramm eine eigene Datei im Dateisystem an.
Sollen selbst erstellte Diagramme auch anderen Entwicklern zur Verfügung gestellt wer-
den, müssen wir diese gemeinsam mit dem Sourcecode publizieren. EclipseUML erhebt
zwar den Anspruch, aus dem Sourcecode einzelne Diagramme erzeugen zu können. Den-
noch werden einzelne Layoutinformationen separat in diesen Dateien abgelegt. Zur Editie-
rung der UCD-Datei zeigt EclipseUML eine eigene View an, in der wir jetzt unsere rudi-
mentären Klassen modellieren.
112
eclipse_v01.book Seite 113 Montag, 30. Januar 2006 12:02 12
Unterhalb der Editorleiste befinden sich Toolbar-Icons, die es erlauben, einzelne Elemente
im Diagramm zu erzeugen. Die jeweiligen Funktionen können durch Überfahren mit der
Maus visualisiert werden.
Über das Icon CREATE A PACKAGE legen wir ein neues Package mit dem Namen ex-
ample.tree an (siehe Abb. 3.3).
Wenn wir einen Blick auf den Package Explorer werfen, sehen wir, dass EclipseUML ein
Package mit diesem Namen angelegt hat. Alle folgenden Aktionen, die wir visuell im
Diagramm vornehmen, werden stets synchron auch in entsprechenden Dateien und Java-
Elementen ausgeführt, so dass ein zusätzlicher Generierungsschritt vom Diagramm zum
Modell entfällt.
Als Nächstes legen wir im Package example.tree ein Interface Unternehmensteil so-
wie die Klassen Abteilung und Mitarbeiter an. Wir wählen das neu angelegte Package
example.tree an und erzeugen mittels der rechten Maustaste OPEN | CREATE/OPEN
CLASS DIAGRAM ein Diagramm für das Package, wohinein wir die neuen Typen legen kön-
nen.
Dazu klicken wir nun auf die entsprechenden Toolbar-Icons und ziehen ein Rechteck an der
Stelle mit der Maus, an der diese im Package erzeugt werden sollen.
Wir lassen die beiden Klassen das Interface Unternehmensteil implementieren, wofür
wir auf das Generalisierungs-Icon und jeweils einmal auf die Klasse sowie einmal auf das
Interface klicken (siehe Abb. 3.4.).
Anschließend klicken wir mit der rechten Maustaste auf das Interface. EclipseUML bietet
zu jedem Element eine ganze Reihe von Funktionen an. Im oberen Bereich befinden sich
Sourcecode-Aktionen und Refactor-Maßnahmen für das Interface, darunter im Wesentli-
chen Menüpunkte, die auf die Visualisierung des Diagramms (Zoom, gepackte Ansicht,
Anzeige von Abhängigkeiten und Vererbung, Reihenfolge der Elemente etc.) eingehen
(siehe Abb. 3.5).
113
eclipse_v01.book Seite 114 Montag, 30. Januar 2006 12:02 12
OMONDO EclipseUML
Über den Menüpunkt PREFERENCES am Ende des Menüs lassen sich weitere Eigenschaften
des Interface – darunter dessen Sichtbarkeit – steuern.
114
eclipse_v01.book Seite 115 Montag, 30. Januar 2006 12:02 12
Wir legen jetzt über NEW | METHOD eine erste Methode an. Als Name für die Methode wird
addElement eingetragen (siehe Abb. 3.6).
Über den ADD-BUTTON im Parameterbereich fügen wir dann einen Parameter hinzu, dessen
Name newElement lautet und dessen Typ example.tree.Unternehmensteil heißt.
Der Vollständigkeit halber fügen wir über ein Exceptions-ADD eine java.lang.Illega-
lArgumentException (eigentlich überflüssig) hinzu. Im Register JAVADOC können wei-
tere Kommentare für diese Methode erfasst werden.
Die neu generierte Methodensignatur lautet nun:
Drei weitere Methoden werden auf die gleiche Art und Weise im Interface ergänzt:
115
eclipse_v01.book Seite 116 Montag, 30. Januar 2006 12:02 12
OMONDO EclipseUML
Wir klicken das Register 2ND ASSOCIATION END an. Es beschreibt die Beziehung zwischen
Abteilung und Unternehmensteilen. Wir lassen hier die Checkbox NAVIGABLE aktiviert und
tragen als Namen unternehmensteile ein. Dann wird die Multiplicity auf * gesetzt,
denn eine Abteilung kann ein oder mehrere Unternehmensteile enthalten, und auf BROWSE
gedrückt, um den Typ der Sammlung von Elementen auf java.util.Vector zu ändern.
Den Association Type stellen wir noch auf COMPOSITION und klicken anschließend auf OK.
EclipseUML erzeugt jetzt in der Klasse Abteilung ein private-Attribut vom Typ Vec-
tor mit dem Namen Unternehmensteile und dazu public-Zugriffsmethoden.
Auf diese Weise erhalten wir ein zugegebenermaßen sehr simples Klassendiagramm. Die
Erarbeitung der Business-Logik dahinter fehlt noch (die add-, remove- und die getName-
Methoden haben noch keinen Inhalt). Allerdings haben wir die grobe Baumstruktur skiz-
ziert und ohne weitere Programmieraufwände generiert (siehe Abb. 3.9).
116
eclipse_v01.book Seite 117 Montag, 30. Januar 2006 12:02 12
117
eclipse_v01.book Seite 118 Montag, 30. Januar 2006 12:02 12
EclipseUML ist außerdem behilflich beim Reverse Engineering, bei der Erzeugung von
Klassendiagrammen aus Sourcecode-Strukturen. Man kann sich schnell einen Überblick
auch bei unbekannten Java-Klassen verschaffen, indem man einzelne Java-Klassen auf die
Diagrammoberfläche zieht und per Menünavigation ihre Superklassen, Interfaces usw. ein-
blendet und somit weitere Abhängigkeiten aufzeigt.
EclipseUML speichert seine Metadaten über Beziehungen zwischen Klassen oder Daten
über Rollennamen in den Diagrammen im Source mit speziellen Tags im Javadoc ab. Dies
ermöglicht die im Gegensatz zu früheren Versionen sehr nahe Bindung zwischen Source-
code und UML-Diagramm, was auch die erneute Erzeugung der Diagramme aus dem
Source vereinfacht.
1. http://www.omg.org/cgi-bin/doc?formal/05-05-01
2. http://www.eclipse.org/emf/
118
eclipse_v01.book Seite 119 Montag, 30. Januar 2006 12:02 12
Nach der Erzeugung eines entsprechenden EMF-Modells (z.B. über die manuelle Erzeu-
gung via XML) erlaubt es ein spezieller EMF-Generator, Java-Implementierungsklassen
zum Modell zu erzeugen. Die so erzeugten Modellklassen können ohne Beeinträchtigung
von Modellierungsansätzen jederzeit wieder neu generiert werden.
Das EMF unterteilt sich in drei Hauptbereiche:
쐌 Einen Core-Framework-Anteil samt Metamodell (Ecore) u.a. zur Beschreibung und
Persistenz der EMF-Objekte
쐌 Ein Framework zur Erzeugung von EMF-Editoren namens EMF.Edit
쐌 Ein Code-Erzeugungssystem namens EMF.Codegen samt grafischer Benutzerober-
fläche
Das EMF ermöglicht also umfangreiche Editierung und Manipulation von Metamodellen
und die Generierung von Sourcecode-Fragmenten daraus. Im Download eingeschlossen
sind sehr umfangreiche Tutorials und Beispiele zum Umgang mit dem EMF und dem Im-
und Export in andere Applikationen.
Was EMF nicht mitliefert, ist hingegen der für viele Anwendungen so typische grafische
Editor für UML-Programme. Besonders, wer sich hier ein integriertes Produkt mit allen
Raffinessen von Forward und Reverse Engineering wie Omondos EclipseUML wünscht,
findet im EMF eher eine Basisplattform zur Erzeugung und zum Umgang mit einem Hin-
tergrundmodell. Umfangreiche Anleitungen und Dokumentation finden sich beispielsweise
auf dieser Webseite1.
Nicht umsonst verwendet Omondo noch ein zweites Eclipse-Framework, das wir unter dem
Namen GEF bei Eclipse ebenfalls herunterladen können.
1. http://www.eclipse.org/emf/docs.php
119
eclipse_v01.book Seite 120 Montag, 30. Januar 2006 12:02 12
3.3.3 UML2
Die Unified Modelling Language führte mit ihrer Version 2.0 eine Reihe von Erweiterun-
gen ein. In diesem Kontext findet sich auch die heute notwendige Unterstützung für UML
Profiles, der individuellen Ergänzung der Modelle durch Metatags, die z.B. in modellge-
triebener Anwendungsentwicklung genutzt werden kann.
Das UML2-Projekt bietet nun eine auf EMF-aufbauende Implementierung für den UML-
2.0-Standard an. Hierfür bietet UML2 ein entsprechendes Metamodell an.
Die UML2-Versionsnummern laufen dabei kongruent zur jeweiligen Eclipse 3.x-Version.
UML2 1.1 ist somit kompatibel zu Eclipse 3.1. Zum Drucklegungszeitpunkt ist Version 2.0
für Eclipse 3.2 in Entwicklung.
Das rund 11 MB große Download-Paket kann wie die beiden genannten Vorgänger auch
von der Eclipse-Seite heruntergeladen werden2.
1. http://www.eclipse.org/gef/ - derzeit in Version 3.1.1 für Eclipse 3.1 und als Milestonerelease für die Eclipse
3.2 Version
2. http://www.eclipse.org/uml2/
120
eclipse_v01.book Seite 121 Montag, 30. Januar 2006 12:02 12
4 Qualitätssicherung in Eclipse
121
eclipse_v01.book Seite 122 Montag, 30. Januar 2006 12:02 12
Größtes Problem in diesem Kontext bleibt allerdings die problematische Umsetzung vor al-
lem umfangreicher Softwaretests, die eine ganze Reihe von Anwendungsschichten in ei-
nem oder mehreren Testfällen durchlaufen. Hier sind oftmals umfangreichste Konfigura-
tionen vonnöten, um zum gleichen Zeitpunkt verschiedenste angebundene Fremdsysteme
und Ressourcen (wie Datenbanken oder HTTP-Verbindungen) zu einem definierten Zeit-
punkt auf einen gemeinsamen Stand zu bringen. In diesen Fällen kann das „Stubbing“ also
das Wegschneiden von bestimmten Kommunikationsverbindungen und Ersetzen durch de-
finierte, fixe, gegebenenfalls auch leicht dynamische Antwortergebnisse weiterhelfen. Für
solche Funktionalitäten bietet Eclipse derzeit allerdings keine inhärente Unterstützung an,
wohl finden sich aber diverse Open-Source-Produkte dazu im Internet.
1. http://www.atreides-technologies.com/
122
eclipse_v01.book Seite 123 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
1. http://checkstyle.sourceforge.net/
123
eclipse_v01.book Seite 124 Montag, 30. Januar 2006 12:02 12
Test, der den Bug wiederholbar erzeugt, geschrieben werden. Erst dann
sollte der Fehler korrigiert und der Fehlertest in das Build-Skript integriert
werden.
124
eclipse_v01.book Seite 125 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
Die Unterstützung für JUnit sowie für das Ant-Build-Tool wird, wie bereits erwähnt, durch
Eclipse mitgeliefert.
1. http://checkstyle.sourceforge.net/
2. http://sourceforge.net/projects/eclipse-cs
125
eclipse_v01.book Seite 126 Montag, 30. Januar 2006 12:02 12
In der Abbildung sehen wir zudem, dass mehrere Konfigurationen gleichzeitig angelegt
und konfiguriert werden können und in welchen Projekten derzeit die Checkstyle-Prüfun-
gen aktiv sind. Als Beispiel- und gleichzeitige Default-Einstellung sind die recht restrikti-
ven, aber allgemein anerkannten Sun Code Conventions1 standardmäßig hinterlegt.
Über den NEU-Button lassen sich weitere Konfigurationen anlegen bzw. über den KONFIGU-
RIEREN-Button modifizieren. Im Dialog werden unter einem logisch eindeutigen Namen die
Regeln und der Schweregrad des Bruchs der jeweiligen Regel erfasst (siehe Abb. 4.2).
Regeln können hinzugefügt, geändert und gelöscht werden, wobei die jeweilige Art der Er-
fassung der Regeleigenschaften im Wesentlichen vom Regeltyp bestimmt wird, was die
Freiheit für neue Regeln wiederum einschließt. Da die Sun Code Conventions bereits sehr
breitgefächerte Regeln bereitstellen, stellt sich die Frage, welche dieser Regeln wie streng
gelten sollen.
Unter die Themenbereiche fallen Javadoc Kommentarverwendung, Namenskonventionen,
Header- und Importvorgaben, Verletzungen von Größenbeschränkungen, Whitespace-Ver-
wendung, Anwendung von Modifiern, Konventionen für das Schreiben von geklammerten
Codeblöcken, schwierige Codestellen (verdeckte Variablen, komplexe Zuweisungen und
1. http://java.sun.com/docs/codeconv/
126
eclipse_v01.book Seite 127 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
Checkstyle bindet sich in den Compile und den Build-Prozess von Eclipse ein. Das kann bei
einem langsamen Rechner oder einer großen Dateimenge durchaus zu Verzögerungen in
der Arbeit führen. Daher sollte genau überlegt werden, welche Regeln wirklich sinnvoll
127
eclipse_v01.book Seite 128 Montag, 30. Januar 2006 12:02 12
4.3.3 Sourcecode-Metrics
Der Übergang von Stilrichtlinien, wie wir sie in Abschnitt 4.3.2 gesehen haben, zu Metri-
ken ist fließend. Während eine Sourcecode-Konvention vorgeben könnte, dass eine Klasse
nicht mehr als 1000 Zeilen Sourcecode besitzen darf, versuchen Metriken auf etwas ab-
strakterer Ebene die Sourcecode-Beschaffenheit in Zahlenmaterial greifbar zu machen,
allerdings auch unter Anwendung von Grenzen und Schwellenwerten, bei deren Über-
schreitung das Tool entsprechende Nachrichten hinterlässt.
128
eclipse_v01.book Seite 129 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
1. http://metrics.sourceforge.net/update
2. http://www.touchgraph.com/
129
eclipse_v01.book Seite 130 Montag, 30. Januar 2006 12:02 12
Wir finden dort eine ganze Reihe von Wertparametern, die im Hintergrund in der Metrik-
datenbank zu den jeweiligen Projekten bzw. Klassen ausgewertet und gespeichert werden.
Die Erzeugung und Ermittlung der notwendigen Metrikdaten erfolgt gemeinhin nach dem
Compile.
Hierfür integriert das Tool einen eigenen METRICS BUILDER, der beim Build des Projekts
angesprochen wird. Wir aktivieren ihn, indem wir das zu vermessende Java-Projekt im
PACKAGE EXPLORER auswählen und seine Eigenschaften (RECHTE MAUSTASTE | PROPERTIES)
aufrufen.
In dem Baumpunkt METRICS findet sich die dazu notwendige Aktivierungscheckbox. Sie er-
gänzt den in Abb. 4.6. zu sehenden METRICS BUILDER im Projekt, der im Anschluss an den
JAVA BUILDER zum Einsatz kommt.
Grundsätzlich ist Metrics nur in der Lage, kompilierte Java-Sourcen in Java-Projekten in
Eclipse zu vermessen. Eine Unterstützung für weitere Programmiersprachen finden wir
hier in der aktuellen Version nicht.
Kommen wir zurück zur Liste der Messwerte, die Metrics in einem entsprechenden Source-
code veranschlagt und prüft. Sie kann für die Reporterstellung der Metriken beliebig um-
sortiert werden. Tabelle 4.1 zeigt die Abkürzungen und eine kurze Erläuterung ihrer Bedeu-
tung1.
130
eclipse_v01.book Seite 131 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
LCOM* Lack of Cohesion Misst den Zusammenhalt einer Klasse nach der so
of Methods genannten Henderson-Sellors-Methode.
TLOC Total lines of code Gesamtzahl der Codezeilen eines Typs ohne leere
und Kommentarzeilen.
WMC Weighted Methods Summe aller VG-Werte für alle Methoden einer
per Class Klasse.
131
eclipse_v01.book Seite 132 Montag, 30. Januar 2006 12:02 12
Hier ist bereits zu erkennen, welche Arten von Prüfungen uns im Bereich der Metrikanalyse
begegnen. Sollte dies noch nicht ausreichen, empfehle ich z.B. einen Blick auf die IBM
Alphaworks-Seite und das dort zu findende Produkt „Structural Analysis for Java“.
Neben der Einstellung der Farben, die Metrics verwenden soll und einer Konfigurierbarkeit
der LCOM*- und NORM-Wertermittlung erlauben es die Preferences von Metrics auch,
die ermittelten Metrikwerte als Warnungen in den Problems auszuweisen.
Dies ist recht angenehm, da man sich die Suche in den unterschiedlichen Tabellen erspart,
die oftmals nur dann erfolgt, wenn es gerade nötig ist oder Zeit vorhanden war.
Abb. 4.7 zeigt hier die Einstellungstabelle für die verschiedenen Metrikwerte. Ob man sie
intensiv verwendet, dürfte davon abhängen, welche Bedeutung man den Zahlen selbst zu-
weisen möchte.
Die erzeugten Daten können schließlich zur weiteren Verarbeitung (z.B. als Entwicklungs-
statistik eines Programms in einem Refactoring-Prozess oder innerhalb der verschiedenen
Entwicklungsstadien) als XML-Report gespeichert werden. Wie diese Speicherung erfol-
gen soll, kann ebenfalls in den Preferences des Produkts konfiguriert werden.
132
eclipse_v01.book Seite 133 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
Bei Metrics 1.3.6 zeigten sich bei mir hin und wieder kleinere Refresh-Pro-
bleme beim Anzeigen der Tabellenstatistiken. Sie ließen sich durch einen
Workaround und den Wechsel in die Projekteigenschaften und zurück
allerdings auch schnell beheben.
—
Metrics bietet zwei Ansichten, jeweils für den Überblick auf reiner Klassen- und einmal für
die Ansicht auf Package-Ebene. Hierfür finden sich jeweils eine Tabelle und ein zugehöri-
ger Graph. In der Abb. 4.9 können wir die dafür aufklappbaren Tabellenelemente anhand
des Beispiels von Jakarta ORO sehen.
Jede Tabellenview besitzt ein Graph-Icon, um auf Visualisierungssicht umzuschalten. Hier
ist dann sehr gut zu erkennen, welche Abhängigkeiten zwischen den einzelnen Klassen be-
stehen. Durch Doppelklicken auf den jeweiligen Klassennamen wandelt sich der Graph und
konzentriert sich auf das angewählte Element und dessen referenzierte Objekte (siehe Abb.
4.10).
Ebenfalls über die Tabellenview bietet Metrics auch den besagten Export der XML-Daten
an. Abb. 4.11 zeigt einen Ausschnitt des exportierten XML.
133
eclipse_v01.book Seite 134 Montag, 30. Januar 2006 12:02 12
134
eclipse_v01.book Seite 135 Montag, 30. Januar 2006 12:02 12
4 – Qualitätssicherung in Eclipse
Leider ist ein Import bestehender Daten hier nicht vorgesehen, auch lassen sich die erzeug-
ten Graphen nicht per Produkt speichern.
4.3.6 Ant-Integration
Metrics bietet schließlich neben der Integration als Eclipse-Plug-In auch eine Unterstüt-
zung für das Buildtool Ant an. Eine ant-metricstask.jar-Datei hilft hier, das Produkt in den
Compile-Prozess einzubinden.
Die Ausgabe der erzeugten Metrikdaten erfolgt hierbei ähnlich wie in der reinen Eclipse-
Integration durch XMLs. Wer also in Nightbuild-Prozesse oder zur weiteren Verarbeitung
in Webseiten derartige Daten automatisch sammeln möchte, kann die Erstellung leicht au-
tomatisieren.
Für weiterführende Informationen und Beispiel-Ant-Task-Aufrufe ist ein Blick in die mit-
gelieferte Dokumentation empfehlenswert.
135
eclipse_v01.book Seite 136 Montag, 30. Januar 2006 12:02 12
Methoden. Derartiges kann von einem Metriktool nicht oder nur kaum messbar gemacht
werden.
Drittes Problem: die so genannte „Hegemonie der dominanten Dekomposition“. Diesen
Begriff hat man vielleicht schon einmal gehört, wenn man sich mit MDSOC (multi-dimen-
sional separation of concerns) oder aspektorientierter Programmierung beschäftigt hat. Es
geht um die Fragestellung, ob es möglich ist, eine Aufgabe oder einen Logikteil immer ein-
deutig einer bestimmten Sourcecode-Stelle (Klasse, Interface oder Methode) zuzuordnen.
Was hat das nun mit Metriken zu tun?
Es gibt Metriken, die den Zusammenhalt von Packages und deren Klassen bewerten, die
prüfen, ob es zirkuläre Abhängigkeiten oder Beziehungen gibt, die allgemein als uner-
wünscht und verwerflich erachtet werden. In späteren Phasen eines Projekts oder bei zu-
nehmender Größe einer Anwendung nimmt das Problem zu, ohne größere Refactoring-
Aufwände eine klare Aufgabentrennung und Bestimmung beizubehalten. Dass dies so
schwierig ist, liegt auch an der Java-Sprache an sich.
Um die Metrikwerte korrekt bzw. aussagekräftig bewerten zu können, müssen wir also das
Gesamtbild der Anwendung im Auge behalten. Welche Architektur haben wir, wie alt ist
die Software, in welcher Teamkonstellation ist sie entstanden, wie viel Sourcecode wird
automatisch generiert und nicht geschrieben, welches Ziel verfolgen wir mit der Analyse
dieser Zahlen überhaupt?
Metriken haben den Charme, PowerPoint-Folien mit Qualitätsbalken füllen zu können und
damit die echten Probleme von Projekt und Sourcecode gleichzeitig zu verschleiern. Ich
hatte selbst beispielsweise in einigen meiner entwickelten Komponenten einen sehr hohen
Komplexitätswert von einem Metriktool ausgewiesen bekommen, bis man mich darauf hin-
wies, man könne das Tool sehr gut austricksen, indem man viele öffentliche Getter- und
Setter-Methoden erzeugt. Unnützer Sourcecode, der nie verwendet würde, aber bei Ma-
nagementpräsentationen gut ankäme.
136
eclipse_v01.book Seite 137 Montag, 30. Januar 2006 12:02 12
137
eclipse_v01.book Seite 138 Montag, 30. Januar 2006 12:02 12
Das hier vorgestellte Build Management System baut auf drei Komponenten auf:
1. Versionsverwaltung: Diese wird im Wesentlichen durch das CVS-System unterstützt.
Neben der Versionierung einzelner Dateien wird hier festgelegt, was zu einem „Paket“
(z.B. volles Release, Patch, Zusatzkomponenten) gehört, welches ausgeliefert werden
kann. In einem Exkurs wird die Einbindung von CVS in Eclipse dargestellt.
2. Konfiguration, Auslieferung und Testen: Hier kommen CVS, Ant1 und das automati-
sche Testen gemeinsam zum Einsatz. Das Build Management-Werkzeug Ant wird The-
ma eines zweiten Exkurses sein.
3. Dokumentation: Hier kommen Ant- und Eclipse-Features zum Einsatz. Es wird mitge-
schrieben, welche Pakete auf welcher Umgebung wie installiert wurden.
1. vgl. http://ant.apache.org
138
eclipse_v01.book Seite 139 Montag, 30. Januar 2006 12:02 12
den Änderungen durchzuführen sind und man sich die Fehlermeldungen in den Zwischen-
stadien ersparen möchte. Der mögliche Preis ist dann gegebenenfalls eine lange Liste von
Fehlermeldungen am Ende der Änderungen. Daher ist zu überlegen, ob sich der Komplex
von Änderungen nicht in kleine Abschnitte aufteilen lässt, die wieder eine kompilierfähige
Stufe darstellen.
139
eclipse_v01.book Seite 140 Montag, 30. Januar 2006 12:02 12
Mit der Auswahl CREATE NEW FOLDER können Verzeichnisse aus dem Dateisystem ausge-
wählt und mit einem eigenen Namen in den Projektordner aufgenommen werden. Dabei ist
zu bemerken, dass dies kein Kopiervorgang ist. Die Verzeichnisse und Dateien bleiben an
ihrem ursprünglichen Ort liegen und werden nur in den Projektordner verlinkt.
Mit EDIT können wir durch den Projektbaum navigieren und Unterverzeichnisse für das
Build auswählen. Wenn wir das Verzeichnis aufklappen, erhalten wir einen Filter, mit dem
genauer eingegrenzt werden kann, welche Dateien für das Build relevant sind. Durch Aus-
wahl des Filtersymbols und Anklicken des EDIT-Buttons können wir die Filterkriterien de-
finieren, wobei mit Hilfe von regulären Ausdrücken (Wildcards) bestimmte Namensmuster
für Dateien und Verzeichnisse angegeben werden können. (Hier empfiehlt es sich, bereits
eine Namenskonvention für die Quelldateien verwendet zu haben, so dass hier einfache Fil-
ter gesetzt werden können.)
Schließlich kann mit REMOVE wieder ein Verzeichnis vom Build entfernt werden.
Neben der Auswahl der Quellverzeichnisse kann im unteren Teil des Fensters noch ein
Ausgabeverzeichnis bestimmt werden. Es wird ein Standardverzeichnis festgelegt, welches
innerhalb des Workspace angelegt wird. Durch den BROWSE-Button kann dieses auch direkt
im Dateisystem ausgewählt werden.
Alternativ lässt sich auch durch Setzen des Häkchens ALLOW OUTPUT FOLDERS FOR SOURCE
FOLDERS jedem Quellverzeichnis ein eigenes Ausgabeverzeichnis zuordnen. Beim Setzen
140
eclipse_v01.book Seite 141 Montag, 30. Januar 2006 12:02 12
des Häkchens wird ein zusätzlicher Eintrag im Verzeichnisbaum generiert, diesem kann
wieder mit EDIT ein Verzeichnis zugeordnet werden.
Der zweite Reiter in diesem Fenster erlaubt die Auswahl von ganzen Projekten, die für den
Build-Pfad verwendet werden sollen. Falls mehrere Projekte vorhanden sind, werden alle
außer dem aktuell ausgewählten hier angezeigt und können ausgewählt bzw. ausgenommen
werden.
Der dritte Reiter erlaubt die Auswahl und das Einbinden von Bibliotheken und Verzeich-
nissen. Es werden die bereits eingebundenen .jar-Dateien und Bibliotheken angezeigt. Da-
neben befinden sich Buttons zum Anpassen dieser Liste:
Mit ADD JARS können eigene Pakete (die bereits in einem Projekt des Workspace erstellt
wurden) eingebunden werden.
Mit ADD EXTERNAL JARS können Pakete aus anderen Quellen ausgewählt werden. Es öffnet
sich jeweils ein Fenster mit einem Arbeitsverzeichnis. In diesem kann zu dem gewünschten
Paket navigiert werden. Voreingestellt sind die Dateitypen *.jar und *.zip. Wenn das ge-
wünschte Paket erscheint, kann es ausgewählt (auch eine Mehrfachauswahl ist möglich)
und die Auswahl mit OK bestätigt werden.
Mit ADD VARIABLE lassen sich die bestehenden Java-Variablen verändern oder neue definie-
ren. Diese Variablen werden an den Compiler übertragen z.B. um weitere Verzeichnisse für
Libraries oder Komponenten einzubinden. Es erscheint ein Fenster mit den bereits definier-
ten Variablen und deren Werten. Mit EDIT kann die Liste als ganzes bearbeitet werden, d.h.,
es können Variablen neu definiert, ihre Werte verändert oder ganz gelöscht werden. Einige
Variablen sind jedoch als „reserved“ gekennzeichnet, d.h., sie können nicht hier editiert
werden, sondern sie werden aus andere Parametern abgeleitet.
Mit EXTEND lassen sich Verzeichnisse auf Basis einer Java-Variablen angeben, mit CONFI-
GURE VARIABLES schließlich kann man neue Variablen erstellen, ihnen Dateien und Ver-
zeichnisse als Werte zuordnen oder bestehende Einträge wieder löschen. Abb. 5.2 zeigt die
verschiedenen Fenster zur Einrichtung und Bearbeitung von Variablen.
Durch ADD LIBRARY gelangen wir zu einem kleinen Wizard, durch den wir zum einen die
JRE-Bibliothek(en) festlegen und zum anderen notwendige Plug-Ins einbinden können.
Mit ADD CLASS FOLDER schließlich fügen wir weitere Verzeichnisse von .class-Dateien aus
Projekten hinzu.
Sobald wir einen Eintrag aus der Liste der Pakete und Bibliotheken ausgewählt haben, ste-
hen noch die Buttons EDIT und REMOVE zur Bearbeitung bzw. zum Löschen des entspre-
chenden Eintrags zur Verfügung.
Eng verbunden mit diesem Reiter ist der vierte Reiter, bei dem wir die Reihenfolge des Ein-
bindens bestimmen können. Es wird die Liste der Pakete und Bibliotheken angezeigt. Dies-
mal können wir jedoch durch Auswählen von einem (oder mehreren) Listenelement(en)
mit den Buttons UP und DOWN ihre Reihenfolge bestimmen: Je weiter oben ein Eintrag
steht, desto früher wird er eingebunden. Dies hat dieselbe Auswirkung wie die Reihenfolge
der Dateien in der Classpath Systemvariable. Wenn gleichnamige Klassen in der Liste vor-
kommen, wird die Klasse verwendet, die in dieser Reihenfolge zuerst aufgeführt ist.
141
eclipse_v01.book Seite 142 Montag, 30. Januar 2006 12:02 12
Zusätzlich können wir durch Selektieren von Einträgen festlegen, welche hiervon expor-
tiert werden, d.h. in von dem aktuellen Projekt abhängigen Projekten zur Verfügung stehen
sollen.
Die Reihenfolge des gesamten Build, d.h. über mehrere Projekte hinweg, kann weiterhin
festgelegt werden über:
Menü WINDOW | PREFERENCES | BUILD ORDER
142
eclipse_v01.book Seite 143 Montag, 30. Januar 2006 12:02 12
ne und/oder mit einer anderen Java-Version gestartet werden soll. Weiterhin kann hier ein-
gestellt werden, ob Zusatzinformationen, die zum Debugging wichtig sind, bei den erzeug-
ten .class-Dateien hinzugefügt werden sollen oder nicht.
Der Reiter BUILD PATH öffnet ein Fenster, in dem das Verhalten bei bestimmten Fehlersitu-
ationen während des Build bestimmt werden kann. Die möglichen Fehler sind:
쐌 Unvollständige Build-Pfade
쐌 Im Kreis laufende Abhängigkeiten
쐌 Mehrfache Quellen
쐌 Inkompatible Versionen von eingebundenen Quellen (Paketen, Bibliotheken usw.)
Für jede dieser Fehlerarten kann bestimmt werden, ob sie zum Abbruch des Build führen
(Error), lediglich als Meldung angezeigt werden (Warning) oder völlig unbeachtet blei-
ben (Ignore). Ob es bei einem Projekt gute Gründe gibt, weshalb die eine oder andere Feh-
lersituation toleriert werden kann, möge jeder für sich entscheiden. Insgesamt sollte man
aber vorsichtig mit dem Abschalten dieser Fehlerbehandlungen umgehen und sich klar ma-
chen, welche Risiken sich hieraus ergeben.
Die darunter liegenden Checkboxen erlauben noch weitere Einzelheiten. Die beiden ersten
Häkchen bestimmen, ob ein Fehler zu einem Abbruch führen soll und ob ein komplettes
Build mit einem Löschen der Ausgabeverzeichnisse beginnen soll. Diese beiden Einstel-
lungen sollten eigentlich obligatorisch sein. Die beiden nachfolgenden (Ausschluss von
Dateien durch reguläre Ausdrücke und Erlaubnis zu mehreren Ausgabepfaden) hängen von
den jeweiligen Projekterfordernissen ab.
Der Menüpunkt JAVADOC schließlich erlaubt die Einstellungen bezüglich der automatisch
generierbaren Dokumentation. Hier kann im Wesentlichen das Ausgabeverzeichnis für die
Dokumentation festgelegt werden. Dieser Eintrag wird von dem entsprechenden Wizard
benutzt.
143
eclipse_v01.book Seite 144 Montag, 30. Januar 2006 12:02 12
144
eclipse_v01.book Seite 145 Montag, 30. Januar 2006 12:02 12
Zunächst muss die Art der Anwendung ausgewählt werden. Dies erfolgt in der linken
Baumstruktur durch Anklicken einer Anwendungsart und Betätigen des NEW-Buttons. Es
wird ein neuer Unterpunkt angelegt; zu jeder Anwendungsart können auch mehrere Kon-
figurationen erzeugt werden. Zunächst lässt sich noch die Darstellungsart in Eclipse (Per-
spektive) auswählen, anschließend können unter den einzelnen Reitern folgende Einstel-
lungen getroffen werden:
쐌 MAIN: Hier wird das zu startende Projekt eingetragen sowie je nach Anwendungsart die
main-Klasse, das Applet oder die Hauptklasse zum Testen.
쐌 ARGUMENTS:: Hier werden die Kommandozeilenparameter zum Programm wie zur VM
eingestellt. Zusätzlich wird das zu verwendende Arbeitsverzeichnis bzw. im Fall von
Plug-In- oder Workbench-Anwendungen das Workspace-Verzeichnis festgelegt.
쐌 PARAMETERS: Dieser Reiter erscheint nur bei Java Applets, hier lassen sich Größe und
Name des Applet-Fensters festlegen sowie Applet-spezifische Parameter definieren.
쐌 JRE: Hier kann bei Applets, Anwendungen und Test eine der auf dem Rechner instal-
lierten JREs ausgewählt werden, mit der das Programm betrieben werden soll. Diese
kann durchaus eine andere als die von Eclipse verwendete sein. Für Workbench-An-
wendungen steht diese Auswahl unter dem Reiter ARGUMENTS zur Verfügung.
쐌 CLASSPATH: Dieser Reiter ist ebenfalls bei Applets, Anwendungen und Tests verfügbar.
Hier werden die Build Path-Einstellungen als Voreinstellungen übernommen und kön-
nen in analoger Weise modifiziert werden, vgl. Abschnitt 5.3.1. Außerdem lassen sich
die Systemeinstellungen (Bootstrap Entries) verändern, z.B. können auch hier
noch weitere Bibliotheken hinzugefügt und ihre Reihenfolge bestimmt werden. Der
Button ADVANCED bietet auch die Möglichkeit zur Bearbeitung von Variablen.
쐌 SOURCE: Dieser Eintrag bestimmt die Verzeichnisse und Bibliotheken, die nach Quell-
dateien durchsucht werden. Die Einträge im Build Path werden als Voreinstellung ver-
wendet, sie bilden hier eine Einheit, die nur als Ganzes entfernt werden kann. Es können
zusätzliche Verzeichnisse angegeben werden, z.B. die Quelldateien einer externen
Bibliothek, die für das Debugging untersucht werden soll.
쐌 ENVIRONMENT: (nicht bei Java Applets) Hier ist ein Zugriff auf die Systemvariablen ge-
geben. Mit dem Button SELECT werden die existierenden Systemvariablen aufgelistet
und sie können zum Editieren in die Liste aufgenommen werden. Mit NEW können neue
Variablen angelegt werden. Mit EDIT lassen sich die Werte der Variablen bearbeiten, wo-
bei die Werte sowohl explizit gesetzt als auch durch andere Variablen definiert werden
können. Schließlich kann hier entschieden werden, ob die eingestellte Liste die vorhan-
denen Systemvariablen lediglich ergänzen oder komplett ersetzen soll.
쐌 COMMON: Mit diesem Reiter kann die getroffene Konfiguration entweder zur lokalen
Verwendung gekennzeichnet werden oder aber zur gemeinsamen Benutzung Shared
Configuration bereitgelegt werden. Bei Letzterem wird ein Verzeichnis eingetragen, in
dem die Konfiguration zur Verfügung gestellt wird. Für diesen Eintrag sind nur Ver-
zeichnisse innerhalb des Projekts möglich. Andere Teammitglieder können diese Kon-
figuration nutzen, indem sie FILE | PROJECT PROPERTIES | BUILDERS | IMPORT anklicken und
dort auf die Konfiguration zugreifen. Die Konfiguration kann auch als externes Build
geladen werden, dies werden wir im Abschnitt 5.5.4 näher erläutern.
145
eclipse_v01.book Seite 146 Montag, 30. Januar 2006 12:02 12
Die folgenden Reiter stehen nur bei Konfigurationen für Plug-In-Test und der Workbench
zur Verfügung:
쐌 PLUG-INS: Zunächst wird hier ausgewählt, ob alle installierten Plug-Ins oder lediglich
eine Auswahlliste einbezogen werden sollen. Soll eine Auswahlliste verwendet werden,
so wird eine Liste aller installierten Plug-Ins angezeigt, durch das Setzen von Häkchen
können diese einzeln ein- bzw. ausgeschlossen werden. Hat man die Auswahl getroffen,
so werden mit Drücken der Schaltfläche ADD REQUIRED PLUG-INS die Plug-Ins ergänzt,
die zur Erfüllung von Abhängigkeiten zu den ausgewählten notwendig sind.
쐌 TRACING: Technik zur Fehlersuche und Programmanalyse, bei der Aufrufe und Status-
informationen bereitgestellt werden. Als Standardeinstellung ist das Tracing abgeschal-
tet, hier kann es aktiviert werden. Sofern ein Plug-In eine Tracing-Funktionalität unter-
stützt, lässt sich dieses hier für das Tracing auswählen und mögliche weitere Parameter
können gesetzt werden.
쐌 CONFIGURATION: Hier werden die Plug-Ins ausgewählt, die automatisch gestartet werden
sollen, und ihnen wird ein so genannten Start-Level zugeordnet. Der Start-Level be-
stimmt, in welcher Phase des Programmstarts das jeweilige Plug-In einbezogen wird.
146
eclipse_v01.book Seite 147 Montag, 30. Januar 2006 12:02 12
Schließlich bestimmen wir die Zieldatei im unteren Bereich des Fensters. Durch weitere
Checkboxen wird die Komprimierung der Inhalte aktiviert sowie bestimmt, ob vorhandene
Dateien in einer bereits existierenden .jar-Datei überschrieben werden sollen.
Sobald alle Angaben gemacht wurden, wird die Schaltfläche FINISH aktiv und wir können
die Erzeugung des Exports fertig stellen lassen. Falls jedoch auch nach Ausfüllen aller Ein-
träge die Fläche nicht auswählbar wird, so hat Eclipse einen Fehler erkannt, eine entspre-
chende Meldung erscheint im Kopf des Fensters.
Der Wizard arbeitet in ähnlicher Weise auch für andere Exportformate, z.B. für .zip-Datei-
en, und das Anlegen von Verzeichnissen, wobei es Unterschiede lediglich in Details gibt.
So kann bei .zip-Dateien bestimmt werden, ob nur die ausgewählten Verzeichnisse angelegt
werden oder die Verzeichnisstruktur beginnend beim Projekt-Homeverzeichnis abgebildet
wird.
1. Frei verfügbar unter GPL ist das Buch „Open Source Development with CVS“ von Karl Fogel und Moshe Bar,
eine .pdf Version kann unter http://cvsbook.red-bean.com eingesehen und geladen werden.
2. http://www.cvshome.org
147
eclipse_v01.book Seite 148 Montag, 30. Januar 2006 12:02 12
148
eclipse_v01.book Seite 149 Montag, 30. Januar 2006 12:02 12
In dem Wizard ist der Eintrag CONNECTION TYPE mit dem Wert „pserver“ vorbelegt. Dies ist
die Standardverbindungsart von CVS-Systemen, stellt möglicherweise jedoch ein Sicher-
heitsrisiko dar. Falls die Verbindung eine ssh-Verschlüsselung benutzen soll, kann dies hier
oder bei PROPERTIES eingestellt werden.
149
eclipse_v01.book Seite 150 Montag, 30. Januar 2006 12:02 12
Wenn nun ein Projekt aus dem CVS-Repository bearbeitet werden soll, muss zunächst eine
lokale Kopie der zugehörigen Dateien erstellt werden. Mit einem Rechtsklick auf den Pro-
jektordner und Auswahl von CHECK OUT AS ... wird ein Wizard zum Kopieren der Projekt-
daten gestartet. Man erhält ein Dialogfenster mit drei Auswahlmöglichkeiten:
쐌 CHECK OUT AS A PROJECT IN THE WORKSPACE: Mit den Dateien wurde auch eine Projekt-
konfiguration für Eclipse im CVS abgelegt, diese wird dann für das lokal zu erzeugen-
de Projekt verwendet. Das ist eine bequeme Art, den Programmierern nicht nur den
Quellcode, sondern auch zusätzliche projektspezifische Einstellungen zukommen zu
lassen. Nach dem Drücken von NEXT kann der zu verwendende Workspace ausgewählt
werden.
150
eclipse_v01.book Seite 151 Montag, 30. Januar 2006 12:02 12
쐌 CHECK OUT AS A PROJECT CONFIGURED USING THE NEW PROJECT WIZARD: Es gibt keine Eclipse-
Projektkonfiguration (oder sie soll nicht verwendet werden) und es wird der Wizard zum
Einrichten eines neuen Projekts in Eclipse gestartet. Hier kann noch ein anderer Projekt-
name bestimmt werden, was aber normalerweise nicht notwendig ist.
쐌 CHECK OUT INTO AN EXISTING PROJECT: Es wird lokal kein neues Projekt angelegt, sondern
die Dateien werden einem bestehenden Projekt hinzugefügt. Dies kann sinnvoll sein,
kann aber auch leicht zu Konflikten in der Abgrenzung führen, wenn nicht alle Dateien
dem CVS zugeführt werden sollen.
Anschließend erfolgt die Auswahl der zu verwendenden Version. Über HEAD erhält man die
aktuellen Dateien, ansonsten kann über die Auswahl von Tags auf ältere Stände zugegriffen
werden. Mit FINISH wird der Dialog abgeschlossen und die lokalen Kopien der Dateien ste-
hen in der RESSOURCE-Perspektive zur Bearbeitung bereit.
Nun behandeln wir den umgekehrten Fall, dass ein lokales Projekt dem Repository hinzu-
gefügt werden soll.
Mit einem Rechtsklick im Navigator oder Explorer und der Auswahl TEAM|SHARE PROJECT...
wird ein Wizard zum Einfügen des Projekts gestartet. Zunächst kann bestimmt werden, ob
das Projekt in einem bereits verwendeten Repository abgelegt werden soll oder eine neue
Verbindung erstellt wird. Anschließend wird der Modulname für das CVS bestimmt oder
das Projekt kann einem Modul hinzugefügt werden. Die Standardauswahl ist hier, den Pro-
jektnamen auch als Modulnamen zu verwenden. Mit NEXT wird bereits der CVS-Server
kontaktiert, um zu prüfen, ob schon ein gleichnamiges Modul existiert. Ist dies der Fall, so
kann ausgewählt werden, mit welcher Version die Dateien verglichen werden sollen. Sollte
das Projekt nicht diesem Modul zugeordnet werden, so kann man mit BACK einen Schritt
zurückgehen und einen neuen Modulnamen festlegen.
Anschließend kann für einzelne Verzeichnisse oder Dateien angegeben werden, dass sie ex-
plizit nicht dem CVS zugeordnet werden sollen. Sinnvoll ist diese Auswahl z.B. in folgen-
den Fällen:
쐌 Es handelt sich um temporäre Dateien (z.B. eigene Notizen) ohne Bedeutung für andere
Teammitglieder.
쐌 Es handelt sich um Dateien mit starkem lokalen Bezug, die auf anderen Rechnern un-
passend oder sogar schädlich sind.
쐌 Es handelt sich um erzeugte oder binäre Dateien, z.B. Java Class-Dateien oder Archive,
die aus den .java-Dateien erstellt wurden.
Um den letzten Punkt besser zu verstehen, muss man wissen, dass CVS auf die Verwaltung
von Textdateien ausgerichtet ist und nur auf solchen die Änderungsverfolgung effektiv und
vor allem effizient in Speichernutzung und Übertragungsraten arbeitet. Bei Textdateien
wird die letzte Version der Datei gespeichert und alle anderen Versionen werden lediglich
durch ihre Unterschiede beschrieben. Bei binären Dateien erfolgt lediglich eine Prüfung
auf die bitgenaue Gleichheit; ist diese nicht gegeben, wird die gesamte Datei im System ge-
speichert bzw. zwischen Client und Server transferiert.
Ist diese Auswahl getroffen, kann der Prozess mit FINISH abgeschlossen werden; Eclipse
bietet noch die Möglichkeit zu einer Beschreibung des ersten Eintrags des Projekts.
151
eclipse_v01.book Seite 152 Montag, 30. Januar 2006 12:02 12
152
eclipse_v01.book Seite 153 Montag, 30. Januar 2006 12:02 12
UPDATE und COMMIT in einer gemeinsamen Oberfläche. Hier können Dateien verglichen
und Änderungen übernommen oder abgelehnt werden.
Während die beiden ersten Befehle essenziell sind, ist die Verwendung der Perspektive
SYNCHRONIZE WITH REPOSITORY eher eine Frage des Komforts, aber auch der Übung mit die-
ser Darstellungsweise. Während es bei der täglichen Arbeit eher eine Geschmacksfrage ist,
kann die Perspektive in komplexeren Situationen wie dem Zusammenführen von Verzwei-
gungen (BRANCH, siehe unten) hilfreich sein.
Zwei Hinweise sind zum Verhalten des COMMIT noch hinzuzufügen, bezüglich des Um-
gangs des CVS mit neuen Dateien bzw. dem Löschen von Dateien.
Wird eine Datei oder ein Verzeichnis neu angelegt, so wird dies nicht automatisch ins CVS
übernommen, selbst wenn die Datei in einem Projekt unter CVS-Kontrolle angelegt wird.
Während bei vielen CVS-Clients der Entwickler die Datei explizit anmelden muss, erkennt
Eclipse beim COMMIT normalerweise neue Dateien und Verzeichnisse und fragt nach, ob sie
ins CVS übernommen werden sollen.
Eine Ablehnung dieser Option ist mit Vorsicht zu betrachten: Diese Auswahl wird notiert
und bei allen folgenden Arbeitsschritten übernommen. Soll die Datei später doch in das
CVS-Repository, so muss dies explizit angefordert werden, was aber auch schon mal gerne
vergessen wird.
153
eclipse_v01.book Seite 154 Montag, 30. Januar 2006 12:02 12
Insgesamt ist man immer auf der sicheren Seite, wenn mit dem Anlegen einer Datei auch
sofort ihre Anmeldung zur CVS-Kontrolle erfolgt. Dies geschieht im Navigator durch
Rechtsklick auf den Dateinamen und Auswahl von TEAM | ADD TO VERSION CONTROL...
Beim Löschen einer Datei sollte man sich klar machen, dass diese im CVS-Repository le-
diglich als gelöscht markiert wird, jedoch nicht wirklich verschwindet. Immerhin ist sie ja
legitimer Bestandteil älterer Versionen. Das wirkliche Löschen einer Datei im CVS-Repo-
sitory ist ein schwieriger und meist auch fragwürdiger Vorgang, er wird nicht von Eclipse
unterstützt.
Neben diesen Hauptbefehlen für die tägliche Arbeit gibt es zwei weitere wichtige CVS-
Techniken, die für die mittel- und längerfristigen Aufgaben von Bedeutung sind: TAG und
BRANCH.
Mit einem TAG wird eine Version des CVS-Moduls bzw. des Projekts markiert, d.h. es wird
ein bestimmter Stand der Dateien als zu dieser Version gehörig gekennzeichnet. Dies ist
notwendig, da jede Datei einen eigenen Versionszähler besitzt; oft geänderte Dateien haben
also eine wesentlich höhere Versionsnummer als solche mit wenigen Änderungen. Um hier
den Überblick zu behalten, welche Einzelversionen der Dateien zu einer bestimmten Pro-
grammversion gehören, wird durch ein TAG in jeder Datei der jeweilige Stand ausgezeich-
net.
Ein TAG kann für ein gesamtes Projekt, Verzeichnisse oder einzelne Dateien vergeben wer-
den.
Man erreicht dies z.B. im Navigator durch Rechtsklick auf die Datei oder ein Verzeichnis
und Auswahl von TEAM | TAG AS VERSION... Dann wird man aufgefordert, einen Namen für
den TAG zu vergeben. Dieser sollte im Normalfall eindeutig und erklärend sein, z.B. worum
es sich bei dieser Version handelt („Test“, „Beta“, „Stable“ ...)
Wichtig ist, dass jeweils die lokalen Dateiversionen (also des Clients) mit dem TAG ver-
sehen werden. Dies können also ältere Stände sein als auf dem Server vorhanden sind, was
durchaus beabsichtigt sein kann, aber beachtet und überlegt werden sollte.
Es besteht aber auch die Möglichkeit, bereits vorhandene TAG-Namen wieder zu wählen.
Mit Auswahl der Checkbox MOVE TAG IF ALREADY EXISTS wird das Tag bei den Dateien, die
dieses TAG bereits besitzen, auf die neuere Version verschoben.
Dies ist eine einfache Möglichkeit, nachträglich noch Fehlerkorrekturen zu einer Version
hinzuzufügen, ist aber auch mit Vorsicht zu genießen: Nicht nur kann die Versionshistorie
verfälscht werden (z.B. hat ein bereits ausgeliefertes Programm andere Sourcen bei glei-
cher Versionsbezeichnung), auch kann so eine Kombination von Dateiversionen zusam-
mengestellt werden, die bis dahin nicht getestet worden ist.
Der CVS-Befehl zum Löschen eines TAG wird von Eclipse nicht unterstützt, was wohl als
Absicht und Sicherheitsmaßnahme angesehen werden kann.
Wie bereits in Abb. 5.5 erkennbar, kann man sich in der Perspektive CVS REPOSITORY EX-
PLORING alle Versionen des Projekts anzeigen lassen.
Während die bisher beschriebenen Funktionen mit etwas Übung leicht zu handhaben sind,
wird mit den Anlegen eines BRANCH (d.h. einer Verzweigung) oft eine höhere Komplexi-
154
eclipse_v01.book Seite 155 Montag, 30. Januar 2006 12:02 12
tätsstufe in ein Projekt gebracht, deren Bewältigung nicht nur technischer Unterstützung
bedarf, sondern auch organisatorisch wohl überlegt sein soll.
Ein BRANCH unterstützt das parallele Arbeiten auf zwei oder mehr Entwicklungssträngen.
Oft gibt es eine Fortsetzung des bisherigen Projekts, die als Hauptzweig bezeichnet wird,
und eine Teilmenge von Dateien, die den BRANCH ausmachen. Dies kann z.B. notwendig
sein, wenn die Entwicklung einer neuen Version begonnen wird, während zugleich noch
Fehlerkorrekturen der bestehenden Version durchgeführt werden. Man kann einen oder
mehrere BRANCHES anlegen sowie auch einen BRANCH selbst verzweigen, wir wollen hier
aber nur den elementaren Schritt des Anlegens und Zurückführens eines BRANCH beschrei-
ben. Komplexere Situationen erfordern einen wesentlich höheren Organisationsaufwand,
sind aber technisch bzw. in Bezug auf die Durchführung in Eclipse lediglich eine mehrfa-
che Kombination der dargestellten Schritte.
Das Anlegen eines BRANCH in Eclipse wird erreicht durch Rechtsklick im Navigator und
Auswahl von TEAM|BRANCH... Man wird aufgefordert, sowohl einen Namen für den BRANCH
zu vergeben (BRANCH TAG) als auch einen TAG auf den Dateiversionen vor dem Anlegen des
BRANCH anzulegen. Der BRANCH TAG markiert im Gegensatz zu einem anderen TAG immer
die jeweils neueste Version der Dateien des BRANCH auf dem Server.
Der zweite TAG ist nicht in allen CVS-Clients erforderlich, empfiehlt sich jedoch, wenn spä-
ter einmal die Entwicklungsstränge wieder zusammengeführt werden sollen. Weiterhin
kann der Entwickler bestimmen, ob er ab sofort auf dem BRANCH arbeiten möchte. Falls er
sich dafür entscheidet, werden alle Änderungen bei einem COMMIT dem BRANCH zugeord-
net. Andere Entwickler arbeiten zunächst weiter auf dem Hauptzweig, sie müssen explizit
auf den BRANCH wechseln. Dies lässt sich auf folgende Arten erreichen:
쐌 Mit der Auswahl TEAM | SWITCH TO ANOTHER BRANCH OR VERSION... kann ein BRANCH aus-
gewählt und auf diesen gewechselt werden. Dies ist für den Wechsel auf den BRANCH zu
bevorzugen.
쐌 Der Entwickler lädt den BRANCH als neues Projekt mit anderem Namen in seinem Work-
space. Dies erlaubt es ihm, sowohl auf dem BRANCH als auch auf dem Hauptzweig zu ar-
beiten.
쐌 Schließlich kann der Entwickler noch das Projekt aus dem Workspace löschen und den
BRANCH aus dem Repository laden.
Die weitere Arbeit verläuft durch UPDATE und COMMIT wie bereits beschrieben, jedoch soll-
te sich der Entwickler immer im Klaren sein, auf welcher Verzweigung er Änderungen vor-
nimmt. Die Befehle beziehen sich immer auf den Zweig, dem die Datei zugeordnet ist. So
ist es nicht möglich, eine Datei des BRANCH zu verändern und dies in den Hauptzweig oder
einen anderen BRANCH zu übertragen.
Die Entwicklung mit mehreren Entwicklungssträngen kann einfach dadurch beendet wer-
den, dass ein BRANCH beendet wird, z.B. wenn die Fehlerbehebung einer alten Programm-
version eingestellt wird. Dies ist keine besondere Herausforderung, lediglich das Archivie-
ren des letzten Stands ist ratsam.
Häufig kommt es aber vor, dass zwei Entwicklungsstränge wieder zusammengeführt wer-
den sollen (MERGE), was eine sehr anspruchsvolle Aufgabe darstellen kann.
155
eclipse_v01.book Seite 156 Montag, 30. Januar 2006 12:02 12
Zunächst sollte im Workspace die Version des Hauptzweigs vorhanden sein, auf der das
Zusammenführen stattfinden soll. Eclipse unterstützt diese Arbeit über die Auswahl
TEAM|MERGE... im Navigator.
Zunächst ist anzugeben, welcher BRANCH in welcher Version zurückgeführt werden soll.
Wird hier ein BRANCH TAG angegeben, so werden die jeweils letzten Versionen der Dateien
im BRANCH verwendet. Wird ein anderer „normaler“ TAG auf dem BRANCH gewählt, so wer-
den die markierten Versionen der Datei verwendet.
Mit den Hilfsfunktionen REFRESH TAGS und CONFIGURE TAGS lassen sich Details abfragen
oder es kann auf dem Server nach weiteren TAGS gesucht werden.
Weiter kann bestimmt werden, ob die SYNCHRONIZE View verwendet wird, um vorab das Er-
gebnis des MERGE-Prozesses einzusehen, oder dies direkt im lokalen Workspace ausgeführt
wird.
Nach dem Durchführen des MERGE-Prozesses ist das Ergebnis zu überprüfen, wobei die
TEAM SYNCHRONIZING-Perspektive hilfreich sein kann, vgl. Abb. 5.6. Hier können Dateien
strukturell und im Editor verglichen, Konflikte überprüft und aufgelöst und in das lokale
Projekt übernommen werden.
Die Arbeit wird durch ein COMMIT auf dem fertig gestellten Projekt abgeschlossen. Aller-
dings ist es sehr wichtig zu beachten, dass mit dem Auflösen von Konflikten längst nicht
alle möglichen Fehler behoben sind, die durch die Zusammenführung entstehen können.
Bevor also das COMMIT ausgeführt wird, sollte die entstandene Version gewissenhaft getes-
tet werden.
Auch wenn dieser Abschnitt mit dieser Annahme eingeleitet wurde: Ein MERGE bedeutet
nicht automatisch das Beenden der Arbeit an einem BRANCH. Es kann auch sinnvoll sein,
über MERGE die beiden Entwicklungsstränge in regelmäßigen Abständen zu synchronisie-
ren und beide Stränge weiterzuführen.
Technisch ist dies keine besondere Änderung, allerdings sollte bei der Durchführung des
ersten MERGE ein TAG auf dem BRANCH erstellt werden, welches die Version bei der Zusam-
menführung kennzeichnet. (Dies ist notwendig, weil das BRANCH TAG ja jeweils die neueste
Version bezeichnet, also keinen Anhaltspunkt mehr über die verwendeten Versionen lie-
fert.) Mit der Auswahl TEAM | MERGE... im Navigator wird das Zusammenführen gestartet,
wobei nun als START TAG das TAG auf dem BRANCH unmittelbar vor dem letzten MERGE an-
gegeben wird.
Beim zweiten (und jedem weiteren) MERGE wird ebenfalls ein entsprechendes TAG auf dem
BRANCH erstellt. Dieses wird beim nächsten MERGE als START TAG bestimmt, so dass sich die
Unterschiede jeweils nur aus den Änderungen seit der letzten Zusammenführung und nicht
mehr aus allen Änderungen seit Erstellen des BRANCH ergeben.
Neben diesen Kernfunktionen, die allen CVS-Clients gemeinsam sind, bietet Eclipse noch
eine Reihe weiterer Funktionen, die die Arbeit mit CVS komfortabel gestalten, zum Bei-
spiel:
쐌 Vergleich einer Datei in verschiedenen Versionen oder BRANCH mittels Rechtsklick und
Auswahl von COMPARE WITH | ANOTHER BRANCH OR VERSION, vgl. Abb. 5.6
156
eclipse_v01.book Seite 157 Montag, 30. Januar 2006 12:02 12
쐌 Ersetzen einer Datei durch eine andere Version mittels Rechtsklick und Auswahl von
REPLACE WITH | ANOTHER BRANCH OR VERSION
쐌 Erzeugen eines Patch, d.h. einer Beschreibung der Unterschiede zwischen zwei Ver-
sionen, die verschickt und von anderen (die z.B. keinen eigenen Zugriff auf das CVS-
Repository haben) zum Abgleich verwendet werden kann, mittels Rechtsklick und Aus-
wahl von TEAM | CREATE PATCH...
Wir wollen allerdings diese Funktionen hier nicht mehr im Detail beschreiben, sondern
möchten dazu einladen, selbst etwas hiermit zu experimentieren und so eigene Erfahrungen
im Umgang mit diesen Techniken zu sammeln.
157
eclipse_v01.book Seite 158 Montag, 30. Januar 2006 12:02 12
158
eclipse_v01.book Seite 159 Montag, 30. Januar 2006 12:02 12
159
eclipse_v01.book Seite 160 Montag, 30. Januar 2006 12:02 12
Die Auswahl von Ant in diesem Abschnitt liegt nicht allein darin begründet, dass Eclipse
eine direkte Unterstützung für Ant bietet. Der Erfolg von Ant als Build-Management-Tool
ist begründet in seiner Umsetzung als Java-Programm, seiner XML-basierten Konfigura-
tionssprache und seiner Plattformunabhängigkeit.
Wir wollen versuchen, die Struktur der Skripte darzulegen und Skriptauszüge so aufzube-
reiten, dass sie auch mit wenig Vorkenntnissen verständlich sind.
Wenn wir das Build etwas von dem direkten Programmieren trennen und als eigenen Schritt
betrachten, so sind eine Reihe von Aspekten zu beachten:1
쐌 Zusammenstellung aller Quelldateien: Was von einem einzelnen Programmierer viel-
leicht noch überblickt werden kann, wird spätestens in Projekten mit mehreren Mitar-
beitern schnell zur Falle: die Frage, welche Dateien in welcher Fassung benötigt werden
oder nicht. Zu einer Versionierung der Quelldateien gibt es hier kaum eine realistische
Alternative und auch ein zumindest minimaler Workflow, in welchem Stadium sich eine
Datei befindet („wird erstellt“, „bereit zum Test“, „fertig“), ist sehr sinnvoll.
쐌 Ausführung des Kompilierens: Was wir bereits bei den Einstellungen für das interne
Build vorgestellt haben, muss entsprechend auch für das Build mit Ant durchgeführt
werden. Dies betrifft sowohl die Reihenfolge des Kompilierens und die Beachtung von
Abhängigkeiten als auch die Strukturierung, welche Programmteile zusammenhängend
bzw. unabhängig voneinander kompiliert werden sollen.
쐌 Konfiguration für das Zielsystem: Je nachdem, für welche Maschinen das Ergebnis des
Build verwendet werden soll (oder auch das Build ausgeführt werden soll), kann sich
der Build-Vorgang z.B. durch die Verwendung unterschiedlicher Compiler bzw. Com-
piler-Versionen, Libraries oder maschinenspezifischer Programmteile erheblich unter-
scheiden. Diese Angaben sollten durch Parameter einstellbar sein und die einzelnen
Konfigurationen sollten abgelegt sein.
쐌 Nachvollziehbarkeit von ausgeführten Schritten und Fehlern: Je mehr Schritte während
des Build-Prozesses ausgeführt werden, desto schwieriger ist die Fehlersuche im Falle
eines misslungenen oder unvollständig ausgeführten Build. Daher ist es wichtig, dass
einerseits die Fehlermeldungen z.B. des Compilers aufgezeichnet werden, andererseits
die einzelnen Schritte mit sinnvollen Meldungen ihre Durchführung dokumentieren.
Am günstigsten ist das Führen einer zentralen Log-Datei, in der die Meldungen in der
chronologischen Reihenfolge eingetragen sind.2
1. Anm. des Autors: Es gibt eine ganze Reihe von Projekten und Erweiterungen zu Ant, die genau auf die im fol-
genden genannten Aspekte abzielen und Unterstützung z.B. bei der Erkennung von Abhängigkeiten oder der
automatischen Dokumentation bieten. Wir werden hier nicht auf diese Tools eingehen. Wer sich jedoch in
einem größeren Projekt mit diesen Fragen auseinandersetzt, dem sei empfohlen, einmal die externen Tools zu
Ant zu studieren. Dies ist zu finden auf der Ant Homepage http://ant.apache.org unter „RELATED PROJECTS“ und
„EXTERNAL TOOLS AND TASKS“.)
2. Über Größe, Detaillierungsgrad und Lesbarkeit dieser Datei kann man lange diskutieren. Nach Meinung des
Autors sind zu viele Einträge weniger störend als der Fall, dass die gerade hilfreiche Meldung nicht notiert
wurde. Werden die Einträge strukturiert, so kann man auch nachträglich leicht die wichtigen Stellen heraus-
filtern.
160
eclipse_v01.book Seite 161 Montag, 30. Januar 2006 12:02 12
쐌 Dokumentation des Build: Je weiter das Build automatisiert ist, z.B. bei einem „Nightly
Build“, das regelmäßig um dieselbe Zeit beginnt und automatisch ausgeführt wird, des-
to wichtiger wird es, dass nicht nur ein Ergebnis vorliegt, sondern auch, wie dieses Er-
gebnis erzielt wurde. Daher sollten alle Daten notiert werden, die notwendig sind, um
das Build identisch zu wiederholen. Ein Großteil dieser Arbeiten kann wieder durch den
Einsatz einer Versionierung erfolgen, wenn z.B. im Build nur Dateiversionen mit einem
bestimmten TAG1 verwendet werden oder umgekehrt die Dateien durch das Build mit ei-
nem TAG versehen werden.
쐌 Deployment: Das Ergebnis des Build (kompilierter Code, Libraries u.a.) kann direkt im
Zielsystem abgelegt, in einem Austauschverzeichnis bereit gestellt oder noch auf ande-
re Umgebungen verteilt werden. Auch diese Schritte sollten automatisiert erfolgen, um
Fehlerquellen zu vermeiden.
1. Vgl. Seite 154f. Aber auch ohne Versionsverwaltung sollte eine Methode benutzt werden, die jeweiligen
Stände der Dateien zu kennzeichnen oder zu fixieren.
161
eclipse_v01.book Seite 162 Montag, 30. Januar 2006 12:02 12
Auch wenn hier nichts Wesentliches passiert, kann dieser Code bereits in Ant geladen wer-
den. Dazu wird er in einer Datei gespeichert, die üblicherweise mit build.xml als Standard-
bezeichnung von Ant benannt und im Folgenden auch mit diesem Namen verwendet wird.
162
eclipse_v01.book Seite 163 Montag, 30. Januar 2006 12:02 12
Startet man nun Ant ohne weitere Angaben, so wird in der ersten Zeile das Standard-Target
alles erkannt. Nun erkennt Ant den description-Eintrag und die Definitionen in den
Property-Einträgen, die hier als globale Variablen gesetzt werden. Die anschließenden
Targets werden nicht direkt ausgeführt, sondern Ant beginnt nun, das Target mit Namen
alles abzuarbeiten. Dies hängt aber von dem Target dist ab, also wird Ant zunächst die-
ses Target ausführen, bevor die Tasks in alles ausgeführt werden. Dieses hängt aber seiner-
seits vom Target compile ab und dieses wiederum von init. Somit wird durch die
Abhängigkeiten erzwungen, dass die Targets in der Reihenfolge init|compile|dist
ausgeführt werden.
Das Target clean wird anschließend in alles ausgewertet. Es hängt von init ab, da die-
ses Target jedoch schon ausgeführt wurde, kommt es nun nicht mehr zum Einsatz. Inner-
halb eines Aufrufs wird jedes Target nur einmal ausgeführt.
Wollen wir zum Beispiel nicht das Target alles ausführen, sondern nur bis zum Schritt
compile gehen, müssen wir Ant mit dem Aufruf ANT COMPILE starten. In diesem Fall wer-
den wegen der Abhängigkeiten nur init und compile ausgeführt.
163
eclipse_v01.book Seite 164 Montag, 30. Januar 2006 12:02 12
ner Zielumgebung durchgeführt, so ist es ratsam, eine Überprüfung des Erfolgs dieses
Schritts vorzusehen.
쐌 TEST: Dies ist oft nicht ein einziges Target, sondern kann als Teilaufgabe nach Ab-
schluss der verschiedenen Targets vorkommen, z.B.:
– TEST_PREPARE: Kann feststellen, ob die benötigten Dateien aus dem Repository
gezogen wurden.
– TEST_COMPILE: Kann auf Fehlermeldungen und Warnungen des Compilers rea-
gieren und den Prozess beenden oder Nachrichten versenden.
– TEST_DEPLOY: Kann feststellen, ob eine Bereitstellung stattgefunden hat, also
z.B. eine Datei an einem bestimmten Ort erzeugt wurde, bzw. ob sich ein Programm
starten lässt. Es kann auch vorbereitete Testszenarien starten.
쐌 REPORT: Hier geht es im Wesentlichen darum, aus der möglicherweise unübersichtli-
chen Menge von Status-, Warn- und Fehlermeldungen einige Kernaussagen zu extrahie-
ren und diese gezielt darzustellen. Weiterhin gilt es, die darzustellenden Informationen
an die geeigneten Adressaten zu verteilen.
쐌 ALL: Die Standardaufgabe für ein komplettes Build.
Natürlich kommt man meist nicht mit einem einzigen Target pro Ziel aus, so ist es z.B. rat-
sam, jeweils ein Target compile pro Paket zur Verfügung zu stellen. Damit ergibt sich auch
wieder die Analogie zum internen inkrementellen bzw. kompletten Build. Als Konsequenz
hieraus sollten auch prepare und deploy paketweise arbeiten können. Und schließlich ist
noch zu beachten, dass Abhängigkeiten zwischen Paketen auch korrekt widergespiegelt
sind.
164
eclipse_v01.book Seite 165 Montag, 30. Januar 2006 12:02 12
165
eclipse_v01.book Seite 166 Montag, 30. Januar 2006 12:02 12
166
eclipse_v01.book Seite 167 Montag, 30. Januar 2006 12:02 12
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/MyProjectTest.jar"
basedir="${build}"/>
<echo message="Auslieferung der Test-Version abgeschlossen!"/>
</target>
<target name="deployForDist" if="DIST_INIT"
description="Auslieferung einer Distributionsversion">
<!-- Erstellt ein neues Verzeichnis fuer eine Distribution, legt
das Kompilat in einem .jar-File dort ab -->
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/MyProject.jar" basedir="${build}"/>
<echo message="Auslieferung der Auslieferungs-Version
abgeschlossen!"/>
</target>
<target name="deploy"
depends="compile, javadoc, deployForTest, deployForDist"
description="Aufruf zum Erstellen einer Distribution">
<!-- Es koennen weitere versionsunabhaengige Schritte folgen -->
<echo message="Auslieferung abgeschlossen!"/>
</target>
<target name="cleanup" depends="init"
description="Entfernt temporaere Daten und Verzeichnisse">
<delete dir="${src}"/>
<delete dir="${build}"/>
<echo message="Temporaere Dateien und Verzeichnisse
aufgeraeumt"/>
</target>
<target name="all" depends="deploy,test,javadoc,cleanup"
description="vollstaendige distribution">
<!-- Distribution wird durch Abhaengigkeit erstellt, hier wird
das abschliessende Reporting erstellt -->
<echo message="Erstellung der Distribution beendet!"/>
<echo message="Temporaere Verzeichnisse wieder aufgeraeumt!"/>
</target>
</project>
Die einzelnen Aufgaben sind hier natürlich sehr einfach. Die Struktur kann als Gerüst ge-
nutzt werden und den individuellen Anforderungen entsprechend angepasst werden. Dieses
Skript ist entlang der Entwicklungsschritte zum Standard-Target geführt:
INIT à PREPARE à COMPILE à DISTRIBUTE à ALL
Diese Kette ist durch die Abhängigkeiten (Attribute: DEPENDS) definiert. Das Standard-Tar-
get ist noch erweitert durch die beiden Ziele TEST und CLEANUP. TEST hängt von COMPILE
ab und kann auch als selbstständiges Ziel aufgerufen werden. CLEANUP hängt nur von INIT
ab, daher kann es auch dann verwendet werden, wenn einer der Schritte PREPARE oder
COMPILE abgebrochen ist und wieder aufgeräumt werden soll.
167
eclipse_v01.book Seite 168 Montag, 30. Januar 2006 12:02 12
Da es keine weiteren Beziehungen zwischen TEST und CLEANUP gibt, werden diese beiden
Ziele in der aufgeführten Reihenfolge ausgeführt. Dies erlaubt es, dass die Tests auch auf
den Zwischenergebnissen laufen können und nicht allein auf dem Endergebnis. So können
Hilfsklassen o.Ä. bei den Tests zur Verfügung gestellt werden, die im Endprodukt nicht ent-
halten sein sollen.
Die Dokumentationserstellung ist hier durch JavaDoc in dem Target JAVADOC realisiert.
Sie ist lediglich von PREPARE abhängig, kann also auch erstellt werden, ohne dass COM-
PILE aufgerufen wird. Umgekehrt ist DEPLOY wieder von JAVADOC abhängig, so wird die
Dokumentation als Bestandteil der Auslieferung eingebunden.
Es werden zwei Versionsarten angeboten, eine Testversion und eine Auslieferungsversion.
Die Schritte, die unterschiedlich für die beiden Versionen sind, werden jeweils in einen ver-
sionsunabhängigen Teil und die versionsabhängigen Teile aufgespaltet. Der unabhängige
Teil, z.B. INIT, wird in den allgemeinen Abhängigkeiten aufgeführt. Die abhängigen Teile,
hier initForDist, initForTest, werden von INIT eingebunden.
Über eine Kommandozeilenoption wird bestimmt, welche Version erstellt wird. Es kann
nur eine Version pro Lauf erstellt werden. Dies wird ebenfalls mit dem INIT-Ziel geregelt
und durch eine PROPERTY weitergegeben. Somit ist ein Fehler durch die gleichzeitige Erstel-
lung von Versionen mit unterschiedlichen Parametern weitestgehend ausgeschlossen.
Für REPORT wurde in diesem Skript auf die eingebaute Funktion MailLogger zurückge-
griffen, um eine Benachrichtigung der betroffenen Personen (Programmierer, Tester, Nut-
zer) umzusetzen. Ein sehr leistungsstarkes Werkzeug ist durch die Unterstützung von
„Log4J“ bereitgestellt. Hierdurch können sehr individuell und gezielt Informationen über
den Fortschritt oder Fehler im Build gesammelt und aufbereitet werden.1
Es wurden noch einige weitere Funktionen und Möglichkeiten von Ant eingebaut, die bei
weitem nicht den vollen Funktionsumfang dieses Werkzeugs abbilden, sondern lediglich
einen Eindruck von den Einsatzmöglichkeiten vermitteln sollen:
쐌 Einige Targets sind mit Bedingungen verknüpft, z.B. in
<target name="deployForDist" if="DIST_INIT"
Dieser Zusatz bewirkt, dass das entsprechende Target nur ausgeführt wird, wenn die
genannte Property definiert ist. (Es ist eine Eigenart von Ant, dass hier die reine Exis-
tenz der Property das Kriterium zur Erfüllung der Bedingung ist, nicht deren Wert.)
Die Bedingung wird in dem Moment geprüft, wenn das Target entsprechend der
Abhängigkeiten ausgeführt werden soll. Die Negation der if-Bedingung ist durch
unless gegeben.
쐌 Das init-Target enthält die Zeile
<tstamp prefix="start">
Dies ist eine gängige Praxis zum Erzeugen einer Property, die einen String mit der
aktuellen Zeit oder dem Datum enthält. Dieser kann z.B. verwendet werden, um Datei-
namen mit Zeitstempel zu generieren.
1. Eine Beschreibung dieses Tools würde hier zu weit führen. Informationen und Downloads zu Log4J sind unter
http://logging.apache.org/log4j/docs/ zu finden.
168
eclipse_v01.book Seite 169 Montag, 30. Januar 2006 12:02 12
Zur Verwendung einer SHARED CONFIGURATION wählen wir das Menü RUN|EXTERNAL
TOOLS|EXTERNAL TOOLS.., hierzu siehe auch Abb. 5.7. Mit der Auswahl von PROGRAM und der
169
eclipse_v01.book Seite 170 Montag, 30. Januar 2006 12:02 12
Schaltfläche NEW können wir eine neue Konfiguration erstellen lassen. Unter dem Reiter
MAIN können wir im Feld BUILDFILE die Datei mit der gewünschten Konfiguration eintra-
gen. Falls die Datei fehlerhaft ist, wird eine entsprechende Meldung angezeigt, sonst wird
die Schaltfläche RUN aktiviert und wir können das Build hierüber starten.
Wir können eine Ant Build-Datei wie folgt aufrufen: Wir wählen die Build-Datei (meistens
build.xml) im Navigator aus.1 Zum Starten eines Build mittels Ant-Skript wählen wir RUN |
EXTERNAL TOOLS | RUN AS | ANT BUILD. Mit der Ausführung der Datei wird eine Console ge-
öffnet, in der die Meldungen und Fehlerhinweise angezeigt werden.
Die Integration von Ant in Eclipse geht allerdings noch weiter, so können wir Ant als Werk-
zeug für alle Builds verwenden, indem die automatischen Builds ebenfalls dieses externe
Tool verwenden. Zum Aktivieren von Ant für automatische Builds sind die folgenden Ein-
stellungen vorzunehmen:
In den PROJEKT PROPERTIES (zu erreichen z.B. durch Auswahl des Projekts in der Navigation,
dann mit der Tastenkombination Ç-Æ) wählen wir den zweiten Punkt BUILDERS aus.
Im rechten Fenster erscheint eine Liste der eingebundenen Builder. Standardmäßig ist hier
der interne Java Builder eingetragen. Der Java Builder ist automatisch konfiguriert, er kann
weder editiert noch deaktiviert werden (die Schaltfläche DISABLE ist abgeschaltet). Die Rei-
henfolge in der Liste entscheidet über die Ausführungsreihenfolge. Der Java Builder steht
standardmäßig an erster Stelle, wird also zuerst verwendet. Ein anderer Builder kann aber
mithilfe der Schaltflächen UP und DOWN auch an die erste Stelle gesetzt werden.
Mit der Schaltfläche NEW können wir neue Builder anlegen, wir wählen hier den Ant Build
aus und bestätigen mit OK. Es öffnet sich ein Fenster wie in Abb. 5.8 dargestellt, in dem die
Einstellungen des Builder vorgenommen werden. Wir können dieses Fenster mit OK schlie-
ßen. Wir sehen nun einen weiteren Eintrag NEW_BUILDER für Ant in der Liste der Builder.
1. Ggf. muss die Datei zuerst in ein zum Projekt gehörigen Verzeichnis verschoben werden.
170
eclipse_v01.book Seite 171 Montag, 30. Januar 2006 12:02 12
Durch die Auswahl dieses Ant Builder werden auch die übrigen Schaltflächen aktiviert,
wovon wir nun die Schaltfläche EDIT näher betrachten wollen. Wird diese gewählt, so öffnet
sich wieder das Fenster für die Einstellungen des Ant Builder.
Unter dem Reiter MAIN werden die Hauptpfade eingestellt. Für die Dateien und Verzeich-
nisse kann entweder durch den Workspace gesucht werden, d.h., es wird die in Eclipse ver-
wendete Projektstruktur durchsucht, oder durch die reale Verzeichnisstruktur gesucht wer-
den. Es lassen sich aber auch bereits definierte Variablen verwenden.
Der erste Eintrag zeigt auf die zu benutzende Build-Datei von Ant (standardmäßig
build.xml). Der zweite Eintrag enthält das Hauptverzeichnis für das Build.
Der dritte Eintrag enthält die Aufrufparameter zum Start des Builder. Dies können zum
einen allgemeine Angaben sein, zum anderen können hier Variablen verwendet werden, die
im Kontext der Ausführung entsprechend ersetzt werden. Eine Liste der verfügbaren Vari-
ablen ist durch die Schaltfläche rechts vom Eingabefeld einzusehen. Ein Beispiel einer sol-
chen Variablen ist ${build_type}: Je nach Aufrufsituation wird diese Variable ersetzt
durch die Werte incremental, full, auto oder none. (Allerdings ist dies nur dann sinn-
voll, wenn in der Ant-Konfiguration auch diese Werte verwendet werden.) Bei einigen Va-
riablen, die Pfadangaben zum Inhalt haben, erscheint im unteren Teil des Fensters eine Aus-
wahl, ob die Standardpfade oder spezifische Einstellungen verwendet werden sollen, sowie
ein Navigationsfenster, in dem die Auswahl spezifischer Verzeichnisse vorgenommen wer-
den kann.
Schließlich ist hier noch ein Häkchen CAPTURE OUTPUT gesetzt, welches bewirkt, dass der
Ant-Output von Eclipse aufgenommen und angezeigt bzw. ignoriert wird.
Unter dem Reiter TARGETS werden die Targets mit ihrer Beschreibung (Description aus
der Konfigurationsdatei) aufgelistet und bestimmt, welche ausgeführt werden sollen. Hier
wird auch die Default-Auswahl aus dem Skript angezeigt, diese muss aber nicht übernom-
men werden, d.h., dieses Target muss nicht zwangsläufig ausgeführt werden. Es können
hier auch mehrere Targets ausgewählt werden, hierbei entscheidet die Reihenfolge das An-
klickens auch über die Reihenfolge ihrer Ausführung. Diese wird im unteren Teil des Fens-
ters aufgelistet und lässt sich dort auch nachträglich editieren. Der Hauptnutzen dieser Ein-
stellungen ist wohl darin zu sehen, dass hier verschiedene Builder für unterschiedliche
Zwecke konfiguriert werden können, welche alle auf dieselbe Datei build.xml zugreifen.
Zwei Checkboxen SORT TARGETS (Targets alphabetisch sortieren gegenüber Anzeige in der
Reihenfolge im build.xml) und HIDE INTERNAL TARGETS (Ausblenden der als intern erkannten
Targets) dienen der leichteren Bedienung dieses Fensters.
Mit REFRESH wird bestimmt, welche Ressourcen nach dem Build aktualisiert werden sollen.
Laut Voreinstellung wird keine Aktualisierung vorgenommen, was dazu führen kann, dass
eine neu erstellte Datei oder ein Verzeichnis nicht direkt z.B. im Navigator sichtbar ist. Es
werden hier verschiedene Stufen angeboten, vom gesamten Arbeitsbereich bis zu einzelnen
Verzeichnissen oder Dateien. Falls nicht konkrete projektspezifische Gründe dem entge-
genstehen, sollte man hier zur Vermeidung von Inkonsistenzen und Verwirrung eine groß-
zügige Einstellung treffen, d.h. den gesamten Arbeitsbereich oder das betroffene Projekt
aktualisieren lassen.
171
eclipse_v01.book Seite 172 Montag, 30. Januar 2006 12:02 12
Unter CLASSPATH, JRE und ENVIRONMENTS werden die Parameter für die Ausführung von
Ant bestimmt. Das Vorgehen für diese Einstellungen ist ganz analog zu den entsprechenden
Einstellungen für das interne Build. Hierbei können unter ENVIRONMENTS nur dann Einträge
vorgenommen werden, wenn für das Build eine andere JRE verwendet werden soll als für
den Workspace. Gegebenenfalls kann man unter JRE die Auswahl SEPARATE JRE einstellen
und die gleiche Version auswählen wie sie der Workspace verwendet. Möchte man Ant so-
wohl über Eclipse als auch eigenständig verwenden, so sollten diese Parameter möglichst
denen entsprechen, die auch für eine Ausführung des Build ohne Eclipse, z.B. über die
Kommandozeile, gelten, damit die Ausführung in beiden Fällen identisch verläuft.
Unter PROPERTIES lassen sich weitere Eigenschaften bestimmen. Diese können entweder
den globalen Properties aus Ant entsprechen (und sind hier nicht mehr veränderbar), hier
definiert werden oder aus anderen Property-Dateien eingelesen werden. Die Definition er-
folgt über ADD PROPERTY und besteht aus einem Namen und einem Wert, der entweder fest
bestimmt wird oder auf die in Eclipse vorhandenen Variablen aufbaut.
Schließlich kann unter BUILD OPTIONS festgelegt werden, wann dieses Tool für ein Build
verwendet werden soll. Hier können wir also zum Beispiel bestimmen, dass Ant für manu-
ell gestartete Builds verwendet wird, während bei automatischen Builds der interne Java
Builder benutzt werden soll. Die Einstellung ist eine Kombination aus dem Setzen der ent-
sprechenden Häkchen und der oben beschriebenen Reihenfolge, in der die externen und in-
ternen Builder aufgelistet sind. Tritt ein Ereignis wie der Aufruf eines manuellen Build ein,
so wird die Liste der definierten Builder von oben nach unten durchlaufen, bis der erste
Builder gefunden wird, bei dem das entsprechende Häkchen gesetzt ist.
Sind alle Angaben gemacht worden, kann die Eingabe mit dem OK-Button abgeschlossen
werden. Wird nun ein Build gestartet, so werden die ausgewählten Targets der Reihe nach
durchgeführt. Die Status- und Fehlermeldungen werden im Console-Fenster angezeigt.
Ant und eine existierende Konfigurationsdatei build.xml können aber auch noch auf andere
Weise in Eclipse integriert werden, indem es als ein eigenes Projekt aufgefasst wird. Hier-
bei beginnen wir über FILE | IMPORT | EXISTING ANT BUILDFILE ein neues Projekt. In dem er-
scheinenden Fenster können wir einen Projektnamen vergeben und die Datei build.xml mit
Pfad oder durch Navigation im Arbeitsbereich eintragen. Wird die Datei im Navigator aus-
gewählt und mit WINDOWS | SHOW VIEW | ANT geöffnet, so erkennt Eclipse die Struktur und
stellt diese als Outline dar (siehe unten links in Abb. 5.8).
Klicken wir mit der rechten Maustaste auf ein Target und wählen die Option RUN ANT ..., so
gelangen wir wieder zu dem Konfigurationsfenster wie in Abb. 5.8. Die Einstellungsmög-
lichkeiten entsprechen den bereits oben beschriebenen. Sie werden allerdings hier als eine
Konfiguration gespeichert. Zusätzlich steht ein Reiter COMMON zur Verfügung, mit dem die-
se Konfiguration wieder als SHARED CONFIGURATION gekennzeichnet und zur Benutzung im
Team abgelegt werden kann. Wir können auch mehrere Konfigurationen erstellen, ihnen
Namen geben und später weiterverarbeiten.
Zum Ausführen kann nun ein Target per Doppelklick aufgerufen werden. Falls eine einzige
Konfiguration existiert, wird sofort eine Console eingeblendet und das Target ausgeführt.
Bei mehreren Konfigurationen erscheint erst ein kleines Fenster, in dem ausgewählt werden
kann, welche Konfiguration für die Ausführung verwendet werden soll.
172
eclipse_v01.book Seite 173 Montag, 30. Januar 2006 12:02 12
5.6 Zusammenfassung
Mit diesen Ausführungen möchten wir das Thema Build Management beenden. Wir haben
die internen Einstellmöglichkeiten von Eclipse zum Build kennen gelernt. Es wurde der
CVS-Client von Eclipse vorgestellt und die Verknüpfung von Versions- und Build Manage-
ment umrissen. Wir haben die typischen Aufgaben im Build Management kurz erläutert
und deren technische Umsetzung mit Hilfe von Ant angerissen. Schließlich wurden ver-
schiedene Arten der Integration von Ant als Beispiel eines externen Tools in Eclipse darge-
stellt.
Es sei noch einmal darauf hingewiesen, dass die Unterstützung von Ant in Eclipse eine her-
vorragende Ergänzung von Eclipse durch ein anderes gutes Werkzeug darstellt. Außerdem
können beide durch ihren Charakter als offene und erweiterbare Plattformen auf die indivi-
duellen Projektgegebenheiten zugeschnitten werden. Die effiziente Nutzung dieser Werk-
zeuge erfordert allerdings auch eine Struktur und vorausschauende Planung des Build als
ein sich wiederholender Prozess. In einem Entwicklungsprojekt sollte man sich damit früh-
zeitig um das Build Management Gedanken machen und sich mit den einzelnen Stufen und
geeigneten Werkzeugen vertraut machen. Wenn man mit einem guten Augenmaß den rich-
tigen Weg zu einer effizienten Lösung dieser Aufgaben findet, sind bereits einige Stolper-
steine und Fallen aus dem Weg geräumt und die eigentliche Entwicklung kann ungehindert
durchgeführt werden.
173
eclipse_v01.book Seite 174 Montag, 30. Januar 2006 12:02 12
eclipse_v01.book Seite 175 Montag, 30. Januar 2006 12:02 12
Für die Entwicklung von Graphical User Interfaces (GUIs) existieren verschiedene Biblio-
theken. Unabhängig davon, welche Bibliothek verwendet wird (AWT, Swing oder SWT),
ist die Entwicklung von GUIs in Java sehr schreibintensiv, sofern hierfür keine Werkzeuge
eingesetzt werden. Im Folgenden werden daher die beiden GUI-Designer Visual Editor für
Java und WindowBuilder vorgestellt, die ein visuelles Entwerfen von GUIs mit AWT-,
Swing- und SWT-Komponenten ermöglichen.
Die Darstellung beginnt jeweils mit der Beschreibung der Installation und des Aufrufs des
Designers. Anschließend wird erläutert, wie Komponenten hinzugefügt und entfernt, Ei-
genschaften und Layouteinstellungen vorgenommen und Ereignisse für Komponenten defi-
niert werden können. Da wir beim Visual Editor sowohl die Erstellung eines GUI mit
Swing- als auch die Erstellung eines GUI mit SWT-Komponenten beschreiben, ist anschlie-
ßend eine differenzierte Betrachtung erforderlich. Für beide Fälle werden zunächst die je-
weils unterstützten Komponenten und die Layouteinstellungsmöglichkeiten vorgestellt, be-
vor der automatisch generierte Quelltext und ein Beispiel betrachtet werden. Im Falle des
WindowBuilder beschränken wir uns auf die Beschreibung der Erstellung eines GUI mit
SWT-Komponenten, so dass wir direkt anschließend an die Betrachtung der Ereignisverar-
beitung den automatisch generierten Quelltext und ein Beispiel vorstellen.
Während für die Darstellung der GUI-Designer das AWT und die Swing-Technologie als
bekannt vorausgesetzt werden, erfolgt vor den Betrachtungen zur Erstellung eines GUI mit
SWT-Komponenten eine Einführung in SWT. Sie umfasst zunächst eine kurze Abgrenzung
der drei Grafikbibliotheken AWT, Swing und SWT. Anschließend beschreiben wir den
Aufbau einer Applikation. Daran schließt sich die Erläuterung einer Reihe wichtiger Klas-
sen sowie der Layoutmanager an. Als Letztes wird die Ereignisverarbeitung dargestellt.
Die Beschreibung von SWT erhebt hierbei nicht den Anspruch der Vollständigkeit. Viel-
mehr beschränken wir uns im Wesentlichen auf die Bereiche, die zum Verständnis des Ar-
beitens mit den Designern erforderlich sind.
6.1 Allgemeines
Die beiden im Folgenden vorgestellten GUI-Designer funktionieren nach dem gleichen
Prinzip. Eine Komponente wird dem GUI hinzugefügt, indem der Benutzer die gewünschte
Komponente mit der Maus in einer Liste anwählt und dann ebenfalls mithilfe der Maus in
einer baumartigen Darstellung des GUI oder in einer WYSIWYG-Darstellung an der ge-
wünschten Position platziert. Die Eigenschaften einer Komponente müssen ebenfalls nicht
im Quelltext eingegeben werden. Stattdessen steht ein Fenster zur Verfügung, in dem je-
weils die Eigenschaften einer Komponente eingestellt werden können. Des Weiteren unter-
stützen die GUI-Designer verschiedene Layoutmanager. Hinsichtlich der Ereignisverarbei-
tung wird der Benutzer insoweit unterstützt, als er für eine Komponente aus einer Liste von
175
eclipse_v01.book Seite 176 Montag, 30. Januar 2006 12:02 12
Ereignissen das gewünschte auswählen kann. Im Quelltext werden daraufhin das zuge-
hörige Interface sowie die zugehörige Methodendeklaration implementiert. Die weitere Im-
plementation muss dann durch den Benutzer im Quelltext vorgenommen werden.
Weiterhin ist bei beiden Designern jederzeit eine Synchronisation zwischen dem Quelltext
und den verschiedenen Sichten bzw. Fenstern der Designer möglich. Das heißt, Änderun-
gen, die in einer Sicht eines Designers gemacht werden, wie z.B. das Hinzufügen einer neu-
en Komponente oder das Ändern einer Eigenschaft, werden sofort im Quelltext angezeigt.
Umgekehrt werden aber auch Änderungen, die statt in einer Sicht direkt im Quelltext vor-
genommen werden und die die grafische Darstellung betreffen, in den Sichten des De-
signers angezeigt. Beim Visual Editor kann darüber hinaus die Synchronisation unterbro-
chen – in diesem Fall sind nur noch Änderungen im Quelltext möglich – und bei Bedarf
wieder gestartet werden. Ferner lässt sich die Zeitspanne zwischen Änderung und Synchro-
nisation variieren. Voreingestellt ist hier 1 sec.
Beide Designer verfügen
쐌 über eine Sicht, welche das GUI in einer baumartigen Struktur anzeigt,
쐌 über eine Sicht, welche das GUI in einer Art WYSIWYG-Darstellung anzeigt, und
쐌 über eine Sicht, welche die Eigenschaften einer angewählten Komponente anzeigt.
Des Weiteren erzeugen beide Designer eine Java-Quelltextdatei und keine weiteren Datei-
en. Dieses hat den Vorteil, dass bereits anderweitig erstellte Java-Quelltextdateien mit ei-
nem Designer weiterbearbeitet werden können.
176
eclipse_v01.book Seite 177 Montag, 30. Januar 2006 12:02 12
Eclipse-Verzeichnis entpackt werden. Auch hier sind die in der zip-Datei gespeicherten
Pfadangaben zu verwenden.
Bevor wir eine oder mehrere Klassen eines GUI mit dem Visual Editor (VE) implementie-
ren können, müssen wir zunächst ein Java-Projekt erstellen. Um dann anschließend eine
neue Klasse mit dem Visual Editor programmieren zu können, rufen wir FILE | NEW | OTHER
auf. Im daraufhin erscheinenden Fenster wählen wir unter WIZARDS den Eintrag VISUAL
CLASS. Ist dieser nicht sichtbar, müssen wir zuvor auf das +-Zeichen vor JAVA klicken. Nach
dem Klicken auf NEXT benennen wir im nächsten Fenster unsere neue Klasse und wählen
unter STYLE diejenige Klasse, die unsere Klasse erweitern soll. Diese wird daraufhin unter
SUPERCLASS angezeigt. Alternativ können wir die Superklasse auch direkt unter SUPERCLASS
angeben.
Existiert in einem Projekt bereits eine Klasse, so lässt sie sich im Visual Editor öffnen, in-
dem sie im Package Explorer angewählt wird und anschließend im Kontextmenü über OPEN
WITH | VISUAL EDITOR geöffnet wird.
Der Visual Editor besitzt keine eigene Perspektive, sondern wird, wie die Abb. 6.1 zeigt, in
die Java-Perspektive integriert. Statt des Java Editor-Fensters wird das Visual Editor-Fens-
ter angezeigt. Dieses besteht aus einer Design View, einer Source View und der aufklapp-
baren Palette mit den Komponenten. Design View und Source View sind standardmäßig in
177
eclipse_v01.book Seite 178 Montag, 30. Januar 2006 12:02 12
der linken Fensterhälfte des Visual Editor-Fensters untereinander angeordnet. Die Palette
findet sich am rechten Fensterrand. Über WINDOW | PREFERENCES | JAVA | VISUAL EDITOR | AP-
PEARANCE | ON SEPARATE NOTEBOOK TABS können wir dafür sorgen, dass die Design View und
die Source View für eine Klasse auf separaten Registerkarten angeordnet werden, wobei die
Palette in diesem Fall nur bei der Design View angezeigt wird. Es sei noch einmal darauf
hingewiesen, dass die Änderung der Einstellung für bereits im Visual Editor-Fenster ange-
zeigte Klassen erst wirksam wird, wenn die Klassen im Visual Editor geschlossen und dann
wieder geöffnet werden.
Weiterhin wird die Java-Perspektive standardmäßig beim Öffnen des Visual Editors um
zwei weitere Sichten ergänzt, und zwar um die Java Beans View und die Properties View.
Die Java Beans View zeigt die Komponenten der gewählten Klasse als Baum. In der Pro-
perties View werden die Werte für die Eigenschaften einer in der Java Beans View oder De-
sign View angewählten Komponente angezeigt.
178
eclipse_v01.book Seite 179 Montag, 30. Januar 2006 12:02 12
Ist unter WINDOW | PREFERENCES | JAVA | VISUAL EDITOR | APPEARANCE die Option PROMPT FOR
BEAN NAME DURING CREATION aktiviert, erscheint sowohl in der Design View als auch in der
Java Beans View nach dem abschließenden Klick ein Fenster, das uns die Möglichkeit gibt,
den vom Visual Editor automatisch erzeugten Namensvorschlag zu ändern.
Wurde eine Komponente an der falschen Stelle eingefügt, kann sie entweder im Baum der
Java Beans View oder aber in der Design View verschoben werden. Beim Verschieben im
Baum der Java Beans View zeigt wiederum eine dicke horizontale Linie jeweils an, wo die
Komponente nach dem Loslassen der linken Maustaste eingefügt werden würde.
179
eclipse_v01.book Seite 180 Montag, 30. Januar 2006 12:02 12
6.2.5 Layouteinstellungen
Der Visual Editor stellt sowohl für AWT- und Swing-Container als auch für SWT-Container
verschiedene Layoutmanager zur Verfügung.
Die Auswahl eines Layoutmanagers erfolgt dadurch, dass wir den gewünschten Container
entweder in der Design View oder in der Java Beans View anklicken und anschließend in
der Properties View unter der Eigenschaft LAYOUT in der Spalte VALUE den Layoutmanager
wählen. Wenn wir anschließend auf das +-Zeichen vor der Eigenschaft LAYOUT klicken,
werden zusätzlich die allgemeinen Einstellungsmöglichkeiten für das gewählte Layout an-
gezeigt, wie z.B. die Anzahl der Spalten im Falle des GridLayouts, so dass jetzt direkt in der
Properties View Veränderungen der Einstellungen vorgenommen werden können. Für eine
Reihe von Layoutmanagern besteht darüber hinaus alternativ die Möglichkeit, voraus-
gesetzt der gewünschte Container ist angewählt, im Kontextmenü den Befehl CUSTOMIZE
LAYOUT oder in der Werkzeugleiste das Symbol anzuklicken und im daraufhin erschei-
nenden Customize Layout-Fenster im Register LAYOUT die Einstellungen vorzunehmen.
Die bei einigen Layoutmanagern möglichen individuellen Einstellungen für jede Kompo-
nente können wiederum entweder über die Properties View oder z.T. auch über das Cus-
tomize Layout-Fenster vorgenommen werden. Voraussetzung ist hier, dass die gewünschte
Komponente zuvor in der Design View oder in der Java Beans View angewählt worden ist.
Eine detailliertere Beschreibung hierzu findet sich in den Abschnitten 6.3.2 und 6.5.2.
Alternativ können wir den Layoutmanager aber auch auf null setzen, so dass Position und
Größe für jede Komponente explizit angegeben werden müssen. In diesem Fall stellt der
Visual Editor eine Reihe von Hilfen bereit. Wenn wir beispielsweise eine Komponente in
der Palette angewählt haben und anschließend den Mauscursor zum Hinzufügen in die De-
sign View bewegen, erscheint am Mauscursor eine gelbe Infobox, die die aktuelle Position
in Pixel angibt. Wenn wir, statt sofort zu klicken, bei gedrückt gehaltener linker Maustaste
einen Rahmen in der für die Komponente gewünschten Größe aufspannen, können wir hier-
180
eclipse_v01.book Seite 181 Montag, 30. Januar 2006 12:02 12
bei auch gleich die gewünschte Größe der Komponente einstellen. Weiterhin kann die Grö-
ße und Position einer bereits eingefügten Komponente, wie bereits in Abschnitt 6.2.4 be-
schrieben, mithilfe der Maus direkt in der Design View geändert werden. Wurden mehrere
Komponenten markiert, können diese mithilfe der Symbole im Register COMPONENT des
Customize Layout-Fensters zueinander ausgerichtet werden.
Haben wir zunächst einen Layoutmanager benutzt und entscheiden uns anschließend, den
Layoutmanager auf null zu setzen, so werden für die bisher eingefügten Komponenten als
Einstellungen für die Größe und Position die bisher durch den Layoutmanager definierten
Werte realisiert.
Hinsichtlich des Hinzufügens von Komponenten bei Wahl eines Layoutmanagers soll noch
darauf hingewiesen werden, dass in diesem Fall eine Komponente nicht immer an jeder be-
liebigen Stelle platziert werden kann. Der Visual Editor unterstützt den Benutzer insofern,
als dass am Mauscursor ein +-Zeichen erscheint, wenn eine Komponente an der aktuellen
Mausposition eingefügt werden kann.
6.2.6 Ereignisverarbeitung
Um für eine Komponente eine Ereignisverarbeitung zu implementieren, müssen wir die
Komponente zunächst in der Java Beans View oder der Design View anklicken. Anschlie-
ßend wählen wir im Kontextmenü den Befehl EVENTS. Es öffnet sich ein Menü, das Ereig-
nisse anzeigt, die besonders häufig für die gewählte Komponente vorkommen. Aufgeführt
wird hierbei der Name der für das Ereignis zuständigen Methode im entsprechenden Inter-
face bzw. der Adapterklasse. Über den Befehl ADD EVENTS, der sich ebenfalls im Menü be-
findet, kann aber auch ein Fenster geöffnet werden, in dem alle Ereignistypen mit ihren
möglichen Ereignissen aufgeführt sind. Wird ein Ereignis angewählt, wird automatisch
rechts im Fenster CREATE NEW LISTENER aktiviert, sofern nicht bereits ein Listener imple-
mentiert worden ist. Existiert für den Listener eine Adapterklasse, können wir außerdem
wählen, ob die Adapterklasse oder das Interface implementiert werden soll. Für den Fall,
181
eclipse_v01.book Seite 182 Montag, 30. Januar 2006 12:02 12
dass bereits ein Listener vorhanden ist, ist zu beachten, dass dieser vom Visual Editor nur
erkannt wird, wenn er als anonyme Klasse implementiert worden ist.
Nach dem Hinzufügen des Ereignisses wird dieses in der Java Beans View angezeigt, vor-
ausgesetzt, die Anzeige wurde aktiviert. Hierzu befindet sich in der Titelleiste der Java
Beans View das Symbol . Wird es angeklickt, erscheinen drei mögliche Optionen: NO
EVENTS, SHOW EVENTS, EXPERT EVENTS. Während bei Wahl von SHOW EVENTS nur die zu ei-
nem Ereignis zugehörige Methode angezeigt wird, erscheint bei Wahl von EXPERT EVENTS
auch der implementierte Listener. Wurde der Listener als anonyme Klasse implementiert,
verdeutlicht die Farbe des Symbols vor dem Listener die Art der Implementation: lila
– Interface, grün – Adapterklasse. Bei einer Implementation als benannte innere Klasse da-
gegen erscheint in beiden Fällen vor dem Listener das Symbol .
Abb. 6.4: Ereignisse in der Java Beans View bei Wahl der Option Expert Events
Das Entfernen eines implementierten Ereignisses ist sehr einfach dadurch möglich, dass
wir den entsprechenden Eintrag in der Java Beans View anklicken und anschließend das Er-
eignis mit der ¢-Taste löschen.
182
eclipse_v01.book Seite 183 Montag, 30. Januar 2006 12:02 12
6.3.2 Layoutmanager
Der Visual Editor stellt für AWT- und Swing-Container die sechs Layoutmanager Border-
Layout, BoxLayout, CardLayout, FlowLayout, GridBagLayout und GridLayout zur Verfü-
gung.
Neben der Möglichkeit, alle allgemeinen und individuellen Einstellungen für ein Layout in
der Properties View vornehmen zu können (allgemeine Einstellungen: Eigenschaft LAYOUT,
individuelle Einstellungen: Eigenschaft CONSTRAINT), können die allgemeinen Einstellun-
gen für das GridLayout auch über das Register LAYOUT im Customize Layout-Fenster (an-
wählbar über das Kontextmenü oder den Button in der Werkzeugleiste) realisiert werden.
Die bei Wahl des GridBagLayouts möglichen individuellen Einstellungen für jede dem
Container hinzugefügte Komponente können ebenfalls alternativ über die Properties View
oder das Customize Layout-Fenster vorgenommen werden. In diesem Fall ist das Register
COMPONENT zu wählen. Es sei noch einmal darauf hingewiesen, dass die Komponente zuvor
in der Design View oder der Java Beans View angewählt worden sein muss.
183
eclipse_v01.book Seite 184 Montag, 30. Januar 2006 12:02 12
Hinsichtlich des Hinzufügens von Komponenten wird der Benutzer beim BoxLayout,
FlowLayout und GridLayout insofern zusätzlich unterstützt, als dass in der Design View an
der dem Mauscursor nächst gelegenen möglichen Einfügeposition eine dicke Linie er-
scheint. Beim BorderLayout erscheint nicht nur das +-Zeichen am Mauscursor, wenn eine
Komponente an einer gewählten Position eingefügt werden kann, sondern es wird zusätz-
lich der aktuelle Bereich markiert und benannt (North, West, Center, East, South). Beim
GridBagLayout werden noch die Zeile und die Spalte des Gitternetzes am Mauscursor ein-
geblendet, wobei die Zählung bei 0 beginnt. Des Weiteren kann eine Komponente beim
GridBagLayout sehr leicht mithilfe der Maus in einer neuen Zeile oder Spalte platziert wer-
den. Wir müssen hierzu nur mit der Maus in der Zeile auf die vertikale Gitternetzlinie ge-
hen, wo die neue Komponente links in einer neuen Spalte eingefügt werden soll, bzw. in der
Spalte auf die horizontale Gitternetzlinie, wo die neue Komponente oberhalb in einer neuen
Zeile eingefügt werden soll.
6.3.3 Codegenerierung
Erstellt der Benutzer eine neue Klasse mit dem VE New Class Wizard, so wird automatisch
ein Quelltext generiert. Dieser enthält die Deklaration einer neuen Klasse, die die im VE
New Class Wizard gewählte Superklasse erweitert. Des Weiteren wird die Superklasse
automatisch in der neuen Klasse importiert.
import javax.swing.JFrame;
public class Fenster extends JFrame {
Weiterhin enthält der generierte Quelltext den Standardkonstruktor, der den Konstruktor
der Superklasse und eine Methode initialize aufruft.
public Fenster {
super();
initialize();
}
184
eclipse_v01.book Seite 185 Montag, 30. Januar 2006 12:02 12
Erweitert die neue Klasse beispielsweise die Klasse JFrame oder JInternalFrame, wird
automatisch eine ContentPane dem Fenster hinzugefügt. Diese wird als Attribut der Klasse
deklariert und mit null initialisiert.
Des Weiteren wird eine Getter-Methode implementiert, die die ContentPane als Objekt der
Klasse JPanel erzeugt und mit dem BorderLayout versieht. Die Klasse JPanel und die
Klasse BorderLayout werden ebenfalls automatisch importiert.
In der Methode initialize werden die ContentPane und die Eigenschaften der Klasse
gesetzt, wie z.B. die Größe und der Titel des Fensters bei einer Klasse, die die Klasse
JFrame erweitert. Anfänglich umfasst die Methode initialize nur den folgenden Quell-
text:
Fügt der Benutzer dem GUI Komponenten hinzu, werden diese als Attribute der Klasse mit
dem Zugriffsrecht private deklariert und mit null initialisiert. Hierbei werden die Klas-
sen der GUI-Komponenten automatisch importiert, so dass sie nicht mit ihrem vollständi-
gen Namen angesprochen werden müssen.
Mit Ausnahme der Komponenten Label und JLabel wird für jede Komponente, die einer
anderen Komponente hinzugefügt wird, automatisch eine Getter-Methode implementiert,
die nicht nur einen Wert zurückliefert, sondern, falls für eine Komponente noch kein Objekt
existiert, dieses erzeugt. Die Getter-Methoden besitzen das Zugriffsrecht private. Des
Weiteren finden sich Änderungen, die in der Properties View an Eigenschaften einer Kom-
ponente vorgenommen werden und dazu führen, dass Eigenschaften von der Voreinstellung
abweichende Werte erhalten, als Anweisungen in den Getter-Methoden wieder.
185
eclipse_v01.book Seite 186 Montag, 30. Januar 2006 12:02 12
Die Komponenten Label und JLabel dagegen werden direkt in derjenigen Komponente
erzeugt, der sie hinzugefügt werden. Weiterhin wird automatisch eine Beschriftung des
Labels implementiert.
Komponenten, die direkt auf der ContentPane platziert werden, werden in der Methode
getJContentPane dem GUI hinzugefügt.
Das Hinzufügen einer Komponente zu einer anderen Komponente erfolgt in der Getter-Me-
thode der anderen Komponente.
Wird im Visual Editor einer Komponente ein Ereignis hinzugefügt, wird die für das Ereig-
nis zuständige Methode sowie, falls der Listener für das Ereignis noch nicht vorhanden ist,
dieser ebenfalls im Quelltext implementiert und der Komponente hinzugefügt. Die Reali-
sierung des Listener erfolgt als anonyme Klasse. Die für das Ereignis relevante Methode
enthält eine println-Anweisung sowie einen TODO-Kommentar. In der Source View
wird automatisch der Ausschnitt mit der Listener-Implementation angezeigt und die Zeile,
186
eclipse_v01.book Seite 187 Montag, 30. Januar 2006 12:02 12
die die Methodendeklaration beinhaltet, wird farblich hervorgehoben. Wie bereits in Ab-
schnitt 6.2.6 erwähnt, können wir für die Listener-Implementation zwischen Interface und
Adapterklasse wählen. Wenn wir uns für das Interface entscheiden, werden neben der
Methode für das ausgewählte Ereignis noch die Methoden für die weiteren Ereignisse des
Ereignistyps implementiert, und zwar in diesem Fall mit leerem Methodenrumpf.
6.3.4 Beispiel
Im Folgenden soll zunächst anhand eines Swing-Beispiels der Einsatz des Visual Editors
demonstriert werden. In Abschnitt 6.5.4 findet sich darüber hinaus ein kleineres SWT-Bei-
spiel.
Abb. 6.8: Internal Frames zur Dateneingabe und für die tabellarische Übersicht
Im Menü EINSTELLUNGEN kann ein Internal Frame zum Verändern der Fenstergröße und der
Hintergrundfarbe des Hauptfensters geöffnet werden. Ein weiteres zu öffnendes Internal
Frame weist zwei Register auf: ein Register, um über einen Schieberegler die Schriftgröße
der Beschriftungen im Eingabefenster zu verändern, und ein zweites Register, um die Ta-
belle mit oder ohne Gitternetzlinien darzustellen.
187
eclipse_v01.book Seite 188 Montag, 30. Januar 2006 12:02 12
Abb. 6.9: Internal Frames für Einstellungen des Hauptfensters und der Internal Frames
Der Einfachheit halber wird bei der Implementation nicht berücksichtigt, dass das Internal
Frame für die Einstellungen zur Ansicht erst aufgerufen werden darf, wenn bereits die ent-
sprechenden Internal Frames aus dem Menü ANSICHT aufgerufen worden sind. Des Weite-
ren sind die Änderungen nur bei einem geöffneten Internal Frame bis zum nächsten Schlie-
ßen wirksam.
package daten;
188
eclipse_v01.book Seite 189 Montag, 30. Januar 2006 12:02 12
189
eclipse_v01.book Seite 190 Montag, 30. Januar 2006 12:02 12
Abb. 6.10: Die Java Beans View für die Klasse HauptFenster
Da ausgehend vom Hauptfenster mehrere Internal Frames erzeugt werden sollen, müssen
wir die ContentPane in der Java Beans View löschen und stattdessen aus der Kategorie
SWING CONTAINERS die Komponente JDesktopPane dem Fenster hinzufügen. Um das Haupt-
fenster auch angezeigt zu bekommen, gehen wir weiterhin in die Source View und erzeugen
dort in der main-Methode ein Objekt der Klasse HauptFenster.
package gui;
import java.awt.BorderLayout;
import javax.swing.*;
190
eclipse_v01.book Seite 191 Montag, 30. Januar 2006 12:02 12
191
eclipse_v01.book Seite 192 Montag, 30. Januar 2006 12:02 12
Bevor wir jetzt die Klassen für die Internal Frames implementieren, sorgen wir noch dafür,
dass die Anwendung beendet werden kann, und zwar zum einen über das Systemmenü und
zum anderen über den Menübefehl DATEI | BEENDEN.
Für das Beenden über das Systemmenü müssen wir das Fenster in der Java Beans View oder
Design View anklicken, den Befehl EVENTS aus dem Kontextmenü wählen und anschlie-
ßend den Eintrag WINDOWCLOSING. Im Quelltext wird daraufhin die Adapterklasse Window-
Adapter als anonyme Klasse implementiert und dem Fenster hinzugefügt. Wir müssen
jetzt lediglich in der Source View die automatisch generierte println-Anweisung löschen
und stattdessen die Anweisung System.exit(0) eingeben.
192
eclipse_v01.book Seite 193 Montag, 30. Januar 2006 12:02 12
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
Für das Beenden über DATEI | BEENDEN muss für den Menübefehl im Kontextmenü unter
EVENTS der Eintrag ACTIONPERFORMED gewählt werden. Hierdurch wird ein ActionListener
als anonyme Klasse implementiert und dem Menübefehl hinzugefügt.
jMenuItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
System.exit(0);
}
});
package gui;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JInternalFrame;
193
eclipse_v01.book Seite 194 Montag, 30. Januar 2006 12:02 12
jContentPane.setLayout(new BorderLayout());
}
return jContentPane;
}
}
In der Properties View nehmen wir anschließend für das Internal Frame eine Reihe von Ver-
änderungen vor. Das >-Zeichen vor einer Eigenschaft zeigt, dass diese Eigenschaft geän-
dert worden ist.
194
eclipse_v01.book Seite 195 Montag, 30. Januar 2006 12:02 12
Anschließend wählen wir die ContentPane an und wählen in der Properties View unter der
Eigenschaft layout das GridLayout aus. Nachdem wir dann auf das +-Zeichen vor lay-
out geklickt und damit die Eigenschaft layout erweitert haben, geben wir unter columns
2 und unter rows 3 an. Als horizontalen und vertikalen Abstand wählen wir jeweils 50.
Alternativ hätten wir auch über den Befehl CUSTOMIZE LAYOUT im Kontextmenü oder den
Button in der Werkzeugleiste das Customize Layout-Fenster öffnen und dort im Register
LAYOUT die Einstellungen vornehmen können.
Jetzt können der ContentPane die einzelnen Dialogelemente hinzugefügt werden. Wir be-
ginnen mit einem ersten Label. Hierzu wählen wir in der Palette in der Kategorie Swing
Components JLabel an und klicken entweder in der Java Beans View oder in der Design
View auf die ContentPane. Als Nächstes folgt ein Textfeld. Um die richtige Position des
Textfelds rechts neben dem ersten Label zu erhalten, erfolgt das Hinzufügen hier am besten,
indem wir das gewünschte Dialogelement in der Palette anklicken und anschließend in der
Java Beans View die Maus kurz unterhalb des Labels platzieren. Es erscheint dort dann ein
waagerechter Strich. Ein Klicken fügt das Textfeld ein. In der Design View erscheint das
Textfeld zunächst unterhalb des Labels. Erst wenn mehr Dialogelemente eingefügt worden
sind, als Zeilen zur Verfügung stehen, wird zur gewünschten zweispaltigen Darstellung ge-
wechselt.
Analog fügen wir nacheinander noch ein weiteres Label, ein weiteres Textfeld und zwei
Buttons ein. Für die Label stellen wir in der Properties View unter text als Beschriftung
KUNDENNUMMER und KUNDENNAME ein, für die Buttons ÜBERNEHMEN und SCHLIESSEN. Alter-
nativ hätten wir, nachdem wir die Komponente in der Design View angeklickt haben, noch
ein weiteres Mal klicken und dann den Text in dem daraufhin erscheinenden Eingabefeld
eingeben können.
Für jedes Dialogelement wird beim Hinzufügen automatisch die entsprechende Klasse im-
portiert und das Dialogelement selbst als Attribut deklariert und mit null initialisiert.
Des Weiteren erfolgt in der Getter-Methode für die ContentPane das Hinzufügen der Dia-
logelemente und für die Label auch das Erzeugen.
195
eclipse_v01.book Seite 196 Montag, 30. Januar 2006 12:02 12
Für die Textfelder und Buttons werden die Dialogelement-Objekte in Getter-Methoden er-
zeugt, welche dem Quelltext ebenfalls automatisch hinzugefügt werden. Der folgende
Quelltext enthält die Implementation für den ersten Button. Für die weiteren Dialogelemen-
te wird ein analoger Quelltext generiert, wobei für die beiden Textfelder der Aufruf der Me-
thode setText nicht erforderlich ist.
Jetzt fehlt in der Klasse IFEingabe noch die Ereignisverarbeitung. Wird auf den ÜBERNEH-
MEN-Button geklickt, sollen die in den beiden Textfeldern eingegebenen Werte gespeichert
werden und die beiden Textfelder geleert werden. Wir wählen zunächst den Button an, dann
im Kontextmenü EVENTS und anschließend ACTIONPERFORMED. Im Quelltext erzeugen wir
ein neues Datensatzobjekt, welches wir mit den Werten aus den Textfeldern initialisieren.
Da sich die Klasse Daten in einem anderen Package befindet, müssen wir den vollständi-
gen Klassennamen angeben oder alternativ die Klasse importieren. Das Datensatzobjekt fü-
gen wir anschließend einer Liste daten hinzu. In der Liste daten werden alle eingegebe-
nen Datensätze gespeichert.
196
eclipse_v01.book Seite 197 Montag, 30. Januar 2006 12:02 12
Damit auch das Internal Frame, welches die Daten in einer tabellarischen Übersicht aus-
gibt, auf die Daten zugreifen kann, wird die Liste daten als Attribut des Hauptfensters de-
finiert. Hierzu wird in der Klasse HauptFenster das Attribut daten als vom Typ ja-
va.util.LinkedList deklariert und mit null initialisiert, in der Methode initialize
das Objekt erzeugt und die Zugriffsmethoden über SOURCE | GENERATE GETTERS AND SETTERS
generiert.
Die Definition der Liste als Attribut der Klasse HauptFenster macht es erforderlich, dass
in der Klasse IFEingabe auf das Hauptfenster zugegriffen werden kann. Hierzu muss das
Hauptfenster als Attribut der Klasse IFEingabe definiert werden.
Weiterhin kopieren wir im Quelltext den Standardkonstruktor und ändern die Kopie, indem
wir als Parameter das Hauptfenster übergeben.
Als Letztes dürfen wir nicht vergessen, in der Methode actionPerformed die Textfelder
zu leeren. Die Implementation des Listeners sieht dann wie folgt aus:
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
daten.Daten datSatz = new daten.Daten(jTextField.getText(),
jTextField1.getText());
parent.getDaten().add(datSatz); // Hinzufügen zur Liste
jTextField.setText(""); // Textfeld leeren
jTextField1.setText(""); // Textfeld leeren
}
});
197
eclipse_v01.book Seite 198 Montag, 30. Januar 2006 12:02 12
Die Implementation des SCHLIESSEN-Buttons ist weniger aufwändig. Das Internal Frame soll
geschlossen werden, wenn auf den SCHLIESSEN-Button geklickt wird. Hierzu wird dem
SCHLIESSEN-Button das Ereignis hinzugefügt und innerhalb der Methode actionPerformed
die Methode dispose für das Internal Frame aufgerufen. Da innerhalb der anonymen Klasse
nicht direkt auf die Referenz des Internal Frame zugegriffen werden kann, wird vor der Imple-
mentation der anonymen Klasse eine Konstante definiert, die eine Referenz auf das Internal
Frame enthält.
Nachdem die Klasse IFEingabe implementiert worden ist, kann für den Menübefehl AN-
SICHT | EINGABE im Hauptfenster die Ereignisverarbeitung realisiert werden. Da wir später
noch von einer anderen Klasse aus auf das Internal Frame zugreifen wollen, wird es als
Attribut des Hauptfensters deklariert.
In der Methode actionPerformed wird dann das Objekt iFEingabe erzeugt und mithil-
fe der Methode add der DesktopPane des Hauptfensters hinzugefügt. Da beim Aufruf des
Konstruktors in der anonymen Klasse das Hauptfenster als Parameter übergeben wird, müs-
sen wir noch vor der Implementation des Listener eine Konstante definieren, die eine Re-
ferenz auf das Hauptfenster enthält.
198
eclipse_v01.book Seite 199 Montag, 30. Januar 2006 12:02 12
Anschließend wählen wir auch hier in der Properties View für die ContentPane das Grid-
Layout. Als Spaltenanzahl geben wir 1 und als Zeilenanzahl 2 ein. Der horizontale und ver-
tikale Abstand soll jeweils 50 betragen. Anschließend wird eine scrollbare Tabelle der Con-
tentPane hinzugefügt. Hierzu wird in der Palette in der Kategorie Swing Components die
Komponente JTable on JScrollPane gewählt.
199
eclipse_v01.book Seite 200 Montag, 30. Januar 2006 12:02 12
Um die bereits eingegebenen Daten in der Tabelle anzuzeigen, wird eine Methode
getTableModel implementiert, die ein Objekt der Klasse DefaultTableModel zurück-
liefert. Das Objekt wird in der Methode erzeugt und mit den Daten aus der Liste daten ini-
tialisiert. Da auch hierbei, genau wie bei der Klasse IFEingabe, auf das Hauptfenster zu-
gegriffen werden muss, müssen wir ebenfalls einen zweiten Konstruktor implementieren
und das Hauptfenster als Attribut der Klasse IFTabelle definieren.
In der Methode getJTable muss nun nur noch nach dem Erzeugen des Objekts jTable
das Modell gesetzt werden:
jTable.setModel(getTableModel());
Als zweites Dialogelement fügen wir der ContentPane jetzt noch einen Button hinzu. Der
Button soll unterhalb der Tabelle platziert werden und die Beschriftung AKTUALISIEREN auf-
weisen. Wird auf den Button geklickt, sollen alle bisher eingegebenen Daten angezeigt
werden. Hierzu wählen wir für den Button im Kontextmenü wiederum den Befehl EVENTS
und anschließend ACTIONPERFORMED. Im Quelltext muss dann in der actionPerformed-
Methode die Anweisung
jTable.setModel(getTableModel());
implementiert werden.
Die Ereignisverarbeitung für den Menübefehl ANSICHT | TABELLE kann jetzt analog zum
Menübefehl ANSICHT | EINGABE realisiert werden.
200
eclipse_v01.book Seite 201 Montag, 30. Januar 2006 12:02 12
Als Layout für die ContentPane wählen wir wiederum GridLayout. Die Anzahl der Zeilen
und Spalten ist jeweils 2, der horizontale und vertikale Abstand 50. Als Nächstes werden
die Komponenten der ContentPane hinzugefügt, und zwar zunächst ein Label, dann eine
Combobox – diese findet sich in der Palette in der Kategorie Swing Components –, danach
wieder ein Label und anschließend die Komponente JScrollPane aus der Kategorie Swing
Containers. In die ScrollPane wird als Letztes noch eine Liste eingefügt. Die richtige An-
ordnung lässt sich auch hier am einfachsten erreichen, indem die jeweilige Komponente in
der Palette angewählt wird und anschließend in der Java Beans View an die entsprechende
Stelle geklickt wird. Dem ersten Label geben wir entweder in der Properties View unter der
Eigenschaft text, oder indem wir in der Design View das Texteingabefeld aktivieren, die
Beschriftung FENSTERGRÖSSE, dem zweiten Label die Beschriftung HINTERGRUNDFARBE. Die
Einträge für die Combobox und die Liste müssen direkt im Quelltext implementiert wer-
den. Bei der Combobox werden die einzelnen Einträge mithilfe der Methode addItem dem
201
eclipse_v01.book Seite 202 Montag, 30. Januar 2006 12:02 12
JComboBox-Objekt hinzugefügt. Bei der Liste werden die einzelnen Einträge zunächst in
einem Feld gespeichert und dann wird das Feld mithilfe der Methode setListData dem
JList-Objekt bekannt gemacht.
Um für die Combobox das Ereignis „Klick auf einen Eintrag“ zu implementieren, wählen
wir im Kontextmenü wiederum den Befehl EVENTS und anschließend ACTIONPERFORMED. Im
Quelltext müssen wir dann das Setzen der Fenstergröße wie folgt implementieren:
jComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
String item = (String)jComboBox.getSelectedItem();
if (item.equals("600x400")) parent.setSize(600,400);
else if (item.equals("750x500")) parent.setSize(750,500);
else if (item.equals("900x600")) parent.setSize(900,600);
}
});
Während bei der Anwahl eines Ereignisses in der Combobox ein ActionEvent ausgelöst
wird, wird bei der Anwahl eines Ereignisses in der Liste ein ListSelectionEvent ausgelöst.
Auch hier können wir wieder das Ereignis über den Befehl EVENTS im Kontextmenü dem
Quelltext hinzufügen. Allerdings muss hier anschließend der Befehl VALUECHANGED ge-
wählt werden, um die Methode valueChanged zu erhalten, in der wir die folgenden An-
weisungen zur Änderung der Hintergrundfarbe implementieren.
202
eclipse_v01.book Seite 203 Montag, 30. Januar 2006 12:02 12
jList.addListSelectionListener(
new javax.swing.event.ListSelectionListener() {
public void valueChanged(
javax.swing.event.ListSelectionEvent e) {
int[] items = jList.getSelectedIndices();
switch (items[0]) {
case 0: parent.getJDesktopPane().
setBackground(java.awt.Color.gray);
break;
case 1: parent.getJDesktopPane().
setBackground(java.awt.Color.blue);
break;
case 2: parent.getJDesktopPane().
setBackground(java.awt.Color.white);
break;
case 3: parent.getJDesktopPane().
setBackground(java.awt.Color.red);
break;
case 4: parent.getJDesktopPane().
setBackground(java.awt.Color.green);
break;
case 5: parent.getJDesktopPane().
setBackground(java.awt.Color.yellow);
break;
}
}
});
Da wir hier auf die Methode getJDesktopPane zugreifen müssen, um die Hintergrund-
farbe für das Hauptfenster zu ändern, und diese bisher als private in der Klasse Haupt-
Fenster deklariert ist, müssen wir das Zugriffsrecht noch erweitern. Wir wählen hier
public, damit auch Klassen anderer Packages auf die DesktopPane zugreifen können.
Die Ereignisverarbeitung für den Menübefehl ANSICHT | ALLGEMEIN im Hauptfenster kann
jetzt wieder analog zu den bereits implementierten Befehlen realisiert werden.
203
eclipse_v01.book Seite 204 Montag, 30. Januar 2006 12:02 12
Nachdem wir in der Properties View die in der Abb. 6.14 dargestellten Eigenschaften ein-
gestellt haben, fügen wir der ContentPane die Komponente JTabbedPane aus der Kategorie
Swing Containers hinzu. Die Register erhalten wir anschließend, indem wir der Tabbed-
Pane zwei Panels ebenfalls aus der Kategorie Swing Containers hinzufügen. Das erste
Panel erhält in der Properties View bei der Eigenschaft tab title als Beschriftung EIN-
GABE, das zweite Panel TABELLE. Das hierfür erforderliche Anwählen eines Panel erfolgt
hierbei in der Java Beans View. Jetzt wird für das erste Panel das GridLayout mit einer
Spalte und zwei Zeilen sowie einem horizontalen und vertikalen Abstand von 0 gewählt.
Danach werden dem Panel ein Label und die Komponente JSlider (Schieberegler) aus der
Kategorie Swing Components hinzugefügt. Für das Label geben wir als Beschriftung
SCHRIFTGRÖSSE ein. Für den Schieberegler wird unter den Eigenschaften majorTick-
Spacing und minorTickSpacing jeweils 2 eingestellt sowie unter der Eigenschaft
maximum 16 und minimum 8. Um eine Beschriftung zu erhalten, müssen wir des Weiteren
bei der Eigenschaft paintLabels true einstellen und für eine Unterteilung bei paint-
Ticks true. Unter value geben wir dann noch die aktuelle Schriftgröße für die Beschrif-
tungen in der Klasse IFEingabe an, nämlich 12.
private JSlider.getJSlider() {
if (jSlider == null) {
jSlider = new JSlider();
jSlider.setMajorTickSpacing(2);
jSlider.setMaximum(16);
jSlider.setMinimum(8);
jSlider.setPaintLabels(true);
jSlider.setPaintTicks(true);
204
eclipse_v01.book Seite 205 Montag, 30. Januar 2006 12:02 12
jSlider.setValue(12);
jSlider.setMinorTickSpacing(2);
}
Um bei einer Veränderung des Schiebereglers den neuen Wert zu erhalten, müssen wir ei-
nen ChangeListener mit dem Ereignis stateChanged über den Befehl EVENTS hinzufügen.
Mithilfe der folgenden Anweisungen, die wir anschließend im Quelltext implementieren,
können wir auf den Wert zugreifen und die Schriftgröße für die Label im Internal Frame zur
Dateneingabe ändern.
jSlider.addChangeListener(new javax.swing.event.ChangeListener()
{
public void stateChanged(javax.swing.event.ChangeEvent e) {
parent.getIFEingabe().getJLabel().setFont(
new java.awt.Font("Dialog",java.awt.Font.PLAIN,
jSlider.getValue()));
// analog für die restlichen Beschriftungen
}
});
Da die Methoden getJButton und getJButton1 vom Visual Editor in der Klasse
IFEingabe als private deklariert worden sind, müssen wir hier das Zugriffsrecht verän-
dern, z.B. auf public setzen, um der Klasse IFAnsicht den Zugriff zu gewährleisten.
Weiterhin ist über die Befehlsfolge SOURCE | GENERATE GETTERS AND SETTERS jeweils eine
Getter-Methode in der Klasse HauptFenster für das Attribut iFEingabe und in der
Klasse IFEingabe für die Attribute jLabel und jLabel1 zu erzeugen.
Für das zweite Panel wird zunächst in der Properties View unter layout GridLayout mit
einer Spalte, drei Zeilen und einem horizontalen und vertikalen Abstand von 0 eingetragen.
Dann werden dem Panel ein Label und zwei Radiobuttons aus der Kategorie Swing Com-
ponents hinzugefügt. Das Label erhält über die Eigenschaft text die Beschriftung TABELLE
und die Radiobuttons ebenfalls über die Eigenschaft text die Beschriftungen MIT GITTER-
NETZLINIEN und OHNE GITTERNETZLINIEN. Die Eigenschaft selected wird anschließend für
den ersten Radiobutton auf true gesetzt werden, damit dieser ausgewählt ist. Um bei einer
Änderung der Einstellung diese bei der Anzeige des Internal Frame auch zu verwirklichen,
wird beiden JRadioButton-Objekten jeweils ein ItemListener mit dem Ereignis item-
StateChanged hinzugefügt. Anschließend implementieren wir im Quelltext die erforder-
lichen Anweisungen. Zu beachten ist hier, dass für das Attribut iFTabelle der Klasse
HauptFenster noch die Getter-Methode implementiert werden muss sowie die Methode
getJTable z.B. das Zugriffsrecht public erhalten muss.
jRadioButton.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent e) {
if (jRadioButton.isSelected()) {
jRadioButton1.setSelected(false);
205
eclipse_v01.book Seite 206 Montag, 30. Januar 2006 12:02 12
Das SWT
parent.getIFTabelle().getJTable().setShowGrid(true);
}
}
}
org.eclipse.swt.*;
org.eclipse.swt.widgets.*;
Für die Anzeige von SWT-Komponenten auf dem Bildschirm müssen ein GUI-Prozess, der
das Verbindungsglied zwischen der Anwendung und dem Betriebssystem bildet, und ein
Fenster erzeugt werden. Für den GUI-Prozess steht die Klasse Display zur Verfügung. Ein
Fenster wird repräsentiert durch die Klasse Shell. Dem Shell-Objekt wird hierbei beim
Erzeugen im Konstruktor das Display-Objekt übergeben. Dadurch wird die Shell als
Hauptfenster der Anwendung festgelegt.
206
eclipse_v01.book Seite 207 Montag, 30. Januar 2006 12:02 12
Darüber hinaus kann optional ein Stilparameter angegeben werden, mit dem das Aussehen
und das Verhalten des Fensters gesteuert werden. Ein Stilparameter setzt sich aus einer oder
mehreren so genannten Stilkonstanten zusammen. Nähere Erläuterungen hierzu finden sich
im nächsten Abschnitt. Für eine Shell existieren u.a. die folgenden Stilkonstanten:
Stilkonstante Bedeutung
SWT.NONE Standardfenster
SWT.BORDER Fenster mit Rand
SWT.CLOSE Fenster mit Titelleiste und Schließen-Button
SWT.MIN Fenster mit Titelleiste und Minimalisieren-Button
SWT.MAX Fenster mit Titelleiste und Maximalisieren-Button
SWT.NO_TRIM Fenster ohne Titelleiste und Rand
SWT.RESIZE Fenstergröße kann durch Ziehen mit der Maus verändert werden
SWT.TITLE Fenster mit Titelleiste
SWT.SHELL_TRIM Kombination von Stilkonstanten für das Hauptfenster einer Applika-
tion (SWT.CLOSE, SWT.TITLE, SWT.MIN, SWT.MAX, SWT.RESIZE)
SWT.DIALOG_TRIM Kombination von Stilkonstanten für Dialogfenster (SWT.CLOSE,
SWT.TITLE, SWT.BORDER)
Wird kein Stilparameter angegeben, so wird eine Voreinstellung realisiert. Diese ist abhän-
gig vom Betriebssystem und von der Art der Shell (Hauptfenster oder Dialogfenster).
Innerhalb einer Anwendung lassen sich weitere Shells definieren. In diesem Fall ist beim
Konstruktoraufruf das übergeordnete Shell-Objekt anzugeben.
Nach dem Erzeugen der Shell können hierfür die Einstellungen vorgenommen werden, die
nicht über Stilkonstanten möglich sind, wie z.B. das Festlegen eines Titels für die Titelleiste
des Fensters. Des Weiteren können die SWT-Komponenten definiert und hierfür ebenfalls
die gewünschten Einstellungen erfolgen. Abschließend müssen wir die Shell mithilfe der
Methode open öffnen, eine Schleife für die Ereignisverarbeitung implementieren, die erst
beendet wird, wenn die Shell entfernt wird, und das Display-Objekt mit der Methode
dispose entfernen.
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
207
eclipse_v01.book Seite 208 Montag, 30. Januar 2006 12:02 12
Das SWT
6.4.2 SWT-Komponenten
Wird in einer Anwendung eine SWT-Komponente instanziiert, so erzeugt SWT die zuge-
hörige Komponente des Betriebssystems, sofern diese existiert. Da bei vielen Betriebssys-
temen beim Erzeugen eines GUI-Elements das übergeordnete GUI-Element angegeben
werden muss, ist dieses im SWT ebenfalls erforderlich. Das heißt, bei der Instanziierung ei-
ner SWT-Komponente muss im Konstruktor die übergeordnete Komponente angegeben
werden. Dadurch wird die Komponente der übergeordneten Komponente hinzugefügt. Eine
add-Methode wie im AWT oder in Swing muss deshalb nicht aufgerufen werden.
Soll für eine Eigenschaft die Voreinstellung realisiert werden, muss keine Stilkonstante an-
gegeben werden. Sollen für alle Stilkonstanten einer Komponente die Voreinstellungen gel-
ten, wird als Stilparameter lediglich die Stilkonstante SWT.NONE angegeben. Eine SWT-
Komponente verfügt über die in der zugehörigen Klasse definierten Stilkonstanten sowie
die aus Superklassen geerbten Stilkonstanten.
208
eclipse_v01.book Seite 209 Montag, 30. Januar 2006 12:02 12
Widget
• Caret
• Control
• Button
• Label
• ProgressBar
• Sash
• Scale
• Scrollable
• Composite
• Canvas
• Decorations
• Shell
• Combo
• CoolBar
• Group
• Spinner
• TabFolder
• Table
• ToolBar
• Tree
• List
• Text
• Slider
• Item
• CoolItem
• MenuItem
• TabItem
• TableColumn
• TableItem
• ToolItem
• TreeItem
• Menu
• ScrollBar
• Tracker
Abb. 6.15: Die Klasse Widget und ausgewählte Subklassen
209
eclipse_v01.book Seite 210 Montag, 30. Januar 2006 12:02 12
Das SWT
nicht mithilfe einer add-Methode hinzugefügt, sondern beim Erzeugen eines neuen Wid-
get-Objekts wird das Composite-Objekt als Parameter übergeben.
Einem Composite können nicht nur GUI-Elemente, wie Buttons, Labels etc., sondern auch
ein oder mehrere weitere Composites hinzugefügt werden, so dass sich die Hierarchie der
Composites und der weiteren GUI-Elemente als Baum darstellen lässt mit der Shell als
Wurzel.
Für die Klasse Composite hält das SWT die Stilkonstante SWT.NO_RADIO_GROUP bereit,
die verhindert, dass bei mehreren auf einem Composite angeordneten Radiobuttons nur ein
Radiobutton ausgewählt werden kann, sowie die Stilkonstanten SWT.NO_BACKGROUND,
SWT.NO_FOCUS, SWT.NO_MERGE_PAINTS, SWT.NO_REDRAW_RESIZE. Letztere sind al-
lerdings mit Ausnahme der Klasse Canvas für die Subklassen der Klasse Composite un-
definiert.
SWT.LEFT
SWT.RIGHT Ausrichtung für Text bzw. Grafik
SWT.CENTER
210
eclipse_v01.book Seite 211 Montag, 30. Januar 2006 12:02 12
SWT.SHADOW_IN
SWT.SHADOW_OUT Schattendarstellung der Linie im Fall eines Separators
SWT.SHADOW_NONE
Das Festlegen des Texts bei einem Textlabel erfolgt mithilfe der Methode setText, das
Festlegen des Bilds bei einem Bildlabel mithilfe der Methode setImage.
SWT.CHECK Checkbox
SWT.RADIO Optionsfeld
SWT.TOGGLE Umschaltfläche
Weiterhin existieren noch Stilkonstanten, die die Ausrichtung und das Aussehen festlegen.
SWT.LEFT
SWT.RIGHT Ausrichtung für Text oder Grafik
SWT.CENTER
211
eclipse_v01.book Seite 212 Montag, 30. Januar 2006 12:02 12
Das SWT
SWT.LEFT
SWT.RIGHT
Pfeilrichtung
SWT.UP
SWT.DOWN
Neben Text kann ein Button analog zu einem Label auch mit einer Grafik versehen werden.
Hierfür stehen die Methoden setText bzw. setImage zur Verfügung.
// Checkbox
Button checkButton = new Button(composite, SWT.CHECK);
checkButton.setText("Checkbox");
// Pfeiltaste nach unten
Button arrowButton = new Button(composite, SWT.ARROW | SWT.DOWN);
Mithilfe der Methode getSelection kann für alle Arten von Buttons ermittelt werden, ob
ein Button angewählt worden ist.
Im Falle eines mehrzeiligen Textfelds kann dieses über die aus der Klasse Scrollable ge-
erbten Stilkonstanten SWT.H_SCROLL und SWT.V_SCROLL auch mit einer horizontalen
und vertikalen Scrollleiste versehen werden.
212
eclipse_v01.book Seite 213 Montag, 30. Januar 2006 12:02 12
Die Klasse Text verfügt über eine Vielzahl von Methoden für die programmseitige Text-
eingabe und -bearbeitung sowie für das Abrufen von Informationen.
213
eclipse_v01.book Seite 214 Montag, 30. Januar 2006 12:02 12
Das SWT
Für die Ermittlung der ausgewählten Listenelemente sowie die programmseitige Auswahl
von Listenelementen stehen die folgenden Methoden zur Verfügung:
SWT.DROP_DOWN Die Auswahlliste wird erst beim Klick auf die Pfeiltaste ange-
zeigt.
SWT.SIMPLE Die Auswahlliste ist immer sichtbar.
SWT.READ_ONLY Nur eine Listenauswahl, aber keine Texteingabe ist möglich.
Für das Hinzufügen von Elementen zu einer Liste existieren analog zur Klasse List die
Methoden add, setItem und setItems. Für die Ermittlung der ausgewählten Listenele-
mente bzw. des eingegebenen Texts sowie die programmseitige Auswahl von Listenele-
menten bzw. die Bearbeitung des Texts existieren folgende Methoden:
214
eclipse_v01.book Seite 215 Montag, 30. Januar 2006 12:02 12
Für die Ermittlung der eingegebenen Zahl und die Gestaltung des numerischen Eingabe-
felds existieren folgende Methoden:
Hierbei kann immer am Ende angefügt werden oder aber auch an beliebiger Stelle einge-
fügt werden. In diesem Fall muss im Konstruktor die gewünschte Position durch Angabe
der Zeilennummer angegeben werden, wobei die Zählung bei 0 beginnt. Im folgenden Bei-
spiel ist tableItem1 die erste Zeile und tableItem2 zunächst die zweite. TableItem3
wird dann als zweite Zeile eingefügt, so dass tableItem2 anschließend die dritte Zeile ist.
215
eclipse_v01.book Seite 216 Montag, 30. Januar 2006 12:02 12
Das SWT
setText(String string) Fügt in der gewählten Zeile in der ersten Spalte ein.
setText(int index, Fügt in der gewählten Zeile in der index+1-ten
String string) Spalte ein.
setText(String[] strings) Fügt in der gewählten Zeile bei den ersten n Spalten
ein, wobei n die Dimension von strings ist.
tableItem1.setText("S1Z1");
tableItem1.setText(1,"S2Z1");
tableItem2.setText(new String("S1Z2", "S2Z2");
Darüber hinaus lässt sich eine Tabelle über die aus der Klasse Scrollable geerbten Stil-
konstanten SWT.H_SCROLL und SWT.V_SCROLL mit Scrollleisten versehen.
Mithilfe der Methoden setHeaderVisible und setLinesVisible kann festgelegt
werden, ob Spaltenüberschriften und Trennlinien sichtbar sein sollen. Die Methoden set-
Background bzw. setForeground ermöglichen es, die Hintergrundfarbe der Tabellen-
zellen bzw. die Schriftfarbe der Tabelleneinträge festzulegen. Werden sie in Zusammen-
hang mit einem Table-Objekt verwendet, gelten die Einstellungen für alle Zellen der
Tabelle. Angewendet auf ein TableItem-Objekt können aber auch für einzelne Zellen
individuelle Einstellungen vorgenommen werden.
Die Klasse TableColumn stellt die Stilkonstanten SWT.LEFT, SWT.RIGHT und SWT.CEN-
TER zur Verfügung, um die Ausrichtung einer Tabellenspalte festzulegen.
In der Klasse TableItem sind keine Stilkonstanten definiert.
216
eclipse_v01.book Seite 217 Montag, 30. Januar 2006 12:02 12
Die Anordnung wird sowohl bei der Klasse Slider als auch bei der Klasse Scale über die
Stilkonstanten SWT.HORIZONTAL und SWT.VERTICAL beeinflusst.
Für die weiteren möglichen Einstellungen existieren für beide Klassen die folgenden Me-
thoden:
Die Klasse Slider weist darüber hinaus noch folgende Methoden auf:
Die aktuelle Position kann mit der Methode getSelection abgefragt werden.
217
eclipse_v01.book Seite 218 Montag, 30. Januar 2006 12:02 12
Das SWT
Des Weiteren existieren analog zu den Klassen Slider und Scale die Methoden set-
Maximum, setMinimum sowie setSelection und getSelection. Im folgenden Bei-
spiel ist ein Fortschrittsbalken implementiert, der unterbrochen jeweils von einer Pause von
1000 Millisekunden vom Wert 10 auf den Wert 20 wächst. Zu beachten ist, dass der Fort-
schritt nur sichtbar wird, wenn die Schleife zum Setzen der Werte nach dem Öffnen der
Shell ausgeführt wird.
218
eclipse_v01.book Seite 219 Montag, 30. Januar 2006 12:02 12
Die Beschriftungen für die Baumknoten werden mithilfe der Methode setText gesetzt.
Darüber hinaus kann jedem Baumknoten neben einer Beschriftung noch mithilfe der Me-
thode setImage eine Grafik zugeordnet werden.
Mithilfe der Methode getSelection können für einen Baum die angewählten Baumkno-
ten ermittelt werden. Die Methode setSelection erlaubt eine programmseitige Auswahl
von Baumknoten.
shell.setLayout(new FillLayout());
SashForm sash = new SashForm(shell, SWT.VERTICAL);
Composite compOben = new Composite(sash, SWT.NONE);
compOben.setLayout(new GridLayout());
Button buttonOben = new Button(compOben, SWT.NONE);
button1.setText("Oberer Button");
Composite compUnten = new Composite(sash, SWT.NONE);
compUnten.setLayout(new GridLayout());
Button buttonUnten = new Button(compUnten, SWT.NONE);
button2.setText("Unterer Button");
Im Gegensatz zur Klasse Sash befindet sich die Klasse SashForm nicht im Package
org.eclipse.swt.widgets, sondern im Package org.eclipse.swt.custom.
219
eclipse_v01.book Seite 220 Montag, 30. Januar 2006 12:02 12
Das SWT
shell.setLayout(new FillLayout());
TabFolder tabFolder = new TabFolder(shell, SWT.NONE);
TabItem tabItem1 = new TabItem(tabFolder, SWT.NONE);
tabItem1.setText("Item 1");
Composite composite = new Composite(tabFolder,SWT.NONE);
composite.setLayout(new GridLayout());
tabItem1.setControl(composite);
Button button1 = new Button(composite, SWT.NONE);
button1.setText("Button 1");
TabItem tabItem2 = new TabItem(tabFolder, SWT.NONE);
tabItem2.setText("Item 2");
Group group = new Group(tabFolder,SWT.NONE);
group.setLayout(new GridLayout());
tabItem2.setControl(composite2);
Button button2 = new Button(group, SWT.NONE);
button2.setText("Button 2");
Während die Methode getSelection ein Array der ausgewählten Register zurückliefert,
lässt sich mit der Methode getSelectionIndex der Index des ersten angewählten Regis-
ters ermitteln. Die Methode setSelection ermöglicht die programmseitige Auswahl von
Registern.
220
eclipse_v01.book Seite 221 Montag, 30. Januar 2006 12:02 12
SWT.PUSH Button
SWT.CHECK Checkbox
SWT.RADIO
Optionsfeld
SWT.SEPARATOR
Separator
SWT.DROP_DOWN
Button mit Pfeiltaste
Die Beschriftung eines Buttons erfolgt auch hier über die Methode setText. Soll der But-
ton eine Grafik beinhalten, muss die Methode setImage verwendet werden. Für die Defi-
nition eines Tooltipps existiert die Methode setToolTipText. Mithilfe der Methode
getSelection kann ermittelt werden, ob ein Button angewählt wurde.
Wird als Stilkonstante SWT.DROP_DOWN gewählt, erscheint nicht automatisch beim Klick
auf die Pfeiltaste ein Drop-Down-Menü. Dieses muss explizit programmiert werden.
Anschließend werden für jedes Menü ein Menütitel sowie das Menü selbst erzeugt. Einen
Menütitel erhalten wir hierbei durch das Erzeugen eines Objekts der Klasse Menu, wobei
als übergeordnetes Composite die Shell und als Typ in diesem Fall SWT.DROP_DOWN anzu-
geben ist. Das Menü selbst wird repräsentiert durch ein Objekt der Klasse MenuItem. Als
Stilkonstante ist hier beim Erzeugen des Objekts im Konstruktor SWT.CASCADE zu wählen.
221
eclipse_v01.book Seite 222 Montag, 30. Januar 2006 12:02 12
Das SWT
Mithilfe der Methode setText kann dem Menü anschließend eine Beschriftung zugewie-
sen werden und über die Methode setMenu muss die Zuordnung Menü-Menütitel vorge-
nommen werden.
Das Hinzufügen eines Menüeintrags zu einem Menü erfolgt nun durch Erzeugen eines Ob-
jekts der Klasse MenuItem. Hierbei werden der zugehörige Menütitel sowie die gewünsch-
te Art des Menüeintrags angegeben. Als Stilkonstanten für die verschiedenen Arten stehen
zur Verfügung:
Für die Definition der Beschriftung ist wiederum die Methode setText zuständig.
6.4.3 Layoutmanager
Analog zum AWT und zu Swing besteht im SWT sowohl die Möglichkeit, die Position und
Größe von Komponenten explizit festzulegen als auch Layoutmanager zu verwenden, die
die Komponenten auf einem Composite automatisch anordnen und dabei Position und Grö-
ße berechnen. Wird das Composite in der Größe verändert, wird die Anordnung der Kom-
ponenten automatisch neu berechnet.
Das SWT stellt die fünf Layouts FillLayout, RowLayout, GridLayout, FormLayout und
StackLayout zur Verfügung. Darüber hinaus können aber auch eigene Layouts definiert
werden.
Layouts werden einem Composite mithilfe der Methode setLayout zugewiesen. Wäh-
rend beim FillLayout und beim StackLayout alle Komponenten gleich behandelt werden,
erlauben die anderen drei Layouts für jede Komponente spezifische Einstellungen. Diese
Layoutdaten werden einer Komponente mit der Methode setLayoutData zugewiesen.
Einzelheiten hierzu werden bei der folgenden detaillierten Betrachtung der verschiedenen
Layouts vorgestellt.
222
eclipse_v01.book Seite 223 Montag, 30. Januar 2006 12:02 12
Das FillLayout
Das FillLayout ist das einfachste der im SWT bereits definierten Layouts. Hierbei sind alle
GUI-Elemente gleich groß und werden in einer Zeile oder Spalte angeordnet, wobei kein
Zeilenumbruch möglich ist. Die GUI-Elemente füllen das gesamte Composite – abzüglich
eines definierbaren Randbereichs – aus. Für die einzelnen GUI-Elemente sind keine indi-
viduellen Einstellungen möglich. Für das Composite dagegen existieren folgende Einstel-
lungsmöglichkeiten:
Der Zugriff auf die Attribute marginHeight, marginWidth, space und type erfolgt
hierbei direkt und nicht über eine Setter-Methode.
Anwendung findet das FillLayout z.B. für Werkzeugleisten, die Zusammenfassung von
Checkboxen in einer Group oder wenn ein GUI-Element ein Composite komplett ausfüllen
soll, wie beispielsweise ein Composite-Objekt die Shell.
Abb. 6.18: Fenster mit FillLayout in verschiedenen Größen jeweils ohne Randbereich und
Zwischenraum
223
eclipse_v01.book Seite 224 Montag, 30. Januar 2006 12:02 12
Das SWT
Das RowLayout
Ähnlich wie beim FillLayout ordnet das RowLayout die GUI-Elemente in einer Zeile oder
Spalte an. Allerdings sind Zeilenumbrüche möglich. Darüber hinaus existieren einige wei-
tere Einstellungsmöglichkeiten. Im Folgenden sind alle Layoutoptionen aufgelistet:
Im folgenden Beispiel werden für einige Optionen von der Voreinstellung abweichende
Einstellungen vorgenommen. Hierbei ist das Setzen der Option type auch beim Erzeugen
des RowLayout-Objekts im Konstruktor möglich.
224
eclipse_v01.book Seite 225 Montag, 30. Januar 2006 12:02 12
Sollen für alle Optionen die Voreinstellungen realisiert werden, ist nur die folgende Anwei-
sung erforderlich:
composite.setLayout(new RowLayout());
Im Gegensatz zum FillLayout können für die GUI-Elemente eines Composite mit RowLay-
out die Breite und die Höhe jedes einzelnen GUI-Elements gesetzt werden. Hierzu müssen
wir ein Objekt der Klasse RowData erzeugen, die Breite und Höhe des GUI-Elements ent-
weder bei der Erzeugung des RowData-Objekts oder aber durch explizites Festlegen der
Werte setzen und das RowData-Objekt mithilfe der Methode setLayoutData dem GUI-
Element zuweisen.
composite.setLayout(new RowLayout());
Button button1 = new Button(composite, SWT.PUSH);
button1.setText("100x50");
button1.setLayoutData(new RowData(100,50));
Button button2 = new Button(composite, SWT.PUSH);
button2.setText("75x50");
RowData rowData = new RowData();
rowData.width = 75;
rowData.height = 50;
button2.setLayoutData(rowData);
225
eclipse_v01.book Seite 226 Montag, 30. Januar 2006 12:02 12
Das SWT
Des Weiteren kann für ein GUI-Element ab der Version 3.1 von Eclipse mithilfe der Lay-
outoption exclude festgelegt werden, dass es seine Position und Größe nicht durch den
Layoutmanager erhält und auch nicht für die Bestimmung der Position und Größe der an-
deren GUI-Elemente herangezogen wird. Die Voreinstellung ist hier false, d.h. Position
und Größe werden durch den Layoutmanager festgelegt.
Das GridLayout
Beim GridLayout werden die GUI-Elemente auf einem Gitternetz angeordnet. Da eine
Vielzahl von Einstellungsmöglichkeiten existieren, ist das GridLayout relativ kompliziert
zu handhaben, es bietet allerdings auch sehr umfangreiche Einsatzmöglichkeiten.
Im Einzelnen stehen folgende allgemeine Einstellungsmöglichkeiten zur Verfügung:
226
eclipse_v01.book Seite 227 Montag, 30. Januar 2006 12:02 12
227
eclipse_v01.book Seite 228 Montag, 30. Januar 2006 12:02 12
Das SWT
Eine Reihe von Layoutoptionen für ein GUI-Element lassen sich aber auch bei der Erzeu-
gung des GridData-Objekts im Konstruktor vornehmen. Hierzu hält die Klasse GridData
folgende Konstruktoren bereit:
쐌 GridData(int style)
쐌 GridData(int width, int height)
쐌 GridData(int horizontalAlignment, int verticalAlignment, boolean
grapExcessHorizontalSpace, boolean grapExcessVerticalSpace)
쐌 GridData(int horizontalAlignment, int verticalAlignment, boolean
grapExcessHorizontalSpace, boolean grapExcessVerticalSpace, int
horizontalSpan, int verticalSpan)
228
eclipse_v01.book Seite 229 Montag, 30. Januar 2006 12:02 12
composite.setLayout(new GridLayout());
Button button = new Button(composite, SWT.PUSH);
GridData gridData = new GridData(GridData.CENTER,
GridData.BEGINNING,false,false);
gridData.widthHint = 100;
gridData.heightHint = 50;
gridData.horizontalSpan = 2;
button.setLayoutData(gridData);
Abb. 6.20: Fenster mit GridLayout. Die Textfelder erstrecken sich über zwei Spalten.
Das FormLayout
Die Klasse FormLayout wurde mit der Version 2.0 von Eclipse eingeführt. Sie ermöglicht
ebenfalls eine sehr flexible Gestaltung eines GUI. Im Gegensatz zum GridLayout werden
die GUI-Elemente jedoch nicht in einem Gitter angeordnet, sondern es lässt sich für jede
Seite eines GUI der Abstand zu der Seite eines übergeordneten Composite oder eines an-
deren GUI-Elements festlegen.
Für das FormLayout selbst stehen analog zum RowLayout bzw. GridLayout die Einstel-
lungsmöglichkeiten marginBottom, marginHeight, marginLeft, marginRight,
marginTop, marginWidth und spacing zur Verfügung, die die Größe des Randbereichs
bzw. den Zwischenraum zwischen zwei GUI-Elementen definieren. Die Voreinstellung ist
hier überall 0.
Für jedes GUI-Element lassen sich über die Layoutoptionen heigth und width die Höhe
und Breite des GUI-Elements in Pixel angeben. Zum Festlegen der Abstände existieren die
Layoutoptionen top, bottom, left und right.
Individuelle Layouteinstellungen für einzelne GUI-Elemente werden in einer Instanz der
Klasse FormData gespeichert und an die Methode setLayoutData übergeben.
229
eclipse_v01.book Seite 230 Montag, 30. Januar 2006 12:02 12
Das SWT
shell.setLayout(new FormLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText("OK");
FormData formData = new FormData();
button.setLayoutData(formData);
Das FormData-Objekt erlaubt jetzt das Festlegen der Größe des GUI-Elements sowie der
Abstände. Für die Definition der Abstände existieren grundsätzlich zwei Möglichkeiten.
Zum einen können Abstände nur für zwei Seiten definiert werden, und zwar für die Kom-
binationen links-oben, links-unten, rechts-oben, rechts-unten. In diesem Fall ist es erforder-
lich, die Größe für ein GUI-Element explizit zu setzen, und zwar entweder beim Erzeugen
des FormData-Objekts im Konstruktor oder direkt durch Wertzuweisung an die Attribute
heigth und width der Klasse FormData. Zum anderen können wir die Abstände auch für
alle vier Seiten festlegen, so dass hierüber automatisch auch die Größe eines GUI-Elements
definiert wird. Werden für ein GUI-Element keine Abstände definiert, wird es automatisch
links oben in der Ecke des übergeordneten Composite platziert. Werden für mehrere GUI-
Elemente keine Abstände festgelegt, werden alle übereinander ebenfalls in der linken obe-
ren Ecke des übergeordneten Composite angeordnet.
Für das Festlegen der Abstände ist die Klasse FormAttachment zuständig, wobei, wie
oben bereits erläutert, zwei Möglichkeiten bestehen. Es lassen sich für ein GUI-Element
sowohl die Abstände zu dem übergeordneten Composite als auch zu einem anderen GUI-
Element angeben. Sollen die Abstände zu einem übergeordneten Composite angegeben
werden, existieren wiederum zwei Möglichkeiten. Die Anweisung
führt beispielsweise dazu, dass das GUI-Element vertikal an der Position (50/100)*Höhe-
5 platziert wird, wobei Höhe die Höhe des übergeordneten Composite in Pixel ist. Die Zahl
50 ist hier eine Prozentangabe, daher die Division durch 100. Die Anweisung
Abb. 6.21: Fenster mit FormLayout in verschiedenen Größen (Abstand zur Shell nach oben
und links jeweils 50%, Buttongröße vorgegeben)
230
eclipse_v01.book Seite 231 Montag, 30. Januar 2006 12:02 12
Abb. 6.22: Fenster mit FormLayout in verschiedenen Größen (Abstand zur Shell nach oben
und links jeweils 50%, unten und rechts jeweils 75%)
Für die Angabe der Abstände zu einem anderen GUI-Element hält die Klasse Form-
Attachment drei Konstruktoren bereit:
쐌 FormAttachment(control)
쐌 FormAttachment(control, abstand)
쐌 FormAttachment(control, abstand, ausrichtung)
Der Parameter control gibt hierbei das GUI-Element an, zu dem der Abstand festgelegt
werden soll, der Parameter abstand den Abstand in Pixel und der Parameter ausrich-
tung, zu welcher Seite des GUI-Elements der Abstand gelten soll. Wird der Parameter ab-
stand nicht angegeben, wird dieser auf Null gesetzt. Wird der Parameter ausrichtung
weggelassen, wird die nächstliegende Seite benutzt. Für die vertikale Ausrichtung existie-
ren die Stilkonstanten SWT.TOP, SWT.BOTTOM und SWT.CENTER. Für die horizontale Aus-
richtung die Stilkonstanten SWT.LEFT, SWT.RIGHT und SWT.CENTER.
Das StackLayout
Das StackLayout nimmt eine Sonderstellung unter den Layouts ein. Erstens befindet sich
die Klasse StackLayout nicht wie die Klassen der anderen Layouts im Package org.
eclipse.swt.layout, sondern im Package org.eclipse.swt.custom, und zweitens
wird innerhalb eines Composite immer nur ein GUI-Element angezeigt. Dieses liegt darin
begründet, dass alle GUI-Elemente gleich groß gemacht werden und an der gleichen Stelle
übereinander positioniert werden. Dadurch ist immer nur das oberste Element sichtbar. Als
Layoutoptionen stehen zur Verfügung:
Eine sinnvolle Anwendung für das StackLayout ist ein GUI, bei dem zwischen den ver-
schiedenen GUI-Elementen hin- und hergeschaltet werden soll.
231
eclipse_v01.book Seite 232 Montag, 30. Januar 2006 12:02 12
Das SWT
6.4.4 Ereignisverarbeitung
Ereignisse sind im SWT analog zum AWT zu Ereignistypen zusammengefasst. Es existie-
ren verschiedene Ereignistypen, die jeweils durch eine Klasse repräsentiert werden. Die
Klassen weisen die Namen XyzEvent auf, wobei Xyz für den Ereignistyp steht. Um ein
Ereignis für ein GUI-Element abzufangen, muss diesem der für das Ereignis relevante Lis-
tener mithilfe der Methode addXyzListener hinzugefügt werden. Xyz steht hierbei wie-
derum für den Ereignistyp. Des Weiteren muss eine Implementation des Listener-Interface
erfolgen. Analog zum AWT existiert in einem Listener-Interface für jedes Ereignis eine
Methode. Für Interfaces, die mehr als eine Methode aufweisen, existieren im SWT Adap-
terklassen.
Die Implementation des Ereignisses „Klick auf einen Button“ sieht beispielsweise wie folgt
aus:
In diesem Fall wird das Interface als anonyme Klasse realisiert. Da für die widgetDe-
faultSelected-Methode kein Quelltext implementiert ist, bietet sich die Implementation
der entsprechenden Adapterklasse an.
Im Folgenden findet sich zunächst eine Übersicht über die Listener-Interfaces und die Er-
eignistyp-Klassen und anschließend eine Übersicht über die Methoden für die Ereignisse
eines Ereignistyps sowie die GUI-Elemente, für die die Ereignisse eintreten können. Es
werden allerdings nur GUI-Elemente aufgeführt, die hier zuvor vorgestellt worden sind.
232
eclipse_v01.book Seite 233 Montag, 30. Januar 2006 12:02 12
Listener-Interface / Beschreibung
Ereignistyp-Klasse
ArmListener / Tritt auf, wenn ein GUI-Element für die Selektion vorbe-
ArmEvent reitet wird.
ControlListener / Tritt auf, wenn ein GUI-Element bewegt oder in der
ControlEvent Größe verändert wird.
DisposeListener / Tritt auf, wenn ein GUI-Element entsorgt wird.
DisposeEvent
FocusListener / Tritt auf, wenn ein GUI-Element den Fokus erhält oder
FocusEvent verliert.
HelpListener / Tritt auf, wenn für ein GUI-Element Hilfe angefordert
HelpEvent wird, z.B. durch Drücken der É-Taste.
KeyListener / Tritt auf, wenn Tasten der Tastatur betätigt werden.
KeyEvent
MouseTrackListener / Tritt auf, wenn die Maus sich über ein GUI-Element
MouseEvent bewegt.
PaintListener / Tritt auf, wenn ein GUI-Element neu gezeichnet werden
PaintEvent muss.
SelectionListener / Tritt auf, wenn ein GUI-Element selektiert wird.
SelectionEvent
ShellListener / Tritt auf, wenn der Zustand einer Shell sich ändert.
ShellEvent
TraverseListener / Tritt auf, wenn der Benutzer mit der TAB-Taste zum
TraverseEvent nächsten Feld springt.
TreeListener / Tritt auf, wenn Baumknoten ein- oder ausgeblendet wer-
TreeEvent den.
VerifyListener / Tritt auf, bevor Text modifiziert wird.
VerifyEvent
233
eclipse_v01.book Seite 234 Montag, 30. Januar 2006 12:02 12
Das SWT
Die Implementation der Reaktion auf ein Ereignis macht es häufig erforderlich, dass auf be-
stimmte Informationen zugegriffen wird, beispielsweise, welches Listenelement bei einer
Liste ausgewählt ist. Eine Reihe von Methoden steht hierfür jeweils in den Klassen für die
GUI-Elemente zur Verfügung. Darüber hinaus liefert die Methode getSource aus der
234
eclipse_v01.book Seite 235 Montag, 30. Januar 2006 12:02 12
6.5.2 Layoutmanager
Wenn wir ein GUI mit SWT-Komponenten erstellen, lassen sich die Layoutmanager Fill-
Layout, FormLayout, GridLayout und RowLayout über die Properties View anwählen. De-
ren allgemeine und individuelle Einstellungsmöglichkeiten lassen sich wiederum ebenfalls
in der Properties View realisieren, und zwar über die Eigenschaft layout (allgemein) bzw.
layoutdata (individuell). Darüber hinaus können die allgemeinen Einstellungen zum
FillLayout, GridLayout und RowLayout alternativ auch über das Register LAYOUT im Cus-
tomize Layout-Fenster vorgenommen werden. Beim GridLayout sind die individuellen
Einstellungen ebenfalls über das Customize Layout-Fenster möglich. In diesem Fall ist das
Register COMPONENT zu wählen.
235
eclipse_v01.book Seite 236 Montag, 30. Januar 2006 12:02 12
Beim Hinzufügen einer Komponente zu einem Container mit GridLayout werden zwar
nicht wie beim GridBagLayout die Zeile und Spalte des Gitternetzes am Mauscursor ein-
geblendet. Jedoch kann auch hier eine Komponente sehr leicht mithilfe der Maus in einer
neuen Zeile oder Spalte positioniert werden, indem wir analog zum GridBagLayout mit der
Maus in der Zeile auf die vertikale Gitternetzlinie gehen, wo die neue Komponente links in
einer neuen Spalte eingefügt werden soll, bzw. in der Spalte auf die horizontale Gitternetz-
linie, wo die neue Komponente oberhalb in einer neuen Zeile eingefügt werden soll.
Abschließend sei noch darauf hingewiesen, dass Layoutoptionen, die erst seit der Version
3.1 von Eclipse existieren (allgemeine Einstellungen GridLayout und FormLayout:
marginBottom, marginLeft, marginRight, marginTop, individuelle Einstellungen
RowLayout bzw. GridLayout: exclude, minimumWidth, minimumHeight, vertical-
Indent), in der hier betrachteten Version 1.1.0.1 vom Visual Editor direkt im Quelltext
realisiert werden müssen. Des Weiteren ist das Festlegen der Abstände beim FormLayout
ebenfalls bisher nicht möglich.
236
eclipse_v01.book Seite 237 Montag, 30. Januar 2006 12:02 12
6.5.3 Codegenerierung
Wählt der Benutzer bei der Erstellung einer neuen Klasse im VE New Class Wizard unter
STYLE | SWT den Eintrag SHELL, wird eine neue Klasse implementiert, die das Attribut
sShell vom Typ org.eclipse.swt.widgets.Shell sowie die Methode create-
SShell aufweist. In dieser Methode wird das Attribut sShell instanziiert, der Titel in der
Titelzeile des Fensters gesetzt und die Größe des Fensters festgelegt. Weiterhin werden die
bis zu diesem Zeitpunkt erforderlichen Klassen importiert.
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
Hat der Benutzer darüber hinaus im VE New Class Wizard unter WHICH METHOD STUBS
WOULD YOU LIKE TO CREATE? den Eintrag PUBLIC STATIC VOID MAIN(STRING[] ARGS) aktiviert,
wird der Quelltext noch um die main-Methode mit folgendem Quelltext erweitert:
Fügen wir jetzt der Shell ein Composite hinzu, wird der Quelltext um die Methode
createComposite erweitert. Diese enthält zunächst nur die Anweisung zur Instanzi-
ierung und Zuordnung des Composite-Objekts und die Anweisung für die Festlegung der
Position und Größe des Composite. Werden anschließend in der Properties View Änderun-
gen an den Eigenschaften des Composite vorgenommen, wie beispielsweise als Layout
GridLayout gewählt und die Spaltenanzahl auf 2 gesetzt, wird der Quelltext hierfür eben-
falls in der createComposite-Methode implementiert.
237
eclipse_v01.book Seite 238 Montag, 30. Januar 2006 12:02 12
Wird einem GUI-Element ein Ereignis im Visual-Editor hinzugefügt, werden analog zu Er-
eignissen bei AWT- und Swing-Komponenten der für das Ereignis zuständige Listener und
die zuständige Methode im Quelltext implementiert und der Komponente hinzugefügt. Die
Implementation erfolgt als anonyme Klasse und die Methode enthält eine println-
Anweisung und einen TODO-Kommentar. Die entsprechenden Anweisungen finden sich
in der createComposite-Methode. Entscheiden wir uns bezüglich des Listener für die
Realisierung des Interface und nicht der Adapterklasse, werden auch hier die Methoden für
die weiteren Ereignisse des Ereignistyps mit leerem Methodenrumpf implementiert.
button.addSelectionListener(new
org.eclipse.swt.events.SelectionAdapter() {
public void widgetSelected(
org.eclipse.swt.events.SelectionEvent e) {
System.out.println("widgetSelected()");
// TODO Auto-generated Event stub widgetSelected()
}
});
238
eclipse_v01.book Seite 239 Montag, 30. Januar 2006 12:02 12
6.5.4 Beispiel
Da wir bereits für ein GUI mit Swing-Komponenten ein umfangreiches Beispiel betrachtet
haben, soll im Folgenden nur ein kleines Beispiel für ein GUI mit SWT-Komponenten vor-
gestellt werden.
239
eclipse_v01.book Seite 240 Montag, 30. Januar 2006 12:02 12
VISUAL EDITOR | APPEARANCE die Option PROMPT FOR BEAN NAME DURING CREATION aktiviert ist,
erscheint nach dem Klick in das Composite jeweils das Fenster zur Namensgebung und wir
benennen dort das erste Textfeld mit txtEingabe1, das zweite mit txtEingabe2 und das
Label mit lblAusgabe. Falls das Fenster zur Namensgebung nicht erscheint, verändern
wir den Namen in der Properties View unter der Eigenschaft field name. Anschließend
löschen wir noch den standardmäßig eingetragenen Text aus dem Label, und zwar entweder
direkt in der Design View oder in der Properties View unter text.
Da wir den Layoutmanager GridLayout eingestellt haben, können wir für jede SWT-Kom-
ponente weitere Angaben machen. In unserem Fall ist dies für das Label erforderlich. Wir
wählen dieses in der Design View oder der Java Beans View an und geben entweder im
Customize Layout-Fenster oder in der Properties View unter layoutdata an, dass das
Label sich horizontal über zwei Zellen erstrecken (horizontalSpan=2) und diese ausfül-
len (horizontalAlignment=FILL) soll.
Im Quelltext wird in der Methode createComposite ein GridData-Objekt erzeugt, bei
dem die gewählten Einstellungen realisiert werden, bevor es in der Methode setLayout-
Data dem Label-Objekt übergeben wird:
sShell.addShellListener(new
org.eclipse.swt.events.ShellAdapter(){
public void shellActivated(org.eclipse.swt.events.ShellEvent e){
txtEingabe1.setText("Hello");
txtEingabe2.setText("World");
}
});
Als Nächstes programmieren wir, dass der Inhalt der Textfelder beim focusGained-Er-
eignis markiert wird und beim focusLost-Ereignis der Text aus dem ersten mit dem aus
dem zweiten Textfeld zusammengesetzt und in das Label ausgegeben wird. Da für beide
240
eclipse_v01.book Seite 241 Montag, 30. Januar 2006 12:02 12
Ereignisse des Focus Events eine Reaktion erfolgen soll, verwenden wir in diesem Fall
nicht die Adapterklasse, sondern wählen im Dialogfenster zur Auswahl der Ereignisse ei-
nes der beiden Ereignisse focusGained oder focusLost und geben anschließend an,
dass der FocusListener implementiert werden soll. Für das Markieren des Inhalts der Text-
felder nutzen wir die Methode selectAll aus der Klasse Text. Für das focusLost-Er-
eignis programmieren wir die Methode lblAusgabeTextSetzen in der äußeren Klasse
(SWTFenster). Auf diese Weise können wir dieselbe Funktionalität für mehrere Ereignisse
verwenden und müssen sie nicht mehrfach implementieren.
txtEingabe1.addFocusListener(
new org.eclipse.swt.events.FocusListener(){
public void focusGained(org.eclipse.swt.events.FocusEvent e) {
txtEingabe1.selectAll();
}
public void focusLost(org.eclipse.swt.events.FocusEvent e) {
lblAusgabeTextSetzen();
}
});
txtEingabe2.addFocusListener(
new org.eclipse.swt.events.FocusListener(){
public void focusGained(org.eclipse.swt.events.FocusEvent e) {
txtEingabe2.selectAll();
}
public void focusLost(org.eclipse.swt.events.FocusEvent e) {
lblAusgabeTextSetzen();
}
});
Als letztes Ereignis implementieren wir noch, dass sich bei Klick auf das Label
lblAusgabe die Schriftgröße um zwei Punkt vergrößert. Hierbei handelt es sich um ein
mouseDown-Ereignis, das wir im Dialogfenster zur Auswahl der Ereignisse unter MOUSE
auswählen. Da noch zwei Ereignisse für den Mouse Event existieren, auf die jedoch nicht
reagiert werden soll, implementieren wir hier wieder die entsprechende Adapterklasse. In
ihr können wir bei SWT die Schriftgröße eines Label-Objekts nicht direkt verändern, son-
dern müssen uns eine Referenz auf das Font-Objekt des Labels erzeugen. Die zugrunde
liegende Font-Klasse stammt aus dem Package org.eclipse.swt.graphics. Aller-
dings kann die Schriftgröße auch nicht im Font-Objekt direkt angepasst werden, sondern
es muss eine Referenz auf das zugehörige FontData-Objekt-Array erzeugt werden. Das
erste Element des Arrays enthält die Daten zum Font des Labels. Mit der setHeight-Me-
241
eclipse_v01.book Seite 242 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
thode setzen wir die Schriftgröße auf den um zwei vergrößerten Wert. Danach instanziieren
wir ein neues Font-Objekt mithilfe des veränderten FontData-Objekt-Arrays und ordnen
es dem Label zu.
lblAusgabe.addMouseListener(
new org.eclipse.swt.events.MouseAdapter() {
public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
org.eclipse.swt.graphics.FontData[] fd =
lblAusgabe.getFont().getFontData();
fd[0].setHeight(fd[0].getHeight()+2);
org.eclipse.swt.graphics.Font font =
org.eclipse.swt.graphics.Font(composite.getDisplay(),fd);
lblAusgabe.setFont(font);
}
});
242
eclipse_v01.book Seite 243 Montag, 30. Januar 2006 12:02 12
Eclipse-Hilfe integriert. Bevor wir jetzt den WindowBuilder nutzen können, müssen wir
ihn noch aktivieren. Hierzu starten wir unter WINDOW | PREFERENCES | DESIGNER | LICENSE
durch Klick auf den Button REGISTRATION AND ACTIVATION den Online Activation Wizard
und führen die daraufhin erscheinenden Anweisungen aus.
Der WindowBuilder verfügt über einen eigenen Projekt-Wizard. Analog zum Projekt-
Wizard von Eclipse müssen wir zunächst FILE | NEW | PROJECT aufrufen. In dem daraufhin
erscheinenden Fenster klicken wir auf das +-Zeichen vor dem Eintrag DESIGNER, so dass die
Option SWT/JFACE JAVA PROJECT angezeigt wird, die wir dann anwählen. Nach dem Kli-
cken auf NEXT können wir nun im nächsten Fenster für das neue Projekt den Projektnamen
eingeben.
Um eine Klasse mit dem WindowBuilder zu erstellen, wählen wir FILE | NEW | OTHER. In
dem dann erscheinenden Fenster klicken wir unter DESIGNER auf das +-Zeichen vor dem
Eintrag SWT und wählen die Option APPLICATION WINDOW. Im nächsten Fenster geben wir
das Quelltextverzeichnis, das Package und den neuen Klassennamen an. Haben wir zuvor
im Package Explorer das gewünschte Package angeklickt, ist es im Fenster bereits einge-
stellt.
Sind die erforderlichen Informationen eingegeben und FINISH ist angeklickt worden, wird
statt des Java Editor-Fensters von Eclipse das Designer-Fenster angezeigt. Wenn wir hier
dann das Register SOURCE wählen, erscheint der Quelltext der SWT-Applikation. Bei der
243
eclipse_v01.book Seite 244 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
Wahl des Registers DESIGN erscheint das in Abb. 6.26 dargestellte Fenster. Dieses weist
mehrere Bestandteile auf:
쐌 eine Root List, die für ein GUI die Container der obersten Ebene in einer Liste anzeigt,
쐌 ein Control Tree, der alle Komponenten eines GUI in einer baumartigen Struktur dar-
stellt,
쐌 eine Control-Palette, die der Auswahl der Komponenten dient,
쐌 die so genannte Content Pane, die das GUI so zeigt, wie es nach dem Start der Anwen-
dung erscheinen wird, und
쐌 ein Inspector, der die Eigenschaften bzw. Ereignisse einer angewählten Komponente
zeigt.
Unter WINDOW | PREFERENCES | DESIGNER | EDITOR LAYOUT lassen sich alternative Anordnun-
gen der einzelnen Bestandteile festlegen.
244
eclipse_v01.book Seite 245 Montag, 30. Januar 2006 12:02 12
쐌 SWT Controls
Button, Label, Text, Combo, List, Tree etc.
쐌 Menu Controls
MenuBar, PopupMenu, SubMenu, MenuItem etc.
Um eine SWT-Komponente einem Composite hinzuzufügen, wählen wir die gewünschte
SWT-Komponente zunächst in der Control-Palette an und klicken anschließend an die ge-
wünschte Stelle in der Content Pane oder auch im Control Tree. Je nachdem, welchen Lay-
outmanager wir verwenden, werden wir in unterschiedlicher Weise unterstützt. In Ab-
schnitt 6.6.5 erfolgt hierzu eine detaillierte Beschreibung.
Haben wir eine Komponente an der falschen Stelle eingefügt, können wir sie in der Content
Pane oder im Control Tree verschieben.
6.6.5 Layouteinstellungen
Der WindowBuilder unterstützt die vorgestellten Layoutmanager FillLayout, FormLayout,
GridLayout, RowLayout und StackLayout. Sofern unter WINDOW | PREFERENCES | DESIGNER |
SWT die Option ALLOW ABSOLUTE/NULL LAYOUT (SETBOUNDS()) aktiviert ist, kann alternativ
auch der Layoutmanager auf null gesetzt werden, so dass wir für jede Komponente ihre
Position und Größe explizit angeben müssen.
Haben wir zunächst einen Layoutmanager benutzt und setzen ihn dann auf null, werden –
wie auch beim Visual Editor – für die bisher eingefügten Komponenten als Einstellungen
für die Größe und die Position die bisher durch den Layoutmanager definierten Werte rea-
lisiert.
245
eclipse_v01.book Seite 246 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
Die Wahl des Layouts ist entweder im Inspector unter LAYOUT möglich oder aber indem in
der Palette das gewünschte Layout in der Kategorie SWT Layout angewählt wird und an-
schließend im Control Tree oder der Content Pane der Container, der mit dem Layout ver-
sehen werden soll, angeklickt wird. Nachdem unter LAYOUT der gewünschte Layout-
manager gewählt worden ist, können anschließend für alle Layoutmanager die allgemeinen
Layouteinstellungen ebenfalls über den Inspector vorgenommen werden. Hierzu muss le-
diglich der Eintrag LAYOUT durch Klicken auf das +-Zeichen erweitert werden. Alternativ
lässt sich beim FillLayout die Anordnung – horizontal oder vertikal – über das Ausrich-
tungssymbol , das sich in der Content Pane rechts oben am angewählten Container be-
findet, einstellen.
Die bei Wahl des FormLayout, GridLayout und RowLayout für jede Komponente mögli-
chen individuellen Einstellungen können ebenfalls über den Inspector vorgenommen wer-
den. Hierzu wird die gewünschte Komponente in der Content Pane oder im Control Tree
angewählt und anschließend können wir die Einstellungen unter LAYOUTDATA im Inspector
realisieren.
Beim FormLayout wird zusätzlich zu den Markern an jeder Seite einer angewählten Kom-
ponente in der Content Pane ein Symbol in der folgenden Form gezeigt, über das alter-
nativ eine Reihe von individuellen Einstellungen vorgenommen werden können. Beim
GridLayout besitzt eine angeklickte Komponente drei Arten von Kennzeichnungen. Mithil-
fe der beiden Symbole am oberen rechten Rand kann die Ausrichtung der Kompo-
nente in der Zelle festgelegt werden. Die schwarzen Marker ermöglichen das Festlegen der
Größe und über die grünen Marker lässt sich einstellen, über wie viele Zeilen bzw. Spalten
sich die Komponente erstrecken soll. Darüber hinaus findet sich im Kontextmenü noch ein
Befehl, mit dem wir angeben können, ob sich die Komponente horizontal bzw. vertikal der
Zellgröße anpassen soll. Beim RowLayout können wir durch Ziehen an den Markern die
Größe verändern.
Als dritte Alternative lassen sich beim GridLayout alle individuellen Einstellungen und
beim FormLayout ein Teil der individuellen Einstellungen über einen Layoutassistenten
vornehmen. Dieser wird, nachdem die gewünschte Komponente angewählt worden ist, über
das Symbol in der Symbolleiste des WindowBuilder gestartet.
Wie bereits in Abschnitt 6.6.2 erwähnt, stellt der WindowBuilder auch eine Reihe von Hil-
fen beim Hinzufügen einer Komponente zu einem Container zur Verfügung. Verwenden
246
eclipse_v01.book Seite 247 Montag, 30. Januar 2006 12:02 12
wir keinen Layoutmanager, erscheint, nachdem wir eine Komponente in der Palette ange-
wählt haben und anschließend den Mauscursor zum Hinzufügen in die Content Pane be-
wegt haben, am Mauscursor eine gelbe Infobox, die die aktuelle Position in Pixel angibt.
Wenn wir, statt sofort zu klicken, bei gedrückt gehaltener linker Maustaste einen Rahmen
in der für die Komponente gewünschten Größe aufspannen, können wir hierbei auch gleich
die gewünschte Größe der Komponente einstellen. In diesem Fall erscheint am Mauscursor
eine weitere gelbe Infobox, die die aktuelle Größe angibt. Weiterhin kann die Größe und
Position einer bereits eingefügten Komponente nachträglich mithilfe der Maus direkt in der
Content Pane geändert werden. Hierbei erscheinen sowohl beim Verschieben als auch bei
der Größenänderung wiederum die gelben Infoboxen. Haben wir mehrere Komponenten
markiert, können wir diese mithilfe der Ausrichtungssymbole in der Symbolleiste des De-
signers ausrichten.
Beim FillLayout und beim RowLayout erscheint an den Stellen, an denen eine Komponente
hinzugefügt werden kann, in der Content Pane jeweils eine rote und im Control Tree eine
waagerechte dicke schwarze Linie. Beim FormLayout erscheinen in der Nähe des Maus-
cursors zwei gelbe Infoboxen: eine, die die Entfernung in Pixel zum oberen Rand des ge-
wählten Containers angibt, und eine, die die Entfernung in Pixel zum linken Rand ausweist.
Beim GridLayout werden, wie beim Visual Editor auch, falls eine mögliche Einfügeposi-
tion angewählt worden ist, in der Content Pane die Zeile und Spalte am Mauscursor einge-
blendet. Beim StackLayout ist keine weitere Unterstützung erforderlich, da im gewählten
Container auch bei Vorhandensein mehrerer Komponenten immer nur eine Komponente
gleichzeitig angezeigt wird, die den Container vollständig ausfüllt.
6.6.6 Ereignisverarbeitung
Um für eine Komponente eine Ereignisverarbeitung zu implementieren, muss diese zu-
nächst in der Content Pane oder im Control Tree angeklickt werden. Anschließend müssen
wir gegebenenfalls im Inspector noch auf das +-Zeichen vor der Eigenschaft events kli-
cken, um alle möglichen Ereignistypen für die angewählte Komponente anzuzeigen. Wenn
wir dann auf das +-Zeichen eines Ereignistyps klicken, erscheinen die möglichen Ereignis-
se dieses Typs. Jetzt können wir entweder in der rechten Spalte doppelt beim gewünschten
Ereignis klicken oder in die linke Spalte klicken und Æ drücken. Der WindowBuilder
fügt den Quelltext für das Ereignis ein und wechselt dann zur Anzeige des Quelltextes. Im
Inspector erscheint in der rechten Spalte für das Ereignis die Angabe der Zeile in der Quell-
textdatei, in der der eingefügte Quelltext beginnt.
Für einen Button (Button, Check Button, Radio Button) und einen Menüeintrag ist ein
schnellerer Weg möglich. Hier reicht für die Implementation eines Ereignisses ein Dop-
pelklick auf die Komponente.
Um ein bereits implementiertes Ereignis für eine Komponente zu löschen, müssen wir die
Komponente zunächst anwählen, dann im Inspector unter der Eigenschaft events das zu
entfernende Ereignis sichtbar machen und anwählen und anschließend mit der ¢-Taste
löschen. Dadurch verschwindet die Angabe, in welcher Zeile der Quelltextdatei sich der zu-
gehörige Quelltext befindet, und dieser wird ebenfalls gelöscht.
247
eclipse_v01.book Seite 248 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
Über WINDOW | PREFERENCES | DESIGNER | CODE GENERATION | EVENT HANDLERS können wir
steuern, in welcher Form die Ereignisverarbeitung implementiert werden soll: anonyme
Klasse, innere Klasse oder Implementation des für das Ereignis zuständigen Interface in der
Klasse für das GUI.
6.6.7 Codegenerierung
Wird mithilfe des WindowBuilder eine SWT-Applikation erstellt, wird automatisch ein
Quelltext generiert. Unter WINDOW | PREFERENCES | DESIGNER | CODE GENERATION lassen sich,
wie der Abb. 6.29 zu entnehmen ist, eine Reihe von Einstellungen vornehmen, die die
Codegenerierung beeinflussen.
248
eclipse_v01.book Seite 249 Montag, 30. Januar 2006 12:02 12
Der Quelltext enthält in jedem Fall die import-Anweisungen für die verwendeten Klassen
Display und Shell, die Deklaration der neuen Klasse, eine main-Methode und eine
open-Methode, die in der main-Methode aufgerufen wird. Ist bei der Erstellung der SWT-
Applikation die Option PROTECTED CREATECONTENTS() METHOD aktiviert worden, verfügt der
Quelltext weiterhin noch über eine Methode createContents, in der in diesem Fall das
Shell-Objekt erzeugt wird. Im Folgenden wird diese Implementationsvariante beschrie-
ben. Hierbei wird in der main-Methode ein Objekt der implementierten Klasse erzeugt und
die open-Methode aufgerufen. In der open-Methode erhalten wir dann das Display-Ob-
jekt, die Methode createContents wird aufgerufen, die Shell geöffnet und die Schleife
für die Ereignisverarbeitung implementiert. Die dispose-Anweisung für das Entfernen
des Display-Objekts fehlt hier.
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
Werden dem GUI Komponenten hinzugefügt, wird der größte Teil der Komponenten in der
main-, open- oder createContents-Methode deklariert und instanziiert. Für einige
Komponenten, wie z.B. Textfelder, Comboboxen und Listen wird allerdings auch ein Attri-
but der Klasse mit dem Zugriffsrecht private deklariert und in der main-, open- bzw.
createContents-Methode erfolgt dann die Instanziierung des Objekts.
249
eclipse_v01.book Seite 250 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
Ist die Blockbildung aktiviert worden (siehe WINDOW | PREFERENCES | DESIGNER | CODE GENE-
RATION), gibt sie die Hierarchie der Komponenten wieder. Im folgenden Beispiel wird zu-
nächst der Shell ein Button und ein Composite hinzugefügt. Anschließend wird dem Com-
posite noch ein Button hinzugefügt. Der Block hierfür befindet sich nicht auf der gleichen
Ebene wie die Blöcke für den ersten Button und das Composite, sondern innerhalb des
Blocks des Composite.
{
final Button button = new Button(shell, SWT.NONE);
button.setText("button");
}
{
final Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new FillLayout());
{
final Button button = new Button(composite, SWT.NONE);
button.setText("button");
}
}
Wird einer Komponente ein Ereignis über den Inspector hinzugefügt, erfolgt je nach gewähl-
ter Option unter WINDOW | PREFERENCES | DESIGNER | CODE GENERATION | EVENT HANDLERS |
EVENT CODE GENERATION eine unterschiedliche Implementation.
Bei Wahl von CREATE ANONYMOUS CLASS wird eine anonyme Klasse implementiert, die das
für den gewählten Ereignistyp zuständige Listener-Interface implementiert bzw., falls eine
Adapterklasse existiert, diese erweitert. In beiden Fällen weist die für das gewählte Ereignis
zuständige Methode einen leeren Methodenrumpf auf.
250
eclipse_v01.book Seite 251 Montag, 30. Januar 2006 12:02 12
Wird die Option CREATE INNER CLASS aktiviert, erfolgt die Implementation statt als anonyme
Klasse als innere Klasse.
Wird die dritte Möglichkeit IMPLEMENT LISTENER INTERFACE IN PARENT CLASS aktiviert, wird in
jedem Fall, also auch bei Vorhandensein einer Adapterklasse, das Interface implementiert,
und zwar direkt in der Klasse für das GUI.
6.6.8 Beispiel
Im Folgenden soll anhand eines Beispiels der Einsatz des WindowBuilders veranschaulicht
werden. Das Beispiel ähnelt dem Swing-Beispiel, verwendet jedoch der Einfachheit halber
keine Menüleiste und umfasst nur eine Klasse für die Implementation des GUI.
251
eclipse_v01.book Seite 252 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
package daten;
// Konstruktoren ...
252
eclipse_v01.book Seite 253 Montag, 30. Januar 2006 12:02 12
Für die Implementation des GUI wählen wir im Package Explorer das Package gui an und
rufen FILE | NEW | OTHER | DESIGNER | SWT | APPLICATION WINDOW, um den New SWT Appli-
cation Wizard zu starten. Als Klassennamen geben wir dann im Wizard Fenster ein. Des
Weiteren lassen wir unter CREATE CONTENTS IN die Option PROTECTED CREATECONTENTS() ME-
THOD aktiviert.
Nach dem Beenden des Wizard erhalten wir im Register SOURCE den generierten Quelltext.
Wir wechseln jetzt zum Register DESIGN und nehmen, wie in Abb. 6.31 gezeigt, im Inspec-
tor Veränderungen bei den Eigenschaften layout und text vor.
package gui;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
Wir fügen jetzt als Erstes der Shell ein SashForm hinzu, indem wir in der Control-Palette
unter SWT Composites den Eintrag SASHFORM anklicken und anschließend entweder im
253
eclipse_v01.book Seite 254 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
Control Tree auf die Shell oder in der Content Pane auf das Fenster klicken. Als Nächstes
werden dem SashForm ebenfalls durch Anwahl in der Control-Palette und Klicken auf das
SashForm im Control Tree oder in der Content Pane zwei Composites hinzugefügt. Für bei-
de Composites wird als Layout das FillLayout eingestellt. Weiterhin erhält das erste Com-
posite unter VARIABLE als Bezeichner compLi, das zweite Composite erhält den Bezeichner
compRe.
Um sowohl die linke als auch die rechte Hälfte des SashForm jeweils wiederum in zwei Be-
reiche aufzuteilen, fügen wir beiden Composites noch ein SashForm hinzu. Das linke Sash-
Form erhält im Inspector unter VARIABLE den Bezeichner sashFoLi und das rechte den Be-
zeichner sashFoRe. Des Weiteren stellen wir für beide SashForms im Inspector unter
STYLE ORIENTATION als Anordnung vertical ein, so dass wir im Gegensatz zum ersten
SashForm eine vertikale Aufteilung erhalten.
Um jetzt in den vier durch die beiden SashForms entstandenen Bereichen GUI-Elemente
platzieren zu können, versehen wir das SashForm sashFoLi mit zwei Composites und das
SashForm sashFoRe mit einer Group und einem Composite. Als Bezeichner vergeben wir
für das obere und das untere Composite der linken Seite compLo und compLu. Die Group
bzw. das Composite der rechten Seite erhalten die Bezeichner compRo und compRu.
Als Erstes wird nun der linke obere Bereich fertig gestellt. Als Layout wählen wir, nachdem
wir das Composite compLo im Control Tree angeklickt haben, im Inspector unter LAYOUT
das GridLayout. Unter NUMCOLUMNS geben wir 2 ein. Anschließend wählen wir in der Con-
trol-Palette in der Kategorie SWT Controls den Eintrag LABEL aus und klicken im Control
Tree auf das Composite compLo. Unter LAYOUTDATA stellen wir im Inspector für hGrap und
vGrap true ein, für hIdent 5 und als Beschriftung unter TEXT Kundennummer.
254
eclipse_v01.book Seite 255 Montag, 30. Januar 2006 12:02 12
Als Nächstes fügen wir ein Textfeld ein. Hierzu wählen wir in der Control-Palette in der
Kategorie SWT Controls den Eintrag TEXT und klicken anschließend im Control Tree wie-
derum auf das Composite compLo. Die Einstellungen unter LAYOUTDATA werden danach
analog zum Label vorgenommen.
Nachdem ein Label und ein Textfeld in dem Composite compLo platziert worden sind, wer-
den auf die soeben beschriebene Art ein weiteres Label und ein weiteres Textfeld eingefügt.
Dem Label geben wir die Beschriftung Kundenname.
Um nach der Eingabe eines Datensatzes diesen zu speichern, fügen wir jetzt noch dem
Composite einen Button hinzu. Für den Button nehmen wir unter LAYOUTDATA die gleichen
Einstellungen vor, wie für die Label und Textfelder. Als Beschriftung geben wir im Inspec-
tor unter TEXT Übernehmen ein. Damit ist die Implementation des linken oberen Bereichs
abgeschlossen.
Für das Composite des linken unteren Bereichs wird als Layout FillLayout gewählt. Da
eine Tabelle und ein Button untereinander angeordnet sein sollen, verändern wir die Ein-
stellung layout style auf vertical. Dann fügen wir zunächst dem Composite compLu
eine Tabelle hinzu und anschließend der Tabelle zwei Spalten. Hierzu wählen wir in der
Control-Palette aus der Kategorie SWT Controls die Einträge Table und Table column.
Die erste Tabellenspalte erhält als Spaltenüberschrift unter TEXT Kundennummer, die zwei-
te Kundenname.
255
eclipse_v01.book Seite 256 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
Als Letztes fügen wir im linken unteren Bereich noch einen Button ein. Dieser erhält als
Beschriftung Aktualisieren.
Die Bearbeitung des rechten oberen Bereichs beginnen wir mit den Einstellungen zur
Group. Im Inspector wählen wir als Layout GridLayout, unter NUMCOLUMNS 2 und unter
TEXT geben wir Allgemeine Einstellungen ein. Anschließend fügen wir der Group ein
Label hinzu, welches die Beschriftung Fenstergröße erhält. Als Nächstes wählen wir in
der Control-Palette aus der Kategorie SWT Controls den Eintrag COMBO und klicken im
Control Tree oder der Content Pane die gewünschte Position an. Um die Einträge für die
Combobox zu definieren, klicken wir im Inspector unter ITEMS auf das Symbol und ge-
ben im daraufhin erscheinenden Fenster die Einträge 600x400, 750x500, 900x600 unterei-
nander ein. Jetzt folgt noch ein Label mit der Beschriftung Hintergrundfarbe und als
Letztes fügen wir aus der Kategorie SWT Controls eine Liste ein. Die Einträge für die Liste
(grau, blau, weiß, rot, grün, gelb) werden wieder eingegeben, indem im Inspector unter
ITEMS auf das Symbol geklickt wird.
Zum Abschluss erfolgt die Implementation des rechten unteren Bereichs. Als Layout stel-
len wir hier für das Composite compRu das FillLayout ein und unter LAYOUT STYLE verti-
cal. Dem Composite wird zunächst ein TabFolder aus der Kategorie SWT Composites im
Inspector hinzugefügt. Anschließend werden dem TabFolder zwei TabItems ebenfalls aus
der Kategorie SWT Composites hinzufügt. Unter der Eigenschaft TEXT geben wir dann für
das erste TabItem Eingabe und für das zweite TabItem Tabelle ein.
256
eclipse_v01.book Seite 257 Montag, 30. Januar 2006 12:02 12
Als Layout für das erste Composite wählen wir FillLayout und unter LAYOUT STYLE die Op-
tion vertical. Anschließend fügen wir dem Composite ein Label mit der Beschriftung
Schriftgröße und einen Schieberegler hinzu. Für den Schieberegler muss in der Control-
Palette in der Kategorie SWT Controls der Eintrag SCALE gewählt werden. Im Inspector ge-
ben wir für den Schieberegler unter MAXIMUM 16, unter MINIMUM 8, unter PAGEINCREMENT 2
und unter SELECTION 8 ein.
Die Group erhält zunächst als Layout das GridLayout mit einer Spalte. Anschließend defi-
nieren wir als Beschriftung für die Group Tabelle und fügen der Group zwei Radio-
buttons hinzu. Die Radiobuttons finden sich in der Control-Palette in der Kategorie SWT
Controls. Unter der Eigenschaft TEXT erhalten die Radiobuttons ihre Beschriftung, und zwar
das erste mit Gitternetzlinien und das zweite ohne Gitternetzlinien. Da beim
Starten der Anwendung die Einstellung mit Gitternetzlinien realisiert sein soll, wird die Ei-
genschaft SELECTION für den ersten Radiobutton auf true gesetzt.
257
eclipse_v01.book Seite 258 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
tabelleGroup.setText("Tabelle");
final Button mitGitternetzlinienButton =
new Button(tabelleGroup, SWT.RADIO);
mitGitternetzlinienButton.setSelection(true);
mitGitternetzlinienButton.setText("mit Gitternetzlinien");
final Button ohneGitternetzlinienButton =
new Button(tabelleGroup, SWT.RADIO);
ohneGitternetzlinienButton.setText("ohne Gitternetzlinien");
Nachdem jetzt alle Komponenten dem Fenster hinzugefügt worden sind, implementieren
wir noch die Ereignisverarbeitung. Im linken oberen Bereich soll beim Klicken auf den
ÜBERNEHMEN-Button der eingegebene Datensatz in einer Liste gespeichert werden und die
Textfelder sollen geleert werden. Hierzu fügen wir ein Attribut daten, welches vom Da-
tentyp java.util.LinkedList ist, der Klasse Fenster hinzu. Damit sind die Daten
global innerhalb der Klasse und allen für die Ereignisverarbeitung benötigten anonymen
Klassen bekannt. Anschließend erzeugen wir in der Methode createContents ein Objekt
der Klasse LinkedList zum Speichern der Daten in einer Liste. Da in der Liste Objekte
vom Typ Daten gespeichert werden sollen, die Klasse Daten sich aber im Package daten
befindet, muss außerdem die Klasse Daten importiert werden.
import daten.Daten;
Danach wählen wir den ÜBERNEHMEN-Button im Control Tree oder in der Content Pane an
und wählen im Inspector unter EVENTS zunächst SELECTION. Anschließend klicken wir dop-
pelt in die Zelle rechts neben dem Eintrag WIDGETSELECTED. Wir gelangen dadurch automa-
tisch in die Quelltextansicht. Hier wurde bereits die Adapterklasse SelectionAdapter
mit einem leeren Methodenrumpf für die Methode widgetSelected implementiert. Wir
programmieren jetzt den Methodenrumpf wie folgt:
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Daten datSatz = new Daten(text.getText(),text_1.getText());
daten.add(datSatz);
text.setText("");
text_1.setText("");
}});
258
eclipse_v01.book Seite 259 Montag, 30. Januar 2006 12:02 12
Auch für die Ereignisverarbeitung der weiteren GUI-Elemente müssen wir jeweils das Er-
eignis widgetSelected im Inspector auswählen und anschließend im Quelltext in der
Methode widgetSelected die erforderlichen Anweisungen eingeben. Im Folgenden sind
für die weiteren GUI-Elemente die gewünschten Reaktionen sowie die Implementationen
der widgetSelected-Methode dargestellt.
Wird im linken unteren Bereich auf den AKTUALISIEREN-Button geklickt, sollen die bisher
eingegebenen Daten in der Tabelle angezeigt werden.
aktualisierenButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
String[][] datFeld = new String[daten.size()][2];
for (int i=0; i<daten.size(); i++) {
Daten datSatz = new Daten();
datSatz = (Daten)daten.get(i);
datFeld[i][0] = datSatz.getKundenNr();
datFeld[i][1] = datSatz.getKundenName();
}
final TableItem[] tableItem = new TableItem[daten.size()];
for (int i=0; i<daten.size(); i++) {
tableItem[i] = new TableItem(table,0);
tableItem[i].setText(datFeld[i]);
}
daten = new java.util.LinkedList();
}});
Da nur für die seit dem letzten Klick auf den AKTUALISIEREN-Button eingegebenen Daten
Tabellenzeilen erzeugt werden müssen, wird jeweils die Liste daten durch die letzte An-
weisung geleert.
Die Auswahl einer Fenstergröße im rechten oberen Bereich soll die Größe entsprechend
verändern.
combo.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
String item = combo.getText();
if (item.equals("600x400")) shell.setSize(600,400);
else if (item.equals("750x500")) shell.setSize(750,500);
else if (item.equals("900x600")) shell.setSize(900,600);
}
});
Die Wahl einer Hintergrundfarbe sorgt dafür, dass der Hintergrund der beiden oberen Be-
reiche in der ausgewählten Farbe erscheint.
259
eclipse_v01.book Seite 260 Montag, 30. Januar 2006 12:02 12
Der WindowBuilder
list.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
String[] farbe = list.getSelection();
Display display = Display.getDefault();
if (farbe[0].equals("grau")) {
compLo.setBackground(
display.getSystemColor(SWT.COLOR_GRAY));
compRo.setBackground(
display.getSystemColor(SWT.COLOR_GRAY));
}
else if (farbe[0].equals("blau")) {
compLo.setBackground(
display.getSystemColor(SWT.COLOR_BLUE));
compRo.setBackground(
display.getSystemColor(SWT.COLOR_BLUE));
}
// analog für weiß, rot, grün, gelb
Wird im rechten unteren Bereich im Register EINGABE der Schieberegler betätigt, so ändert
sich entsprechend die Schriftgröße der Label- und Button-Beschriftungen im linken oberen
Bereich.
scale.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Display display = Display.getDefault();
kundennummerLabel.setFont(new org.eclipse.swt.graphics.Font(
display,"Arial",scale.getSelection(),SWT.NORMAL));
kundennummerLabel.pack();
kundennameLabel.setFont(new org.eclipse.swt.graphics.Font(
display,"Arial",scale.getSelection(),SWT.NORMAL));
kundennameLabel.pack();
button.setFont(new org.eclipse.swt.graphics.Font(
display,"Arial",scale.getSelection(),SWT.NORMAL));
button.pack();
}});
Die Wahl der Einstellung mit Gitternetzlinien im Register TABELLE sorgt dafür, dass die Ta-
belle mit Gitternetzlinien dargestellt wird.
mitGitternetzlinienButton.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
table.setLinesVisible(true);
}});
260
eclipse_v01.book Seite 261 Montag, 30. Januar 2006 12:02 12
Die Wahl der Einstellung ohne Gitternetzlinien zeigt bei der Tabelle keine Gitternetzlinien
an.
mitGitternetzlinienButton.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
table.setLinesVisible(false);
}});
Damit ist die Implementation des SWT-Beispiels mithilfe des WindowBuilder abgeschlos-
sen.
261
eclipse_v01.book Seite 262 Montag, 30. Januar 2006 12:02 12
eclipse_v01.book Seite 263 Montag, 30. Januar 2006 12:02 12
Die Java 2 Platform, Enterprise Edition (J2EE) definiert einen Standard für die Entwick-
lung von mehrschichtigen Anwendungen. Wie bei der Java 2 Platform, Standard Edition
(J2SE) gilt der Grundsatz der Plattformunabhängigkeit. J2EE kombiniert die bereits in
J2SE existierenden Technologien, wie JDBC API für Datenbankzugriffe oder RMI für den
Aufruf von Objekten in entfernten virtuellen Maschinen. Daneben unterstützt J2EE als ser-
verseitige Komponenten die so genannten Enterprise Java Beans (EJBs) sowie die Java
Servlet API und Java Server Pages (JSP). J2EE verwendet einen einheitlichen Standard für
diese Technologien, so dass Anwendungen mit den unterschiedlichsten Anforderungen ab-
gebildet werden können. Ein Beispiel für die Architektur einer J2EE-Anwendung ist in
Abb. 7.1 dargestellt.
1. Der Tomcat Server wird im Rahmen des Apache Jakarta Project entwickelt und kann unter
http://jakarta.apache.org/tomcat herunter geladen werden. Der JBoss Server wird von der JBoss Group
entwickelt und steht unter http://www.jboss.org zur Verfügung.
263
eclipse_v01.book Seite 264 Montag, 30. Januar 2006 12:02 12
XML
Die Entscheidung für einen Server hat aber kaum Auswirkungen auf die Entwicklung der
Webkomponenten oder der EJBs. Es existieren vor allem Unterschiede bei der Verteilung
der Komponenten auf die Systeme (Deployment). Der Programmcode der Beispiele in die-
sem Buch und die Beschreibung der technischen Aspekte können auch auf andere J2EE-
fähige Systeme übertragen werden.
Im Folgenden beschäftigen wir uns zunächst mit den Technologien XML und JSP. Es wird
die Fragestellung behandelt, wie diese Technologien mit Eclipse gehandhabt werden. Für
das komfortable Erstellen und Editieren von solchen Dokumenten sind das Hervorheben
von Tags und Befehlen (Highlighting) sowie eine Syntaxprüfung erforderlich. Rudimentäre
Funktionalitäten sind in Eclipse vorhanden. Für weitere Anforderungen an einen XML-
bzw. JSP-Editor stehen diverse Plug-Ins zur Verfügung, von denen wir die gängigen und
leistungsfähigsten betrachten. Die Erstellung von statischen HTML-Seiten kann als eine
Umsetzung von XML-Dokumenten oder als eine Spezialform eines JSP-Dokuments be-
trachtet werden. Aus diesem Grund werden wir darauf nicht explizit eingehen.
Im Anschluss werden wir uns damit beschäftigen, wie wir Webanwendungen erstellen und
auf dem Webserver installieren. Die Architektur einer solchen Anwendung ist noch ver-
gleichsweise einfach, da ausschließlich Browser und Webserver miteinander kommunizie-
ren. Die erste Erweiterung, die wir betrachten, ist die Integration von Datenbankservern.
Wir verwenden den MySQL Datenbankserver1. Dabei ist es grundsätzlich irrelevant, wel-
ches System benutzt wird.
Den Schwerpunkt dieses Kapitels bildet aber die Integration von Enterprise Java Beans.
Wir betrachten die unterschiedlichen Arten von EJBs (Session, Entity und Message Driven
Beans). Neben der Entwicklung der Serverkomponenten der Anwendung werden wir aber
auch verschiedene Clients untersuchen. Abhängig von der Systemkonfiguration sind einige
Aspekte zu unterscheiden.
7.1 XML
7.1.1 Einführung
XML (Extensible Markup Language) ist eine Metasprache zur Definition von Markup-
Sprachen. XML-Dokumente speichern Daten, die als Entitäten bezeichnet werden. Sie be-
stehen im Wesentlichen aus Tags und Daten. Die logische Bedeutung der Tags kann frei
festgelegt werden. XML-Dokumente eignen sich für den Datenaustausch zwischen unter-
schiedlichen Systemen und zur Speicherung von Informationen.
Bei der Entwicklung von XML selbst wurde und wird auf Plattformunabhängigkeit und
eine einfache Verarbeitung durch Programme Wert gelegt. Dies wird dadurch erreicht, dass
XML-Dokumente in der Regel in einfachen Textdateien gespeichert und strenge Kriterien
an die Gültigkeit von XML-Dokumenten gestellt werden.
264
eclipse_v01.book Seite 265 Montag, 30. Januar 2006 12:02 12
Tags
In XML-Dokumenten treten Tags in der Regel paarweise als Start- und als End-Tag auf. Sie
geben an, welche Bedeutung der dazwischen liegende Text besitzt. Tags können auch ver-
schachtelt werden, wobei jeweils das innere Start-Tag vor dem äußeren Start-Tag durch ein
End-Tag beendet werden muss. Tags können außerdem Attribute enthalten, deren Werte
immer in Quotes-Zeichen (entweder " oder ’) eingeschlossen sind.
Prolog
XML-Dokumente beginnen mit einem Prolog. Hierbei handelt es sich um eine Deklaration,
die die XML-Version angibt, z.B.:
Außerdem wird für die Kodierung des Dokuments UTF-8 angegeben. Dabei handelt es sich
um das 8-bit Unicode Transformation Format, mit dem sich alle Unicode-Zeichen abbilden
lassen.
Das Wort DOCTYPE leitet die Deklaration ein. Danach folgt der Name des Root-Elements,
welches alle anderen Elemente (Entitäten) einschließt. Die DTD-Datei wird im Anschluss
angegeben, wobei sie wie hier auf demselben oder aber auch auf einem anderen System lie-
gen kann. In diesem Fall wird sie über eine URL angesprochen.
Die DTD definiert die Struktur und den Aufbau des Dokuments. In ihr werden die Elemente
definiert. Beispielsweise soll eine Kundenliste Kundenelemente beinhalten, die wiederum
265
eclipse_v01.book Seite 266 Montag, 30. Januar 2006 12:02 12
XML
aus Elementen wie Name, Adresse und Telefon bestehen. Dann könnte eine DTD-Datei
wie folgt aussehen1:
Die erste Zeile definiert das Root-Element Kundenliste, welches Elemente vom Typ
Kunde beinhaltet. Durch den Stern (*) wird angegeben, dass beliebig viele Kunden in der
Kundeliste stehen dürfen. Das Element Kunde besteht wiederum aus den Elementen Name,
Adresse und Telefon. Das Fragezeichen hinter Adresse gibt an, dass dieses Element
optional ist. Die Reihenfolge der Angaben ist verbindlich. Im Anschluss folgt die Defini-
tion der Elemente, denen ausschließlich Texte (Parsed Character Data: PCDATA) und
keine weiteren Elemente zugeordnet werden dürfen. Als Letztes wird schließlich eine Attri-
butsliste (ATTLIST) angegeben, die bei Verwendung des Elements Telefon zwingend not-
wendig (REQUIRED) ist.
Mithilfe der DTD wird die Struktur von XML-Dokumenten verbindlich und zentral festge-
legt. Gültige XML-Dokumente, die einen Verweis auf eine DTD enthalten, müssen dieser
DTD entsprechen. Eine solche Gültigkeitsprüfung wird von vielen XML verarbeitenden
Tools angeboten. Mir der beschriebenen DTD kann ein XML-Dokument wie folgt aufge-
baut sein2:
266
eclipse_v01.book Seite 267 Montag, 30. Januar 2006 12:02 12
XML Schema
Ein XML Schema ist eine XML-basierte Alternative zum DTD-Konzept. Es beschreibt die
Struktur eines XML-Dokuments. Dazu zählen:
쐌 Definition der Elemente
쐌 Definition der Attribute
쐌 Definition der Elemente, die innerhalb anderer Elementen vorkommen und deren Be-
ziehungen
쐌 Definition, ob ein Element Text enthält oder nicht
쐌 Definition der Datentypen für Elemente und Attribute
쐌 Definition von Standard- oder festgelegten Werten
Die Technik der XML Schemas ist leistungsfähiger als die der DTDs. Insbesondere die
Existenz von Datentypen und der Aspekt, dass sie in XML geschrieben werden und damit
leicht erweiterbar sind, ist ein Vorteil. Außerdem können Namensräume definiert werden,
in denen verschiedene Datentypen zusammengefasst werden. Wir verwenden beispiels-
weise den Namensraum http://www.w3.org/2001/XMLSchema, in dem einfache Daten-
typen wie string, long oder double definiert sind.
Als Beispiel diene wiederum die Kundenliste aus dem vorherigen Abschnitt zu den DTDs.
Wir entwickeln hierfür ein XML Schema. Dieses enthält das Root-Element <schema>,
welches einige Attribute besitzt. Die Deklaration des XML Schema sieht damit wie folgt
aus1:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://eclipsebuch.entwickler.com"
xmlns:tns="http://eclipsebuch.entwickler.com"
elementFormDefault="qualified">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Die Zeilen
targetNamespace="http://eclipsebuch.entwickler.com"
xmlns:tns="http://eclipsebuch.entwickler.com"
legen den Targetnamespace fest und geben an, dass die komplexen Datentypen, die in
diesem Schema definiert werden, dem eigenen Namensraum (this namespace: tns) "http://
eclipsebuch.entwickler.com" zugeordnet werden. Wir schreiben bei der Verwendung der
Datentypen jeweils den Namensraum davor.
267
eclipse_v01.book Seite 268 Montag, 30. Januar 2006 12:02 12
XML
Der Teil
elementFormDefault="qualified"
beschreibt, dass alle Elemente des Schemas einem Namensraum zugeordnet sein müssen.
Anschließend werden die einzelnen Elemente festgelegt:
Der Name des Tags wird hier mit Kundenliste bestimmt und ist vom Typ tns:myKun-
denliste, den wir anschließend definieren:
<xsd:complexType name="myKundenliste">
<xsd:sequence>
<xsd:element name="Kunde" type="myKunde"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
268
eclipse_v01.book Seite 269 Montag, 30. Januar 2006 12:02 12
<xsd:complexType name="myKunde">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Adresse" type="xsd:string"
minOccurs="0" />
<xsd:element name="Telefon"
minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="Typ" type="tns:myTelefontypen"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="myTelefontypen">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="mobil"/>
<xsd:enumeration value="privat"/>
<xsd:enumeration value="geschäftlich"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
269
eclipse_v01.book Seite 270 Montag, 30. Januar 2006 12:02 12
XML
In einem XML-Dokument, das auf diesem Schema basiert, verändert sich gegenüber dem
Beispiel mit der DTD das Root-Element, welches jetzt einen Verweis auf die XML Sche-
ma-Datei kundenliste.xsd besitzt1:
<Kunde>...</Kunde>
</Kundenliste>
Die Attribute des Root-Elements spezifizieren als Default Namespace (xmlns) http://
eclipsebuch.entwickler.com. Das bedeutet, dass alle in diesem XML-Dokument verwende-
ten Elemente in dem entsprechenden Namensraum deklariert worden sind.
Nach der Definition des Namensraums xsi (XML Schema Instance) kann das Attribut
schemaLocation verwendet werden. Dieses gibt den Ort des XML Schema für das vor-
liegende XML-Dokument an.
Nach Vergabe des Projektnamens belassen wir die Standardeinstellungen auf den beiden
folgenden Eingabemasken (PLUG-IN PROJECT STRUCTURE und PLUG-IN CONTENT).
Danach wählen wir als Projekt-Vorlage das Template PLUG-IN WITH AN EDITOR (siehe Abb.
7.2).
270
eclipse_v01.book Seite 271 Montag, 30. Januar 2006 12:02 12
Bei Klick auf FINISH wird ein neues Projekt erzeugt, welches die Grundfunktionalitäten ei-
nes Editors zur Bearbeitung von XML-Dokumenten beinhaltet. Im Rahmen der Plug-In-
Entwicklung können weitere Funktionalitäten hinzugefügt werden, was aber an dieser Stel-
le nicht Gegenstand der Betrachtung sein soll.
Um das Plug-In in Eclipse zu integrieren, müssen wir noch ein Java-Archiv mit den neu ge-
nerierten Klassen erstellen. Dazu klicken wir mit der rechten Maustaste auf das Projekt und
wählen EXPORT DEPLOYABLE PLUG-INS AND FRAGMENTS aus. Auf der folgenden Eingabe-
maske markieren wir unser Projekt sowie den Punkt DIRECTORY im Bereich EXPORT DESTI-
NATION. Als Zielverzeichnis geben wir den Namen des Eclipse-Verzeichnisses an und kli-
cken auf FINISH (siehe Abb. 7.3)1.
Das Plug-In wird in das plugins-Verzeichnis der Eclipse-Installation kopiert und nach dem
Neustart von Eclipse mit ausgeführt. Daraufhin können wir Dateien mit der Endung .xml
mit dem Sample XML Editor anzeigen lassen.
271
eclipse_v01.book Seite 272 Montag, 30. Januar 2006 12:02 12
XML
Der Sample XML Editor ist vor allem in der Lage, XML-Dokumente anzuzeigen (siehe
Abb. 7.4). Allerdings fehlt eine Darstellung in Form einer Outline View oder die Syntax-
prüfung eines XML-Dokuments in Bezug auf eine DTD oder XML-Schema-Datei. Solche
Funktionalitäten können wir durch Programmieren dem Plug-In hinzufügen, wir wollen
das aber an dieser Stelle nicht vertiefen, da wir auf andere frei verfügbaren XML-Editoren
zurückgreifen.
Abb. 7.4: Darstellung eines XML-Dokuments mit dem Sample XML Editor
272
eclipse_v01.book Seite 273 Montag, 30. Januar 2006 12:02 12
Ant Editor
Der Ant Editor ist ein Editor für die so genannten Ant-Skripte, die als XML-Dokumente
abgespeichert werden. In Ant-Skripten können beispielsweise die Schritte, die für das
Deployment einer Anwendung auf einen J2EE Server notwendig sind, zusammengefasst
werden. Beim Deployment der Anwendung muss dann nur noch das Ant-Skript und nicht
jeder Schritt einzeln ausgeführt werden. Ant-Skripte besitzen eine bestimmte Struktur und
beinhalten wie HTML-Dokumente spezielle Tags. Der Ant Editor überprüft die Struktur
und hilft bei der Erstellung von Ant-Skripten durch Angabe von möglichen Tags und Attri-
buten.
Über das Menü WINDOWS | PREFERENCES können wir Einstellungen für den Ant Editor vor-
nehmen. Dazu zählen beispielsweise die Farbgebung der einzelnen Teile des Ant-Skripts
und Angaben zur Formatierung.
Der Ant Editor verfügt weiterhin über eine Outline View, in der die Elemente des Ant-
Skripts übersichtlich angezeigt werden.
XMLBuddy
Ein weiteres Plug-In zur Bearbeitung von XML-Dokumenten in Eclipse ist XMLBuddy,
welches von der Firma Bocaloco Software als Eclipse Plug-In entwickelt worden ist.1
XMLBuddy bietet eine benutzerdefinierbare Farbgebung, Unterstützung bei Verwendung
und Generierung von DTDs, Gültigkeitsprüfungen in Bezug auf DTDs und XML Schemas
sowie eine synchronisierte Outline View. Vor der Nutzung müssen wir XMLBuddy in das
plugins-Verzeichnis von Eclipse kopieren und Eclipse neu starten.
Darstellung
Nach dem Öffnen eines XML-Dokuments mit XMLBuddy erscheint unter anderem die
Outline View. Hier sehen wir die einzelnen Elemente strukturiert dargestellt. Weiterhin
wird der Menüleiste der Eintrag XML hinzugefügt. Im Editorfenster selbst werden die
Tags, Texte, Kommentare etc. farblich unterschiedlich hervorgehoben. Die verwendeten
Farben können vom Benutzer verändert werden. Außerdem ist es möglich, den XML-Code
automatisch zu formatieren. Dazu muss der (gesamte oder Teile vom) Code markiert und
der Menüpunkt XML | FORMAT ausgewählt werden, wodurch die Zeilen, die zu einem Ele-
ment gehören, jeweils eingerückt werden.
Gültigkeitsprüfung
Über den Menüpunkt XML | VALIDATE können wir eine Gültigkeitsprüfung starten. Diese
vergleicht das XML-Dokument mit der DTD oder mit dem XML Schema und meldet even-
tuell auftretende Fehler. Mögliche Fehler sind, dass die Elemente nicht in der vorgegebenen
Reihenfolge stehen, dass Attributswerte nicht definiert sind oder dass nichtoptionale Felder
ausgelassen worden sind. In Abb. 7.5 wird dem Attribut Typ des Elements Telefon der
Wert moil statt mobil zugeordnet. Daher wird die Zeile als fehlerhaft markiert, weil der
Wert moil in der entsprechenden Enumeration im XML Schema nicht vorkommt.
273
eclipse_v01.book Seite 274 Montag, 30. Januar 2006 12:02 12
XML
JSP-Editoren
JSP-Editoren benötigen wir zum Erstellen von JSP-Dokumenten. Hierbei werden HTML-
Tags und Java-Code in einem Dokument vermischt. Daraus ergibt sich, dass ein JSP-Editor
einerseits Gültigkeitsüberprüfungen und Code-Assistenz für den HTML-Teil als auch eine
Syntaxüberprüfung des Java-Codes bereitstellen sollte.
274
eclipse_v01.book Seite 275 Montag, 30. Januar 2006 12:02 12
JSP-Editoren werden bei der Erstellung von Webanwendungen verwendet. Da wir uns noch
nicht näher mit JSP-Dokumenten beschäftigt haben, werden wir uns den Funktionalitäten
von JSP-Editoren im Abschnitt 7.3.2 widmen, nachdem wir die Erstellung von JSP-Doku-
menten untersucht haben.
7.2 Webanwendungen
7.2.1 Grundlagen
Webanwendungen sind mehrschichtige Anwendungen. Die Präsentationsschicht liegt da-
bei auf der einen Seite beim Webclient bzw. beim Browser, der z.B. HTML-Dokumente
darstellt. Auf der anderen Seite wird die Präsentation vom Webserver aufbereitet, der bei-
spielsweise über JSP-Dokumente oder Servlets HTML-Dokumente erzeugt und versendet.
JSPs und Servlets können dabei auf Datenbankserver oder andere Systeme zugreifen. In
diesem Kapitel wird zunächst die Programmierung für den Webserver im Vordergrund ste-
hen.
Grundsätzlich lässt sich die Kommunikation zwischen Browser und Webserver wie folgt
darstellen:
1. Der Browser sendet eine Anfrage (HTTP Request) an einen Webserver.
2. Der Webserver verarbeitet diesen Request. Dies erfolgt beispielsweise durch Aufruf
von bestimmten Methoden innerhalb eines Servlets. Dabei wird aus dem HTTP-Re-
quest ein Request-Objekt erzeugt, so dass die Informationen der Anfrage innerhalb des
Servlets genutzt werden können.
3. Zusätzlich wird ein Response-Objekt erzeugt, welches unter anderem das neu erzeugte
HTML-Dokument erhält und nach Bearbeitung des Servlets an den Client bzw. Brow-
ser zurückgesendet wird.
Der Ablauf ist in Abb. 7.6 schematisch dargestellt.
275
eclipse_v01.book Seite 276 Montag, 30. Januar 2006 12:02 12
Webanwendungen
276
eclipse_v01.book Seite 277 Montag, 30. Januar 2006 12:02 12
Das Response-Objekt wird ebenfalls an die Methoden übergeben. Es ist ein Objekt vom
Typ javax.servlet.http.HttpServletResponse. Es enthält die Daten, die an den
Client zurückgesendet werden. Wir verwenden es vor allem für das Verschicken des
HTML-Dokuments.
Der Programmcode des Servlets zur Addition zweier Zahlen sieht wie folgt aus:
package com.entwickler.eclipsebuch.web;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
277
eclipse_v01.book Seite 278 Montag, 30. Januar 2006 12:02 12
Webanwendungen
Beim Klick auf den Submit Button BERECHNEN wird ein HTTP Get Request an den Webser-
ver gesendet. Dort wird ein Objekt der Klasse Rechenmaschine instanziiert und die do-
Get-Methode aufgerufen. Dazu verweist das action-Attribut des FORM-Tags auf calcu-
lator. Dieser Name wird in der Konfigurationsdatei zu dieser Anwendung (Deployment-
Deskriptor) spezifiziert und der entsprechenden Servlet-Klasse zugeordnet. Das name-
Attribut legt den Namen des Parameters fest, der für den Inhalt des Textfelds verwendet
wird. Dieser Wert wird im Servlet mithilfe der Methode getParameter(name) aus dem
Objekt request ausgelesen.
Deployment-Deskriptor
Der Deployment-Deskriptor ist ein XML-Dokument. Es trägt stets den Namen web.xml.
Damit die Informationen dem Tomcat Server zur Verfügung stehen, muss die Datei im
WEB-INF-Verzeichnis der Anwendung stehen. Der Deployment-Deskriptor sieht wie folgt
aus:
<servlet-mapping>
<servlet-name>rechner</servlet-name>
<url-pattern>/calculator</url-pattern>
</servlet-mapping>
</web-app>
Das Element <url-pattern> gibt den Namen vor, über den das Servlet von einem
HTML-Dokument aus angesprochen wird. Besitzt also das action-Attribut eines Form-
Tags den Wert calculator, so wird vom Tomcat Webserver das Servlet mit dem Namen
rechner (Element <servlet-name>) erzeugt. Das Element <servlet-class> gibt den
Typ (com.entwickler.eclipsebuch.web.Rechenmaschine) des Servlets an. Je
nachdem, ob das method-Attribut des Form-Tags im HTML-Dialog den Wert get oder
post besitzt, wird die Methode doGet bzw. doPost aufgerufen.
278
eclipse_v01.book Seite 279 Montag, 30. Januar 2006 12:02 12
Deployment
Nachdem wir nun die Programmierung abgeschlossen haben, müssen wir das Servlet noch
kompilieren und das Projekt auf den Server übertragen. Im Verzeichnis des Tomcat Web-
servers gibt es dafür ein Unterverzeichnis webapps. Alle Webanwendungen, die hier ge-
speichert sind, werden beim Start von Tomcat standardmäßig initialisiert.
Vor dem Deployment überprüfen wir, ob die für Webanwendungen verwendete Verzeich-
nisstruktur von uns korrekt eingehalten worden ist. Sie ist in Abb. 7.7 als Package Explorer
und Navigator View dargestellt.
279
eclipse_v01.book Seite 280 Montag, 30. Januar 2006 12:02 12
Webanwendungen
Nach Klick auf den Button mit der Beschriftung BERECHNEN erscheint das HTML-Doku-
ment aus Abb. 7.9.
Exception Handling
Falls wir aber auf der Eingabemaske keine gültige Zahl eingeben, so wird vom Servlet eine
Exception ausgelöst, für die ein Fehlertext in für den Benutzer wenig ansprechender Form
an den Browser gesendet wird. Wir erweitern daher unser Beispiel Rechenmaschine um
ein Exception Handling, das wir in die doGet-Methode aufnehmen:
…
try{
int x = Integer.parseInt(request.getParameter("x"));
int y = Integer.parseInt(request.getParameter("y"));
out.println("Berechnung: "+x+" + "+y+" = " + (x+y));
}
catch(Exception ex) {
out.println("<H1>");
out.println("Bitte geben Sie gültige ganze Zahlen ein.");
out.println("</H1>");
}
<welcome-file-list>
<welcome-file>eingabe.html</welcome-file>
</welcome-file-list>
Nach dem erneuten Export der Projektdateien und einem Beenden und Starten des Tomcat
Webservers sind die Änderungen wirksam. Nach Eingabe der Adresse (ohne speziellen Da-
teinamen) http://localhost:8080/MyCalculator/ erscheint die Eingabemaske. Stehen in den
280
eclipse_v01.book Seite 281 Montag, 30. Januar 2006 12:02 12
Textfeldern keine gültigen Zahlen, erscheint nach Klick auf den Button BERECHNEN die
Meldung, die in Abb. 7.10 angezeigt wird.
281
eclipse_v01.book Seite 282 Montag, 30. Januar 2006 12:02 12
Webanwendungen
<body>
<H1>
<%-- Java-Ausdruck --%>
<%= ausgabe %>
</H1>
</body>
</html>
Im ersten Teil des Dokuments steht in diesem Beispiel der Java-Code zur Berechnung der
Summe der beiden eingegebenen Zahlen. Auf einem JSP-Dokument können wir dazu das
Objekt mit der Bezeichnung request verwenden. In diesem sind die Informationen des
Request gespeichert. Der zweite Teil beinhaltet die HTML-Tags. In JSP-Dokumenten kön-
nen HTML-Tags und Java-Code beliebig vermischt werden. Dies trägt aber nicht zur Über-
sichtlichkeit bei. Aus diesem Grund haben wir im oberen Teil des Dokuments die Variable
ausgabe definiert, deren Inhalt mithilfe des Java-Ausdrucks <%=ausgabe%> ausgegeben
wird.
Neben dem JSP-Dokument benötigen wir wiederum eine Eingabemaske, die nahezu iden-
tisch zu der aus dem vorherigen Abschnitt ist. Lediglich den Wert des action-Attributs des
Form-Tags verändern wir in ausgabe.jsp1. Dadurch wird bei einem Klick auf den Button
BERECHNEN das eben dargestellte JSP-Dokument aufgerufen.
Deployment-Deskriptor
Abschließend müssen wir noch die Datei web.xml im WEB-INF-Verzeichnis erzeugen.
Weil dieses Projekt über keine Servlets verfügt, sind die entsprechenden Elemente zur De-
finition von Servlets nicht erforderlich und die XML-Datei enthält folgenden Code:
Die Webanwendung besteht in diesem einfachen Fall aus drei Dateien: eingabe.jsp, aus-
gabe.jsp und web.xml, wobei die ersten beiden im Verzeichnis MyCalculatorJSP und der
Deployment-Deskriptor web.xml im Verzeichnis MyCalculatorJSP/WEB-INF liegen. Das
gesamte Verzeichnis MyCalculatorJSP kopieren wir in das webapps-Verzeichnis der Tom-
cat-Installation und starten den Server.
282
eclipse_v01.book Seite 283 Montag, 30. Januar 2006 12:02 12
7.3.1 Features
Das Eclipse-Projekt Web Tools Platform (WTP) erweitert Eclipse um Features, die für die
Entwicklung von Webanwendungen, J2EE-Anwendungen oder Web Services nützlich
sind. Die WTP stellt beispielsweise Editoren für HTML, JSP, XML, DTD, XSD etc. zur
Verfügung, unterstützt den Entwickler bei der Erstellung und dem Deployment von Enter-
prise Java Beans (EJB) oder hilft beim Erzeugen von Web Services und deren Clients.
Das WTP-Projekt ist ein Eclipse-Projekt, welches ursprünglich von IBM und ObjectWeb
unterstützt worden ist. Die beiden Hauptanteile an Code, die in das WTP-Projekt eingegan-
gen sind, sind Teile des WebSphere Studio Application Developer (WSAD) von IBM und
Teile des Lomboz-Plug-In von ObjectWeb.
Das WTP unterteilt sich in zwei Unterprojekte, das Web Standard Tools (WST) und das
J2EE Standard Tools (JST).
Beim WST geht es um die Unterstützung bei der Entwicklung von Webanwendungen und
WSDL-Dokumenten/Web Services. Bei der Programmierung helfen vor allem die Edito-
ren, die für unterschiedliche Arten von Dokumenten (HTML, JSP, XML etc) Features wie
Syntax-Highlighting Vervollständigung von Befehlen oder Tags, Auswahlmöglichkeiten
von Methoden oder Parametern etc. anbieten. Deployment-Deskriptoren werden ebenfalls
erzeugt und das Deployment wird automatisiert durchgeführt.
Im Bereich des JST geht es um die Entwicklung von J2EE-Anwendungen. Assistenten hel-
fen beim Generieren von EJBs und erstellen die notwendigen zusätzlichen Klassen, Inter-
faces und Deployment-Deskriptoren. Spezielle Editoren erlauben dabei unterschiedliche
Sichten auf die Dokumente.
Im Laufe dieses Kapitels werden wir viele Features von WTP (WST und JST) kennen ler-
nen. Auch wenn die WTP uns Arbeit abnimmt und vielfach Klassen, Interfaces oder De-
ployment-Deskriptoren komplett erzeugt, ist es für einen Entwickler dennoch erforderlich,
zu wissen, welche Informationen an welchen Stellen gespeichert werden. Aus diesem
Grund werden wir nicht nur die WTP, sondern auch die theoretischen Hintergründe von
J2EE und den verwandten Technologien untersuchen.
283
eclipse_v01.book Seite 284 Montag, 30. Januar 2006 12:02 12
7.3.2 Editoren
XML Editor
Der XML Editor verfügt über zwei Ansichten. In der SOURCE PANE wird das Dokument text-
basiert angezeigt, wobei die XML-Elemente grün, Attribute lila, Strings blau sowie die In-
halte schwarz angezeigt werden. Diese Farben können auf der Eingabemaske PREFERENCES
unter WEB AND XML XML FILES XML STYLES geändert werden.
In der Design Pane wird das XML-Dokument in einer anderen Form dargestellt. Die Ele-
mente und Attribute erscheinen in einer Spalte und die Inhalte in einer zweiten. Auf diese
Weise erhält man eine Übersicht über die Informationen innerhalb des Dokuments und
kann diese in einfacher Weise ändern. Durch Klick auf die rechte Maustaste, können neue
Elemente, Attribute etc. hinzugefügt werden.
In der Outline View, die ebenfalls mit dem XML Editor verbunden ist, werden lediglich die
Elemente in einer Baumstruktur angezeigt. Bei Auswahl eines Elements wird das entspre-
chende in der SOURCE oder DESIGN PANE ebenfalls ausgewählt. Auf diese Weise können in
komplexen Dokumenten einzelne Elemente vergleichsweise schnell gefunden werden.
284
eclipse_v01.book Seite 285 Montag, 30. Januar 2006 12:02 12
JSP Editor
Beim Editieren von JSP-Dokumenten werden unter anderem JSP- und HTML-Tags sowie
Java Code innerhalb von Scriptlets verwendet. Der entsprechende Editor bietet beispiels-
weise folgende Features an:
쐌 Highlighting: farbliche Hervorhebung von Tags, Texten, Kommentaren etc.
쐌 Code-Assistent für einfache HTML-Tags
쐌 Code-Assistent für JSP Actions, wie z.B. <java:useBean …>
쐌 Code-Assistent für JSP-Ausdrücke, Java-Skriptlets und Direktiven
쐌 Code-Assistent für JSP Taglibs
Es ist zu erkennen, dass die unterschiedlichen Sprachen und deren Elemente unterstützt
werden. Die Farbgebung richtet sich dabei nach den jeweiligen Styles, die auf der Einga-
bemaske PREFERENCES unter WEB AND XML verändert werden können.
Auf dem JSP-Dokument wird der Bereich mit reinem HTML und der mit den Java-Befeh-
len farblich unterschiedlich hervorgehoben. Der Code-Assistent vervollständigt einerseits
im Bereich der Java-Skriptlets die Methodennamen etc. und gibt andererseits die Attribute
zu den HTML-Tags und JSP-Actions an. Zum Anzeigen der Attribute sind hinter dem Tag
die Tasten Ÿ | Leertaste zu drücken. Außerdem wird eine Syntaxprüfung der einzelnen
Bereiche durchgeführt, so dass vor allem einfache Tippfehler leicht beseitigt werden kön-
nen.
7.3.3 Installation
Neben der Eclipse-Installation (Version 3.1) müssen vor dem Verwenden der WTP folgen-
de Plug-Ins installiert werden:
쐌 Eclipse Modeling Framework (EMF, Version 2.1)
쐌 Graphical Editing Framework (GEF, Version 3.1)
쐌 Java EMF Model Runtime (JEM, Version 1.1)1
쐌 WebTools Platform; Runtime (WTP, Version 1.0)
Die Version von EMF, GEF und JEM hängt von der verwendeten Version der WTP ab. Es
gibt ebenfalls die Möglichkeit, WTP mit den drei anderen Plug-Ins komplett zu installieren
oder eine Eclipse-Installation mit integrierter WTP und den anderen notwendigen Plug-Ins
zu verwenden. Hierbei kann es aber zu Problemen kommen, wenn man weitere Plug-Ins
verwendet, die das EMF, GEF oder JEM in einer anderen Version nutzen. Beim Einsatz des
Visual Editors (VE) ist beispielsweise darauf zu achten, dass das WTP und der VE mit den-
selben Versionen arbeiten können.
Neben den Plug-Ins müssen wir zusätzlich noch XDoclet installieren. XDoclet ist eine En-
gine zur Code-Generierung. XDoclet verarbeitet Meta-Daten, die im JavaDoc-Bereich ei-
ner Java-Anwendung angegeben werden, und erstellt daraus beispielsweise Deployment-
Deskriptoren oder Ähnliches. Der Vorteil liegt dabei darin, dass bei der Entwicklung von
Enterprise Java Beans ein Großteil der Programmierarbeit wegfällt und die notwendigen
285
eclipse_v01.book Seite 286 Montag, 30. Januar 2006 12:02 12
Daten zentral in einer Datei, in der so genannten Bean-Klasse gewartet werden können. Wir
benutzen XDoclet in der Version 1.2.3.1 Da diese Version noch keine Java 5-Unterstützung
bietet, müssen wir die Datei xjavadoc-1.1.jar durch eine neue Version (z.B. xjavadoc-1.1-
j5.jar) ersetzen.
7.3.4 Einstellungen
J2EE Perspective
Die Web Tools Platform bietet uns die zusätzliche Perspektive J2EE. Bei Wahl dieser Per-
spektive wird zwischen verschiedenen Arten von Anwendungen unterschieden. Im Project
Explorer erscheinen die möglichen Projekte, die wir entwickeln können (siehe Abb. 7.11).
XDoclet
Weiterhin müssen wir für die Verwendung von XDoclet angeben, wo sich die Installation
befindet. Dazu gibt es in den Preferences von Eclipse (Menü WINDOW | PREFERENCES) den
Punkt XDOCLET. Wichtig ist hier, den XDoclet Builder freizuschalten und den Pfad der
XDoclet-Installation anzugeben. Als Version verwenden wir 1.2.3. Um bei der Entwick-
lung von J2EE-Anwendungen den JBoss Server zu unterstützen, sollte zusätzlich bei EJB-
DOCLET und WEBDOCLET die Checkbox JBOSS angekreuzt werden.
Server
Abhängig von der zu entwickelnden Anwendung und der bestehenden Systemlandschaft,
werden unterschiedliche Server verwendet. Wir unterscheiden dabei zwischen den reinen
Webservern und den Applikationsservern. Die WTP unterstützt verschiedene Server von
Apache, BEA, IBM, JBoss, ObjectWeb und Oracle. Das bedeutet, dass für diese Server vor-
gefertigte Definitionsdateien existieren, in denen steht, welche Bibliotheken benötigt wer-
den oder wie die Server gestartet bzw. gestoppt werden können.
Leider kann die Konfiguration der Server aus Eclipse heraus nicht verändert oder ein neuer
Server/eine neue Version eines Servers eingebunden werden – zumindest nicht in der vor-
liegenden Version der WTP.
286
eclipse_v01.book Seite 287 Montag, 30. Januar 2006 12:02 12
Wie neue Server konfiguriert und in die WTP eingebunden werden, wird in Kapitel 7.6 aus-
führlich beschrieben.
Im Project Explorer erscheint bei den Dynamic Web Projects das Projekt WTP-WEB01. Die
notwendigen Bibliotheken werden in den Classpath automatisch aufgenommen. Außerdem
wird das Verzeichnis, welches auf den Webserver beim Deployment übertragen wird, unter
WEBCONTENT vorgefertigt. Das bedeutet beispielsweise, dass der Deployment-Deskriptor
mit dem Namen web.xml im Verzeichnis WEB-INF schon erzeugt ist. Unter dem Eintrag
WTP-WEB01 werden die Servlets, Servlet Mappings etc. angezeigt (siehe Abb. 7.13).
287
eclipse_v01.book Seite 288 Montag, 30. Januar 2006 12:02 12
Servlet
Um ein neues Servlet zu erzeugen, wählen wir im Kontextmenü des Eintrags SERVLETS die
Option NEW | SERVLET aus. Das Servlet bekommt den Namen Calculator im Package
com.entwickler.eclipsebuch. Auf der folgenden Eingabemaske sind noch die Infor-
mationen für den Deployment Deskriptor einzutragen. Dazu zählen der Name des Servlets
(Tag <servlet-name>), den wir ebenfalls mit Calculator bezeichnen, und das URL
Pattern (Tag <url-pattern>), wofür wir /Calculator eintragen.
Auf der dritten Eingabemaske geben wir vor allem an, welche Methoden generiert werden
sollen. Wir markieren die doGet-Methode und klicken auf FINISH.
Das neu erzeugte Servlet besitzt am Anfang einen XDcolet-Bereich, in dem die Informatio-
nen für den Deployment-Deskriptor angegeben werden:
/**
* Servlet implementation class for Servlet: Calculator
*
* @web.servlet
* name="Calculator"
* display-name="Calculator"
*
* @web.servlet-mapping
* url-pattern="/Calculator"
*
*/
288
eclipse_v01.book Seite 289 Montag, 30. Januar 2006 12:02 12
Dieser Bereich wird von XDoclet analysiert und daraus wird der Deployment-Deskriptor
web.xml erzeugt. In der Console View von Eclipse werden die entsprechenden Meldungen
angezeigt.
Wir müssen die Methode doGet noch wie folgt implementieren und eine Startseite für un-
ser Webprojekt schreiben.
289
eclipse_v01.book Seite 290 Montag, 30. Januar 2006 12:02 12
HTML-Dokument
Die Startseite generieren wir, indem wir im Kontextmenü des Eintrags WEBCONTENT den
Punkt NEW | HTML anklicken und den Namen index.html vergeben. Auf der zweiten Seite
des Assistenten kann noch ein HTML-Template ausgewählt werden. Im Rumpf, also inner-
halb des <body>-Tags des Dokuments, erstellen wir das HTML-Formular:
Das HTML-Dokument wird standardmäßig im HTML-Editor der WTP geladen. Das be-
deutet, das Features wie Syntax Highlighting, Quick Fixes etc. zur Verfügung stehen. Wei-
terhin kann das HTML-Dokument im integrierten Webbrowser betrachtet werden (OPEN
WITH | WEB BROWSER), um das Layout zu kontrollieren.
Deployment
Bei der beschriebenen Entwicklung der Webanwendung wird im Projektverzeichnis ein
Verzeichnis mit dem Namen .deployables erstellt. Darin ist die gesamte Webanwendung
enthalten, die direkt in das webapps-Verzeichnis des Tomcat Servers kopiert werden kann.
Weiterhin gibt es bei Verwendung der WTP die Möglichkeit, den Tomcat Webserver direkt
aus Eclipse heraus zu starten und die Anwendung auf dem Server ablaufen zu lassen. Dazu
gehen wir wie folgt vor (siehe Abb. 7.15):
쐌 Anzeigen der Servers View (WINDOW | SHOW VIEW | SERVERS)
쐌 Auswahl von NEW | SERVER im Kontextmenü der Servers View
쐌 Markieren des Tomcat Servers in der entsprechenden Version
쐌 Konfigurieren des Tomcat- Installationsverzeichnisses
쐌 Hinzufügen des Webprojekts WTP-Web01
290
eclipse_v01.book Seite 291 Montag, 30. Januar 2006 12:02 12
Im Kontextmenü des Eintrags für den Tomcat Server in der Servers View können wir nun
den Server starten, stoppen und die Projekte veröffentlichen.
Nach dem Start des Servers wählen wir im Project Explorer im Verzeichnis WebContent im
Kontextmenü des HTML-Dokuments index.html RUN AS | 1 RUN ON SERVER. Im integrierten
Webbrowser von Eclipse erscheint daraufhin die Startseite der Anwendung, wobei diese
Seite vom Webserver geladen wird (siehe URL: http://localhost:8080/WTP-Web01/in-
dex.html). Nach Eingabe zweier Zahlen und Klick auf den SENDEN-Button wird demnach
auch das Ergebnis angezeigt.
291
eclipse_v01.book Seite 292 Montag, 30. Januar 2006 12:02 12
Mithilfe der Batch-Datei kkp.sql2 kann die Datenbank erzeugt werden. Dazu starten wir die
MySQL-Konsole und geben folgende Zeile ein:
292
eclipse_v01.book Seite 293 Montag, 30. Januar 2006 12:02 12
Auf der Maske zur Spezifikation der Verbindungsparameter sind folgende Eingaben zu ma-
chen (siehe Abb. 7.16):
쐌 Auswahl des Datenbanksystems (MySql)
쐌 Name der Datenbank (kkp)
쐌 Klasse des JDBC-Treibers (com.mysql.jdbc.Driver)
쐌 Ort der JDBC-Treiber-Datei (..\mysql-connector-java-3.1.11-bin.jar)
쐌 URL der Datenbankverbindung (jdbc:mysql://127.0.0.1:3306/kkp)
쐌 Username und Passwort für die Datenbankverbindung (falls erforderlich)
In verschiedenen Ansichten kann man sich anschließend das Schema der Datenbank, die
Inhalte einzelner Tabellen und weitere Informationen über die Datenbank ansehen.
Bei Wahl der Punkte DATA | SAMPLE CONTENTS oder DATA | OPEN im Kontextmenü der Ta-
belle Kunden können die Daten in unterschiedlichen Sichten betrachtet werden.
293
eclipse_v01.book Seite 294 Montag, 30. Januar 2006 12:02 12
Anschließend kann der Treiber in einer Java-Klasse der Webanwendung wie folgt geladen
werden:
Class.forName("com.mysql.jdbc.Driver").newInstance();
Für den Datenbankzugriff benötigen wir noch die URL der Datenbank. Diese setzt sich aus
jdbc:mysql://hostname:port/dbname zusammen.
Den Namen der Datenbank haben wir mit kkp festgelegt.
Der Hostname ist bei uns localhost oder 127.0.0.1, da der Datenbankserver auf dem-
selben Rechner liegt wie die Webanwendung. Der Port ist 3306.
Das Connection-Objekt wird demnach auf folgende Weise erzeugt (gegebenenfalls müs-
sen noch Username und Passwort angegeben werden):
Connection conn;
conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/kkp");
Wir erzeugen in dem Projekt eine neue Java-Klasse und bezeichnen sie mit Pruefung. In
dem Konstruktor der Klasse soll die Datenbankverbindung hergestellt und ein Objekt vom
Typ PreparedStatement erzeugt werden. Dieses Objekt wird dann in der Methode
gueltig verwendet, um ein Objekt vom Typ ResultSet zu generieren, wobei die beiden
Parameter Kreditkartennummer und Kundenname übergeben werden. Wenn dieser Kunde
existiert, dann wird anschließend überprüft, ob die Karte gültig ist. Ist dies der Fall, wird der
Wert true zurückgegeben, ansonsten false.
Der Programmcode der Klasse sieht dann wie folgt aus1:
package com.entwickler.eclipsebuch.kartenpruefer;
import java.sql.*;
public Pruefung(){
try {
String sql;
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/kkp");
sql ="SELECT kknummer, kname, aktiv FROM kunden ";
sql += "WHERE kknummer = ? AND kname = ?";
294
eclipse_v01.book Seite 295 Montag, 30. Januar 2006 12:02 12
ps = conn.prepareStatement(sql);
} catch (Exception e) {
System.out.println("Es ist ein Fehler aufgetreten.");
}
}
Diese Java-Klasse ist so konzipiert, dass sie aus einer beliebigen Java-Anwendung instan-
ziiert werden kann. Ihr Einsatz ist also nicht auf Webanwendungen beschränkt. Für unser
Beispiel benötigen wir noch eine Eingabeseite, auf der Kreditkartennummer und Kunden-
name eingegeben werden können, und ein Dokument, von dem aus ein entsprechendes Ob-
jekt instanziiert und die gueltig-Methode aufgerufen wird.
<html>
<head>
<title>Willkommen zur Kreditkartenprüfung</title>
</head>
<body>
<h2>Bitte geben Sie Namen und Kreidkartennummer ein:</h2>
295
eclipse_v01.book Seite 296 Montag, 30. Januar 2006 12:02 12
<form action="pruefung.jsp">
<p>Kundenname:
<input type='text' name='kundenName' size='50'></p>
<p>Kartennummer:
<input type='text' name='kartenNummer' size='20'></p>
<p>
<input type='submit' name='submit' value='Senden'>
<input type='reset' name='reset' value='Zurücksetzen'>
</p>
</form>
</body>
</html>
296
eclipse_v01.book Seite 297 Montag, 30. Januar 2006 12:02 12
Von dem JSP-Dokument kann auf alle öffentlichen Methoden der Bean vom Typ Prue-
fung aus dem Package com.entwickler.eclipsebuch.kartenpruefer zugegriffen
werden. Die Instanziierung der Bean erfolgt beim ersten Aufruf der Seite. Danach wird im-
mer auf dieselbe Bean zugegriffen.
In der Klasse Pruefung ist die öffentliche Methode gueltig definiert, die als Parameter
zwei String-Werte übergeben bekommt, von denen der erste Wert den Kundennamen und
der zweite die Kreditkartennummer angibt. Nach einer Prüfung auf Korrektheit wird true
zurückgegeben, falls die Kombination gültig ist, und false, wenn das nicht der Fall ist.
Abschließend erstellen wir folgendes JSP-Dokument, um eine entsprechende Meldung
auszugeben.
<%
String ausgabe;
if (pruefungBean.gueltig(request.getParameter("kundenName"),
request.getParameter("kartenNummer"))){
ausgabe = "Die Karte ist gültig !";
}
else{
ausgabe = "Die Karte ist nicht gültig !";
}
%>
<html>
<head>
<title>Prüfergebnis</title>
</head>
<body>
<H1> <%=ausgabe%> </H1>
</body>
</html>
297
eclipse_v01.book Seite 298 Montag, 30. Januar 2006 12:02 12
Die Klasse Pruefung wird direkt vom Webserver bzw. dessen virtueller Maschine ausge-
führt und benötigt keinen eigenen Applikationsserver. Innerhalb der Klasse wird auf eine
Datenbank zugegriffen, deren Verbindung im Konstruktor der Klasse hergestellt wird. Bei
jedem Zugriff wird ein Datensatz mit den entsprechenden Parameterwerten gesucht. Liegt
keiner vor oder besitzt das Feld aktiv den Wert false, so ist die Kreditkarte nicht gültig
und es wird false, ansonsten true zurückgegeben.
298
eclipse_v01.book Seite 299 Montag, 30. Januar 2006 12:02 12
JDBC
Java Database Connectivity (JDBC) dient dazu, aus einem Java-Programm auf Datenban-
ken zuzugreifen. JDBC besteht aus mehreren Teilen:
쐌 JDBC-API:
Die JDBC-API ist die Programmierschnittstelle. Sie definiert Interfaces, die unabhän-
gig von der zugrunde liegenden Datenbank sind. Die dahinter liegende Implementie-
rung wird von den Entwicklern der Datenbanktreiber vorgenommen. Da eine Java-An-
wendung nur die Interfaces sieht, ist sie theoretisch von der Datenbank unabhängig. In
der Regel kann eine Datenbank aber nicht ohne weiteres ausgetauscht werden, da even-
tuell spezielle SQL-Dialekte verwendet oder beispielsweise Stored Procedures imple-
mentiert worden sind, die von einer anderen Datenbank nicht direkt interpretiert werden
können.
299
eclipse_v01.book Seite 300 Montag, 30. Januar 2006 12:02 12
쐌 JDBC-Treiber:
Der JDBC-Treiber muss für eine Datenbank bereitgestellt werden, damit der Zugriff aus
einem Java-Programm mit Hilfe der JDBC-API möglich ist. Es gibt vier Klassen von
JDBC-Treibern:
a) Die Typ 1-Treiber werden auch als JDBC-ODBC-Bridge bezeichnet. ODBC (Open
Database Connectivity) ist ein Standard der Firma Microsoft, der den Zugriff auf
Datenbanken über eine genormte Schnittstelle ermöglicht. Die Typ 1-Treiber dienen
dazu, JDBC-Aufrufe in ODBC-Aufrufe umzuwandeln. Ein solcher Treiber wird in
der Java 2, Standard Edition bereits zur Verfügung gestellt, so dass der Zugriff auf
alle Datenbanken, für die ein ODBC-Treiber vorhanden ist, möglich ist.
b) Die Typ 2-Treiber sind herstellerspezifische Treiber für einzelne Datenbanksysteme.
Im Vergleich zu den Typ 1-Treibern ist die Leistungsfähigkeit höher und der Zugriff
schneller, da sie speziell auf die Technologie der Datenbank optimiert werden kön-
nen. Die Typ 2-Treiber werden zum Teil von den Herstellern der Datenbanken direkt
oder von Drittanbietern angeboten.
c) Die Typ 3-Treiber sind reine Java-Treiber, die für dreischichtige Anwendungen kon-
zipiert sind. Hierbei wird über das Netzwerk mit einer Middleware kommuniziert,
die sich um den Zugriff auf die Datenbank kümmert.
d) Die Typ 4-Treiber sind ebenfalls reine Java-Treiber, die für zweischichtige Client-
Server-Architekturen eingesetzt werden. Der Client kommuniziert direkt mit dem
Datenbank-Management-System, wobei dort eine herstellerspezifische interne und
nach außen unsichtbare Schicht implementiert ist, die als Middleware fungiert.
쐌 JDBC-Treibermanager:
Der JDBC-Treibermanager ist verantwortlich für die Verwaltung und das Laden der
verfügbaren JDBC-Treiber.
300
eclipse_v01.book Seite 301 Montag, 30. Januar 2006 12:02 12
Applikationsserver benötigen Namensdienste, damit der Client die dort installierten Kom-
ponenten von außen ansprechen kann. Die Komponenten erhalten eindeutige Namen, über
die der Client diese identifiziert und anspricht.
LDAP
Aufgrund der Vielzahl unterschiedlicher Verzeichnisdienste, die in vielen Netzwerken Ver-
wendung finden, ist die Abb. der Zugriffsrechte sehr komplex. Unterschiedliche Benutzer-
namen und Passwörter für die verschiedenen Dienste machen es schwierig, Anwendungen
zu entwickeln, bei denen mehrere Verzeichnisdienste miteinander interagieren.
Das Lightweight Directory Access Protocol (LDAP) beseitigt diese Probleme. Mit LDAP
wird definiert, wie die Clients den Datenzugriff auf dem Server vornehmen. Es ist dabei ir-
relevant, um welchen Server es sich handelt und wie dort die Daten abgespeichert sind. Für
die verschiedenen Verzeichnisdienste muss es aber ein LDAP-Front-End geben, damit der
Zugriff möglich ist. Dies ist bei den gängigen Verzeichnisdiensten wie NDS, NIS oder Win-
dows NT Domains der Fall.
LDAP ist die Grundlage für das Java Naming and Directory Interface, das im Folgenden er-
läutert wird.
JNDI
Java Naming and Directory Interface (JNDI) ist ein Interface, das Methoden für den Zugriff
auf Namens- und Verzeichnisdienste bereitstellt. JNDI ist vergleichbar mit JDBC, das für
den Zugriff auf Datenbanken benötigt wird. JNDI entkoppelt die Java-Anwendung von
dem konkreten Namens- bzw. Verzeichnisdienst.
301
eclipse_v01.book Seite 302 Montag, 30. Januar 2006 12:02 12
Mit JNDI können wir ähnlich wie bei den JDBC-Typ-1- und -Typ-2-Treibern entweder
über so genannte Service Provider mit den einzelnen Verzeichnisdiensten interagieren oder
einen LDAP-Service-Provider (analog zu den JDBC-ODBC-Treibern) verwenden, der
wiederum für die wichtigsten Verzeichnisdienste angeboten wird.
JNDI bietet für den Fall Vorteile, dass mehrere Verzeichnisdienste in einer Anwendung ver-
bunden werden müssen. Außerdem macht JNDI es für den Entwickler insgesamt einfacher,
die Interaktion zwischen Client und Verzeichnisdienst zu realisieren, weil jeweils dieselbe
JNDI-API verwendet wird. Die Kommunikation der einzelnen Dienste ist in Abb. 7.18
exemplarisch dargestellt.
Wir werden im Folgenden bei unseren Beispielanwendungen JNDI nutzen, um die EJB-
Komponenten auf dem Applikationsserver zu identifizieren und vom Client aus zu refe-
renzieren. Dabei verwenden wir die Variante, bei der der Namensdienst des Applikations-
servers direkt angesprochen wird. Dazu ist es natürlich erforderlich, dass der Applikations-
server JNDI implementiert hat.
302
eclipse_v01.book Seite 303 Montag, 30. Januar 2006 12:02 12
Die Stateful Session Beans gelten wie das Session-Objekt bei Webanwendungen für einen
Benutzer bei einer Sitzung. Die Stateless Session Beans stellen in der Regel Funktionalitä-
ten zur Verfügung, die alle Benutzer aufrufen können und für die keine Daten gespeichert
werden müssen. Entity Beans dienen zur Speicherung von Daten, auf die zumeist unter-
schiedliche Benutzer zugreifen. Bei Message Driven Beans werden Funktionalitäten nicht
direkt aufgerufen. Sie erhalten Nachrichten, auf die bestimmte Reaktionen, z.B. der Aufruf
von bestimmen Methoden, erfolgen kann.
Die EJBs werden über so genannte EJB-Container zur Verfügung gestellt. Der EJB-Con-
tainer ist ein Teil des EJB Applikationsservers, der neben der Instanziierung und dem
Löschen der Objekte noch Sicherheitskontrollen durchführt oder die Aufgaben des Trans-
aktionsmanagements übernimmt.
303
eclipse_v01.book Seite 304 Montag, 30. Januar 2006 12:02 12
Entity Beans
Entity Beans werden verwendet, um Daten, die für viele Clients zur Verfügung stehen sol-
len, zu speichern. Daneben bieten Entity Beans auch beliebige Funktionalitäten an, die in
öffentlichen Methoden implementiert werden. Entity Beans werden in der Regel persistent
gespeichert. Das bedeutet, dass ihr Zustand jeweils in einer Datenbank vorhanden ist. Es
wird zwischen der Container Managed Persistence (CMP) und der Bean Managed Persis-
tence (BMP) differenziert. Der Unterschied besteht darin, dass bei CMP nur anzugeben ist,
welche Daten persistent gespeichert werden sollen, und der Applikationsserver die Umset-
zung selbstständig übernimmt. Bei der Variante BMP müssen wir im Code in bestimmten
Methoden direkt die Speicherung der Daten programmieren. Der EJB-Container ruft dann
die jeweiligen Methoden auf.
In Abschnitt 7.11 beschreiben wir im Einzelnen den Einsatz von Entity Beans und die Va-
rianten CMP und BMP anhand von Beispielen.
EJB-Container
EJB-Container verwalten Enterprise Java Beans. Dort werden sie instanziiert und gelöscht.
Der EJB-Container ist Bestandteil eines J2EE-Applikationsservers (z.B. JBoss). Der EJB-
Container beinhaltet zum einen Instanzen der EJB-Klassen und zum anderen die dazuge-
hörigen so genannten Home-Objekte. Die Instanziierung der EJBs übernimmt der EJB-
Container. Es werden eine Instanz oder ein Pool von Instanzen erzeugt. Die Home-Objekte
zu den EJBs erzeugen dann vor dem Zugriff durch einen Client Referenzen auf diese beste-
henden Instanzen. Das erhöht die Performance, da nicht bei jedem neuen Zugriff die Ob-
jekte instanziiert werden müssen.
304
eclipse_v01.book Seite 305 Montag, 30. Januar 2006 12:02 12
Für die Installation einer EJB in einem EJB-Container sind folgende Schritte durchzufüh-
ren:
쐌 Zunächst werden Java-Archiv-Dateien mit entsprechenden Klassen und Interfaces so-
wie dem Deployment-Deskriptor an den Server übertragen. Der Deployment-Deskrip-
tor enthält vor allem eine Beschreibung der EJB. Für jede EJB generiert der Container
das korrespondierende Home-Objekt. Dieses beinhaltet die so genannte create-Me-
thode, mit deren Hilfe von einem Client aus eine Referenz auf eine Instanz der EJB-
Klasse erzeugt wird. Diese Instanz stammt aus dem Pool der Instanzen, der vom EJB-
Container gebildet worden ist. Im Allgemeinen ist also keine Instanziierung notwendig.
쐌 Das Home-Objekt muss beim Namensdienst des Servers registriert werden. Über diesen
Namen kann ein Client dann auf das Home-Objekt zugreifen und eine Referenz auf eine
Instanz der EJB-Klasse, also auf das EJB-Objekt, erhalten.
Client
Damit ein Client auf eine EJB zugreifen kann, muss dieser ein so genanntes Proxy-Objekt
erzeugen. Das ist ein clientseitiges Objekt, das die EJB repräsentiert. Die Methodenaufrufe
erfolgen über dieses Objekt und werden an den EJB-Container weitergeleitet, wobei Über-
gabeparameter ebenfalls übertragen werden. Die Datentypen der Übergabeparameter müs-
sen aus diesem Grund serialisierbar sein. Serialisierbar sind einfache Datentypen und Ob-
jekte von Klassen, die das Interface Serializable implementiert haben. Das Ergebnis
eines Methodenaufrufs wird als Rückgabewert an den Client zurückgesendet. Entspre-
chend muss der korrespondierende Datentyp serialisierbar sein.
Der Zugriff vom Client auf die öffentlichen Methoden einer EJB lässt sich demnach wie
folgt zusammenfassen:
쐌 Der Client benötigt für den Zugriff auf eine EJB zwei Interfaces. Das so genannte Home
Interface enthält unter anderem die Deklaration der create-Methode, die im Home-
Objekt implementiert ist. Das andere Interface wird als Remote Interface bezeichnet. Es
besitzt die öffentlichen Methoden der EJB. Der Client erzeugt als Erstes ein Objekt vom
Typ des Home Interface. Dazu wird der Name verwendet, mit dem die Bean sich beim
Namensdienst registriert hat. Der Namensdienst gibt dann eine Referenz auf das so ge-
nannte Home-Objekt im EJB-Container zurück. Mit Hilfe des Home-Objekts wird eine
Referenz der eigentlichen EJB an den Client gegeben.
쐌 Beim Aufruf einer Business-Methode des Bean-Objekts wird jeweils vom Applika-
tionsserver überprüft, ob der Client für den Aufruf der Methode berechtigt ist, und ge-
gebenenfalls eine Transaktion gestartet. Danach delegiert er den Methodenaufruf an die
Bean, die diesen dann ausführt. Falls sich der Zustand des Objekts ändert, wird dieser in
der Datenbank gespeichert und die Transaktion bei Bedarf beendet. Anschließend kann
der Client wieder auf den veränderten Zustand des Objekts zugreifen.
In Abb. 7.19 ist die Kommunikation zwischen Client und Server zum Zugriff auf eine EJB
vereinfacht dargestellt.
305
eclipse_v01.book Seite 306 Montag, 30. Januar 2006 12:02 12
Session Beans
7.5.1 Bean-Klasse
In Abhängigkeit von der Art der Bean (Session, Entity oder Message Driven Bean) imple-
mentiert die Bean-Klasse das Interface SessionBean, EntityBean oder Message-
DrivenBean aus dem Package javax.ejb. Diese Interfaces bzw. dieses Package stammt
aus der Bibliothek j2ee.jar, die in den Classpath eines EJB-Projekts mit aufgenommen wer-
den sollte. Die Datei j2ee.jar stammt aus dem lib-Verzeichnis der Installation des J2EE
SDK1 von Sun.
In den Interfaces stehen jeweils Methoden, die vom EJB-Container zu bestimmten Zeit-
punkten aufgerufen werden. Beispielsweise gibt es die ejbActivate-Methode, die vom
EJB-Container aufgerufen wird, wenn eine Instanz aus dem Pool herausgenommen und
von einem Objekt (des Clients) referenziert wird.
Weiterhin definieren wir in der Bean-Klasse die ejbCreate-Methode. Diese korrespon-
diert mit der create-Methode des Home-Objekts und besitzt jeweils dieselbe Parameter-
liste. Die create-/ejbCreate-Methode kann überladen werden. Für jede ejbCreate-
Methode, die wir in die Bean-Klasse schreiben, müssen wir eine entsprechende create-
Methode mit derselben Signatur im Home Interface definieren. Wir rufen also nicht direkt
die ejbCreate-Methode des EJB-Objekts auf, sondern verwenden die create-Methode
des Home-Objekts, die dann wiederum die ejbCreate-Methode auslöst.
Neben diesen Methoden, die ausschließlich vom EJB-Container angesprochen werden, be-
inhaltet die EJB die Geschäftsmethoden, in denen sich die eigentliche Logik der Kompo-
nenten befindet. Die öffentlichen Methoden können direkt vom Client aufgerufen werden,
sobald eine Referenz auf die EJB besteht. Besitzt eine Methode einen Rückgabewert, wird
dieser nach der Ausführung der Methode an den Client zurückgesendet.
306
eclipse_v01.book Seite 307 Montag, 30. Januar 2006 12:02 12
Die Geschäftsmethoden einer EJB unterscheiden sich nicht von den Methoden einer ein-
fachen Java-Klasse. Die Systematik über Zugriffsbeschränkungen und andere Sicherheits-
mechanismen sowie Transaktionsverarbeitung wird vom J2EE-Applikationsserver gehand-
habt. Eine Session Bean-Klasse zur Abbildung einer Warenkorb-Funktionalität kann dem-
nach wie folgt aussehen1:
package com.entwickler.eclipsebuch.warenkorb;
import java.util.*;
import javax.ejb.*;
// ejbCreate-Methoden
public void ejbCreate(String name) throws CreateException {
this.ejbCreate(name,"0");
}
// Geschäftsmethoden
public void hinzufuegen(String artikel) {
inhalt.addElement(artikel);
}
// Konstruktor
public WarenkorbBean() {}
307
eclipse_v01.book Seite 308 Montag, 30. Januar 2006 12:02 12
Session Beans
Da es sich bei der WarenkorbBean um eine Stateful Session Bean handelt, wird für jede
Session eine neue Instanz erzeugt und Statusinformationen können in den Instanzvariablen
benutzerabhängig gespeichert werden. Die Instanziierung wird ausschließlich vom EJB-
Container vorgenommen und kann von außen nicht gesteuert werden. Nach der Instanzi-
ierung wird das Objekt dem so genannten Instanzenpool zugeordnet, wobei die setSes-
sionContext-Methode ausgeführt wird.
Alle Methoden, die das Präfix ejb besitzen (ejbCreate, ejbRemove, ejbActivate und
ejbPassivate), werden zu verschiedenen Zeitpunkten im Lebenszyklus der EJB aus-
schließlich vom EJB-Container aufgerufen:
쐌 ejbActivate: Instanz wird aus dem Instanzenpool herausgenommen und durch einen
Client referenziert.
쐌 ejbPassivate: Instanz wird in den Instanzenpool zurückgelegt, wenn sie nicht mehr
benötigt wird.
쐌 ejbCreate: Client erzeugt eine Referenz auf eine EJB.
쐌 ejbRemove: Client zerstört Referenz auf eine EJB.
7.5.2 Interfaces
Remote Home Interface/Local Home Interface
Das Remote Home Interface (javax.ejb.EJBHome) und das Local Home Interface (ja-
vax.ejb.EJBLocalHome ) dienen dazu, dass der Client eine Referenz auf eine EJB er-
zeugen kann. Dazu gibt es im EJB-Container das Home-Objekt. Vom Client wird dieses
Objekt referenziert. Der Client definiert die Referenz vom Typ des Remote Home oder vom
Typ des Local Home Interface. Das ist davon abhängig, ob der Client die EJB aus derselben
oder aus einer anderen virtuellen Maschine heraus anspricht.
Wenn ein Client von außen aus einer anderen virtuellen Maschine auf die EJB zugreift,
dann ist das ein entfernter Zugriff und das Remote Home Interface findet seine Verwen-
dung. Wir bezeichnen das auch als einen Zugriff aus einem anderen Kontext.
Wird dagegen von einer EJB aus eine andere EJB innerhalb desselben Containers benutzt,
dann sprechen wir diese lokal an und greifen auf das Local Home Interface zurück. Beide
Komponenten (EJBs) werden hierbei auf derselben virtuellen Maschine bzw. im selben
Kontext ausgeführt.
Der Remote-Zugriff erfolgt über das Protokoll RMI (Remote Method Invocation). In der
throws-Klausel der Methoden des Remote Home Interface geben wir die Ausnahme
java.rmi.RemoteException an, die beim lokalen Zugriff nicht ausgelöst wird.
308
eclipse_v01.book Seite 309 Montag, 30. Januar 2006 12:02 12
Häufig wird beim Remote Home Interface das Wort Remote weggelassen. Wir werden im
weiteren Verlauf nur noch von Home Interface sprechen, wenn wir das Remote Home In-
terface meinen.
In den beiden Interfaces EJBHome und EJBLocalHome ist jeweils die remove-Methode
deklariert. Bei Aufruf dieser Methode durch den Client führt der EJB-Container die ejb-
Remove-Methode der EJB aus. Daneben definieren wir in dem Home/Local Home Inter-
face die create-Methoden. Diese lösen ebenfalls die ejbCreate-Methoden aus. Da die
ejbCreate-Methoden überladen sind, müssen die Parameterlisten mit denen der create-
Methoden übereinstimmen. Das Home Interface zur oben beschriebenen Session Bean
WarenkorbBean sieht dann wie folgt aus:
package com.entwickler.eclipsebuch.warenkorb;
Remote/Local Interface
Vom Typ des Remote/Local Interface wird clientseitig mithilfe der create-Methode eine
Referenz auf eine EJB erzeugt. Das Interface beinhaltet die Deklaration der Geschäfts-
methoden des EJB und ist abgeleitet von dem Interface EJBObject/EJBLocalObject.
Damit steht dem Client eine Referenz bzw. ein Proxy-Objekt, über die die Methoden auf-
gerufen werden können, zur Verfügung.
Das zur Session Bean WarenkorbBean zugehörige Remote Interface lautet:
package com.entwickler.eclipsebuch.warenkorb;
309
eclipse_v01.book Seite 310 Montag, 30. Januar 2006 12:02 12
Session Beans
Das Local Interface ist ähnlich wie das Remote Interface aufgebaut. Die throws-Klausel
fehlt, da beim lokalen Zugriff die java.rmi.RemoteException nicht ausgelöst wird.
package com.entwickler.eclipsebuch.warenkorb;
7.5.3 Deployment-Deskriptor
Beim Deployment werden die notwendigen Java-Dateien (Klasse WarenkorbBean und
Interfaces) zusammen mit dem Deployment-Deskriptor an den Applikationsserver übertra-
gen. Für das Deployment auf den Applikationsserver JBoss, den wir hier ausschließlich
verwenden, werden die beiden XML-Dateien ejb-jar.xml und jboss.xml benötigt. Die Datei
ejb-jar.xml ist (nach dem EJB 2.0-Standard) folgendermaßen aufgebaut:
Die erste Zeile identifiziert die Datei als eine XML-Datei, die folgenden Zeilen geben den
EJB-Standard an und beschreiben das XML-Dokument mithilfe einer DTD (siehe Kapitel
7.1.2).
Der Rumpf der Datei ist eingebettet in das Root-Element <ejb-jar> … </ejb-jar>. In-
nerhalb dieses Elements können verschiedene Tags verwendet werden, um die Klassen der
EJBs festzulegen, Zugriffsrechte oder Transaktionsverhalten zu verwalten etc. Die wich-
tigsten Tags sind:
쐌 <description> (optional)
Innerhalb dieses Elements kann eine Beschreibung des Deskriptors angegeben werden.
Häufig ist es hilfreich, die EJBs, deren Zugriffbeschränkungen oder das Transaktions-
verhalten zu beschreiben.
쐌 <display-name> (optional)
Der Display-Name wird von Tools verwendet, die Deployment-Deskriptoren erzeugen.
Dort werden Namen für das gesamte Java-Archiv oder für einzelne Beans vergeben, die
nicht mit den Klassen- bzw. Dateinamen übereinstimmen müssen.
310
eclipse_v01.book Seite 311 Montag, 30. Januar 2006 12:02 12
<ejb-jar >
<description>Deployment-Deskriptor Warenkorb</description>
<display-name>Warenkorb</display-name>
<enterprise-beans>
<!-- Session Beans -->
<session >
<ejb-name>Warenkorb</ejb-name>
<home>
com.entwickler.eclipsebuch.warenkorb.WarenkorbHome
</home>
<remote>
com.entwickler.eclipsebuch.warenkorb.Warenkorb
</remote>
<Local Home>
com.entwickler.eclipsebuch.warenkorb.WarenkorbLocalHome
</Local Home>
<local>
com.entwickler.eclipsebuch.warenkorb.WarenkorbLocal
</local>
<ejb-class>
com.entwickler.eclipsebuch.warenkorb.WarenkorbBean
</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
Das session-Element enthält die Bezeichner der EJB-Klasse und der Interfaces sowie die
Art der Session Bean (Stateful oder Stateless) und das Transaktionsverhalten. Im Element
<ejb-name> wird der Name bestimmt, der für die interne Verarbeitung erforderlich ist.
311
eclipse_v01.book Seite 312 Montag, 30. Januar 2006 12:02 12
Als zweiten Schritt müssen wir noch die Datei jboss.xml schreiben. Diese wird vom JBoss
Server benötigt und beinhaltet die JNDI-Namen für die EJBs und für andere Ressourcen,
wie z.B. JDBC oder JavaMail. Je nach Art des Zugriffs (remote oder local) werden zwei
JNDI-Namen unterschieden.
Unser Beispiel besteht bisher nur aus der EJB WarenkorbBean und wir vergeben die
JNDI-Namen für diese:
<jboss>
<unauthenticated-principal>nobody</unauthenticated-principal>
<enterprise-beans>
<session>
<ejb-name>Warenkorb</ejb-name>
<jndi-name>WarenkorbBean</jndi-name>
<local-jndi-name>WarenkorbLocal</local-jndi-name>
</session>
</enterprise-beans>
<resource-managers></resource-managers>
</jboss>
Der Wert des Tags <ejb-name> korrespondiert mit dem Wert des gleichnamigen Tags aus
dem Deployment-Deskriptor ejb-jar.xml. Auf diese Weise wird festgelegt, dass über den
JNDI-Namen WarenkorbBean auf die entsprechende EJB zugegriffen wird. Die Fest-
legung der zu dieser EJB gehörigen Klassen und Interfaces erfolgt im Deployment-Des-
kriptor ejb-jar.xml.
Nachdem wir gesehen haben, welche Klassen, Interfaces und Deployment-Deskriptoren
benötigt werden, ist es jetzt noch erforderlich, die entsprechende Datei auf dem Server zu
installieren. Prinzipiell ist eine Java-Archiv-Datei mit den entsprechenden Dateien zu er-
zeugen und diese in das Deployment-Verzeichnis des JBoss Servers zu kopieren. Wenn der
Server läuft, erkennt er sofort, dass eine neue Komponente vorhanden ist, und installiert
diese automatisch.
Es ist aber äußerst fehleranfällig, alle Schritte des Deployments manuell vorzunehmen, so
dass in der Regel Tools eingesetzt werden, die uns beim Deployment unterstützen. Aus die-
sem Grund wollen wir uns im Folgenden damit beschäftigen, wie wir durch die Eclipse
Web Tools Platform bei der Entwicklung und dem Deployment von EJBs unterstützt wer-
den. Zunächst konfigurieren wir einen neuen Server für die WTP.
312
eclipse_v01.book Seite 313 Montag, 30. Januar 2006 12:02 12
darf es einiger Einstellungen. Diese können wir in den Dateien zu dem Plug-In org.eclip-
se.jst.server.generic.serverdefinitions durchführen oder wir erzeugen ein eigenes Plug-In,
das die notwendigen Informationen enthält.
In unserem Beispiel erzeugen wir ein Plug-In, das die Konfigurationsdaten für den JBoss
Server in der Version 4.0.2 enthält1.
Das Projekt erhält den Namen com.entwickler.eclipsebuch.jboss4 und beinhaltet die Datei-
en plugin.xml und plugin.properties sowie die Unterverzeichnisse
쐌 buildfiles
Dieses Verzeichnis enthält Ant-Skripte für das Deployment/Undeployment.
쐌 icons
Dieses Verzeichnis enthält Icons, die in Eclipse für die Server angezeigt werden kön-
nen.
쐌 META-INF
Dieses Verzeichnis enthält die Manifest.inf-Datei.
쐌 servers
Dieses Verzeichnis enthält die Server-Definitionsdateien, die die Informationen zu den
Servern beinhalten.
313
eclipse_v01.book Seite 314 Montag, 30. Januar 2006 12:02 12
Properties
Anschließend werden die so genannten Properties festgelegt. Dies geschieht nach folgen-
dem Schema:
<property id="serverRootDirectory"
label="%ApplicationServerDirectory"
type="directory"
context="runtime"
default="C:\Programme\jboss-4.0.2"
/>
Properties sind Variablen, die aus Eclipse heraus über die grafische Benutzeroberfläche
veränderbar sind. Es existieren verschiedene Attribute, die eingestellt werden können:
쐌 Die id gibt einen eindeutigen Bezeichner im Namespace tns (this namespace) an.
쐌 Der Parameter label ist die Beschriftung, die auf der GUI ausgegeben wird. Der Wert
%ApplicationServerDirectory wird in der Datei plugin-properties aus dem Ver-
zeichnis des neuen Plug-In aufgelöst.
쐌 In type wird der Typ des Werts für die Property definiert. Folgende Angaben sind mög-
lich:
쐌 string
In der GUI wird ein Textfeld für die Property angezeigt.
쐌 directory
In der GUI wird ein Feld für die Property angezeigt, von der aus ein Dateiverzeichnis-
Dialogfenster aufrufbar ist.
쐌 boolean
In der GUI wird eine Checkbox für die Property angezeigt.
쐌 file
In der GUI wird ein Feld für die Property angezeigt, von der aus ein Datei-Dialogfenster
aufrufbar ist.
쐌 Als Einstellung für den context einer Property gibt es die beiden Möglichkeiten ser-
ver und runtime. Die Einstellung runtime bewirkt, dass die Property für den Server
global gesetzt wird. Das heißt, dass z.B. das Verzeichnis für den Server gesetzt wird und
alle Instanzen des Servers dieses benutzen. Ist für eine Property dieses Attribut mit
server angegeben, so wird der Wert für eine Server-Instanz verwendet. Beispielsweise
wird die Server-Adresse oder der Port für jede Instanz angegeben.
쐌 Im Attribut default wird der Initialwert für die Property gesetzt.
Mit Hilfe von ${...} – z.B. ${serverRootDirectory} – können wir auf den Inhalt der Proper-
ty an anderen Stellen des Dokuments zugreifen.
Die Properties werden in der Datei jboss4.serverdef wie folgt definiert:
314
eclipse_v01.book Seite 315 Montag, 30. Januar 2006 12:02 12
<property id="serverRootDirectory"
label="%ApplicationServerDirectory"
type="directory"
context="runtime"
default="C:\Programme\jboss-4.0.2" />
<property id="serverAddress"
label="%serverAddress"
type="string"
context="server"
default="127.0.0.1" />
<property id="port"
label="%serverPort"
type="string"
context="server"
default="8080" />
<property id="serverConfig"
label="%jboss4serverConfig"
type="string"
context="server"
default="default" />
<property id="classPath"
label="%serverclassPath"
type="directory"
context="runtime"
default="C:\Programme\jboss-4.0.2" />
Mit diesen Properties werden das Verzeichnis der JBoss-Installation und eine Classpath-
Variable dafür definiert (Properties serverRootDirectory und classPath). Weil der
JBoss Server in unterschiedlichen Konfigurationen gestartet werden kann, gibt es hierfür
noch eine entsprechende Eigenschaft (Property serverConfig). Abhängig von der Start-
konfiguration des JBoss Servers werden bestimmte Dienste geladen oder nicht. Wir werden
mit der Konfiguration default arbeiten, die für unsere Belange notwendig und auch ausrei-
chend ist. Schließlich werden noch zwei Eigenschaften für die Server-Adresse und den Port
festgelegt (Properties serverAdress und serverPort)
Classpath
Die Definition des Classpath ist ein wichtiger Bestandteil der Server-Definition. Hier wird
festgelegt, welche Bibliotheken für die Entwicklung und für den Ablauf einer J2EE-An-
wendung notwendig sind.
Bei der Entwicklung einer EJB oder eines Servlets werden Bibliotheken benötigt, damit
Eclipse bzw. das JDK die entsprechenden Klassen kennt. Damit diese Bibliotheken stan-
dardmäßig in ein Eclipse-Projekt eingebunden werden, wenn wir ein entsprechendes Pro-
jekt erzeugen, müssen wir bestimmte Angaben in der Datei JBoss4.serverdef machen:
315
eclipse_v01.book Seite 316 Montag, 30. Januar 2006 12:02 12
Bei der Definition des Classpath gibt die id an, über welchen eindeutigen Namen dieser
Classpath referenziert wird. Das Element archive path legt die einzelnen Bibliotheken
fest, die in den Classpath eingebunden werden. Hierbei wird auf die Variable classPath,
die als Property definiert ist, verwiesen.
Dass es sich bei dem Classpath jboss.project um den Classpath handelt, den das
Eclipse-Projekt verwendet, wird dadurch erreicht, dass wir innerhalb des Elements pro-
ject für das Element classpathReference den Wert jboss.project angeben:
<project>
<classpathReference>jboss.project</classpathReference>
</project>
Für den Ablauf einer J2EE-Anwendung bzw. der EJBs innerhalb des JBoss Servers ist ein
weiterer Classpath notwendig:
316
eclipse_v01.book Seite 317 Montag, 30. Januar 2006 12:02 12
<start>
<mainClass>org.jboss.Main</mainClass>
<workingDirectory>${serverRootDirectory}/bin</workingDirectory>
<programArguments>-c ${serverConfig}</programArguments>
<vmParameters></vmParameters>
<classpathReference>jboss</classpathReference>
</start>
<stop>
<mainClass>org.jboss.Shutdown</mainClass>
<workingDirectory>${serverRootDirectory}/bin</workingDirectory>
<programArguments>-S</programArguments>
<vmParameters></vmParameters>
<classpathReference>jboss</classpathReference>
</stop
Publishers
Ant-Skript im Verzeichnis buildfiles
Beim Deployment einer J2EE-Anwendung wird aus den verwendeten Dateien ein jar-, ear-
oder war-Archiv erzeugt und dieses dann in ein spezielles Server-Verzeichnis kopiert.
In einem so genannten Build File mit dem Namen jboss4.xml im Verzeichnis buildfiles wer-
den diese Schritte zusammengefasst:
<target name="deploy.j2ee.ejb">
<jar destfile="${project.working.dir}/${module.name}.jar">
<zipfileset dir="${module.dir}">
<include name="**/*.*"/>
<exclude name="**/*.java"/>
</zipfileset>
</jar>
<move file="${project.working.dir}/${module.name}.jar"
todir="${server.publish.dir}"/>
</target>
Wird beispielsweise dieses Target deploy.j2ee.ejb aufgerufen, dann wird eine jar-Da-
tei mit dem Namen des EJB-Moduls und der Endung .jar erzeugt – das EJB-Modul wird bei
der Entwicklung des Eclipse-Projekts festgelegt. In dieser jar-Datei werden alle Dateien
des Verzeichnisses des EJB-Moduls bis auf die mit der Endung .java kopiert. Anschließend
wird die neu erzeugte jar-Datei in das für das Deployment vorgesehene Verzeichnis des
Servers verschoben.
317
eclipse_v01.book Seite 318 Montag, 30. Januar 2006 12:02 12
<target name="undeploy.j2ee.web">
<delete file="${server.publish.dir}/${module.name}.war">
</delete>
</target>
<target name="undeploy.j2ee.ejb"> ... </target>
<target name="undeploy.j2ee.ear"> ... </target>
</project>
1. Für detaillierte Erläuterungen zu Plug-Ins und den Begriffen Extension Point und Extension siehe Kapitel 9.
318
eclipse_v01.book Seite 319 Montag, 30. Januar 2006 12:02 12
...
<extension point=
"org.eclipse.jst.server.generic.core.genericpublisher">
<genericpublisher class=
"org.eclipse.jst.server.generic.core.internal.AntPublisher"
id="org.eclipse.jst.server.generic.antpublisher"/> </
extension>
...
<publisher id="org.eclipse.jst.server.generic.antpublisher">
<publisherdata>
<dataname>build.file</dataname>
<datavalue>/buildfiles/jboss4.xml</datavalue>
</publisherdata>
<publisherdata>
<dataname>target.publish.j2ee.web</dataname>
<datavalue>deploy.j2ee.web</datavalue>
</publisherdata>
<publisherdata>
<dataname>target.publish.j2ee.ejb</dataname>
<datavalue>deploy.j2ee.ejb</datavalue>
</publisherdata>
<publisherdata>
<dataname>target.unpublish.j2ee.web</dataname>
<datavalue>undeploy.j2ee.web</datavalue>
</publisherdata>
<publisherdata>
<dataname>target.unpublish.j2ee.ejb</dataname>
<datavalue>undeploy.j2ee.ejb</datavalue>
</publisherdata>
<publisherdata>
<dataname>target.publish.j2ee.ear</dataname>
<datavalue>deploy.j2ee.ear</datavalue>
</publisherdata>
319
eclipse_v01.book Seite 320 Montag, 30. Januar 2006 12:02 12
<publisherdata>
<dataname>target.unpublish.j2ee.ear</dataname>
<datavalue>undeploy.j2ee.ear</datavalue>
</publisherdata>
</publisher>
Module
Das Element module gibt die Modultypen an. Es gibt Web-, EJB- und Enterprise Appli-
cation-Module, die für das Plug-In org.eclipse.jst.server.generic.serverdefinitions in der
plugin.xml mit j2ee.web, j2ee.ejb, j2ee.ear definiert werden. Folgende Angaben
werden für jedes Modul gemacht:
쐌 type: Angabe des Modultypen, der in der plugin.xml definiert sein muss
쐌 publishDir: das Server-Verzeichnis, auf das die Module kopiert werden
쐌 publisherReference: die id des Generic Publisher, der für dieses Modul benutzt
werden soll
<module>
<type>j2ee.web</type>
<publishDir>
${serverRootDirectory}/server/${serverConfig}/deploy
</publishDir>
<publisherReference>
org.eclipse.jst.server.generic.antpublisher
</publisherReference>
</module>
<module>
<type>j2ee.ejb</type>
<publishDir>
${serverRootDirectory}/server/${serverConfig}/deploy
</publishDir>
<publisherReference>
org.eclipse.jst.server.generic.antpublisher
</publisherReference>
</module>
<module>
<type>j2ee.ear</type>
<publishDir>
${serverRootDirectory}/server/${serverConfig}/deploy
</publishDir>
<publisherReference>
org.eclipse.jst.server.generic.antpublisher
</publisherReference>
</module>
320
eclipse_v01.book Seite 321 Montag, 30. Januar 2006 12:02 12
Ports
Das Port-Element gibt den Port und die Protokolle für den Server an. Die Werte werden ver-
wendet, um den Server zu identifizieren. Folgende Elemente gibt es:
쐌 no: Port-Nummer
쐌 protocol: Bezeichner des Protokolls, das unterstützt wird
쐌 name: Name des Protokolls
<port>
<no>${port}</no>
<name>Http</name>
<protocol>http</protocol>
</port>
JNDI Properties
Die Daten für die JNDI-Verbindung werden in dem Element jndiConnection festgelegt.
Sie werden von Clients für den Zugriff auf den Applikationsserver benötigt. Folgende Ele-
mente stehen zur Verfügung:
쐌 providerUrl: die URL des JNDI Servers
쐌 initialContextFactory: Name der Initial Context Factory-Klasse für die JNDI-
Implementation des Servers
쐌 jndiProperty: Eigenschaften für die JNDI-Verbindung, wie z.B. Username, Pass-
wort etc.
<jndiConnection>
<providerUrl>jnp://${serverAddress}:1099</providerUrl>
<initialContextFactory>
org.jnp.interfaces.NamingContextFactory
</initialContextFactory>
<jndiProperty>
<name></name>
<value></value>
</jndiProperty>
</jndiConnection>
321
eclipse_v01.book Seite 322 Montag, 30. Januar 2006 12:02 12
<extension point="org.eclipse.wst.server.core.runtimeTypes">
<runtimeType
id="org.eclipse.jst.server.generic.runtime.jboss40"
name="%jboss40runtimeTypeName"
description="%jboss40runtimeTypeDescription"
vendor="%jboss40Category"
version="4.0"
class="org.eclipse.jst.server.generic.
core.internal.GenericServerRuntime"
>
<moduleType types="jst.web" versions="2.2, 2.3, 2.4"/>
<moduleType types="jst.ejb" versions="1.1, 2.0, 2.1"/>
<moduleType types="jst.ear" versions="1.2, 1.3, 1.4"/>
<moduleType types="jst.connector" versions="1.0, 1.5"/>
<moduleType types="jst.utility" versions="1.0"/>
<moduleType types="jst.appclient" versions="1.2,1.3,1.4"/>
</runtimeType>
</extension>
<extension point="org.eclipse.wst.server.core.serverTypes">
<serverType
runtime="true"
class="org.eclipse.jst.server.generic.
core.internal.GenericServer"
id="org.eclipse.jst.server.generic.jboss40"
initialState="stopped"
supportsRemoteHosts="false"
runtimeTypeId=
"org.eclipse.jst.server.generic.runtime.jboss40"
description="%jboss40serverTypeDescription"
launchConfigId="org.eclipse.jst.server.generic.
core.launchConfigurationType"
behaviourClass="org.eclipse.jst.server.generic.
core.internal.GenericServerBehaviour"
name="%jboss40serverTypeName"
startTimeout="50000"
stopTimeout="15000"
hasConfiguration="false"
launchModes="run,debug,profile">
</serverType>
</extension>
322
eclipse_v01.book Seite 323 Montag, 30. Januar 2006 12:02 12
<extension point="org.eclipse.wst.server.ui.serverImages">
<image
id="org.eclipse.jst.server.generic.image"
icon="icons/obj16/jboss.gif"
typeIds="org.eclipse.jst.server.generic.runtime.jboss40"/>
<image
id="org.eclipse.jst.server.generic.image"
icon="icons/obj16/jboss.gif"
typeIds="org.eclipse.jst.server.generic.jboss40"/>
</extension>
<extension point="org.eclipse.wst.server.ui.wizardFragments">
<fragment
id="org.eclipse.jst.server.generic.runtime"
typeIds="org.eclipse.jst.server.generic.runtime.jboss40"
class="org.eclipse.jst.server. generic.
ui.internal.GenericServerRuntimeWizardFragment"/>
<fragment
id="org.eclipse.jst.server.generic.server"
typeIds="org.eclipse.jst.server.generic.jboss40"
class="org.eclipse.jst.server.generic.
ui.internal.GenericServerWizardFragment"/>
</extension>
<extension point=
"org.eclipse.jst.server.generic.core.serverdefinition">
<serverdefinition
id="org.eclipse.jst.server.generic.runtime.jboss40"
definitionfile="/servers/jboss40.serverdef">
</serverdefinition>
</extension>
323
eclipse_v01.book Seite 324 Montag, 30. Januar 2006 12:02 12
<extension point=
"org.eclipse.wst.common.project.facet.core.runtimes">
<runtime-component-type
id="org.eclipse.jst.server.generic.runtime.jboss"/>
<runtime-component-version
type="org.eclipse.jst.server.generic.runtime.jboss"
version="4.0"/>
<adapter>
<runtime-component
id="org.eclipse.jst.server.generic.runtime.jboss"/>
<factory
class="org.eclipse.jst.server.core.
internal.RuntimeClasspathProvider$Factory"/>
<type
class="org.eclipse.jst.common.project.
facet.core.IClasspathProvider"/>
</adapter>
<supported>
<runtime-component
id="org.eclipse.jst.server.generic.runtime.jboss"
version="4.0"/>
<facet id="jst.web" version="2.2,2.3,2.4"/>
<facet id="jst.ejb" version="1.1,2.0,2.1"/>
<facet id="jst.ear" version="1.2,1.3,1.4"/>
<facet id="jst.connector" version="1.0,1.5"/>
<facet id="jst.utility" version="1.0"/>
<facet id="jst.appclient" version="1.2,1.3,1.4"/>
</supported>
</extension>
<extension point=
"org.eclipse.jst.server.core.runtimeFacetMappings">
<runtimeFacetMapping
runtimeTypeId=
"org.eclipse.jst.server.generic.runtime.jboss40"
runtime-component=
"org.eclipse.jst.server.generic.runtime.jboss"
version="4.0"/>
</extension>
324
eclipse_v01.book Seite 325 Montag, 30. Januar 2006 12:02 12
<extension point=
"org.eclipse.wst.common.project.facet.ui.images">
<image runtime-component-type=
"org.eclipse.jst.server.generic.runtime.jboss"
path="icons/obj16/jboss.gif"/>
</extension>
jboss4runtimeTypeName=JBoss 4.0.x
jboss4runtimeTypeDescription=JBoss 4.0.x
jboss4serverTypeName=JBoss 4.0.x
jboss4serverTypeDescription=JBoss 4.0.x
jboss4serverConfig=Server Co&nfiguration (minimal/default/all):
…
325
eclipse_v01.book Seite 326 Montag, 30. Januar 2006 12:02 12
Damit ist das Plug-In aufgebaut, wie es in Abb. 7.21 dargestellt ist. Für das Deployment ge-
nügt es, das Verzeichnis in das plugins-Verzeichnis von Eclipse zu kopieren und Eclipse
neu zu starten.
Um zu gewährleisten, dass die Änderungen wirksam und keine älteren Informationen aus
der plugin.xml von Eclipse gespeichert werden, sollte Eclipse mit der Startkonfiguration
-clean(eclipse.exe -clean) gestartet werden.
Abb. 7.21: Aufbau des Plug-In zur Konfiguration des JBoss Server 4
326
eclipse_v01.book Seite 327 Montag, 30. Januar 2006 12:02 12
Auf der folgenden Maske (siehe Abb. 7.22) werden unter anderem der Name des Package
und der Name der Klasse festgelegt. Bei dem Namen der Klasse wird üblicherweise das
Suffix Bean mit angegeben und es muss an dieser Stelle verwendet werden.
Wir können ein Package auswählen oder ein neues definieren. Wir bezeichnen das Package
mit com.entwickler.eclipsebuch.warenkorb und die Klasse mit WarenkorbBean.
Anschließend sind der EJB-, der JNDI- und der Display-Name zu bestimmen. Diese
Namen sind frei wählbar. Standardmäßig wird der Name der Bean ohne das Suffix Bean
vorgegeben. Außerdem ist auf dieser Maske festzulegen, ob es sich um eine Stateful oder
Stateless Session Bean handelt und ob der EJB-Container oder die Bean selbst die Trans-
aktionsverarbeitung übernehmen soll.
Auf der letzten Maske des Assistenten wird noch das zu implementierende Interface
javax.ejb.SessionBean ausgewählt und die Klasse als abstract definiert, was den
Vorteil hat, dass nicht alle Methoden des Interface in der Bean-Klasse implementiert wer-
den müssen.
327
eclipse_v01.book Seite 328 Montag, 30. Januar 2006 12:02 12
/**
*
* <!-- begin-user-doc -->
* A generated session bean
* <!-- end-user-doc -->
* *
* <!-- begin-xdoclet-definition -->
* @ejb.bean name="Warenkorb"
* description="A session bean named Warenkorb"
* display-name="Warenkorb"
* jndi-name="Warenkorb"
* type="Stateful"
* transaction-type="Container"
*
* <!-- end-xdoclet-definition -->
* @generated
*/
Hier werden der EJB-Name, der JNDI- und der Display-Name sowie die Art des Bean
(Stateful) und die Variante der Transaktionsverarbeitung (Container) festgelegt. Die-
ser Bereich wird von XDoclet bei der Erzeugung des Deployment-Deskriptors etc. ver-
arbeitet. XDoclet startet automatisch, wenn ein neuer Build durchgeführt wird und die
Bean verändert worden ist. XDoclet überschreibt die vorherigen Dateien für Deployment-
Deskriptor etc., so dass in diesen Dateien keine manuellen Änderungen vorgenommen
werden sollten. Beim Arbeiten mit der WTP sollten alle Einstellungen für die Bean im
XDoclet-Bereich vorgenommen werden.
328
eclipse_v01.book Seite 329 Montag, 30. Januar 2006 12:02 12
/**
*
* <!-- begin-xdoclet-definition -->
* @ejb.create-method
* view-type="remote"
* <!-- end-xdoclet-definition -->
* @generated
*
* //TODO: Must provide implementation for bean create stub
*/
Mit dem Ausdruck @ejb.create-method wird bestimmt, dass es sich um eine create-
Methode handelt, die aufgrund der Angabe view-type="remote" ausschließlich für den
Remote-Zugriff verwendet werden kann. Das bedeutet, dass die entsprechende create-
Methode im Remote Home Interface und nicht im Local Home Interface erzeugt wird. Soll
die Methode für beide Zugriffsarten gelten, ist view-type="both" einzustellen.
Bei der Methode foo handelt es ich um eine Methode für das Remote/Local Interface. Von
der WTP wird dafür der Ausdruck ejb.interface-method verwendet. Die Einstellung
des view–type legt fest, ob die Methode für das Remote, Local oder für beide Interfaces
gelten soll.
In unserem Beispiel benötigen wir zwei create-Methoden, die eine besitzt zwei und die
andere einen Parameter vom Typ String. Beim ersten handelt es sich jeweils um den Namen
des Kunden und der zweite ist gegebenenfalls die Kundennummer. Wird diese nicht mit
angegeben, wird sie mit 0 festgelegt. Der XDoclet-Bereich ist identisch zu dem oben ange-
gebenen für eine create-Methode. Im XDoclet-Bereich werden also keine spezifischen
Daten für eine spezielle Methode mit angegeben:
/**
…
*/
public void ejbCreate(String name, String nr)
throws CreateException{
kName = name;
kNr = nr;
}
/**
…
*/
public void ejbCreate(String name) throws CreateException{
this.ejbCreate(name,"0");
}
329
eclipse_v01.book Seite 330 Montag, 30. Januar 2006 12:02 12
/**
*
* <!-- begin-xdoclet-definition -->
* @ejb.interface-method view-type="both"
* <!-- end-xdoclet-definition -->
* @generated
*
* //TODO: Must provide implementation for bean method stub
*/
public void hinzufuegen(String artikel){
inhalt.addElement(artikel);
}
/**
…
*/
public void entfernen(String artikel) {
inhalt.removeElement(artikel);
}
/**
…
*/
public Vector<String> getInhalt() {
return inhalt;
}
Auf Basis dieser Bean-Klasse werden das Remote, Local, Home und Local Home Interface
sowie die Klasse WarenkorbSession erzeugt und in das Verzeichnis ejbModule in das
entsprechende Package kopiert. WarenkorbSession ist von der abstrakten Klasse Wa-
renkorbBean abgeleitet. In ihr werden die Methoden aus dem Interface SessionBean
implementiert. In welcher Klasse wir die Implementierungen der Business- und der ejb-
Create-Methoden vornehmen, ist theoretisch egal. Wir werden jedoch den Programmcode
für die Methoden in die Basisklasse WarenkorbBean schreiben, weil bei jedem neuen Er-
zeugen der Dateien diese im Verzeichnis ejbModule überschrieben werden und Änderun-
gen jeweils verloren gehen. Die in WarenkorbBean implementierten Methoden werden an
die generierte Klasse WarenkorbSession vererbt. Standardmäßig wird die Klasse Wa-
renkorbSession im Deployment-Deskriptor als EJB-Klasse angegeben.
330
eclipse_v01.book Seite 331 Montag, 30. Januar 2006 12:02 12
Deployment
Der Deployment-Deskriptor, der im Verzeichnis ejbModule/META-INF steht und den Na-
men ejb-jar.xml besitzt, wird ebenfalls automatisch erzeugt und beinhaltet das session-
Element mit den Definitionen der EJB-Klasse und der Interfaces:
Weil wir bei der Erzeugung der EJB-Klasse angegeben haben, dass es sich um eine Stateful
Session Bean handeln soll, und dies im XDoclet-Bereich in der Klasse vermerkt worden ist,
wird an dieser Stelle im Element <session-type> der Wert Stateful angegeben.
Für die Darstellung des Deployment-Deskriptors gibt es noch eine Darstellung in tabella-
rischer Form in der Design View (siehe Abb. 7.23).
331
eclipse_v01.book Seite 332 Montag, 30. Januar 2006 12:02 12
Beim Deployment auf den JBoss Server werden die JNDI-Namen für die Home-Objekte,
also die Namen, mit denen sie sich beim Namensdienst registrieren, in der Datei jboss.xml
gespeichert. Wir können XDoclet so einstellen, dass auch diese Datei automatisiert erstellt
wird. Hierzu markieren wir unter WINDOW | PREFERENCES XDOCLET EJBMODULE den
Eintrag JBoss.
Der JBoss Server kann aus Eclipse heraus gestartet werden. In der Servers View der WTP
muss dazu ein neuer Server hinzugefügt und die Bean veröffentlicht werden.
Anschließend wird der JBoss Server mit der Startkonfiguration default aufgerufen. Dabei
werden in der Konsole des JBoss Servers verschiedene Meldungen angezeigt.
Einen Überblick über die laufenden Dienste des Servers oder über die zur Verfügung ste-
henden EJBs etc. erhalten wir, indem wir im Browser die URL http://localhost:8080/jmx-
console/ angeben. Klicken wir in der Gruppe jboss.j2ee auf jndiName=Warenkorb-
Bean,service=EJB, so gelangen wir zu einem Dokument, in dem zu erkennen ist, dass die
Bean als Stateful Session Bean zur Verfügung steht und über den JNDI-Namen Waren-
korbBean angesprochen werden kann.
Nachdem wir nun gesehen haben, dass die EJB im Container richtig installiert worden ist,
wollen wir ein Java-Client-Programm entwickeln, das auf die EJB zugreift und deren Funk-
tionalität aufruft.
332
eclipse_v01.book Seite 333 Montag, 30. Januar 2006 12:02 12
333
eclipse_v01.book Seite 334 Montag, 30. Januar 2006 12:02 12
In der Methode wird ein neues Hashtable-Objekt erzeugt, in das die einzelnen Eigen-
schaften mit entsprechenden Werten eingetragen werden. Das Setzen der Eigenschaften
jnp.socketFactory, jnp.timeout und jnp.sotimeout ist nicht unbedingt erforder-
lich, da wir hier Standardwerte verwenden.
Das InitialContext-Objekt stellt eine Verbindung zum Namensdienst des JBoss Ser-
vers her. Über die lookup-Methode des InitialContext-Objekts generieren wir eine
Referenz auf das Home-Objekt. Die lookup-Methode bekommt als String den JNDI-Na-
men der EJB, auf welche wir zugreifen wollen, übergeben und gibt eine Referenz auf das
zugehörige Home-Objekt zurück. Dieses konvertieren wir in ein Objekt vom Typ des Home
Interface. Anschließend können wir eine create-Methode aufrufen, um eine Referenz auf
die EJB zu erhalten. Dazu ist es erforderlich, dass das Home und das Remote Interface im
Client eingebunden sind.
In unserem Beispiel fügen wir dem Projekt die beiden Interfaces Warenkorb und Waren-
korbHome aus dem Package com.entwickler.eclipsebuch.warenkorb, welche wir
im EJB-Projekt generiert haben, hinzu. Anschließend schreiben wir eine Methode get-
Home, in der das Home-Objekt referenziert wird. Der lookup-Methode übergeben wir die
Klassenkonstante JNDI_NAME aus dem Interface WarenkorbHome, in der der JNDI-Name
der EJB (WarenkorbBean) steht.
334
eclipse_v01.book Seite 335 Montag, 30. Januar 2006 12:02 12
Zurückgegeben wird ein Objekt der Klasse Object. Mithilfe der Klassenmethode narrow
aus der Klasse javax.rmi.PortableRemoteObject überprüfen wir, ob das Objekt in
ein Objekt vom Typ WarenkorbHome konvertiert werden kann, und nehmen anschließend
das Konvertieren vor.
Nachdem wir eine Referenz auf das Home-Objekt erzeugt haben, können wir mithilfe der
create-Methode dieses Objekts eine Referenz auf das eigentliche EJB-Objekt (Waren-
korbBean) generieren.
Wir schreiben den Programmcode zum Testen der Funktionalität in die Methode testBean:
Der Aufruf der Methode getHome().create erzeugt eine Referenz auf die entfernt lie-
gende EJB. Das Home-Objekt ruft zunächst die ejbCreate-Methode (mit einem Parame-
ter vom Typ String) der EJB auf. Die Attribute werden mit den entsprechenden Werten ge-
setzt. Das entfernt liegende EJB-Objekt wird zu diesem Zeitpunkt im Allgemeinen nicht
instanziiert, denn die Instanziierung übernimmt der EJB-Container selbstständig und wir
haben von außen (vom Client) keinen Einfluss darauf.
Der Aufruf der Methode hinzufuegen fügt dem in der EJB enthaltenen Vector-Objekt
jeweils ein neues Element hinzu. Der Inhalt des Warenkorbs, also das Vector-Objekt, kann
mit der getInhalt-Methode aus der EJB ausgelesen wird.
335
eclipse_v01.book Seite 336 Montag, 30. Januar 2006 12:02 12
In der main-Methode derselben Klasse erzeugen wir ein Objekt vom Typ Warenkorb-
Client und rufen die testBean-Methode auf:
Da es sich bei der Bean um eine Stateful Session Bean handelt, wird bei jedem neuen Pro-
grammstart des Clients jeweils ein neues EJB-Objekt verwendet und auf die Daten der vor-
herigen Session kann nicht mehr zugegriffen werden.
Angenommen, WarenkorbBean wäre eine Stateless Session Bean. Dann würden alle Ses-
sions auf dasselbe Objekt zugreifen und bei jedem neuen Start des Client-Programms wür-
den zusätzliche Elemente in das Vector-Object der EJB aufgenommen werden und die
Einkaufsliste geriete immer länger.
Wenn wir versuchen, das Java-Programm zu starten, erscheinen Fehlermeldungen, da wir
noch folgende Bibliotheken in das Projekt einbinden müssen. Die Dateien stehen im Instal-
lationsverzeichnis des JBoss Servers:
쐌 ../client/jboss-client.jar
쐌 ../client/jboss-common-client.jar
쐌 ../client/jboss-j2ee.jar
쐌 ../client/jboss-jaas.jar
쐌 ../client/jbosssx-client.jar
쐌 ../client/jboss-transaction-client.jar
쐌 ../client/jnet.jar
쐌 ../client/jnp-client.jar
쐌 ../client/log4j.jar
쐌 ../server/default/lib/jnpserver.jar
336
eclipse_v01.book Seite 337 Montag, 30. Januar 2006 12:02 12
schnitt wollen wir uns damit beschäftigen, wie auf die EJBs, die im EJB-Container eines
Applikationsservers liegen, aus einer Webanwendung heraus zugegriffen werden kann.
Abb. 7.24 skizziert die Architektur einer solchen Anwendung.
Abb. 7.24: Architektur des Zugriffs eines Webclients auf eine EJB
View
JSP / HTML
Model
Session Bean
C o n tr o l l e r
Controller Servlet
337
eclipse_v01.book Seite 338 Montag, 30. Januar 2006 12:02 12
Das Controller Servlet muss zunächst eine Verbindung zum Applikationsserver herstellen
und ein Objekt vom Typ des Local bzw. Remote Interface erzeugen. Über diese Objekte
können die einzelnen Methoden aufgerufen werden. Das Controller Servlet läuft im Kon-
text, also unter der virtuellen Maschine des Webservers. Das EJB-Objekt und dessen
Home-Objekt laufen dagegen im Kontext, also unter der virtuellen Maschine des Applika-
tionsservers. Die beiden Kontexte können unterschiedlich sein, wie das beim Beispiel des
Java-Client-Programms der Fall war (siehe Kapitel 7.8). Die beiden Kontexte können aber
auch identisch sein, wenn wir beispielsweise den JBoss Server so starten, dass der integrier-
te Webserver auch gleichzeitig gestartet wird. Bei der Startkonfiguration default, die wir
bisher ausschließlich für den JBoss Server verwendet haben, wird der Tomcat-Server mit-
gestartet. Demnach untersuchen wir zunächst den lokalen Zugriff auf eine EJB im selben
Kontext.
package com.entwickler.eclipsebuch.warenkorb;
package com.entwickler.eclipsebuch.warenkorb.WarenkorbLocal;
338
eclipse