Sie sind auf Seite 1von 697

eclipse_v01.book Seite 1 Montag, 30.

Januar 2006 12:02 12

Kai Brüssau (Hrsg.)


Oliver Widder (Hrsg.)
Herbert Brückner
Martin Lippert
Matthias Lübken
Birgit Schwartz-Reinken
Lars Wunderlich

Eclipse – die Plattform


eclipse_v01.book Seite 2 Montag, 30. Januar 2006 12:02 12
eclipse_v01.book Seite 3 Montag, 30. Januar 2006 12:02 12

Kai Brüssau (Hrsg.)


Oliver Widder (Hrsg.)
Herbert Brückner
Martin Lippert
Matthias Lübken
Birgit Schwartz-Reinken
Lars Wunderlich

– die Plattform
Enterprise-Java mit Eclipse 3.1
eclipse_v01.book Seite 4 Montag, 30. Januar 2006 12:02 12

Kai Büssau / Oliver Widder (Hrsg.): Eclipse – die Plattform


Enterprise-Java mit Eclipse 3.1
Frankfurt, 2006
ISBN 3-935042-82-5

© 2006 entwickler.press, ein Imprint der Software & Support Verlag GmbH

http://www.entwickler-press.de
http://www.software-support.biz

Ihr Kontakt zum Lektorat und dem Verlag: lektorat@entwickler-press.de

Bibliografische Information Der Deutschen Bibliothek


Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbiblio-
grafie; detaillierte bibliografische Daten sind im Internet über http://dnb.ddb.de abrufbar.

Korrektorat: Petra Kienle


Satz: text & form GbR, Carsten Kienle
Umschlaggestaltung: Melanie Hahn
Belichtung, Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH,
Paderborn.
Alle Rechte, auch für Übersetzungen, sind vorbehalten. Reproduktion jeglicher Art (Foto-
kopie, Nachdruck, Mikrofilm, Erfassung auf elektronischen Datenträgern oder andere Ver-
fahren) nur mit schriftlicher Genehmigung des Verlags. Jegliche Haftung für die Richtig-
keit des gesamten Werks kann, trotz sorgfältiger Prüfung durch Autor und Verlag, nicht
übernommen werden. Die im Buch genannten Produkte, Warenzeichen und Firmennamen
sind in der Regel durch deren Inhaber geschützt.
eclipse_v01.book Seite 5 Montag, 30. Januar 2006 12:02 12

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

2.7 Debuggen in Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62


2.7.1 Breakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.7.2 Aufsetzen einer Launch configuration . . . . . . . . . . . . . . . . . . . . 64
2.7.3 Die Debug-Perspektive im Überblick . . . . . . . . . . . . . . . . . . . . 67
2.7.4 Grundfunktionen des Debuggens . . . . . . . . . . . . . . . . . . . . . . . . 68
2.7.5 Allgemeine Hinweise zum Debuggen in Eclipse. . . . . . . . . . . . 69
2.7.6 Debug View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.7.7 Breakpoints, Watchpoints und Exceptioncatching. . . . . . . . . . . 75
2.7.8 Hot Code Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
2.8 Navigation im Sourcecode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
2.8.1 Javadoc View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
2.8.2 Navigation über die Toolbar. . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
2.8.3 Suchfunktionen in Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
2.8.4 Open-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
2.9 Weitere Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
2.9.1 Hierarchy View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
2.9.2 Call Hierarchy View. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
2.9.3 Declaration View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
2.9.4 Navigator View. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
2.9.5 Progress View. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
2.10 Java 5 – Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.10.1 Java 5 on board. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.10.2 Migration Java 1.4 nach 5.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
2.11 Customizing Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
2.11.1 Customizing perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
2.11.2 Eclipse individuell starten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
2.12 Eclipse Preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
3 Eclipse als Modellierungswerkzeug. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
3.1 Einleitung ins Thema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
3.2 OMONDO EclipseUML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3.2.1 Versionen von EclipseUML . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3.2.2 Download und Installation von Omondo EclipseUML . . . . . . . 111
3.2.3 Klassendiagramme erstellen. . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
3.3 EMF/GEF und UML2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
3.3.1 Eclipse Modeling Framework (EMF) . . . . . . . . . . . . . . . . . . . . 118
3.3.2 Graphical Editing Framework (GEF). . . . . . . . . . . . . . . . . . . . . 119
3.3.3 UML2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4 Qualitätssicherung in Eclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.1 Einführung ins Thema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

6
eclipse_v01.book Seite 7 Montag, 30. Januar 2006 12:02 12

Inhaltsverzeichnis

4.2 Wie äußert sich ein Mangel an Qualität? . . . . . . . . . . . . . . . . . . . . . . . . . 121


4.2.1 Mangelnde Sourcecodetests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.2.2 Mangelnde Tests der fachlichen Funktionalität . . . . . . . . . . . . . 122
4.2.3 Eingeschränkte Funktionalität. . . . . . . . . . . . . . . . . . . . . . . . . . . 122
4.2.4 Begrenzte Sourcecode-Qualität. . . . . . . . . . . . . . . . . . . . . . . . . . 123
4.2.5 Reviews und Softwareunterstützung. . . . . . . . . . . . . . . . . . . . . . 123
4.3 Eclipse zur Qualitätssicherung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
4.3.1 Testen mit JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
4.3.2 Audits mit Checkstyle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
4.3.3 Sourcecode-Metrics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
4.3.4 Metrics 1.3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
4.3.5 Metrikreports und Graphen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
4.3.6 Ant-Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
4.3.7 Bleiben Sie kritisch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
5 Build Management mit Eclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.1 Aufgaben des Build Managements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.2 Vom Quellcode zum Programm: Build. . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.3 Einstellungen des Eclipse-Build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
5.3.1 Build Path-Einstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
5.3.2 Compiler und JavaDoc-Einstellungen. . . . . . . . . . . . . . . . . . . . . 142
5.3.3 Automatische und manuelle Builds . . . . . . . . . . . . . . . . . . . . . . 143
5.3.4 Weitere Konfigurationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
5.3.5 Erzeugung anderer Ausgabetypen . . . . . . . . . . . . . . . . . . . . . . . 146
5.4 Build Management und Versionierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
5.4.1 Exkurs: Versionierung mit CVS in Eclipse. . . . . . . . . . . . . . . . . 148
5.4.2 Versionierung und Build Management . . . . . . . . . . . . . . . . . . . . 158
5.5 Exkurs: Build Management mit Ant. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5.5.1 Ant Projects, Targets und Tasks . . . . . . . . . . . . . . . . . . . . . . . . . 161
5.5.2 Typische Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
5.5.3 Ein Ant-Beispielskript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
5.5.4 Ant in Eclipse: externe Builds . . . . . . . . . . . . . . . . . . . . . . . . . . 169
5.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
6 GUI-Design mit Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
6.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
6.2 Der Visual Editor für Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6.2.1 Installation und Aufruf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6.2.2 Hinzufügen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . 178
6.2.3 Entfernen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
6.2.4 Ändern von Eigenschaften einer Komponente . . . . . . . . . . . . . . 179

7
eclipse_v01.book Seite 8 Montag, 30. Januar 2006 12:02 12

Inhaltsverzeichnis

6.2.5 Layouteinstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180


6.2.6 Ereignisverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6.3 Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten 182
6.3.1 Unterstützte Komponenten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
6.3.2 Layoutmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
6.3.3 Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
6.3.4 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
6.4 Das SWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
6.4.1 Aufbau einer SWT-Applikation . . . . . . . . . . . . . . . . . . . . . . . . . 206
6.4.2 SWT-Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
6.4.3 Layoutmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
6.4.4 Ereignisverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
6.5 Besonderheiten bei der Erstellung eines GUI mit SWT-Komponenten . 235
6.5.1 Unterstützte Komponenten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
6.5.2 Layoutmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
6.5.3 Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
6.5.4 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
6.6 Der WindowBuilder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
6.6.1 Installation und Aufruf. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
6.6.2 Hinzufügen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . 244
6.6.3 Entfernen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
6.6.4 Ändern von Eigenschaften einer Komponente. . . . . . . . . . . . . . 245
6.6.5 Layouteinstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
6.6.6 Ereignisverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
6.6.7 Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
6.6.8 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
7 Eclipse und J2EE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
7.1 XML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
7.1.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
7.1.2 Bestandteile eines XML-Dokuments . . . . . . . . . . . . . . . . . . . . . 265
7.1.3 Plug-Ins für das Bearbeiten von XML-Dokumenten . . . . . . . . . 270
7.2 Webanwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
7.2.1 Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
7.2.2 Beispiel einer Webanwendung mit Servlets. . . . . . . . . . . . . . . . 276
7.2.3 Beispiel einer Webanwendung mit Java Server Pages . . . . . . . . 281
7.3 Eclipse-Projekt Web Tools Platform (WTP) . . . . . . . . . . . . . . . . . . . . . . 283
7.3.1 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
7.3.2 Editoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
7.3.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
7.3.4 Einstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

8
eclipse_v01.book Seite 9 Montag, 30. Januar 2006 12:02 12

Inhaltsverzeichnis

7.3.5 Entwicklung einer Webanwendung. . . . . . . . . . . . . . . . . . . . . . . 287


7.3.6 Beispielanwendung Kreditkartenprüfer . . . . . . . . . . . . . . . . . . . 292
7.3.7 Server Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
7.3.8 Lomboz Plug-In und WTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
7.4 J2EE-Anwendungen mit Enterprise Java Beans. . . . . . . . . . . . . . . . . . . . 299
7.4.1 Grundlegende Begriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
7.4.2 Enterprise Java Bean (EJB). . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
7.4.3 Zugriff eines Clients auf eine EJB . . . . . . . . . . . . . . . . . . . . . . . 304
7.5 Session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
7.5.1 Bean-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
7.5.2 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
7.5.3 Deployment-Deskriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
7.6 Konfiguration der WTP für einen neuen Server . . . . . . . . . . . . . . . . . . . . 312
7.6.1 Server-Definitionsdatei jboss4.serverdef . . . . . . . . . . . . . . . . . . 313
7.6.2 7.6.2 Konfiguration der plugin.xml . . . . . . . . . . . . . . . . . . . . . . . 321
7.6.3 Konfiguration der plugin.properties . . . . . . . . . . . . . . . . . . . . . . 325
7.7 Erstellung eines EJB-Projekts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
7.7.1 Anlegen des Projekts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
7.7.2 Erzeugen des EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
7.7.3 Bean-Klasse und XDoclet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
7.7.4 Einfügen einer neuen Methode in die Bean-Klasse . . . . . . . . . . 328
7.8 Client für den Remote-Zugriff auf eine EJB . . . . . . . . . . . . . . . . . . . . . . 332
7.8.1 Herstellung einer Verbindung zum JBoss-Namensdienst . . . . . . 332
7.8.2 Beispiel eines Java-Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
7.8.3 WTP zur Erstellung eines Java-Clients. . . . . . . . . . . . . . . . . . . . 336
7.9 Webclient für den Zugriff auf eine EJB . . . . . . . . . . . . . . . . . . . . . . . . . . 336
7.9.1 Lokaler Zugriff innerhalb derselben virtuellen Maschine . . . . . 338
7.9.2 Zugriff bei unterschiedlichen virtuellen Maschinen . . . . . . . . . . 344
7.10 Datenbankzugriff aus einer EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
7.10.1 Einstellungen für den Zugriff auf die MySQL-Datenbank . . . . . 345
7.10.2 Beispiel Onlineshop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
7.11 Entity Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
7.11.1 Grundlagen und Persistenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
7.11.2 Finder-Methoden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
7.11.3 Entity Bean (Container Managed Persistence) . . . . . . . . . . . . . . 354
7.11.4 Entity Bean (BMP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
7.12 Java Messaging Service und Message Driven Beans . . . . . . . . . . . . . . . . 379
7.12.1 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
7.12.2 Message Driven Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
7.12.3 Senden einer Nachricht an eine Message Driven Bean . . . . . . . 383

9
eclipse_v01.book Seite 10 Montag, 30. Januar 2006 12:02 12

Inhaltsverzeichnis

8 Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389


8.1 Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
8.2 Begriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
8.2.1 SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
8.2.2 WSDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
8.2.3 JAX. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
8.3 Entwicklung eines Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
8.3.1 Aufbau eines WSDL-Dokuments . . . . . . . . . . . . . . . . . . . . . . . 392
8.3.2 Erzeugen eines Web Service aus einem WSDL-Dokument. . . . 397
8.3.3 Entwicklung eines Clients für den Web Service . . . . . . . . . . . . 404
8.3.4 Erzeugen eines WSDL-Dokuments aus einer Java-Klasse . . . . 405
9 Plug-In-Entwicklung für die Eclipse Workbench . . . . . . . . . . . . . . . . . . . . . 411
9.1 Everything is a plug-in. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
9.2 In die Tiefen der Oberfläche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
9.3 Eine Outline View für den Texteditor . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
9.3.1 Adapter: Dynamische Erweiterung von Klassen . . . . . . . . . . . . 413
9.3.2 Ein eigener Adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
9.3.3 Alternative 1: Überschreiben der Methode getAdapter . . . . . . . 423
9.3.4 Alternative 2: der Adapter Manager. . . . . . . . . . . . . . . . . . . . . . 425
9.3.5 Ein Extension Point wird geboren . . . . . . . . . . . . . . . . . . . . . . . 441
9.3.6 Schritt 1: Definition des Interface für den Extension Point . . . . 442
9.3.7 Schritt 2: Definition des Extension Point. . . . . . . . . . . . . . . . . . 442
9.3.8 Schritt 3: Implementierung des Extension Point . . . . . . . . . . . . 448
9.3.9 Eine Extension für den neuen Extension Point . . . . . . . . . . . . . 450
9.4 Der eigene Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
9.4.1 Nichts einfacher als ein eigener Texteditor . . . . . . . . . . . . . . . . 452
9.4.2 Wir erweitern den Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
9.5 Und Action ...: Actions in der Eclipse Workbench (Teil 1). . . . . . . . . . . 464
9.6 ... Einschub: Aufbau der Eclipse-Oberfläche . . . . . . . . . . . . . . . . . . . . . 469
9.7 Und Action ...: Actions in der Eclipse Workbench (Teil 2). . . . . . . . . . . 487
9.7.1 Ein Button mit persistentem Status . . . . . . . . . . . . . . . . . . . . . . 488
9.8 Page Book View: ein Buch mit sieben Seiten . . . . . . . . . . . . . . . . . . . . . 495
9.8.1 Action Delegates oder „Wie kommt man von außen
in das Buch?“ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
9.9 Markers und Annotations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
9.9.1 Marker für Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518
9.10 OSGi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
9.10.1 Bundles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
9.10.2 Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
9.10.3 Die Benutzung eines Service . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
9.11 Fazit und Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555

10
eclipse_v01.book Seite 11 Montag, 30. Januar 2006 12:02 12

Inhaltsverzeichnis

10 Plug-In-Entwicklung für das JDT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557


10.1 Soap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557
10.2 Apache Axis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
10.2.1 Installation von Tomcat. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
10.2.2 Installation von Axis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
10.3 Das Web Service Deployment Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . 562
10.4 Den Rahmen erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563
10.5 Die Funktionalität implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569
10.6 Eingabe der Konfigurationsparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . 574
10.6.1 Speichern und Laden der Konfigurationsparameter . . . . . . . . . . 583
10.7 Generierung von service.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
10.8 Generierung eines Ant-Skripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
10.9 Ausführen des Ant-Skripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592
10.10 Das fertige Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592
10.11 Ein Extension Point für die Generierung von Clients . . . . . . . . . . . . . . . 596
10.12 Einschub: Code-Analyse über AST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
10.13 Eine View zur Anzeige des Syntaxbaums . . . . . . . . . . . . . . . . . . . . . . . . 598
10.14 Die Erzeugung von Java-Code über AST. . . . . . . . . . . . . . . . . . . . . . . . . 608
10.15 Ein Extension Point für die Generierung von Clients (Fortsetzung) . . . . 611
10.16 Die Implementierung des Extension Point . . . . . . . . . . . . . . . . . . . . . . . . 613
10.17 Ein Generator für SWT Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621
10.18 Das SWT-Client-Generator-Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
10.19 Die Erzeugung von Java Code über das Java Element API . . . . . . . . . . . 629
10.20 So ganz nebenbei zum Schluss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
11 Eclipse als Rich Client Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
11.1 Kapitelüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
11.1.1 Themenüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
11.1.2 Kapitelstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
11.1.3 Ziele des Kapitels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
11.2 Anwendungen auf Basis der Plug-In-Technologie . . . . . . . . . . . . . . . . . . 636
11.2.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
11.2.2 Sidebar: Bundles versus Plug-Ins . . . . . . . . . . . . . . . . . . . . . . . . 637
11.2.3 Hello World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637
11.2.4 Strukturierung von Anwendungen . . . . . . . . . . . . . . . . . . . . . . . 641
11.2.5 Tipps, Tricks und mögliche Fallen . . . . . . . . . . . . . . . . . . . . . . . 642
11.3 Die Eclipse Rich Client Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645
11.3.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645
11.3.2 Hello World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645
11.3.3 Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
11.3.4 Menüs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 650
11.3.5 Views und Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653

11
eclipse_v01.book Seite 12 Montag, 30. Januar 2006 12:02 12

Inhaltsverzeichnis

11.4 Weitere Themen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655


11.4.1 Swing und/oder SWT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
11.4.2 Eclipse im Client-Server-Umfeld. . . . . . . . . . . . . . . . . . . . . . . . 656
11.4.3 Eclipse in der Projektpraxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657
11.4.4 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659
11.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659
12 Refactoring to Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
12.1 Kapitelüberblick. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
12.1.1 Themenüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
12.1.2 Kapitelstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
12.2 Die Refactorings im Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662
12.3 Refactoring: Konvertiere Standalone-Anwendung in eine
Single-Plug-In-Eclipse-Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662
12.3.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
12.3.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
12.3.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
12.4 Refactoring: Extrahiere Bibliotheks-Plug-In . . . . . . . . . . . . . . . . . . . . . . 666
12.4.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666
12.4.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666
12.4.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
12.5 Refactoring: Extrahiere Erweiterungs-Plug-In . . . . . . . . . . . . . . . . . . . . 667
12.5.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
12.5.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
12.5.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
12.6 Refactoring: Verallgemeinere Extension-Point . . . . . . . . . . . . . . . . . . . . 671
12.6.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671
12.6.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
12.6.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
12.7 Refactoring: Konvertiere Anwendung in RCP-Anwendung . . . . . . . . . . 673
12.7.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
12.7.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
12.7.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674
12.8 Refactoring: Ersetze Swing-Fenster durch RCP-View . . . . . . . . . . . . . . 675
12.8.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
12.8.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
12.8.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
12.9 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
Die Autoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679
Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683

12
eclipse_v01.book Seite 13 Montag, 30. Januar 2006 12:02 12

1 Einleitung

von Lars Wunderlich

1.1 Was ist Eclipse?


Die Antwort auf die Frage, was Eclipse ist, lässt sich je nach Blickwinkel des Benutzers
unterschiedlich beantworten. An dieser Stelle wollen wir die Eclipse-Gründer zitieren:
„Eclipse ist eine Open Source Community, deren Projekte sich auf die Bereitstellung einer
erweiterbaren Entwicklungsplattform und die Erstellung von Applikationsframeworks
zur Softwareentwicklung konzentrieren.“1 Diese Beschreibung zeigt deutlich, dass man
unter dem Begriff „Eclipse“ mehr als eine IDE und Plattform versteht. Mittlerweile haben
sich unter dem Label Eclipse eine ganze Reihe namhafter Softwarefirmen zusammenge-
schlossen, um auf einer gemeinsamen Basis sowohl Entwicklungsumgebungen als auch
Richclient-Anwendungen und Plug-Ins für die unterschiedlichsten Aufgabengebiete zu
entwickeln. Sie werden unterstützt von einer inzwischen riesigen Community, die Eclipse
für eigene Zwecke erweitert, anpasst und in neue Produkte integriert.

1.2 Warum ein Buch über Eclipse?


Eclipse hat in den letzten Jahren das Nischendasein einer einfachen Open Source-Entwick-
lungsumgebung verlassen. Immer mehr Entwickler in Unternehmen oder hobbymäßig zu
Hause entdeckten Eclipse und mit Eclipse teilweise auch erstmalig die Programmierspra-
che Java. Als im Januar 2005 die erste Auflage dieses Buchs mit großem Erfolg eine inte-
ressierte Leserschaft fand, bewog uns das, dieses Buch schnell einem gründlichen Update
zu unterziehen. Eclipse und Java entwickeln sich so schnell weiter, dass nur aktuell bleiben
kann, wer sich mit bewegt. Gleiches gilt natürlich auch für Eclipse selbst, dessen erste 3.2
Milestones Ende 2005 das Licht der Welt erblickten.
Wir möchten Eclipse in diesem Buch sowohl als flexible Oberfläche für die Entwicklung
von Unternehmensanwendungen als auch als Plattform für eigene Erweiterungen vorstel-
len (Rich Client Platform). Erweiterungen sind dabei Plug-Ins oder selbst erstellte IDEs.
Dieses Buch deckt dabei den objektorientierten Softwareentwicklungszyklus vom Design
und der Modellierung in Eclipse, über die Implementierung (Java, EJB, XML, JSP...) bis
hin zum Testen, Debuggen und dem endgültigen Deployment der Anwendung ab. Dabei
werden dediziert Tools und Frameworks vorgestellt, die auch eine Nutzung im professio-
nellen Umfeld erlauben. Eines der herausragendsten Merkmale der Version 3.1 ist zweifels-
ohne die Unterstützung für JDK 5.0, die wir auch in diesem Buch behandeln werden.
Eclipse als Open Source-Produkt unterscheidet sich nicht nur im Preis von einer Reihe
anderer kommerzieller Produkte, sondern in vielen Fällen auch im Leistungsumfang. In
Unternehmen werden oftmals Enterprise-Produkte verwendet, die der Normalnutzer aus

1. Einleitungssatz auf der Eclipse-Homepage http://www.eclipse.org

13
eclipse_v01.book Seite 14 Montag, 30. Januar 2006 12:02 12

An wen richtet sich dieses Buch?

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.3 An wen richtet sich dieses Buch?


Das vorliegende Buch richtet sich an Leserinnen und Leser, die Eclipse 3.1 im Wesentli-
chen in größeren Projekten, d.h. zumeist im Unternehmen, einsetzen oder darüber nachden-
ken, dies zu tun. Wir gehen davon aus, dass bereits eine grobe Vorstellung von Eclipse vor-
handen ist, also z.B. bekannt ist, wie über die Eclipse-Webseite die IDE heruntergeladen
werden kann, wie sie zu installieren ist und wie man einfache Aufgaben (Erstellung von
Java-Projekten, Compile und Debugging) damit durchführen kann.
Implizit bedeutet dies auch, dass entsprechende Java-Kenntnisse (gegebenenfalls auch in
den Java 5-Spracherweiterungen) vorausgesetzt werden, so dass beispielsweise der Unter-
schied zwischen einer abstrakten Klasse, einem Interface und einer Instanzvariablen keine
Schwierigkeiten bereitet.
Gleichzeitig kann dieses Buch aber auch als Entscheidungshilfe bei der Frage verstanden
werden, unter welcher Oberfläche zukünftig implementiert werden soll.
Jenem Entwicklerkreis, dem Eclipse noch nicht bekannt ist, sei ein Blick auf die Homepage
des Eclipse-Projekts1 empfohlen, um diese Umgebung, seine Community und die angebo-
tenen Frameworks kennen zu lernen und sich mit den Basisfeatures vertraut zu machen. Für
jene, die sich leicht in neuen Softwareumgebungen zurechtfinden, aber noch nie Eclipse be-
nutzt und keine Berührungsängste beim Testen und Herumprobieren haben, ist dieses Buch
gleichzeitig eine Art „Jump Start“. Es streift die einfachen Entwicklungsfeatures im ersten
Kapitel, um sich mit Fragen professioneller Softwareentwicklung zu beschäftigen.
Im Gegensatz zu einer technischen Referenz, die den Anspruch erhebt, jede Checkbox in
jedem Dialog detailliert zu dokumentieren, möchten wir die recht gute Online-Hilfe, die bei
Eclipse als Dokumentation mitgeliefert wird, nicht noch einmal „abschreiben“. Vielmehr
wollen wir interessante Punkte vertiefen oder die Möglichkeiten beim Einsatz von Plug-Ins
bei der Entwicklung beschreiben.
In jedem Fall empfiehlt sich ein Blick auf den aktuellen Stand von Eclipse auf der Eclipse-
Webseite.

1.4 Was erwartet Sie in diesem Buch?


Dieses Buch ist in intensiver Zusammenarbeit einer Reihe von Autoren entstanden. Jeder
von ihnen hat sein jeweiliges Know-how eingebracht und dabei Eclipse von unterschiedli-
chen Blickwinkeln aus präsentiert.

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.

1.5 Was benötigen Sie?


Zum Zeitpunkt der Erstellung dieses Buchs existiert Eclipse in Version 3.1.1 und in einer
Milestone-Version 3.2. Da sich bei Milestones allerdings noch viel im Verlaufe der Ent-
wicklung bis zum endgültigen Release ändern kann, konzentrieren wir uns in diesem Buch
schwerpunktmäßig auf die 3.1.x-Version.
Für die Durchführung und den Test der Beispiele in diesem Buch ist Version 3.1.1 (bzw. hö-
her – wenn Sie selbst dies wünschen) der Eclipse-Entwicklungsumgebung erforderlich.
Der Einsatz eines J2SE Entwicklungskits (JDK) in Version 1.4.2 oder höher ist sowohl für
die IDE selbst als auch für die meisten Beispiele dabei ebenfalls empfehlenswert, wobei
Eclipse mit der älteren 1.3-Version auch meist den Start verweigert. Wir werden in diesem
Buch allerdings auch immer wieder auf die speziellen Java 5.0-Sprachfeatures eingehen,
weshalb wir für den Einsatz von Eclipse 3.1.1 auch ein entsprechendes JDK empfehlen.
Weitere Tools und Plug-Ins werden in den folgenden Kapiteln verwendet und an der Stelle
jeweils angegeben.
Wir haben die englische Version von Eclipse genutzt, auf der auch die Beispiele und die Do-
kumentation aufbauen. Die Verwendung von Translation Packages zur Arbeit mit Eclipse
z.B. in Deutsch steht dem Leser frei. Allerdings erschweren Oberflächen und Bücher, die
englische Begriffe ins Deutsche übersetzen, oft das Verständnis.

1.6 Anforderungen an eine moderne IDE


Die Frage, welche Anforderungen es bei der Auswahl einer Entwicklungsumgebung gibt,
orientiert sich idealerweise an einer Liste von Features. Abhängig vom Budget wird so je-
doch häufig die Freiheit erkauft, die Zahl der Features derart zu vergrößern, dass eine teure
Entwicklungsumgebung zur Verfügung steht, von der aber nur ein Bruchteil genutzt wird.
Viele Entwickler haben bei der Auswahl einer Entwicklungsumgebung die Abb. des kom-
pletten Entwicklungszyklus vor Augen. Dazu zählen die Analysephase und die Dokumen-
tation (soweit dies das Tool unterstützen kann), das objektorientierte Design bis hin zur
Programmierung sowie die Themen Qualitätssicherung oder Deployment. Am besten posi-
tionieren sich bei dieser Aufgabe zumeist jene Entwicklungsumgebungen, die in einem
konkreten Produkt all diese Anforderungen abdecken oder – um den Wünschen des Nutzers
noch näher zu kommen – sich diesbezüglich beliebig erweitern lassen. Der Markt der Ent-

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.7 Open Source


Entgegen der Meinung vieler Projektverantwortlicher sind nicht unbedingt immer die teu-
ersten Produkte die besten. Besonders die unter der Apache Group laufenden Jakarta-Sub-
projekte1 sprechen eine ganz andere Sprache und haben Produkte wie LOG4J, Struts, Hive-
mind oder Tomcat zur Welt gebracht, die auch in einer Reihe von kommerziellen Produkten
als Subframeworks Einsatz finden. Der große Vorteil für Unternehmen liegt dabei weniger
in der preislichen Attraktivität als mehr im Vorhandensein des Produkt-Sourcecodes und
Quasi-Standards. Besonders bei Problemen, bei denen die Dokumentation nicht mehr wei-
terhilft, kann die Untersuchung des Sourcecodes Support-Anfragen auch zuweilen erset-
zen. Für Unternehmen ist oft der Zeitfaktor im Projektmanagement erheblich drängender
als der Kostenfaktor. Beide lassen sich ganz erheblich reduzieren, wenn eine Open Source-
Lösung gewählt wird.

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.

Willkommen in der Welt von Eclipse!

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

2 Wegweiser durch Eclipse

von Lars Wunderlich

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 Perspektiven und Views von Eclipse

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).

2.1.2 Perspektiven auswählen


Zur Auswahl einer persönlichen Perspektive muss das Menü WINDOW | OPEN PERSPECTIVE
geöffnet und dann die gewünschte Ansicht angeklickt werden. Für das im Folgenden be-
trachtete Beispiel wählten wir die Java-Perspektive. Die jeweils aktuelle Perspektive ist da-
bei mit einem schwarzen Kreis markiert. Weitere Perspektiven (auch jene, die gegebenen-
falls von Plug-Ins hinzugefügt werden) finden sich unter dem Menüpunkt WINDOW | OPEN
PERSPECTIVE | OTHER.

19
eclipse_v01.book Seite 20 Montag, 30. Januar 2006 12:02 12

Perspektiven und Views von Eclipse

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.

2.1.3 Die Java-Perspektive


Die Standard-Java-Perspektive ist in Abb. 2.1 dargestellt. Die dort erscheinenden einzelnen
Fenster bezeichnen wir als Views. Sie tragen die Beschriftungen Package Explorer, Outline
oder Tasks und beschreiben einen konkreten Sachverhalt oder ein Problem der aktuellen
Arbeit.

Abb. 2.1: Java-Perspektive

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

2 – Wegweiser durch Eclipse

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.

2.1.4 Neues Java-Projekt erzeugen


Zur Erstellung eines Java-Projekts wählen wir zunächst das Menü FILE | NEW | PROJECT und
klicken im nachfolgenden Dialog JAVA PROJECT und den Button NEXT an. Anschließend ge-
ben wir einen Projektnamen ein (z.B. „Testprojekt“) und klicken den FINISH-Button an, um
ein Java-Projekt mit Standardeinstellungen zu erzeugen.
Auf der linken Seite der Java-Perspektive erscheint im PACKAGE EXPLORER das Projekt. Über
das Kontextmenü des Projekts und den Befehl FILE | NEW können Packages und Klassen zu
dem Projekt hinzugefügt werden.

2.1.5 Package Explorer und View-Funktionen


Wie in Abb. 2.2 zu sehen, zeigt der Package Explorer die Projekte mit deren Packages
sowie deren Elementen (Klassen, Interfaces, Methoden, Variablen etc. – hier am Beispiel
eines Ausschnitts der String-Klasse). Die Icons, die zur visuellen Unterstützung der Ele-
mente angezeigt werden, sind abhängig von der View bzw. davon, welche Plug-Ins aktiviert
und welche Label Decorators (siehe Abschnitt 2.12) zugelassen sind.

Abb. 2.2: Package Explorer

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

Perspektiven und Views von Eclipse

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, ...).

Abb. 2.3: Fensterfunktionen

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).

Abb. 2.4: View Stack (Package Explorer ausgewählt)

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

2 – Wegweiser durch Eclipse

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.

2.1.6 Das Eclipse-Editorfenster


Im Zentrum von Eclipse befindet sich der Editor bzw. das Editorfenster. Pro geöffneter Da-
tei existiert ein Editierfenster (siehe Abb. 2.5), wobei jeweils eines aktiv ist. In allen nach-
folgenden Betrachtungen der Fähigkeiten des Eclipse Editors werden wir uns die Aktionen
innerhalb dieses Fensters ansehen.

Abb. 2.5: Eclipse-Editorfenster und Outline View

2.1.7 Outline View


Auf der rechten Seite der Java-Perspektive erscheint die Outline View (Abb. 2.5). Sie vi-
sualisiert abhängig von der jeweils geöffneten Datei deren Inhalte strukturell. Bei Anzeige
einer Java-Datei werden darin die Hauptelemente (Variablen, Methoden, Konstruktoren),
deren Attribute und Abhängigkeiten zu Superklassen angezeigt.
Im Gegensatz zur Package Explorer-Ansicht kann hier die Klassenstruktur ganz individuell
angezeigt werden. Dazu stehen folgende Funktionalitäten in der Outline-View als Shortcuts
zur Verfügung:

23
eclipse_v01.book Seite 24 Montag, 30. Januar 2006 12:02 12

Perspektiven und Views von Eclipse

SORT – Aktivierung/Deaktivierung der Sortierung innerhalb der Java-Elemente der Klasse


HIDE FIELDS – Ein-/Ausblenden von Instanz- und Klassenvariablen
HIDE STATIC FIELDS AND METHODS – Ein-/Ausblenden von Klassenelementen
HIDE NON-PUBLIC MEMBERS – Ein-/Ausblenden aller nicht öffentlichen Variablen/Methoden
HIDE LOCAL TYPES – Ein-/Ausblenden aller lokalen und anonymen Typen der Klasse
LINK TO EDITOR (IM MENÜ) – Synchronisation zwischen Editorfenster und dieser View
GO INTO TOPLEVEL TYPE (IM MENÜ) – öffnet die Ansicht des Baums auf Ebene der angezeig-
ten Klasse

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.

2.1.8 Tasks/Problems View


Rechts unten finden sich in Eclipse standardmäßig die Tasks, Warnings und Errors. Dabei
handelt es sich stets um zu erledigende Aufgaben, allerdings mit unterschiedlicher Priorität.
Im schlimmsten Fall zeigt die Problems View (siehe Abb. 2.6), dass ein komplettes Projekt
nicht kompiliert werden konnte, weil einzelne Bibliotheken oder sogar das komplette Java
Runtime Environment fehlt oder nicht an der gesuchten Stelle gefunden wurde. In einem
anderen Fall werden Methoden, die als deprecated gekennzeichnet sind, aufgerufen, so dass
bestimmte Klassen nicht kompiliert werden können. In der separaten Taskview (aktivierbar
über das Menü WINDOW | SHOW VIEW | OTHER | BASIC | TASKS) können Hinweise angezeigt
werden, was z.B. noch überarbeitet, getestet oder dokumentiert werden soll.

Abb. 2.6: Problems View zur Anzeige von Build-Problemen

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

2 – Wegweiser durch Eclipse

Die Anzeige sollte sinnvollerweise eingeschränkt werden. Hierzu sollte die


Menge der gleichzeitig sichtbaren Fehler (LIMIT VISIBLE ITEMS TO) auf 500
reduziert werden und der Radiobutton ON ANY RESOURCE IN SAME PROJECT
gewählt werden. In diesem Fall werden pro angelegtem Eclipse-Projekt
——

die Fehler angezeigt. Wenn externe Klassen, auf deren Sourcecode-


Debugging nicht verzichtet werden soll oder kann, in eigene Eclipse-Pro-
jekte ausgelagert werden, wird das Durcheinander in der Problem- und
Task-Anzeige deutlich reduziert, allerdings belastet häufiges Wechseln
zwischen den Projekten dann auch die Gesamtperformance der Anwen-
dung. Darüber hinaus besteht die Möglichkeit, durch die Definition von so
genannten Working-Sets (Arbeitsmengen) die Menge der Klassen noch-
mals wesentlich einzuschränken. Nur kann dies auch schnell zu Verwir-
rungen führen.

2.1.9 To be done – Arbeiten mit Tasks


Wird in einem Projekt konsequent modelliert und der Sourcecode von einem CASE-Tool
generiert (siehe auch Kapitel 3 über Modellierung), werden eine Fülle von Klassen und
Methoden erzeugt, deren Ausgestaltung (Implementierung und Erstellung entsprechender
Dokumentation) vom Wohlwollen der Programmierer abhängt.

Abb. 2.7: Tasks View und TODO-Definitionen im Editorfenster

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

Perspektiven und Views von Eclipse

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.

ToDo’s in den Sourcecode zu schreiben ist sehr angenehm und einfach


und überlebt z.B. auch einen Eclipse-Absturz, bei dem hin und wieder lei-
der auch manuell erfasste Tasks verloren gehen können. Wenn die Zahl
der ToDo's (eigene und die von Kollegen) zu unübersichtlich wird, lassen
——

sich auch eigene persönliche definieren. Vordefiniert sind „TODO“,


„FIXME“ und „XXX“.

2.1.10 Eigene Tasks definieren


Die Tasks bzw. die begrifflichen Definitionen, die zu einer Task führen, können in einem
Projekt vollkommen frei vergeben werden. Entweder wird dies in den Preferences einge-
stellt (siehe Abschnitt 2.12) oder man entscheidet sich, dass nur das einzelne Projekt auf
diese Tasks reagieren soll (Kontextmenü des Eclipse-Projekts im Package Explorer PROPER-
TIES | JAVA COMPILER | JAVA TASK TAGS – siehe Abb. 2.8).

Abb. 2.8: Erstellen eigener Tasks über Project-Properties

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
——

nicht gedreht haben.

26
eclipse_v01.book Seite 27 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

2.2 Hilfe in Eclipse


Die Hilfe ist vor allem für diejenigen interessant, die noch nie mit Eclipse gearbeitet haben.
Wir haben sie bereits kurz nach der Installation von Eclipse in Form einer Reihe von Tuto-
rials in der Welcome-Perspektive gesehen. Diese lässt sich bei Bedarf über den Menüpunkt
HELP | WELCOME erneut anzeigen.
Die Standard-Eclipse-Hilfe wird über den Befehl HELP | HELP CONTENTS aktiviert. In zahl-
reichen Dialogen kann aber auch durch Drücken der É-Taste eine kontextsensitive Hilfe
aufgerufen werden, die einzelne Funktionen erläutert.
Eclipse unterstützt zusätzlich einen Mechanismus der sich Cheat Sheets nennt und den Be-
nutzer durch eine Sequenz von definierten Schritten führt. Nach dem Abschluss jedes ein-
zelnen Schritts schreitet das Cheat Sheet voran, wobei jeder Step automatisch ausgeführt
oder manuell durch den Benutzer durchzuführen ist. Die Tutorials in Eclipse unterstützen
diese Cheat-Sheet-Technik, um beispielsweise die Entwicklung eines Hello-World-Bei-
spiels in Eclipse zu präsentieren (HELP | CHEAT SHEETS...). Zu diesem Mechanismus gehört
auch eine Cheat Sheets View, die sich über WINDOW | SHOW VIEW | OTHER | CHEAT SHEETS |
CHEAT SHEETS aktivieren lässt.

Beispielprojekt – Arbeiten mit Regular Expressions


Jedes klassische Buch über Programmierung oder IDEs fängt mit dem berühmten Hello-
World-Beispiel an, das einen zwischen ein paar Minuten Aufwand und mehreren Anrufen
beim entsprechenden Support Zeit kosten kann (eben auch je nach Sprache und Entwick-
lungsumgebung).
Da es allerdings wenige Unternehmen gibt, die Hello-World-Programme auch kommerziell
vertreiben können (außer vielleicht Buchverlage und deren Autoren ;-), werden wir im Fol-
genden ein etwas komplizierteres Beispiel betrachten.
Ziel ist das Entwickeln einer Klasse, die einen StringBuilder (z.B. gelesen aus einer Datei
oder von einer Webseite) nach bestimmten Zeichenkombinationen durchsucht. Gemeinhin
wird so etwas oft mit Regular Expressions realisiert. Da man im Projekt oft schon fertige
Frameworks einsetzt und mit größeren Klassenmengen umgehen muss, werden wir mittels
Jakarta ORO an einer solchen Kleinstanwendung die Funktionen von Eclipse betrachten.
Ziel ist es nicht, ein komplexes Design abzubilden, sondern zunächst einmal Eclipse-
Grundkenntnisse zu erhalten.
Hierzu wird Apache Jakarta ORO (hier in Version 2.0.8) als Sourcecode1 benötigt.
Bevor wir uns dem Beispiel widmen, erfahren Sie, was unter einer Regular Expression zu
verstehen ist. Eine Regular Expression beschreibt, wie ein Computerprogramm ein Text-
muster verarbeiten soll und was zu tun ist, wenn dieses Muster gefunden wird. Das ORO-
Framework prüft unter Verwendung unterschiedlicher Methoden, inwieweit andere Zei-
chenketten eine beschriebene Bedingung erfüllen.
Eine solche Regular Expression könnte lauten: „[0-9]“. Alle Zeichenketten, die genau aus
einer Zahl bestehen, würden in diesem Fall der Regular Expression gehorchen.

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.

Tabelle 2.1: Einfache Regular Expressions

Regular expression Erläuterung

[0-9] eine Ziffer – Beispiel: 0, 1, 2, 3, 4, 5, ...

[0-9]{2} zwei Ziffern – Beispiel: 05, 76, 65, 54, 29, 99, ...

[A-Za-z] irgendein Buchstabe – Beispiel: A, z, Z, j , I, x, C

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:

public Vector <String> getAllOccurrencesOfPattern(


final String originalContent, final String patternString) { }

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

2 – Wegweiser durch Eclipse

Abb. 2.9: Hinweise auf Build-Fehler in Eclipse

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.

Eclipse kompiliert im Gegensatz zu vielen anderen Umgebungen inkre-


mentell, das heißt, nur jene Sourcecodeteile, auf die Änderungen Auswir-
kungen haben, werden kompiliert. Eclipse kompiliert die Teile, die
kompilierbar sind, und lässt die anderen beim Erzeugen des Classfiles
——

unberührt. Voraussetzung für den inkrementellen Compile ist, dass der


automatische Compile des Projekts nicht deaktiviert ist (Menü PROJECT |
BUILD AUTOMATICALLY) und durch die Tastenkombination Ÿ+S kompiliert
wird. Über den Menüpunkt PROJECT kann man nun das gesamte Projekt,
einen Source-Teil (Workingset) oder alle Projekte neu kompilieren und den
Neucompile mittels des Menüpunkts CLEAN forcieren.

29
eclipse_v01.book Seite 30 Montag, 30. Januar 2006 12:02 12

Hilfe in Eclipse

Abb. 2.10: Quick Fix und Lösungsmöglichkeiten im Einsatz

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

2 – Wegweiser durch Eclipse

Die Entscheidung fällt erneut auf die erste Lösungsalternative: das Erzeugen des return-
Statement.

Abb. 2.11: Quick Fix mit Lösungsmöglichkeiten (2)

2.3 Eclipse-Projekte individuell konfigurieren


Vor dem Einsatz des ORO-Frameworks importieren wir es. Hierzu müssen zunächst die zu
Jakarta ORO gehörigen Dateien gespeichert werden.

Abb. 2.12: ORO-Verzeichnisstruktur

Daraufhin sollte am Speicherort die in Abb. 2.12 sichtbare Verzeichnisstruktur zu finden


sein. Neben einem „Document-Verzeichnis“ ist noch das Source-Verzeichnis, in dem die
Java-Klassen liegen, interessant.
Wir wechseln zurück zu Eclipse und erzeugen ein neues Projekt mit dem Namen ORO, in-
dem wir im Menü FILE | NEW | PROJECT | JAVA PROJECT | NEXT wählen und im daraufhin er-
scheinenden Fenster als Projektnamen ORO eingeben. Wir aktivieren den Radiobutton
CREATE PROJECT FROM EXISTING SOURCE und wählen das Verzeichnis, in dem wir ORO ent-
packt haben (z.B. D:\jakarta-oro-2.0.8). Bereits hier können Sie wählen, ob Eclipse später
Sourcecode und generierte Class-Files in unterschiedlichen Verzeichnissen ablegen soll.
Für den Moment lassen wir diese Funktion aber unangetastet.
Eclipse deaktiviert die Definition eines Projektlayouts und versucht nun, das Verzeichnis
nach bereits existierenden Class-Files und Libraries zu durchsuchen. Mit NEXT gelangen
wir auf die Project-Property-Seite.

31
eclipse_v01.book Seite 32 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekte individuell konfigurieren

Abb. 2.13: ORO – New project – Java settings

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

2 – Wegweiser durch Eclipse

Abb. 2.14: Source Folder Inclusion and Exclusion Patterns

Gleiches können Sie auf Wunsch mit dem org-Verzeichnis tun.


Nach der Bestätigung mit dem Button OK ist das Source-Verzeichnis, aus dem wir ORO
laufen lassen wollen, hinreichend beschrieben. Den DEFAULT OUTPUT FOLDER stellen wir von
ORO/bin auf 6ORO/classes ein (dies ist eine der Default-Eigenschaften, die in den Prefe-
rences definiert werden kann, siehe Kapitelabschnitt 2.12).
Eclipse zieht zusätzlich zum Sourcecode auch die jakarta-oro-2.0.8-JAR-Bibliothek mit he-
ran. Auch sie finden wir noch im Projektbaum vor. Über die rechte Maustaste auf der Datei
und den Menüpunkt REMOVE FROM BUILD PATH können wir diese nun wieder ausschließen.
Für jedes erkannte Source-Verzeichnis lässt sich auf Wunsch ein anderes Output-Verzeich-
nis für die Classfiles definieren. Zu diesem Zweck wird die Checkbox ALLOW OUTPUT FOL-
DERS FOR SOURCE FOLDERS aktiviert. Für das Beispiel macht diese Funktion allerdings keinen
Sinn, weshalb wir die Checkbox deaktiviert belassen.

33
eclipse_v01.book Seite 34 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekte individuell konfigurieren

Wenn ein entsprechend umfangreiches Projekt vorliegt und die generier-


ten Classfiles außerhalb noch weiterbearbeitet werden sollen (z.B. in einer
Ant-Task) kann es sinnvoll sein, Teile des Sourcecodes von anderen ört-
lich zu trennen. Für das hier betrachtete einfache Beispiel bringt das aber
——

keine Vorteile.

Abschließend klicken wir den FINISH-Button an, um die Projekt-Properties zu verlassen,


und führen somit den Compile für das Projekt durch, das daraufhin wie in Abb. 2.15 aus-
sehen sollte.

Abb. 2.15: ORO-Projektstruktur

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

2 – Wegweiser durch Eclipse

2.3.1 Vorhandenen Sourcecode ins Projekt Link to Source


Grundsätzlich lässt sich darüber diskutieren, wie mit Sourcecode umgegangen werden
sollte, der gleichzeitig in Form von Classfiles vorliegt. Im obigen Beispiel haben wir den
Sourcecode nicht importiert, sondern quasi das Projekt aus dem normalen Eclipse-Work-
space heraus auf der Festplatte verlinkt, um dort unseren Compile durchzuführen.

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.

Die Varianten im Vergleich


Die Auswirkungen aller drei Varianten sind allerdings sehr unterschiedlich. Letztgenannte
ist zwar sehr schnell und einfach, weil sie keinen Recompile und kein Vorhandensein ab-
hängiger Libraries benötigt, dafür kann man nicht vernünftig durch diese Klassen debug-
gen.
Wird der komplette Sourcecode über die Import-Funktion (rechte Maustaste auf dem Java-
Projekt oder über das Menü FILE | IMPORT) importiert, wird er effektiv eigentlich nur unnö-
tigerweise verdoppelt, ohne dadurch einen Mehrwert zu haben.
Wird zum Sourcecode verlinkt, existiert der Sourcecode nur einmal und er lässt sich debug-
gen. Der Nachteil bei der Variante ist, dass alle abhängigen Libraries vorhanden sein müs-
sen, um kompilieren zu können. Dafür können aber gegebenenfalls auch Modifikationen
am Sourcecode vorgenommen werden.

35
eclipse_v01.book Seite 36 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekte individuell konfigurieren

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
——

der Reihenfolge der Klassen im Classpath die Classfiles den Classloadern


übergibt, macht es Sinn, im Register ORDER der Build Path-Properties des
Projekts die Sourcecode-Dateien vor die restlichen Libraries zu schieben.
Je nach Eclipse-Version und verwendetem JDK zeigt sich Eclipse dann
großzügig und debuggt durch die Sourcecode-Dateien, während im Hinter-
grund für fehlerhafte Klassen, die nicht kompiliert werden konnten, die
Classfiles aus dem Jar-File herangezogen werden. Dies macht auch dann
Sinn, wenn einzelne Funktionen eines Frameworks testhalber deaktiviert
werden sollen und dem Original eine „Fake“-Klasse untergejubelt werden
soll, die weiter vorn in den Build- und Runtime-Classpath gelegt wird.

2.3.2 Projekteigenschaften definieren


Um die Eigenschaften des ORO-Projekts neu zu konfigurieren (siehe Abb. 2.16), klicken
wir auf den Namen des ORO-Projekts mit der rechten Maustaste und wählen den Unter-
punkt PROPERTIES oder drücken Ç+Æ. Auf der linken Seite erscheinen die Kategorien,
für die Einstellungen vorgenommen werden können, auf der rechten Seite daneben die zu-
geordneten Parameter, die durch Anklicken des OK-Buttons übernommen werden können.

Abb. 2.16: Java-Projekt – Eigenschaften

36
eclipse_v01.book Seite 37 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Ü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

Eclipse-Projekte individuell konfigurieren

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.

Die Einstellungen im Bereich BUILDING sind besonders dann interessant,


wenn man beispielsweise mit vielen separaten Source- und unterschiedli-
chen Ausgabe-Compile-Verzeichnissen arbeiten möchte. Hier lässt sich
nun konfigurieren, ob Eclipse auf unvollständige oder „kaputte“ Build-
——

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.

Info und Java Build Path


Die Dialogpunkte INFO und JAVA BUILD PATH des Projekteigenschaftsdialogs schauen wir an
dieser Stelle nicht weiter an. Die Info gibt grundsätzliche Informationen über das Projekt.
Beim Punkt JAVA BUILD PATH handelt es sich um die Zusammenstellung der Source- und
Class-Verzeichnisse und der Libraries, die zum Compile herangezogen wurden (siehe Ab-
schnitt 2.3).

Java Code Style


Unter dem Unterpunkt JAVA CODE STYLES lassen sich individuelle Einstellungen für die Ko-
dierungsrichtlinien dieses Projekts vornehmen. Dies ist besonders in größeren Projekten
mit klar formulierten Design- und Coderichtlinien sehr hilfreich, wenn zahlreiche Einstel-
lungen bereits während der Programmierphase geprüft oder bei der Erstellung entspre-
chend unterstützt werden.

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

2 – Wegweiser durch Eclipse

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.

Fremde Projekte referenzieren


Wir öffnen nun noch einmal die PROPERTIES des RegExtTest-Projekts über die Tastenkombi-
nation Ç+Æ nach Anklicken des Projektnamens im PACKAGE EXPLORER und klicken
auf die Einstellungen des BUILD PATH.
Da die beiden angelegten Projekte RegExTest und ORO sich gegenseitig nicht kennen, muss
das Projekt RegExTest die ORO-Klassen beim Build berücksichtigen. Dies wird dadurch
abgewickelt, dass das ORO-Projekt beim Compile referenziert wird.
Klicken Sie im Register PROJECTS den Button ADD an und wählen Sie das nun neu zu asso-
ziierende ORO-Projekt. Klicken Sie dann auf OK, damit das Projekt in den BUILD PATH-
Eigenschaften von RegExTest erscheint. Auf diese Art und Weise werden die ORO-Klassen
aus den Source-Pfaden des ORO-Projekts für das RegExTest-Projekt sichtbar.

Vom ORO-Projekt selbst wiederum referenzierte weitere Projekte, JAR-


Files oder Verzeichnisse werden erst auf Wunsch über eine separate
Export-Funktion im Register Classpath sichtbar.

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ß.

Das gegenseitige Referenzieren sollte nicht übertrieben werden, um


bösen Überraschungen vorzubeugen. Besonders zirkuläre Beziehungen
kann Eclipse nicht vernünftig bearbeiten, da es nicht weiß, wer nun bei der
Definition der Klassen die Vorreiterrolle spielt und wie der Classpath für

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
*/

public class ExpressionAnalyzer {


public Vector <String> getAllOccurrencesOfPattern(final String
originalContent,final String patternString) {
// Erzeugen eines Ergebnisvectors:
Vector <String> results = new Vector<String>();
// Jedes neue Muster muss zunächst von einem Compiler
// kompiliert werden:
Perl5Pattern pattern =
(Perl5Pattern) regexpCompiler.compile(patternString);
// Für das Auffinden von Mustern benötigen wir einen
// so genannten Matcher und sinnvollerweise
// einen zugehörigen Input, der sich als Objekt aus dem
// Original-Inhalt, den wir der Methode übergeben, ergibt:
Perl5Matcher occurencesMatcher = new Perl5Matcher();
PatternMatcherInput input = new PatternMatcherInput
(originalContent);
return null; // dieser Fehler ist beabsichtigt!
}
}

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

2 – Wegweiser durch Eclipse

Formatierung des Sourcecodes


Wir wollen nun dem Sourcecode etwas Struktur verleihen. Hierzu kehren wir zurück in die
Methode in der ExpressionAnalyzer-Klasse, klicken die rechte Maustaste und wählen
im Untermenü SOURCE den Punkt FORMAT (Ÿ+Á+F) (siehe Abb. 2.17). Daraufhin
wird der Sourcecode so formatiert, wie wir es in den globalen Preferences von Eclipse ein-
gestellt haben.
Sie können so den kompletten Sourcecode einer Klasse, bei Klick auf ein Package sogar
innerhalb eines Packages oder Projekts, oder gegebenenfalls nur markierte Textbereiche
formatieren.

Abb. 2.17: Sourcecode-Aktionen

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.

Die unterschiedlichen hier vorgestellten Funktionen sind nicht immer alle


aktiv. Dies ist abhängig davon, ob man beispielsweise einen Textbereich
markiert hat oder nur eine einzelne Sourcecode-Stelle. Ebenso wichtig ist
es, ob an dieser Stelle die jeweilige Aktion auch syntaktisch überhaupt

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.

Override/Implement Methods/Generate Getters and Setters


Diese Menüpunkte dienen dem Überschreiben von Methoden (Abschnitt 2.5.1) in Unter-
klassen und dem Erzeugen von Getter- und Setter-Methoden (Abschnitt 2.4.2). Für eine de-
tailliertere Beschreibung sei auf die jeweiligen Kapitelteile verwiesen.

Generate Delegate Methods


Öffnet den Delegate-Methoden-Dialog, der es erlaubt, Delegate-Methoden für Felder des
aktuellen Typs (Klasse, Interface) zu erzeugen.

Add Constructor from Superclass


Fügt über einen Wizard der aktuellen Klasse einen weiteren Superklassen-Konstruktor an
der definierten Sourcecode-Stelle (INSERT POINT) hinzu. Der implizite Aufruf des Default-
Konstruktors kann dabei wahlweise ausgespart werden (OMIT CALL TO DEFAULT CONSTRUC-
TOR).

42
eclipse_v01.book Seite 43 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Generate Constructor using Fields


Erzeugt über einen Wizard einen Konstruktor für diese Klasse, der die ausgewählten In-
stanzvariablen der Klasse enthält.

2.4.1 Quick Fix auf Variablen


Dass Quick Fixes auf Fehlern schnell zur Lösung derselbigen beitragen, haben wir schon in
Abschnitt 2.2 gesehen. Jetzt wollen wir die QuickFix-Möglichkeiten auf der Variable reg-
expCompiler nutzen, um die fehlende Variable zu generieren und Getter- und Setter-Me-
thoden für sie zu erzeugen. Wir klicken dafür erneut die kleine Hinweislampe neben dem
Sourcecode oder die regexCompiler-Variable an und drücken Ÿ-1.

Abb. 2.18: Quick Fix – Variablenerzeugung

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:

private Object regexpCompiler;

Wir werden den Typen modifizieren und für dieses Feld, das private deklariert worden
ist, noch eine Setter-Methode definieren.

2.4.2 Automatische Getter/Setter-Erzeugung


Zur automatischen Erzeugung der Getter- und Setter-Methoden markieren wir mit der Maus
den Namen der Variablendeklaration (regexpCompiler) oder selektieren den Instanz-
variablennamen im PACKAGE EXPLORER und wählen über die rechte Maustaste im Kontext-
menü SOURCE den Unterpunkt GENERATE GETTERS UND SETTERS. Die automatische Generie-
rung von Getter- und Setter-Methoden ist besonders dann hilfreich, wenn eine ganze Reihe
von Accessor-Methoden für eine Menge von Instanzvariablen erzeugt werden soll, ohne
jede einzelne manuell anzulegen und Javadoc-Kommentare zu erzeugen. Interessant sind
auch die Steuerung des INSERTION POINT, bei dem angegeben werden kann, wo im Source-

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.

Abb. 2.19: Getter/Setter-Erzeugung im Dialog

2.4.3 Sourcecode-Vervollständigung (Code completion)


Da Object als Klasse innerhalb der Deklaration für die regExpCompiler-Variable nicht
besonders sinnvoll ist, ersetzen wir sie durch PatternCompiler. Leider bietet Eclipse
hierfür noch keine vernünftige Refactoring-Maßnahme an. Allerdings können wir uns die
Code completion zu Nutze machen. Wir löschen dazu den Begriff Object und geben statt-
dessen den Begriff PatternCompiler nur unvollständig ein (z.B. „PatternC“) und drü-
cken dann mit dem Cursor hinter dem letzten Buchstaben die Tastenkombination
Ÿ+Leertaste. Eclipse bietet daraufhin eine Liste von möglichen Vervollständigungen

44
eclipse_v01.book Seite 45 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

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.

Wird Ÿ+Leertaste hinter einer schon voll ausgeschriebenen, allerdings


noch ohne Importstatement versehenen Klasse gedrückt, ergänzt Eclipse
automatisch das fehlende Importstatement (soweit die Klasse nicht unter
einem anderen Package bereits in den Imports vorhanden ist).

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;

public class ExpressionAnalyzer {


private PatternCompiler regexpCompiler;
public Vector<String> getAllOccurrencesOfPattern(
final String originalContent,
final String patternString) {
Vector<String> results = new Vector<String>();
// hier fehlt noch ein Try-Catch-Block:
Perl5Pattern pattern = (Perl5Pattern) regexpCompiler
.compile(patternString);
Perl5Matcher occurencesMatcher = new Perl5Matcher();
PatternMatcherInput input =
new PatternMatcherInput(originalContent);
return null; // hier wird noch null zurückgegeben
}

45
eclipse_v01.book Seite 46 Montag, 30. Januar 2006 12:02 12

Sourcecode-Editor-Features

public Object getRegexpCompiler() {


return regexpCompiler;
}
public void setRegexpCompiler(Object regexpCompiler) {
// hier gibt's noch einen Konvertierungsfehler:
this.regexpCompiler = regexpCompiler;
}
}

Jetzt gibt es noch einen Compile-Fehler in der setRegexpCompiler-Methode und ein


Try-Catch-Problem. Beide Fehler werden wir als Nächstes beseitigen.

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).

Abb. 2.20: Try-Catch-Block-Generierung

46
eclipse_v01.book Seite 47 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

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:

throw new BusinessException("Error in pattern compile and"


+ " execution:"+patternString);

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).

Abb. 2.21: Erweiterung der Throws-Klausel

Zur endgültigen Vervollständigung der Methode getAllOccurrencesOfPattern ma-


chen wir uns Code-Templates zunutze.

47
eclipse_v01.book Seite 48 Montag, 30. Januar 2006 12:02 12

Sourcecode-Editor-Features

2.4.5 Sourcecode-Templates verwenden


Ein Eclipse-Feature, das auch in die Code completion hineinspielt, ist die Verwendung von
Sourcecode-Templates. Templates sind Vorlagen, die verwendet werden können, um die
Erzeugung immer gleicher Sourcecode-Bestandteile zu beschleunigen. Funktional läuft es
genauso ab wie bei der Code completion. Es wird der Name des Template eingegeben und
die Tastenkombination Ÿ+Leertaste gedrückt. Für den Fall, dass es mehrere Vervoll-
ständigungsmöglichkeiten gibt, erscheint eine Auswahlliste.
Für wichtige Sprachkonstrukte wie Schleifen besitzt Eclipse entsprechende Vorlagen. Für
Iterationsstrukturen, wie z.B. For- oder While-Schleife, aber auch für viele andere Kon-
strukte wie Try-Catch-Blöcke oder Kommentare besitzt die IDE Vorlagen. Bei der De-
finition von Vorlagen werden bestimmte Freiheitsgrade offen gelassen. Dazu zählen bei-
spielsweise die Festlegung von Kontextbausteinen, Methodennamen oder Klassennamen.
Detailliert gehen wir darauf in Abschnitt 2.12 ein.
Eine komplette Übersicht der vorhandenen Templates erhalten wir durch Auswahl von
Menü WINDOW | PREFERENCES im Baum JAVA | CODE STYLE | CODE TEMPLATES.

Erinnerung: Sie können auch in der Such-Combobox im Preferences-Dia-


log den Begriff „code templates“ eingeben, um schnell zur gewünschten
Eigenschaftenseite zu gelangen.

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).

Abb. 2.22: Code template für eine While-Schleife

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

2 – Wegweiser durch Eclipse

Abb. 2.23: Code completion – Beispiel

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).

Abb. 2.24: Parameterübergabe

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):

Vector <String> results = new Vector<String>();


try {
Perl5Pattern pattern =
(Perl5Pattern) regexpCompiler.compile(patternString);
Perl5Matcher occurencesMatcher = new Perl5Matcher();
PatternMatcherInput input = new PatternMatcherInput
(originalContent);
while (occurencesMatcher.contains(input,pattern)) {
MatchResult foundObject = occurencesMatcher.getMatch();
String matchingText = foundObject.group(0);
results.add(matchingText);
}
} catch (MalformedPatternException e) {
e.printStackTrace();
throw new BusinessException("Error in pattern compile and"
+ " execution:"+patternString);
}
return null; // Rückgabewert ist absichtlich falsch!

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.

2.4.6 Gimmicks des Editors


Über Sinn und Unsinn komplexer Tastenkombinationen zum Fingerbrechen lässt sich zu-
weilen streiten. Eine Reihe dieser scheinbaren Gimmicks, die Eclipse bereithält, seien hier
der Vollständigkeit halber aber genannt.
Einfügen, Verschieben und Duplizieren
Für diese scheinbar einfachen Aufgaben hält Eclipse die Tastenkombinationen Ç+| /
Ç+~ (Aufwärtsverschieben/Abwärtsschieben der aktuellen (markierten) Zeile(n)) be-
reit. Bei zusätzlich gedrückter Ÿ-Taste dupliziert Eclipse die markierten Zeilen in der
per Pfeil gewählten Richtung.
Zum Einfügen neuer Leerzeilen kann Ÿ+Á+Æ für Zeilen oberhalb oder
Á+Æ für Zeilen unterhalb benutzt werden.

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.

Anzeigen der Typhierarchie


Im Abschnitt 2.9.1 findet sich eine Erläuterung darüber, wie Eclipse detaillierte Informa-
tionen über Vererbungshierarchien zur Verfügung stellt. Eine einfache Version (Quick type
hierarchy view) lässt sich über die Tastenkombination Ÿ+T anzeigen, wenn der Cur-
sor zuvor auf einer Variablen positioniert wird. Mittels der gleichen Tasten lässt sich zwi-
schen normaler und Supertype Hierarchie-Anzeige wechseln.

50
eclipse_v01.book Seite 51 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

2.4.7 Immer ein Undo für die Vergangenheit


Variante 1: Grundsätzlich können alte Zustände einer Arbeit über die Tastenkombination
Ÿ+Z wiederhergestellt (Undo) oder erneut ausgeführt werden (Ÿ+Y, Redo).
Variante 2: Über die rechte Maustaste am linken Editorrand kann eine so genannte Quick
Diff-Referenz (SHOW QUICKDIFF) erzeugt werden. In einem farbig markierten Indikatorstrei-
fen ist erkennbar, ob sich auf Basis der letzten gespeicherten Version an dieser Stelle eine
Änderung ergeben hat. Über die rechte Maustaste besteht auch die Möglichkeit, einzelne
Blöcke (REVERT BLOCK) oder Zeilen (REVERT ADDEDED LINE/REVERT REMOVED LINE) zeitlich zu-
rückzudrehen.
Variante 3: Über die rechte Maustaste und das Menü LOCAL HISTORY erreicht man im Editor
die Standardfunktionen zum Wiederherstellen alter Sourcecode-Zustände. Wie gut dies
funktioniert, hängt davon ab, ob neben dem Eclipse zur Verfügung gestellten RAM-Spei-
cher noch ein Sourcecode-Management-System existiert, das die langfristige Versionie-
rung von Dateien erlaubt.
Eclipse zieht grundsätzlich beim Speichern der Datei eine Version, die es intern mit einem
Zeitstempel belegt. Diese Versionen speichert es für folgende Menüfunktionen zwischen:
COMPARE WITH – Vergleich dieser Version mit einer alten über einen entsprechenden Wizard
REPLACE WITH PREVIOUS – Ersetzen der aktuellen Source-Version mit der letzten gespeicher-
ten
REPLACE WITH – Ersetzen der aktuellen Source-Version mit einer gespeicherten
RESTORE FROM – Wiederherstellung bereits gelöschter Elemente (Methoden, Felder, ...) aus
der lokalen Historie

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.

2.5 Refactoring mit Eclipse


Refactoring wird hin und wieder mit Umorganisieren übersetzt. Dies ist zwar sehr schön
eingedeutscht, verliert damit aber ähnlich an Charakter, wie wenn Application Server mit
Anwendungsdienstleister übersetzt wird, ohne Berücksichtigung der Bedeutung.
Der Autor Martin Fowler verfasste vor Jahren ein Buch mit dem Titel „Refactoring. Impro-
ving The Design Of Existing Code“1 und beschrieb darin eine Reihe von Mechanismen für
objektorientierte Programmiersprachen, um das Design der Anwendung zu verbessern.

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

Refactoring mit Eclipse

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.

1. Fowler, Martin - Refactoring, S. 13, s.o.

52
eclipse_v01.book Seite 53 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Abb. 2.25: Refactoring – Change Method Signature

Beim Refactoring darf der gesunde Menschenverstand nie ausgeschaltet


werden. Ob sich das Design verbessert oder nicht, kann der Editor nicht
entscheiden. Er kann nur helfend zur Seite stehen. Der Entwickler hat
immer die Möglichkeit, einzelne der identifizierten Aktionen in der Preview

auch auszuklicken oder das Redesign von Hand zu beginnen.

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:

MatchResult foundObject = occurencesMatcher.getMatch();


String matchingText = foundObject.group(0);

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

Refactoring mit Eclipse

Abb. 2.26: Refactoring – Extract Method

Folgendes erscheint als fertiges Ergebnis in der While-Schleife:

String matchingText = getMatchingTextFromMatcher


(occurencesMatcher);

Bei allen nachfolgenden Erläuterungen gehen entsprechende Refactoring-Dialoge und Pre-


views Hand in Hand. Tabelle 2.2 enthält einen Überblick über die Refactorings.

Tabelle 2.2: Refactoring-Maßnahmen in Eclipse

Refactoring-Maßnahme Durchgeführte Aktion

Rename (Ç-Á-R) Umbenennen von Java-Elementen (siehe Beispiel oben)

Move (Ç-Á-V) Verschieben von Java-Elementen (z.B. Packagechanges)

Change Method Signature Ändern der Methodensignatur (siehe Beispiel oben)

Convert Anonymous Class Wandelt eine anonyme innere Klasse in eine eingebettete,
to Nested benannte Subklasse um

Convert Nested Type to Wandelt eine eingebettete Unterklasse in eine eigen-


Top Level ständige Klasse um und erzeugt für diese eine eigene
Java-Datei

Move Member Type to Extraktion einer Unterklasse in eine eigene Datei


New File

Push Down Verschiebt eine Menge von Methoden und/oder Feldern zu


einer Unterklasse dieser Klasse

54
eclipse_v01.book Seite 55 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Tabelle 2.2: Refactoring-Maßnahmen in Eclipse (Forts.)

Refactoring-Maßnahme Durchgeführte Aktion

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

Inline Gegenteil des Extrahierens einer Methode. Fügt den Source-


code dieser Methode als Inlinecode an jeder aufrufenden
Stelle ein.

Extract Method Extrahiert eine Menge von Sourcecode-Zeilen in eine


eigene Methode (siehe Beispiel oben)

Extract Local Variable Ersetzt die selektierte Variable durch eine andere mit
anderem Namen unter Zuweisung der ersten an die zweite

Extract Constant Überführt eine Instanzvariable in eine Konstante. Wenn die


Transformation durchführbar ist, werden entsprechende
Referenzen auf die Variable korrigiert.

Encapsulate Field Kapselt eine Instanz- oder Klassenvariable über Accessor-


Methoden (getter und setter)

Introduce Parameter Auf einer selektierten Expression aufgerufen, wird der


umgebenden Methode ein neuer Parameter hinzugefügt
und alle Methodenaufrufe werden entsprechend korrigiert.

Generalize type Nach Selektion einer Variablen, eines Parameters, Felds


oder eines Methodenrückgabetyps zeigt ein Wizard die
Supertyphierarchie des Elements. Nach Auswahl eines
Typs wird die Deklaration des Elements angepasst.

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

Refactoring mit Eclipse

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.).

2.5.1 Überschreiben/Implementieren von Methoden


Beim Überschreiben von Methoden der Basisklasse und beim Implementieren der Metho-
den eines Interface werden wir ebenfalls unterstützt. Im SOURCE-Menü, erreichbar über die
rechte Maustaste im Editor, gibt es hierfür den Menüpunkt OVERRIDE/IMPLEMENT METHODS,
der auch im Editor über die rechte Maustaste erreicht werden kann. Da jede Klasse mindes-
tens von java.lang.Object als Root-Klasse erbt, können zumindest Methoden wie to-
String oder equals in der ExpressionAnalyzer-Klasse überschrieben werden. Sollte
ein weiteres Interface der Klasse hinzugefügt werden, das die Implementierung einzelner
Methoden verlangt, kann ähnlich verfahren werden.
Wird ein Interface manuell der Klasse über implements im Klassenkopf hinzugefügt, bie-
tet Eclipse an, jene zu implementierenden Methoden, die jetzt zum Syntaxfehler führen, au-
tomatisch hinzuzufügen oder die Klasse selbst als abstrakt zu deklarieren.
Während beim Interface oder einer abstrakten Superklasse öfter Methoden in der eigenen
Klasse selbst implementiert werden müssen, um dem Interface zu genügen, muss z.B. die
toString-Methode nicht zwingend implementiert werden. Wir machen es der Übung hal-
ber trotzdem.

Abb. 2.27: Override/Implement Methods

56
eclipse_v01.book Seite 57 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Ü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)+"}";

Welche Methoden überschrieben wurden, zeigt Eclipse an einem kleinen


nach oben zeigenden Dreieck neben der Methodensignatur im Source-
code. Entsprechende Hinweissymbole finden sich zudem in der Outline-
view und der Vererbungshierarchieanzeige.

2.5.2 Auslagern von Zeichenketten/Mehrsprachigkeit


Für unser Beispiel ist es zwar nicht so relevant, aber wir könnten sehr einfach die Fehler-
meldung, die in unserer BusinessException weitergereicht wird, im Sourcecode auslagern.
Dies ist ein erster Schritt zur Implementierung einer Mehrsprachigkeit, die wir damit um-
setzen können, wenn wir entsprechende Resource-Bundle-Klassen geschrieben haben.
Wir klicken mit der rechten Maustaste auf den Klassennamen im Package Explorer und
wählen im Menü SOURCE | EXTERNALIZE STRINGS.

57
eclipse_v01.book Seite 58 Montag, 30. Januar 2006 12:02 12

Refactoring mit Eclipse

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).

Abb. 2.28: Externalize Strings – Dialog

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

2 – Wegweiser durch Eclipse

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:

throw new BusinessException(Messages.getString(


"ExpressionAnalyzer.ERROR_PATTERN_COMPILE1") //$NON-NLS-1$
+ Messages.getString(
"ExpressionAnalyzer.ERROR_PATTERN_COMPILE2") + patternString);
//$NON-NLS-1$

2.6 Erstellung eines JUnit-Tests


Unit-Tests sind ein probates Mittel für kleine Tests (vor allem Klassen). Für einen tieferen
Einblick in JUnit sei auf die JUnit-Webseite1 verwiesen.
JUnit-Tests vereinfachen vor allem den Test von Schnittstellen zu Klassen, wobei unter-
schiedliche Konstellationen von Inputdaten in Form von Parametern gegen die korrekten
Rückgabewerte bzw. das erwartete Auftreten von Exceptions getestet werden. Mit JUnit
können auch sehr komplexe Testszenarien erzeugt werden.
Ein Vorteil von JUnit ist die ständige Reproduzierbarkeit von Tests per Mausklick. Aber
auch nach der Implementierung macht das Aufsetzen eines Tests Sinn.
In unserem Fall ist ein Fehler offensichtlich. Die Methode getAllOccurrencesOfPat-
tern gibt immer null zurück (wenn dies von Ihnen nicht schon korrigiert worden ist) und
diesen Fehler wollen wir jetzt „entdecken“ und debuggen.
Man unterscheidet zwei Varianten von JUnit-Klassen: Test Cases und Test Suites. Während
der Test Case einen bzw. mehrere Testfälle durchspielt, ist die Test Suite eine darüber lie-
gende Klammer, die die Test Cases strukturiert.

Ab einer gewissen Phase und unter entsprechendem Zeitdruck des Pro-


jekts ist man immer gerne versucht, Test Cases nicht zu schreiben oder
geschriebene nicht auszuführen, weil sie eh nicht mehr funktionieren. Um
den Testvorgang zu automatisieren, werden die Test Cases als Target in

das Ant-Build-Skript, das für das Deployment verwendet wird, gehängt.

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

Erstellung eines JUnit-Tests

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).

Abb. 2.29: JUnit-Test-Case – Generierung

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

2 – Wegweiser durch Eclipse

[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).

Abb. 2.30: Junit-Test-Case – Ergebnisse

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 Debuggen in Eclipse

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

2 – Wegweiser durch Eclipse

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.

Abb. 2.31: Breakpoint-Properties-Dialog

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.

2.7.2 Aufsetzen einer Launch configuration


Für jedes Starten einer virtuellen Maschine – egal ob im Debug- oder Run-Modus – können
wir eine eigene Ausgangsumgebung schaffen, einen eigenen Classpath definieren, eine vir-
tuelle Maschine auswählen usw. So können wir den Build bzw. den Compile-Lauf vollkom-
men anders und mit einer anderen VM durchführen als mit der, mit der wir testen wollen.
Dieses Maximum an Flexibilität hat allerdings den Nachteil, dass wir aufpassen müssen,
was wir wo einstellen.
Über den Debug-Button in der Toolbar und den Menüpunkt DEBUG (oder über das Menü
WINDOW | DEBUG...) wollen wir uns die Session jetzt individuell definieren. Bereits erzeugte
Sessions (wie die vom Schnelltest vorhin bei JUnit) stehen bereits im Menü.
Im Schnelldurchlauf wollen wir uns diese Konfigurationen ansehen. Im linken Fenster kön-
nen dem Menübaum neue Launch-Konfigurationen hinzugefügt und alte entfernt werden.

Abb. 2.32: Launch configuration für einen JUnit-Test-Debugdurchlauf

64
eclipse_v01.book Seite 65 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Denjenigen, die zu den Programmierern gehören, die gern mehrere Stages


(Entwicklungsumgebung, Integrationstest, Kundentest, Produktion) in einer
Workbench haben, kann es schnell passieren, dass sich die gleichen Klas-
sen in unterschiedlichen Projekten wiederfinden. Besonders dann muss bei

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.

Wenn Probleme mit dem Klassenpfad auftauchen und bestimmte Klassen


oder Ressource-Dateien nicht gefunden werden, ist zunächst zu klären,
ob das File bzw. Verzeichnis im Classpath ist, und danach zu überlegen,
durch welchen Classloader (besonders wichtig bei Application Servern

oder Servlet Containern wie Tomcat) es geladen werden sollte. Erscheint


der Fehler „java.lang.Object kann nicht gefunden werden“, ist die Konfigu-
ration des JRE für das Projekt defekt oder fehlerhaft.Versuchen Sie durch
Korrekturen des Classpath und ein Clean auf dem Projekt den Compile zu
korrigieren.

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

2 – Wegweiser durch Eclipse

mehreren Java-Projekten zusammenbauen, die unabhängig kompiliert werden und dennoch


zum Start der Applikation gemeinsam vorhanden sein sollen. Dies kann sich zum Debug-
Zeitpunkt als sinnvoll erweisen.

Arbeiten Sie in einem großen Multiprojektumfeld, ist es unerlässlich, die


dort verwendeten Teilprojekte zu strukturieren. Hierbei hilft Eclipse, indem
man mehrere Projekte im Package Explorer zu so genannten Working
Sets gruppieren, einblenden und ausblenden lassen kann. Diese Funktio-

nen können auch helfen, sinnvolle Launch-Konfigurationen zu erstellen


und Programme aus Einzelkomponenten zusammenzusetzen.

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.

2.7.3 Die Debug-Perspektive im Überblick


Verschaffen wir uns einen Schnellüberblick über die Debug-Perspektive, indem wir den
JUnit-Test nochmals mit aktiviertem Breakpoint im Debug-Modus starten. Klicken Sie
dafür auf Debug im Dialog der Launch Configurations oder im Menü auf RUN DEBUG
HISTORY | EXPRESSIONANALYZERTEST. Unter Umständen fragt Eclipse dabei noch einmal, ob

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).

Abb. 2.33: Debug-Perspektive im Überblick

2.7.4 Grundfunktionen des Debuggens


Es ist bereits durch die Markierung der Sourcecode-Zeile zu sehen, dass der Debugger zum
Stehen gekommen ist. Der kleine blaue Pfeil zeigt dabei auch auf die Zeile, in der der De-
bugger angehalten hat. Im Sourcecode verankerte Breakpoints sind durch den kleinen run-
den Kreis und ein Häkchen daneben gekennzeichnet.
Da davon ausgegangen wird, dass bereits Erfahrungen mit dem Debuggen in den unter-
schiedlichsten IDEs vorliegen, wird im Folgenden lediglich eine kurze Liste der wichtigs-
ten Tastaturaktionen vorgestellt. Die beschriebenen Funktionen lassen sich auch über die

68
eclipse_v01.book Seite 69 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

rechte Maustaste auf der aktuellen Methode im Stack, die Toolbar des Debugviews oder
über das RUN-Menü ausführen (siehe Tabelle 2.3).

Tabelle 2.3: Primäre Debug-Funktionen

Aktionsname Durchgeführte Funktion

Open Declaration Type Öffnen des Sourcecode-Abschnitts, in dem das aktuell mar-
kierte Objekt deklariert ist

Open Declaration Type Öffnen der Vererbungshierarchieanzeige des aktuellen


Hierarchy Objekts

Resume – Ð Fortsetzen des Programms bis zum nächsten Breakpoint

Suspend Anhalten des Programms (Threads), während es läuft

Terminate Beenden des Programms (normalerweise gleichbedeutend


mit dem Beenden aller Threads)

Step Into – Í Debuggen in den Methodenaufruf hinein

Step Over – Î Zur nächsten Sourcecode-Zeile in dieser Methode weiter-


gehen

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

Relaunch Neustart dieser Launch Configuration/dieses Programms

Terminate All Beenden aller in Eclipse laufenden virtuellen Maschinen

Disconnect Löst eine Verbindung zu einem fernen Prozess. Diese Funk-


tion wird allgemein bei Remotedebugging von Java-Anwen-
dungen außerhalb der Eclipse-Umgebung verwendet.

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.

2.7.5 Allgemeine Hinweise zum Debuggen in Eclipse


Im Bereich des Java Debuggens hat sich seit den ersten JDKs viel getan. IBM schaffte vor
Jahren mit dem damaligen Visual Age für Java-Produkte etwas ganz Erstaunliches. Da IBM
eine eigene virtuelle Maschine mit der IDE auslieferte, war es dem Entwickler möglich,
nicht nur einzelne Werte von Variablen zur Laufzeit zu ändern, sondern sogar große Teile
des Sourcecodes und der Klassenstrukturen zum Debug-Zeitpunkt dauerhaft zu ändern. Wo
andere Produkte einen Rebuild des Sourcecodes brauchten, konnte der Entwickler hier den

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

2 – Wegweiser durch Eclipse

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.

2.7.6 Debug View


In der Degub View (links oben in der Debug-Perspektive) erscheinen alle laufenden Run/
Debug-Sessions sowie deren Namen und Typ. Tote Sessions werden als terminiert ange-
zeigt. Des Weiteren wird die Startklasse und die Port-Adresse für die Kommunikation zwi-
schen Eclipse-VM und Debug-VM angezeigt (siehe Abb. 2.34).

Abb. 2.34: Threadstack in der Debug View

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

entfernt werden (z.B. -Xdebug -Xnoagent -Djava.compiler=NONE


Xrunjdwp:transport=dt_socket,suspend=y,address=localhost:4253). Diese
Parameter können allerdings benutzt werden, falls Remote-Debugging
selbst durchgeführt werden soll.

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

2 – Wegweiser durch Eclipse

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.

Abb. 2.35: Variables View

Besonders das Debuggen komplexer Objekte stellte in den vorangegan-


genen Eclipse-Versionen große Probleme dar. Die kleine Variables View
hat nicht nur Probleme, umfangreiche Objektstrukturen wie beispielsweise
alle Member-Variablen eines JFrame anzuzeigen, es finden sich darin

auch oft verhältnismäßig viele, für den Debug-Prozess „uninteressante“


Informationen und Werte. Um dieses Problem zu lösen, gibt es zwei Mög-
lichkeiten: 1. uninteressante Membertypen wegblenden (über das Menü in
der Variables View lassen sich Konstanten und statische Elemente ein-
und ausblenden) und 2. die logische Baumstruktur modifizieren.
Mit Eclipse 3.1 ist ein neuer Formatter eingeführt worden, der nicht die
Detailansicht (also die toString()-Ausgabe) modifiziert, sondern die logi-
sche Baumstruktur des jeweiligen Objekts anpasst. Er ist über das Kon-
textmenü der Variables View erreichbar und trägt den Namen JAVA LOGICAL
STRUCTURES. Seine Bedienung ist ein wenig kompliziert. Über den Button
ADD können für einzelne vollqualifizierte Klassennamen einzelne oder
Baumstrukturen definiert und in einer Vorschauansicht begutachtet wer-
den. Haben Sie also eine der berüchtigten Swing-Klassen zur Hand, die
gedebuggt werden sollen, können Sie hier die wenigen interessanten
Membervariablen herausfiltern und alle anderen ausschließen.

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.

Tabelle 2.4: Variables View-Funktionen

Menüpunkt Aktion

Select All Selektiert alle geöffneten Baumelemente.

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

2 – Wegweiser durch Eclipse

Tabelle 2.4: Variables View-Funktionen (Forts.)

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.

2.7.7 Breakpoints, Watchpoints und Exceptioncatching


Grundsätzlich gibt es mehrere Möglichkeiten, die virtuelle Maschine zur Laufzeit anzuhal-
ten. Bei den Breakpoints wird eine Position im Sourcecode angegeben. Unter Umständen
wird ein Breakpoint mit einer Bedingung verbunden. Wie das funktioniert, wurde bereits
betrachtet.
Watchpoints:
Ein Watchpoint ist eine Art Beobachter, allerdings wird nicht der Sourcecode, sondern es
werden die benutzten Variablen in Form von Objekten oder primitiven Typen beobachtet.
Dies kann zu einem häufigen Stoppen der virtuellen Maschine führen, wenn der als Watch-
point gewählte Typ in unterschiedlichen Kontexten sehr oft vorkommt.
Ein Watchpoint lässt sich über die Funktion TOGGLE WATCHPOINT in der Variables View, die
wir gerade angesehen haben, setzen. Wird ein Watchpoint aktiviert, ändert sich in der Va-
riables View zunächst gar nichts. In der Breakpoint View kommt allerdings ein zusätzlicher
Watchpoint-Eintrag (Brillensymbol mit Stift, siehe Abb. 2.36) hinzu.

Abb. 2.36: Breakpoint View, Statements, Watchpoints, Exceptions

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-

trag aktiviert werden, wenn sie benötigt werden.

Die möglichen Eigenschaften der jeweiligen Breakpoints lassen sich erwartungsgemäß


durch die rechte Maustaste auf dem jeweiligen Breakpoint erreichen. Typabhängig kann
hier z.B. für den Watchpoint eingetragen werden, ob er bei MODIFICATION oder bei ACCESS zu-
schlagen soll. Typunabhängig hingegen sind allgemeine Informationen wie ENABLE, also
Aktivieren des Breakpoints, DISABLE oder REMOVE und REMOVE ALL zum Löschen eines
oder aller Breakpoints. Der Unterschied zwischen SUSPEND VM und SUSPEND THREAD wurde
bei den normalen Breakpoints bereits dargestellt. Über diesen Menüpunkt ist wählbar, ob
nur der Thread, in dem der Breakpoint gefunden wurde, oder alle Threads der VM (also die
VM selbst) angehalten werden sollen.
In der Variables View können die Breakpoints durch Anklicken der jeweiligen Variable und
Auswahl des Menüpunkts INSTANCE BREAKPOINTS sogar auf einzelne Variablen beschränkt
werden.
Kommen wir zum dritten Typus von Breakpoints, zum Javastacktrace, den die meisten
Java-Anwendungen in einen Outputstream schreiben. Wenn es zu einem Fehler bzw. einer
Exception kommt, hilft es dem Programmierer zumeist schon, den Fehler auf eine Methode
einzukreisen.

Wird der Stacktrace im Fehlerfall auf die Konsole geschrieben (System.out/


.err) und diese nicht umgeleitet, so erscheinen die Ausgaben in Eclipse in
der Console View. Wenn man mit der Maustaste durch einen solchen
Stacktrace wandert, erkennt Eclipse die Methodennamen und führt den

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

2 – Wegweiser durch Eclipse

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.

Es ist selbstverständlich ungünstig, in der Vererbungshierarchie sehr weit


oben stehende Exception-Typen wie beispielsweise „caught“ Nullpoin-
terexceptions als Breakpoints zu aktivieren, denn dadurch taucht sehr
schnell die erste Exception in manchen Frameworks auf und wird abgefan-

gen, ohne sichtbar zu werden. Daher sollten sehr abstrakte Exceptions


(z.B. aus dem java.lang-Package) soweit möglich erst aktiviert werden,
wenn man schon weiß, dass diese gleich auftreten werden.

Class Load Breakpoint

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

Klasse zum ersten Mal durch einen Classloader geladen wird.

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

Da es in umfangreichen Applikationen zu komplexen und großen Break-


point-Listen kommen kann, die abhängig vom jeweiligen Testfall oder der
Komponente nur aktiv werden sollen, können in Eclipse WORKING SETS
angelegt oder Breakpoints anderweitig sortiert/organisiert werden. Hilf-

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).

Abb. 2.37: Display View mit Code Completion

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

2 – Wegweiser durch Eclipse

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.

Watch und Inspect


Watchpoints und Watchexpressions wurden bereits im vorangehenden Kapitelabschnitt
kurz erläutert. Die Expression, die beobachtet werden soll, kann auch in der Display View
eingegeben (z.B. analyzer==null) und dann über die rechte Maustaste zur Watch Ex-
pression gemacht werden.
Gleichzeitig kann durch Eingabe des Variablennamens und Markierung des Namens mit
anschließender Auswahl von INSPECT über die rechte Maustaste der Inhalt der Variablen an-
gezeigt werden. Wenn wir also analyzer.toString() markieren und mit INSPECT anse-
hen wollen, wird die Methode auf der Analyzer-Instanz aufgerufen und das Rückgabeob-
jekt (in diesem Fall String) mit seinen Unterelementen (Inhalte, Größe, Characterarray, ...)
in der Expression View angezeigt.

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.

Alle hier vorgestellten Aktionen (Inspect, Display, Execute und Watch)


können auch über das Kontextmenü der jeweiligen Objekte im Editor auf-
gerufen werden. So kann jedes Objekt untersucht und wiedergefunden
werden, ohne die Views manuell zu durchsuchen.

2.7.8 Hot Code Replacement


Wir kommen jetzt zu Funktionen in der Debug View, deren korrekte und erfolgreiche Ar-
beit sehr stark von der Unterstützung und damit zumeist der Version der darunter liegenden
und im Debug-Modus verwendeten VM abhängt. Welche VM diesbezüglich sich als taug-
lich erweist, muss man austesten oder beim entsprechenden Hersteller erfragen.
Eclipse erlaubt in begrenztem Maße, zur Laufzeit den Sourcecode einer Methode zu än-
dern. Dies hat den Vorteil, dass, wenn der Fehler gefunden worden ist, kein komplettes
Build durchgeführt und bis zum Fehler vordebuggt werden muss.
Diese Fähigkeit wird als Hot Code Replacement oder oft auch im Zusammenhang als Hot-
swap Feature bezeichnet. Ob einem die VM einen solchen Eingriff erlaubt, hängt von der
Implementierung der JVMTI für die jeweilige virtuelle Maschine ab (siehe Abschnitt
2.7.5).
Diese Fähigkeit soll kurz am Beispiel der NullPointerException aus dem Beispiel-
projekt betrachtet werden. Sollte dieser Fehler nicht behoben sein, muss an die Sourcecode-
Stelle debuggt werden, an der ein return null die Methode verlässt. Dieses wird ersetzt
durch return results und danach mittels Ÿ+S gespeichert. Anschließend sollte
eine VM, die Hotswap unterstützt, den geänderten Sourcecode akzeptieren und der Debug-
ger wieder an den Beginn der Methode zurückspringen.
Sollte das Hotswap fehlschlagen, gibt es eine ganze Reihe von möglichen Gründen. Einige
davon sind:
1. Hinzufügen, Entfernen oder Umbenennen von Methoden, Klassen oder Instanzvariab-
len, die vom Classloader während des Debug-Vorgangs schon in die VM geladen wor-
den sind.
2. Sourcecode-Änderungen, die zu Compile- und somit Syntaxfehlern führen.
3. Modifikationen in anderen Methoden des Stacks oder Sourcen, die nicht der aktuellen
Methode entsprechen.
4. Einsatz einer virtuellen Maschine, die das entsprechende Hotswap-Feature nicht unter-
stützt.

80
eclipse_v01.book Seite 81 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

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.

2.8 Navigation im Sourcecode


Java ist eine Sprache, die vor allem durch die einfache und sichere Abbildung objektorien-
tierter Lösungen in Klassen und Interfaces populär wurde. Ein komplexes Beziehungs-
geflecht zwischen diesen beiden kann bei einer großen Anzahl eben solcher Elemente al-
lerdings auch schnell zur Verwirrung des Entwicklers führen.
Die Geschwindigkeit und Qualität, in der der Entwickler arbeitet, hängt dabei vorzugweise
von der Dokumentation des bestehenden Sourcecodes (vor allem Javadoc), aber auch von
der Fähigkeit ab, sich schnell in Vererbungshierarchien einarbeiten zu können, zu wissen,
welche Methoden z.B. überschrieben wurden und welche Interfaces zu implementieren
sind.
Selbstverständlich stellt Eclipse hierfür diverse Views und Funktionen bereit, teilweise stel-
len sie nur unterschiedliche Blickrichtungen auf ein und dieselbe semantische Tatsache dar,
weshalb wir ihre Aufzählung auf die wesentlichen von ihnen beschränken.

2.8.1 Javadoc View


Zu einer Klasse, dem Objekt einer Klasse oder einer Methode erscheint der zugehörige
Javadoc-Kommentar, wenn im Editor mit der Maus darübergefahren wird. Drücken der
Ê-Taste ermöglicht es, in diesem Fenster durch den vollständigen Kommentar zu scrol-
len.
Eclipse verfügt zusätzlich über eine eigene View für den Javadoc-Kommentar, die wie alle
anderen Views auch über das Menü WINDOW | SHOW VIEW | OTHER | JAVA | JAVA DOC aktiviert
werden kann. Jedes Mal, wenn im Sourcecode der Cursor neu gesetzt wird, wird der jeweils
im Kontext zugehörige Javadoc-Kommentar angezeigt. Über die rechte Maustaste in der
View kann man sich zur entsprechenden Implementierung führen lassen.

Über WINDOW | PREFERENCES kann man sich im Unterpunkt JAVA | COMPILER |


JAVADOC das falsche Ausfüllen des Javadoc zur Anzeige von Fehlern in der
Problems View anzeigen lassen. Entsprechende QuickFixes zur Korrektur
existieren ebenso.

81
eclipse_v01.book Seite 82 Montag, 30. Januar 2006 12:02 12

Navigation im Sourcecode

2.8.2 Navigation über die Toolbar


Man kann sehr schnell bei der Navigation durch den Sourcecode die Stelle aus den Augen
verlieren, an der man vor wenigen Momenten noch gewesen ist. Hilfreich ist hier die Tool-
bar, über die die entsprechende Positionierung wiedergefunden werden kann.

Abb. 2.38: Toolbar-Navigationsfunktionen

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.

2.8.3 Suchfunktionen in Eclipse


Die umfassendste Suche kann sicherlich mit dem SEARCH-Dialog durchgeführt werden, der
über die Taschenlampe in der Toolbar oder über den Menüpunkt SEARCH | SEARCH erreichbar
ist (siehe Abb. 2.39).
Die unterschiedlichen Register (FILE SEARCH, JAVA SEARCH, PLUG-IN SEARCH, NLS KEYS) ge-
ben die verschiedenen Kategorien bekannt, anhand derer gesucht werden kann. Über den
CUSTOMIZE-Button ist auswählbar, wie viele und welche Register angeboten werden.
Da die Plug-Ins in diesem Kapitel nicht betrachtet werden, werfen wir zunächst einen Blick
auf die FILE SEARCH.

82
eclipse_v01.book Seite 83 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Abb. 2.39: Standard-Suchdialog

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

2 – Wegweiser durch Eclipse

Open Type (Menü, Ÿ+Á+T)


Dieser Befehl ermöglicht es, nach einem Typ (Klasse oder Interface) in der Workbench zu
suchen. Dabei bezieht sich die Suche auf die Menge aller identifizierten Typen in allen Pro-
jekten.
In einem Dialog wird der Name des Typs bzw. ein Suchmuster genannt, nach dem der
Name gefunden werden soll. In der darunter erscheinenden Liste von MATCHING TYPES kann
dann der zutreffende zur Anzeige ausgewählt werden.
Um die Suche nach immer wiederkehrenden Suchergebnissen zu erleichtern, wird in
Eclipse auch eine Liste von Vorschlägen automatisch angezeigt, die bereits einmal gefun-
dene Klassen anzeigt.

Open Declaration (Menü, rechte Maustaste, Ë)


Über diese Funktion kann man einen Typ, eine Methode oder ein Feld finden und dessen
Definition im Editor öffnen. Wenn es mehrere Ergebnisse zur Suchanfrage geben sollte,
werden diese in einem Auswahldialog zur Verfügung gestellt.

Open Type Hierarchy (Menü, rechte Maustaste, Ì)


Öffnet die Vererbungshierarchieansicht in einer entsprechenden View, abhängig davon,
welches Element selektiert worden ist. Handelt es sich beim selektierten Element um kei-
nen Typ, so wird die Typhierarchie des umgebenden Sourcecode-Elements (Klasse bzw. In-
terface) dargestellt. Für weitere Informationen zur Hierarchieanzeige siehe Hierarchy
View-Abschnitt 2.9.1.

Open Call Hierarchy (Menü, rechte Maustaste, Ç+Ÿ+H)


Zeigt die Calls to method View an, in der die Aufrufhierarchie nachvollzogen werden kann.
Entweder navigiert man zu den aufrufenden Methoden (Caller) oder zu den durch diese
Methode aufgerufenen (Callee). Einen Kurzüberblick zur Calls to method View folgt in
Abschnitt 2.9.2.

Open Super Implementation (Menü, rechte Maustaste)


Zeigt die „Super“-Implementierung einer Methode. Wenn der Cursor in eine Methode posi-
tioniert wird, die überschrieben worden ist, und dann die Aktion OPEN SUPER IMPLEMENTA-
TION ausgeführt wird, führt diese in die noch nicht überschriebene Originalimplementie-
rung.

Open External Javadoc (Menü, Á+Ê)


Vorausgesetzt, Javadoc befindet sich an einer anderen Stelle als nur im Sourcecode selbst,
kann man sich mit OPEN EXTERNAL JAVADOC die Javadoc-Kommentare im Browser anzeigen
lassen. Sinnvoll ist diese Funktion eigentlich nur für Classfiles, bei denen man keine
Sourcen besitzt und daher aus diesen keinerlei Informationen über Typen und Methoden
erlangen kann.

85
eclipse_v01.book Seite 86 Montag, 30. Januar 2006 12:02 12

Navigation im Sourcecode

Abhängigkeiten in Java finden


Bisher haben wir uns angesehen, wie man konkrete Klassen, deren Superklassen oder auch
Kommentare findet. Zwei Dinge klangen parallel schon an: das Suchen nach Referenzen
und das nach Implementierungen. In der Hierarchy View (siehe Abschnitt 2.9.1) kann an-
hand einer Baumdarstellung schnell nachvollzogen werden, wer dort welche Methode auf-
ruft.

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

um Informationhiding zu kümmern, sondern Originalreferenzen um bisher


sorgsam als private deklarierte Variablen nach außen zu geben, ist es in
einem Review (wenn man meint, eine Komponente funktioniert) sinnvoll,
zu schauen, wer die Methoden aufruft. Es muss nicht alles private
deklariert werden, aber vielleicht ist der Gültigkeitsbereich protected
oder über ein Package auch schon ausreichend. Dabei kann die Suche
nach Referenzen an dieser Stelle helfen. Das rettet allerdings nicht vor
den „Feinden des sauberen Programmierens“, z.B. der Java Reflection.

Alle Suchfunktionen bezüglich Abhängigkeiten finden sich im SEARCH-Menü oder können


über die rechte Maustaste (im Editor oder auch in einer entsprechenden View wie dem
Package Explorer) auf dem entsprechenden Objekt aufgerufen werden.
Bei jeder Suchanfrage (Referenzen, Deklarationen, Implementierungen, Schreib/Lese-Zu-
griff) ist jeweils wählbar, ob im kompletten Workspace (alle Projekte, die zurzeit in Eclipse
sind, mit deren Sourcen), im aktuellen Projekt, in der aktuellen Hierarchie (Vererbungs-/
Implementierungsbaum) oder in einem Working-Set gearbeitet werden soll. Das Prinzip
des Working-Set haben wir bereits in den allgemeinen Suchfunktionen kennen gelernt.
Hierbei legt man unter einem logischen Namen einen Bereich fest, in dem gesucht werden
soll.
Nicht jede Aktion ist auf jedem Objekt (Klasse, Interface, Member-Variable, ...) ausführbar.
Wir dürfen nicht vergessen, dass wir z.B. beim Suchen von Referenzen im Java-Sourcecode
die Dateien ausschließen (die vielleicht Java-Code enthalten), die wir für den Build-Prozess
nicht als Sourcen mit ins Projekt einbezogen haben. Im Gegensatz zur Volltextsuche kann
Eclipse Referenzen in diesen Dateien nicht erkennen (z.B. wenn aus Performance-Gründen
Teile des Sourcecodes nicht kompiliert werden sollen).
Die Menge der Suchergebnisse (hier z.B. die Suche nach Referenzen auf die getAll-
OccurrencesOfPattern-Methode) wird wie immer in der Search View angezeigt (siehe
Abb. 2.40). Die Resultate lassen sich nach unterschiedlichen Kriterien, z.B. Projekte oder
Packages, gruppieren, um bei großen Ergebnismengen den Überblick nicht zu verlieren.
Über die rechte Maustaste besteht in der Search View auch die Möglichkeit, die Suche zu
modifizieren, erneut durchzuführen oder Referenzen und Deklarationen der Suchergebnis-
se sofort wieder aufzuspüren (um nur einige Funktionen zu benennen).

86
eclipse_v01.book Seite 87 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Abb. 2.40: Suchergebnisse in der Search View

2.9 Weitere Views

2.9.1 Hierarchy View


Die Hierarchy View (Ì-Taste auf dem entsprechenden Java-Element oder WINDOW |
SHOW VIEW | HIERARCHY) zeigt, wie bereits im Open Type Hierarchy-Abschnitt 2.8.4 be-
schrieben, die Vererbungs- und Implementierungshierarchie vom jeweils ausgewählten
Java-Typ aus betrachtet (siehe Abb. 2.41). Im oberen Teil wird ein Hierarchiebaum an-
gezeigt. Abhängig davon, welche Toolbar-Einstellung aktiv ist, zeigt dieser entweder die
Hierarchie vom aktuellen Element aufwärts (von welcher Klasse erbt meine Klasse, wel-
che Interfaces werden von meiner Klasse implementiert?) oder abwärts (wer erweitert oder
implementiert den aktuellen Typ?) oder eingeschränkt sogar beides (ganz linker Toolbar-
Menüeintrag).

Abb. 2.41: Hierarchy View

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

2.9.2 Call Hierarchy View


Die Call Hierarchy View (WINDOW | SHOW VIEW | OTHER | CALL HIERARCHY) zeigt (aufgerufen
durch die entsprechende Menüfunktion) die Aufrufhierarchien der aktuellen Methoden
(wer ruft sie auf? welche anderen Methoden werden von ihr aufgerufen?). Über die Toolbar
der Views kann eingestellt werden, in welche Richtung navigiert werden soll, wie das Aus-
sehen der View modifiziert und die Ergebnismenge gefiltert werden.

2.9.3 Declaration View


Die Declaration View zeigt (ähnlich der Javadoc View) beim Klicken auf ein entsprechen-
des Element dessen Deklaration im Sourcecode an. Die View kann, wie alle anderen Views
auch, über das Menü WINDOW | SHOW VIEW geöffnet werden. Wird die View nicht sofort in
der Liste angezeigt, kann sie im Menüpunkt OTHER ausgewählt werden.

2.9.4 Navigator View


Der Vollständigkeit halber sei hier auch kurz auf die Navigator View eingegangen. Letzt-
endlich werden alle Aktionen, egal ob Java-Elemente editieren oder XML-Strukturen er-
zeugen, immer auf Dateien ausgeführt. Will man eine Windows-Explorer-ähnliche Sicht
haben (die Unix- und Linux-Gemeinde mit ihrer Menge an Shells, Konsolen und Window
Managern mögen einen dortigen passenden Vergleich entschuldigen), tut dies die Navi-
gator View. Der große Vorteil liegt hier darin, dass es Eclipse nicht kümmert, was es für
Dateien sind und ob durch Aktionen inkonsistente Zustände erzeugt werden.
Es gibt sicherlich Ausnahmefälle, in denen die Navigator View sinnvolle Dienste leisten
kann (z.B. beim Kopieren von Packages), auf der anderen Seite handelt man sich damit
leicht Probleme an anderer Stelle ein (z.B. fehlerhafte Package-Bezeichnungen).
Die Navigator View kann über WINDOW | SHOW VIEW geöffnet werden.

2.9.5 Progress View


Eine Reihe von Threads laufen in Eclipse hin und wieder im Hintergrund (job infrastruc-
ture). Darunter fallen im Wesentlichen Läufe, die den Workspace bereinigen oder Compiles
nebenbei durchführen. Wenn man wissen möchten, welche Aktivitäten dort laufen, hilft die
Progress View weiter (siehe Abb. 2.42), die sich durch Klick auf das kleine Laufbandsym-
bol in der rechte unteren Ecke des Eclipse-Fensters öffnen lässt. Laufende Aktionen werden
auch mit dem kleinen eingeblendeten Balken in der rechten unteren Ecke angezeigt.
Einzelne Aktionen lassen sich mit dem roten Stop-Button abbrechen und über Links unter
den einzelnen Tasks können weitere Detailinformationen über Ergebnisse der Aktionen ab-
gefragt werden.

88
eclipse_v01.book Seite 89 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Abb. 2.42: Progress View und Progressbar

2.10 Java 5 – Features


Eine der wesentlichen Erweiterungen von Eclipse 3.1 gegenüber der Vorgängerversion 3.0
war zweifelsohne die Unterstützung der Java-5-Sprachspezifikation (Codename „Tiger“).
Dies wird in der kommenden Version Eclipse 3.2 mit Java 6 vermutlich fortgesetzt werden.
Nichtsdestotrotz ist die Kodierung auch weiterhin in Java 1.4 und darunter möglich, sogar
der Compile von 5.0 Classfiles ist möglich, allerdings sind diese mit 1.4 nicht startbar. Die
zahlreichen Wizards und Eclipse-Erweiterungen, die mit Version 3.1 Einzug hielten, wei-
sen allerdings Java 5 schon als Basisplattform für die Entwicklung aus. Einige dieser oft-
mals sanft eingeführten Neuerungen haben wir beim Streifzug durch unser Anwendungs-
beispiel mit Regular Expressions bereits erstmalig kennen gelernt.
Da an dieser Stelle genügend Grundlagen geschaffen sein sollten, um mit Eclipse zu arbei-
ten, werfen wir nun für jene, die Eclipse vorwiegend oder ausschließlich für Java-5-Zwecke
benutzen wollen, einen verschärften Blick auf genau diese Funktionalitäten.

2.10.1 Java 5 on board


Wie bereits besprochen, lassen sich die Java-5-Features vor allem dann gut benutzen, wenn
man eine Java-5-VM installiert hat. In unseren Beispielen in diesem Kapitel ist dies stets
die Java 5.0_05-Version von Sun gewesen.
Danach gilt es, projekt- oder workspace-weit auch die Unterstützung für Java 5 zu aktivie-
ren. Dies geschieht wie bereits angesprochen entweder über die Projekteigenschaften oder
die Workbench-Preferences (WINDOW | PREFERENCES | JAVA | COMPILER | COMPLIANCE LEVEL
5.0). Die dazugehörigen speziellen Java 5 Compile-Optionen sehen wir in Abb. 2.43.
Natürlich ist die Verwendung der Sprachelemente wie Generics oder Enumerations ein op-
tionales Angebot an die Entwickler, um ihren Sourcecode lesbarer und gegebenenfalls auch
typsicherer zu gestalten. Insofern muss man selbst entscheiden, ob ungetypte Listen nun
einen Verstoß darstellen und ob das automatische Boxing und Unboxing primitiver Typen
ein Sicherheitsrisiko darstellt. So sind denn auch die Compile-Optionen, die in Abb. 2.43 zu
sehen sind, ganz individuell nach dem eigenen Geschmack zu konfigurieren.

89
eclipse_v01.book Seite 90 Montag, 30. Januar 2006 12:02 12

Java 5 – Features

Abb. 2.43: J2SE 5.0 Compile-Optionen

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

2 – Wegweiser durch Eclipse

Abb. 2.44: Sourcecode Formatter-Einstellungen

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.

Abb. 2.45: Erweiterte Java 5 Wizards

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;

public class JavaExamples {

public static void main(String[] args) {


List customers = new ArrayList();
// Aufbau einer Kundenliste
Customer newCustomer = null;
for (int i=0;i<args.length;i++) {
String s = args[i];
newCustomer = new Customer();
newCustomer.age = new Integer(32);
newCustomer.name = s;
newCustomer.type = Customer.TYPE_UNKNOWN;
customers.add(newCustomer);
}

// Extraktion eines Kunden nach dem Zufallsprinzip


int randomPosition =
(int) Math.random() * customers.size();
String oneCustomer =
(String) customers.get(randomPosition);
System.out.println(oneCustomer.equals(newCustomer));
System.exit(0);
}
}

1. Das Beispiel ist bewusst hier platziert.

92
eclipse_v01.book Seite 93 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

Anschließend die zugehörige Customer-Klasse:

package com.entwickler.eclipsebuch.kapitel2.examples;

public class Customer {

public static final int TYPE_UNKNOWN = -1;


public static final int TYPE_NORMAL = 0;
public static final int TYPE_GOOD = 1;
public static final int TYPE_VIP = 2;
public String id = null;
public String name = "";
public Integer age = null; //0;
public int type = 0;
public Customer() {
}
}

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.

2.10.2 Migration Java 1.4 nach 5.0


Beginnen wir nun mit der Migration des 1.4er Source nach 5.0. Sollten Sie bislang die JDK-
5.0-Unterstützung für obigen Source nicht aktiviert haben, holen Sie dies bitte wie oben be-
schrieben nach.

Abb. 2.46: Warnhinweis wegen Verwendung eines Raw Type

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.

Abb. 2.47: Infer Generic Type Arguments-Preview-Dialog

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)

Abb. 2.48: Type-Konvertierungsfehler

Wir ändern die Zeile entsprechend und ersparen uns ab jetzt das Casting, womit der Com-
pile-Fehler behoben wäre.

Customer oneCustomer = customers.get(randomPosition);

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

2 – Wegweiser durch Eclipse

Der daraus folgende Sourcecode sieht wie folgt aus:

package com.entwickler.eclipsebuch.kapitel2.examples;

import java.util.ArrayList;
import java.util.List;
// statt Math.random()
import static java.lang.Math.random;

public class JavaExamples {

// statt String[] args:


public static void main(String... args) {
List<Customer> customers = new ArrayList<Customer>();
Customer newCustomer = null;
for (int i=0;i<args.length;i++) {
String s = args[i];
newCustomer = new Customer();
// statt new Integer(32)
newCustomer.age = 32;
newCustomer.name = s;
newCustomer.type = Customer.TYPE_UNKNOWN;
customers.add(newCustomer);
}
int randomPosition = (int) random() * customers.size();
Customer oneCustomer = customers.get(randomPosition);
System.out.println(oneCustomer.equals(newCustomer));
System.exit(0);
}
}

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:

for (String s : args) {


newCustomer = new Customer();
newCustomer.age = 32;
newCustomer.name = s;
newCustomer.type = Customer.TYPE_UNKNOWN;
[...]

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:

public CustomerState type = CustomerState.TYPE_UNKNOWN;

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;

public enum CustomerState {


TYPE_UNKNOWN, TYPE_NORMAL, TYPE_GOOD, TYPE_VIP;
}

In der JavaExamples-Klasse erscheint nun erwartungsgemäß ein Compile-Fehler, dass die


Integer-Zuordnung fehlerhaft ist (siehe Abb. 2.49). Wir wählen dabei die Klassenergän-
zung mittels Ÿ-Leertaste zu CustomerState.

Abb. 2.49: Fehlerhafte Enumerationszuordnung

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;

public class Customer {

@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

2 – Wegweiser durch Eclipse

@Persistent(tableName="customer", columnName="age")
public Integer age = 0;

public CustomerState type = CustomerState.TYPE_UNKNOWN;


}

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.

Abb. 2.50: Erzeugte Annotation

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;

public @interface Persistent {


String tableName();
String columnName();
}

Selbstverständlich bietet Eclipse in den unterschiedlichen Views entsprechende Icons und


Symbole an, um die neuen Sprachelemente Enumerations und Annotations auch zu erken-
nen (siehe Abb. 2.51). Eine ebenso gute Unterstützung kann man auch in den Suchfunk-
tionen und im Debugger erwarten.
An dieser Stelle wollen wir den kleinen Ausflug in Richtung Java 5 vorerst auch wieder be-
enden.

97
eclipse_v01.book Seite 98 Montag, 30. Januar 2006 12:02 12

Customizing Eclipse

Abb. 2.51: Darstellung der Java-5-Sprachelemente im Package Explorer

2.11 Customizing Eclipse


Kommen wir nun zur individuellen Anpassung von Eclipse an die eigenen Bedürfnisse.
Zur Konfiguration von Eclipse existieren viele Einstellungsmöglichkeiten, so dass ein
Blick in die Eclipse-Hilfe (Abschnitt 2.2) immer lohnt. Für die einfache Nutzung von
Eclipse ist es nicht notwendig, alle Einstellungen zu kennen. Für die Festlegung gemein-
samer Standards in Oberflächen und Workflows oder auch für spezielle Problemstellungen
und den Einsatz von weiteren Plug-Ins machen sie aber durchaus Sinn.

2.11.1 Customizing perspective


Über das Menü WINDOW ist der Unterpunkt CUSTOMIZE PERSPECTIVE erreichbar. In diesem
Dialog kann eingestellt werden, welche Icons, welche Menüpunkte und welche Plug-In-
Komponenten an welchen Stellen ein- oder besser ausgeblendet werden sollten.
Im Register SHORTCUTS wird für unterschiedliche Menüs definiert, welche Shortcuts benö-
tigt werden. Im COMMANDS-Register daneben finden sich Befehlsgruppen, wie beispiels-
weise Such- oder Debug-Funktionen, die zu Einheiten verschmolzen aktiviert oder deakti-
viert werden können. Hierbei ist zu beachten, dass die Einstellungen sich auf die aktuelle
Perspektive (im Beispiel die Java-Perspektive) auswirken und nicht auf alle Perspektiven.
Wenn eine Perspektive auf diese Art und Weise individualisiert worden ist, kann sie mit ei-
nem logischen Namen versehen und über SAVE PERSPECTIVE AS im WINDOW-Menü gespei-
chert werden.
Über das WINDOW-Menü lassen sich die Einstellungen auch zurücknehmen. Ebenso können
wir hier die geöffneten Editorfenster steuern, geöffnete Perspektiven schließen und zusätz-
liche Views und Perspektiven öffnen, was wir in den vergangenen Abschnitten bereits
mehrmals praktiziert haben.

98
eclipse_v01.book Seite 99 Montag, 30. Januar 2006 12:02 12

2 – Wegweiser durch Eclipse

2.11.2 Eclipse individuell starten


Auch wenn es für die meisten Anwendungen nicht von so großer Bedeutung ist, kann es in
speziellen Fällen durchaus wichtig sein, das Starten von Eclipse selbst zu konfigurieren.
Die meisten Hürden werden einem von den Default-Einstellungen abgenommen. Die nun
folgenden Hinweise beziehen sich auf die Windows-Variante von Eclipse. Linux- und
MacOS-Varianten haben grundsätzlich gleiche Möglichkeiten, unterscheiden sich dann
aber je nach Plattform durch unterschiedliche Startup-Shells.
Gründe für eine spezielle Konfiguration könnten u.a. sein:
1. Eine alte Eclipse-Version wird auf eine neuere upgegradet und der Workspace der alten
Version soll unverändert in der neuen Version weiterverwendet werden.
2. Bei der Arbeit mit Eclipse tauchen OutOfMemory-Fehler auf und es soll daher sicher-
gestellt werden, dass Eclipse bei der Arbeit genügend Arbeitsspeicher zur Verfügung
hat.
3. Man möchte individuell entscheiden, mit welcher Java-Version aus welchem Verzeich-
nis Eclipse als Java-Anwendung selbst läuft.
Eclipse können über Startparameter (in Windows zumeist mit Desktop-Verknüpfungen und
deren Parametern realisiert) weitere Argumente mitgegeben werden. Die allgemeine Rei-
henfolge lautet dabei:
eclipse [platform options] [-vmargs [Java VM arguments]]
Zu beachten ist, dass Eclipse selbst zum Großteil eine Java-Anwendung ist, die lediglich
einzelne plattformspezifische Anteile (im Wesentlichen die Präsentationsoberfläche) be-
sitzt. Wenn der darunter liegenden Java-VM-Instanz beim Starten bestimmte Parameter
mitgegeben werden sollen (wie beispielsweise die Größe des nutzbaren RAM-Speichers),
so erfolgt dies über den zweiten genannten Parameter, die vmargs.
eclipse -vmargs -Xmx512M
Die Plattformoptionen, die beim Start von Eclipse mitgegeben werden können, sehen wir
uns jetzt in der Übersicht an.
-arch architecture
Definiert die Prozessorarchitektur, in deren Umgebung Eclipse läuft. Die hier eingestellten
Informationen werden den Plug-Ins für optimale Arbeit zur Verfügung gestellt. Mögliche
Werte: x86, sparc, PA-RISC, ppc.
-application applicationId
Definiert den Einstiegspunkt in Eclipse, mit dem Eclipse hochfährt (normalerweise: org.ec-
lipse.core.runtime.applications).
-configuration configurationFileURL
Lokation des Eclipse-Konfigurationsfiles in Form einer URL. Das Konfigurationsfile wird
erstellt, wenn Eclipse installiert oder aktualisiert wird.
-consolelog
Spiegelung des Eclipse-Error-Logs auf die Console, in der Eclipse gestartet wurde. Dies ist
hilfreich in Kombination mit dem Debug-Parameter.

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

2 – Wegweiser durch Eclipse

2.12 Eclipse Preferences


Über das Menü WINDOW | PREFERENCES lassen sich individuelle Anpassungen bezüglich
Oberflächenaussehen und Sourcecodehandling einstellen, wobei diese Einstellungen stets
für die komplette Oberfläche gelten und sich zum Teil projektweise noch einmal konfigu-
rieren lassen. Wie das geht, haben wir bereits im Beispielprojekt gesehen.
Jede einzelne der Funktionen zu beschreiben, würde dieses Kapitel sprengen. Dennoch
lohnt es sich, einen Blick auf die Möglichkeiten des Customizen zu werfen, besonders
wenn Sie im Team eine gemeinsame Entwicklungsumgebung und Richtlinien aufstellen.
Trotzdem ist dies nur eine Schnelleinführung, die nicht den Anspruch eines Referenzwerks
erhebt. Im linken Baum lassen sich thematisch geordnet einzelne Konfigurationen verän-
dern, was besonders für individuelle Einstellungen von Plug-Ins oft sehr hilfreich ist (siehe
Abb. 2.52). Die seit Eclipse 3.1 existierende Suchfunktion in der Combobox vereinfacht
sehr das Auffinden von einzelnen Einstellungen im kompletten Preferences-Baum.

Abb. 2.52: Eclipse-Preferences-Dialog

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

empfiehlt es sich, eine Konfiguration als Standardeinstellung zu definieren


und über die Import- bzw. Export-Funktionen im Menü FILE | IMPORT/EXPORT
| PREFERENCES zu exportieren bzw. so zu hinterlegen (z.B. in einem SCM-
System), dass alle Entwickler die gleiche Umgebung vorfinden, auch wenn
einer von ihnen mal am Rechner des anderen arbeiten muss.

General-Properties
Unter dem Oberpunkt GENERAL verbergen sich alle für die Eclipse-Oberfläche relevanten
Einstellungen.

Tabelle 2.5: General-Properties

Property Eigenschaften/Funktionen

Appearance Wechsel zwischen unterschiedlichen Presentations und Themes, z.B.


zur Aktivierung des alten 2.1er Eclipse Look and Feel.
Daneben finden sich hier die Einstellungen für Farben und Schriften
unterschiedlicher Eclipse-Elemente (Colors/Fonts).
Einzelne Plug-Ins verwenden zuweilen eigene Icons für Dateien, um
deren Zustand abzubilden. In den LABEL DECORATORS können diese
Icons ein- bzw. ausgeschaltet werden.

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.

Compare/ Einstellungen der Compare-Funktionen, d.h. von Sourcecode-Teilver-


Patch gleichen mit älteren Versionen

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

2 – Wegweiser durch Eclipse

Tabelle 2.5: General-Properties (Forts.)

Property Eigenschaften/Funktionen

File Hier werden Dateiendungen und zugehörige externe Editierungssoft-


Associations ware miteinander verknüpft (z.B. Adobe Acrobat Reader und PDF).

Keys Zur Wahl persönlicher Tastenkombinationen dient dieser Unterpunkt.


Fast jede aufrufbare Aktion kann mit einem entsprechenden Shortcut
hinterlegt werden, der sie ausführt. Eine Emacs-Vorbelegung wird mit-
geliefert. Sehr komplexe Tastenkombination sind hier hinterlegbar. Die
Zuordnung lässt sich als CSV-File exportieren.

Perspectives Wahl der Einstiegsperspektive (z.B. Java- oder Debug-Ansicht beim


Starten) und Konfiguration, wie zwischen den einzelnen Perspektiven
und Views umgeschaltet werden soll.

Search Einstellungen für die Suchfunktionen in Eclipse.

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.

Webbrowser Einstellungen zum zu verwendenden Webbrowser.

Workspace Build Order: Definition der Reihenfolge der in einem automatischen


Build durchlaufenen Projekte.
Linked Resources: Definition von Variablen, die Pfade zu verbundenen
Ressourcen definieren und z.B. in Launch configs verwendet werden
können.
Local History: Eine nützliche Funktion für jene, die kein Sourcecode-
Management zur Verfügung haben, um Versionen von Dateien verwal-
ten zu können, ist die LOCAL HISTORY. Hier wird definiert, wie viele und
wie lange sich Eclipse Änderungen an Dateien merken soll.
Wenn ein SCM-System unabhängig von Eclipse im Einsatz ist, kann
vermutlich gut auf eine solche Funktion verzichtet werden. Ist man
dagegen mit dem Laptop unterwegs, empfiehlt es sich, den Zwischen-
speicher für die Änderungshistorie etwas höher anzusetzen. Das ver-
sehentliche Löschen kompletter Dateien beispielsweise kann damit
allerdings nicht rückgängig gemacht 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.

Tabelle 2.6: Ant-Build-Preferences

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

2 – Wegweiser durch Eclipse

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.

Tabelle 2.7: Java-Preferences

Property Eigenschaften/Funktionen

Appearance Wie sollen Java-Elemente (Klassen, Methoden, Variablen) angezeigt


werden, wie sehen deren Signatur und die Abhängigkeiten zwischen
ihnen und die Formatierung der Reihenfolge der Elemente im Source-
code aus?
Das Aktivieren der Checkbox SHOW METHOD RETURN TYPES ist oft von Vor-
teil. Damit wird bestimmt, dass innerhalb der Signaturanzeige in einem
Baum auch der Rückgabetyp angezeigt wird.
Unter MEMBER SORT ORDER, einem der Unterpunkte, stellen wir ein, wie
die einzelnen Java-Elemente in ihrem Sourcecode beim Formatieren mit
Eclipse erscheinen sollen. Oft erscheint es sinnvoll, in fremdem Source-
code zu wissen, ob die Instanzvariablen beispielweise ganz oben im
Code kommen oder ganz unten.

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

Tabelle 2.7: Java-Preferences (Forts.)

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

2 – Wegweiser durch Eclipse

Tabelle 2.7: Java-Preferences (Forts.)

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).

Installed Mit der Fähigkeit, mehrere unterschiedliche virtuelle Maschinen in unter-


JREs schiedlichen Versionen vielleicht sogar von verschiedenen Herstellern
bedienen zu können, hat man sich über Jahre hinweg in vielen Java-
IDEs ausgesprochen schwer getan. Eclipse ist diesbezüglich recht offen
und in den installed JREs können die Pfade zu eigenen JREs, deren
Libraries, Sourcecodes und API-Dokumentationen erfasst und verwaltet
werden.

JUnit In diesem Dialog wird JUnit konfiguriert. Stack Trace-Filter für JUnit-
Klassen sind hier standardmäßig aktiv.

Properties Einstellungen des Property File Editors.


File Editor

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

3 Eclipse als Modellierungswerkzeug

von Lars Wunderlich

3.1 Einleitung ins Thema


UML-Modellierung sowie die Stichwörter Design und Architektur gehören in Unterneh-
men oft zum Alltag. Im Folgenden wird zum Thema Modellierung das sowohl kommer-
zielle als auch frei zugängliche Produkt Omondo EclipseUML vorgestellt.
Im Anschluss daran schauen wir kurz auf die derzeit im Eclipse-Projektumfeld erhältlichen
Produkte EMF, GEF und UML2.
Leider ist es nicht möglich, den vollständigen Funktionsumfang von EclipseUML zu prä-
sentieren, u.a. auch deshalb, weil dies kein Buch über das jeweilige Tool ist, sondern über
Eclipse und weil es helfen soll, verschiedene Facetten der Plug-Ins kennen zu lernen. Wir
werfen daher einen kurzen Blick auf Omondo EclipseUML. Jeder Leser muss für sich
selbst entscheiden, ob er oder sie nun dieses oder eines der kommerziell verfügbaren Pro-
dukte verwenden möchte. Einige von ihnen finden Sie in Tabelle 3.1.

Tabelle 3.1: Eclipse UML Produkte

Produkt Adresse

Visual Paradigm for UML – http://www.visual-paradigm.com/product/vpuml/


Eclipse Integration integrations/eclipse.jsp

Argo2Ecore – Argo UML http://sourceforge.net/projects/argo2ecore


nach Ecore EMF Konverter

Objecteering UML/ http://www.objecteering.com/


Java Enterprise Edition packaging_enterprise_edition_java.php

objectiF Eclipse Edition http://www.microtool.de/objectif/en/


prod_eclipse.asp

UMLet Eclipse Plugin http://homepage.mac.com/martin.auer/umlet/

Poseidon for UML Prof. Edition http://gentleware.com/

MagicDraw UML http://www.magicdraw.com/

Together Developer/ http://www.borland.com/us/products/together/


Designer 2006 for Eclipse index.html#architect

109
eclipse_v01.book Seite 110 Montag, 30. Januar 2006 12:02 12

OMONDO EclipseUML

3.2 OMONDO EclipseUML


Leider bereitete die aktuelle, freie Beta-Version 2.1 einige Probleme bei der Installation.
Die anschließende Dokumentation stellt daher nun das kommerzielle Allround-Studio-
Paket der 2.1er Beta (samt GEF/EMF/UML2 und Datenbank-Plug-Ins rund 88 MB groß)
vor. Zusätzlich zum Download der Studio-Version benötigen Sie auch die Eclipse 3.1-Ver-
sion separat, die Sie bestenfalls vorinstallieren.
Die nachfolgende Dokumentation bezieht sich auf Omondo Eclipse Studio 2.1.0
(EclipseUML 2.1.0.20050927 Studio beta).

3.2.1 Versionen von EclipseUML


Omondo bietet zwei Produktversionen von EclipseUML an:
1 EclipseUML Free Edition bietet alles, um mit der Modellierung in Eclipse zu starten.
Die Version ist kostenlos und ein Tool, das die Integration in die GEF-, EMF- und
UML2-Frameworks nutzt.
2 Die als „EclipseUML Studio“ verfügbare Enterprise Edition erweitert den Funktions-
umfang der Free Edition um die Unterstützung für UML 2, J2EE und diverse Appli-
cation Server, Datenbankmodellierung für die gängigen Datenbankhersteller, Pattern-
unterstützung, Ausbau der bisherigen UML-Features sowie Metrikunterstützung (siehe
Abb. 3.1.).

Abb. 3.1: Architekturüberblick – OMONDO

110
eclipse_v01.book Seite 111 Montag, 30. Januar 2006 12:02 12

3 – Eclipse als Modellierungswerkzeug

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.

3.2.2 Download und Installation von Omondo EclipseUML


EclipseUML kann in der Free Edition2 kostenlos heruntergeladen werden, die Studio Edi-
tion ist ebenfalls auf der Omondo-Webseite als Trial (derzeit für 30 Tage) zu bekommen.
Weitere Dokumentationen zu EclipseUML sind unter www.tutorial-omondo.com verfüg-
bar.
Beide Versionen setzen auf dem EMF (Eclipse Modelling Framework3), dem GEF (Gra-
phical Editing Framework4) und dem auf dem EMF aufsetzenden UML2-Profil (UML2-
Eclipse-Projekt5) von Eclipse auf, die momentan nicht mit Eclipse standardmäßig ausgelie-
fert werden. Omondo bietet auf seiner Webseite eine Auto-Installer-Jar-File-Version an, in
der bereits das Plug-In selbst und beide Frameworks enthalten sind, so dass das Produkt
nach dem Download mit einem Doppelklick installiert werden kann. Nach der Installation
von Eclipse 3.1 und der Installation von EclipseUML kann das Produkt im Einsatz getestet
werden.

3.2.3 Klassendiagramme erstellen


Wir nehmen uns zur Visualisierung der Fähigkeiten von EclipseUML Studio eine recht ein-
fache Modellierung von ein paar Klassen vor. Dabei wird der Aufwand möglichst gering
gehalten.
Nach der Installation von EclipseUML fordert Eclipse gegebenenfalls den Entwickler auf,
sich selbst noch einmal neu starten zu dürfen, um das neue Plug-In zu integrieren. Danach
legen wir ein neues Java-Projekt mit dem Namen Abteilungsbaum über FILE | NEW |
PROJECT an und erzeugen über NEW | OTHER ein UML CLASS DIAGRAMS in diesem Projekt
(siehe Abb. 3.2).
Bereits hier sehen wir, dass EclipseUML die wesentlichen UML-Diagrammtypen unter-
stützt. Da viele Entwickler die meiste Arbeit mit Klassendiagrammen durchführen, wählen
wir UML CLASS DIAGRAMM aus und klicken auf NEXT. Auf der folgenden Maske geben wir
als Namen für das Diagramm overview.ucd an. Unter SELECT YOUR DIAGRAM PRESEN-
TATION MODE aktivieren wir die Checkboxen ASSOCIATION und DEPENDENCY und klicken auf
FINISH.

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

Abb. 3.2: UML-Projektauswahl in Eclipse

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.

Abb. 3.3: Create a package

112
eclipse_v01.book Seite 113 Montag, 30. Januar 2006 12:02 12

3 – Eclipse als Modellierungswerkzeug

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.).

Abb. 3.4: Klassendiagramm – Interface-Implementierung

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

Abb. 3.5: New Method

Über den Menüpunkt PREFERENCES am Ende des Menüs lassen sich weitere Eigenschaften
des Interface – darunter dessen Sichtbarkeit – steuern.

Abb. 3.6: AddElement-Dialog

114
eclipse_v01.book Seite 115 Montag, 30. Januar 2006 12:02 12

3 – Eclipse als Modellierungswerkzeug

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:

public void addElement(Unternehmensteil newElement)


throws java.lang.IllegalArgumentException;

Drei weitere Methoden werden auf die gleiche Art und Weise im Interface ergänzt:

// entfernt ein existierendes Element aus der Struktur


public void removeElement(Unternehmensteil oldElement);
// listet alle Elemente über einen Iterator auf
public java.util.Iterator getElements();
// zeigt den Namen des Elementes an
public String getName();

Da die Klassen Mitarbeiter und Abteilung das Interface implementieren, wechseln


wir in den Sourcecode der jeweiligen Klassen, klicken die kleine Fehlerlampe an und wäh-
len ADD UNIMPLEMENTED METHODS. Danach wird der jeweilige Sourcecode mit Ÿ+S ab-
gespeichert. Hierbei aktualisiert Eclipse stets die Ansicht.
Anschließend benutzen wir eine Assoziation bzw. Komposition, die zwischen der Klasse
Abteilung und dem Interface Unternehmensteil erzeugt wird. Hierzu klicken wir zu-
nächst das Assoziations-Icon, dann die Klasse Abteilung und anschließend das Interface
Unternehmensteil an. EclipseUML öffnet daraufhin ein Fenster, um diese Connection
zu beschreiben.
Ziel ist es, in der Klasse Abteilung einen Vektor von Unternehmensteilen, die die darin
enthaltenen Elemente beschreiben, zu modellieren. Die Assoziation hat zwei Enden, auf
der einen Seite das Interface Unternehmensteil (1st Association End), das die Abteilung
selbst nicht kennt, und auf der anderen Seite das Abteilungsende (2nd Association End),
das 1 bis n Unternehmensteile beinhalten kann (siehe Abb. 3.7).
Wir öffnen zunächst das Register 1ST ASSOCIATION END und deaktivieren die Checkbox
NAVIGABLE, um auszudrücken, dass vom Unternehmensteil nicht zur Abteilung navigiert
werden soll. EclipseUML beachtet dann dieses Assoziationsende nicht weiter. Das Child-
Element kennt bei dieser Konfiguration seinen Parent also nicht.

115
eclipse_v01.book Seite 116 Montag, 30. Januar 2006 12:02 12

OMONDO EclipseUML

Abb. 3.7: Assoziationsbeziehungen

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

3 – Eclipse als Modellierungswerkzeug

Abb. 3.8: 2nd Association End

Abb. 3.9: Fertiges Klassendiagramm

117
eclipse_v01.book Seite 118 Montag, 30. Januar 2006 12:02 12

EMF/GEF und UML2

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.

3.3 EMF/GEF und UML2


Hinter diesen drei Akronymen verstecken sich drei unter der Eclipse-Webseite erhältliche
Erweiterungsprojekte, die zu wesentlichen Bestandteilen der Eclipse-UML-Plattformen
geworden sind.

3.3.1 Eclipse Modeling Framework (EMF)


Das EMF ist das so genannte Modellierungs- und Codegenerierungs-Framework. Grundla-
ge für die Arbeit mit dem EMF ist ein Basismodell, das auf abstrakter Ebene Beziehungs-
geflechte vorwiegend in XMI beschreibt.
XMI ist die XML Metadata Interchange-Beschreibung, ein OMG-Standard1 für den Meta-
datenaustausch. Einer der Hauptanwendungszwecke von XMI ist die Unterstützung von
UML-Metamodellen (MOF: Meta Object Facility). Dies dient dem Austausch und der Se-
rialisierung von UML-Modellen und ihrem Austausch zwischen Applikationen.
EMF selbst entwickelte sich aus der Spezialisierung von MOF für größere und umfang-
reiche Entwicklungsprojekte, angepasst auf die speziellen Bedürfnisse der Programmier-
sprache Java.
EMF erlaubt nun die Bearbeitung und Anzeige solcher mittels Java Annotations, XML-
Dokumenten oder XML-Tools (wie Rational Rose oder Poseidon) erstellten Metabeschrei-
bungen.
Die entsprechenden EMF-Versionen stehen auf der Eclipse-Homepage zum Download be-
reit2. Tabelle 3.2 zeigt die verschiedenen, erhältlichen EMF-Versionen und die zugehörigen
Eclipse-Versionen, unter denen sie einsetzbar sind. Die SDK-Version umfasst derzeit ca.
22 MB und enthält Beispiele und Dokumentation.

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

3 – Eclipse als Modellierungswerkzeug

Tabelle 3.2: EMF- und zugehörige Eclipse-Versionen

EMF-Version Eclipse-Version J2SE-Version

2.2.0 3.2.0 1.4.2 oder 5.0

2.1.1, 2.1.0 3.1.1, 3.1.0 1.4.2

2.0.4/ 2.0.3/ 2.0.2, 2.0.1, 2.0.0 3.0.2, 3.0.1, 3.0.0 1.4.2

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.

3.3.2 Graphical Editing Framework (GEF)


Das GEF erlaubt erwartungsgemäß in Ergänzung zum EMF die Erstellung entsprechender
grafischer Editoren. Notwendig hierfür ist ein entsprechendes Applikationsdatenmodell,
aus dem heraus sich das GEF zur Visualisierung bedienen kann. Das GEF folgt dabei in sei-
nem Design der typischen Modell-View-Controller-Architektur, wie wir sie beispielsweise
auch im Java-Swing-Umfeld als typische Implementierungsvariante für die Kommunika-
tion zwischen Modell und Oberfläche finden.

1. http://www.eclipse.org/emf/docs.php

119
eclipse_v01.book Seite 120 Montag, 30. Januar 2006 12:02 12

EMF/GEF und UML2

Das GEF besteht aus zwei Anwendungsbestandteilen:


쐌 Einem Layout/Rendering-Teil zur Anzeige der Modelle auf dem User Interface (org.
eclipse.draw2d). Dort finden wir typische Elemente wie Layer, Cursor- und Tooltip-
support, Border oder Druckunterstützung.
쐌 Zweiter Bestandteil ist das org.eclipse.gef, eine Anwendungskomponente, die Funktio-
nalitäten wie Paletten, Controller, Undo/Redo-Support und Integration von Modell und
UI unterstützt.
Typische Anwendungsfälle für das GEF sind alle Formen von Diagrammvisualisierungen,
GUI Buildern, UML-Programmen oder Texteditoren.
Das GEF kann auf der Eclipse-Webseite samt entsprechender Beispiele heruntergeladen
werden1. GEF- und Eclipse-Version werden dabei in jeweils synchronen Versionsnummern
angeboten. Für Eclipse 3.1 benötigen Sie also normalerweise auch ein GEF 3.1, falls Sie an
den entsprechenden Funktionalitäten interessiert sind.

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

von Lars Wunderlich

4.1 Einführung ins Thema


Qualitätssicherung ist oft ein Stiefkind vieler Softwareprojekte, egal, ob alleine oder im
Team entwickelt wird. Dennoch taucht der Begriff im Kontext des so genannten magischen
Dreiecks des Projektmanagements auf. Dieses besagt, dass sich die Zieldefinitionen Bud-
get/Ressourcen, Zeit und Qualität gegenseitig beeinträchtigen.
Was bedeutet das? Konkretes Beispiel: Wenn die Zeit knapp wird, kommt es zu Abstrichen
an der Qualität. Genau das Gleiche kann passieren, wenn einfach die Manpower ausgeht,
wenn das Budget nicht ausreicht und somit das selbst gesteckte Qualitätsziel verfehlt wird.
Wir wollen uns kurz die Gründe für fehlende Softwarequalität ansehen und die Chancen,
die bei der Verwendung von Eclipse in diesem Bereich bestehen.

4.2 Wie äußert sich ein Mangel an Qualität?

4.2.1 Mangelnde Sourcecodetests


Einiges an Literatur zum Thema Projektmanagement verweist auf den wichtigen Block des
Testens innerhalb des Projektplans und dennoch sind viele Projektleiter der Meinung, man
könne nach der Realisierung mit der Auslieferung beginnen. Normalerweise geschieht dies
sogar zum Wohlwollen der Entwickler, die ihren eigenen Sourceteil bereits während der
Entwicklung Tests unterzogen haben und gar nicht glauben wollen, dass dort Fehler sein
könnten, wenn auch vielleicht sogar nur fachlicher Art.
Als Bugtracking-Tool bezeichnet man ein Tool, in welchem der Kunde seine Fehler doku-
mentieren und der Bugfixing-Workflow nachverfolgt werden kann. Das Produkt Bugzilla
lässt sich beispielsweise auch in Eclipse integrieren. Dank dieser modernen Techniken wird
oftmals Struktur in die Fehlerbehandlung gebracht. Nichtsdestotrotz wird Bugtracking und
Change Management häufig erst nach Projektende eingesetzt. Um es deutlicher zu formu-
lieren: Oftmals ist das Kind „Qualität“ schon in den Brunnen gefallen, wenn mit dem Tes-
ten begonnen wird. Die Aufwände der daraus resultierenden Aktivitäten sind im Gegensatz
zum Einsatz der Resourcen, die während der Entwicklungsphase dafür notwendig wären,
um einiges höher.
Für mehr technisch orientierte Tests auf einer sehr detaillierten Ebene empfiehlt sich das
JUnit-Framework, welches in Eclipse bereits integriert ist und das bereits in Kapitel 2 kurz
vorgestellt wurde. Von ihm gibt es auch diverse Derivate u.a. zum automatisierten Testen
von Swing-Applikation (JFCUnit) oder Java Enterprise Edition-Komponenten wie Web-
seiten oder Enterprise Java Beans (EJBs) beispielweise.
Daneben gibt es eine ganze Reihe kommerzieller Produkte, die aber zumeist wenig Integra-
tion in Eclipse als Plug-Ins bieten.

121
eclipse_v01.book Seite 122 Montag, 30. Januar 2006 12:02 12

Wie äußert sich ein Mangel an Qualität?

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.

4.2.2 Mangelnde Tests der fachlichen Funktionalität


Mit JUnit-Tests können wir einzelne Klassen oder Interaktionen zwischen diesen testen.
Sie helfen auf Basis von komponentenübergreifenden Problemen aber wie gesagt nur noch
bedingt weiter, da die Menge der Datenkonstellationen häufig unüberschaubar wird.
Daneben gilt es, in der Software die fachlichen Anforderungen abzudecken. Dass dies ge-
schieht, gehört eher in den Bereich des Projektmanagements. Wird streng nach einem ob-
jektorientierten Vorgehensmodell verfahren, sollten sich aus den Use Cases (Anwendungs-
fällen) die Test Cases, also die Testfälle für das System, abbilden lassen. Je nachdem, wie
spezifisch die Dokumentation des Use Case ist, desto eher kann die Einhaltung in den Test
Cases dokumentiert werden. Neben der Anwendung von Modellierungswerkzeugen kön-
nen fachliche Tests nur sehr bedingt technisch abgebildet werden.

4.2.3 Eingeschränkte Funktionalität


Wenn die Seite des Budget- und Ressourcendreiecks besonders hart drückt, wird oft gänz-
lich auf das Testen verzichtet, um den Einführungstermin zu halten und sich letztlich im
Nachgang auf die Kritik des Kunden einzurichten. Teilweise wird auch zusammen mit dem
Kunden die Funktionalität reduziert. Nicht selten ist dies die Folge falschen Projektma-
nagements, was letztendlich mit mangelnden Tests einhergeht. Häufig sind Projektziele
nicht klar definiert, die Motivation sinkt auf den Nullpunkt, die Projektsteuerung hat ver-
sagt oder (was ja auch vorkommen soll) den Projektleitern/innen sind Budget, Ressourcen
oder Geld so weit gestrichen worden, dass sie mit dem Rücken an der Wand stehen.
Bei Erstellung dieser Dokumentation wurde deshalb auch nach Projektmanagement-Plug-
Ins für Eclipse gesucht, z.B. zur Ressourcen- und Projektstrukturplan-Abb.. Leider existie-
ren hier zurzeit nur sehr wenige Plug-Ins. Einen Lichtblick könnte z.B. das AT-Project1
zukünftig bieten, das solche projektleitungsorientierten Aufgabengebiete im Rahmen von
Eclipse unterstützt. Da sich das Tool jedoch noch in einer sehr frühen Entwicklungsphase
befindet, wird es im Folgenden nicht vorgestellt.

1. http://www.atreides-technologies.com/

122
eclipse_v01.book Seite 123 Montag, 30. Januar 2006 12:02 12

4 – Qualitätssicherung in Eclipse

4.2.4 Begrenzte Sourcecode-Qualität


Als Beispiel sei hier zunächst von einem 6000 Zeilen umfassenden BASIC-Programm be-
richtet. Dieses besaß, soweit erkennbar, nur einen gravierenden Bug. Nach acht Stunden
Suche wurde der Fehler vom Entwickler gefunden. Es war eine unglücklich benannte Me-
thode, die der Einfachheit halber nur „C“ genannt worden war und die sich (wie in dama-
liger Basic-Manier gern üblich) neben mehreren anderen Methodenaufrufen auch noch in
einer Zeile wiederfand.
Hieran ist zu erkennen, dass die Qualität des Sourcecodes und der Dokumentation eine we-
sentliche Rolle bei der Arbeit mit dem Quellcode spielen. Niemand liest gerne lange An-
leitungen, aber dort, wo der Sourcecode so unleserlich erscheint, bleibt außer Debuggen oft
keine Möglichkeit, zum Kern von Problemen und Lösungen vorzustoßen.
Während der Einzelprogrammierer hofft, dass er in zwei, drei Monaten sein Programm
noch versteht, ihm einleuchtet, was die Variablen bedeuten und warum hier ein IF die
Schleife mit einem BREAK verlässt, kann ein solches Handeln im Team zu massiven Ver-
zögerungen in der Projektarbeit und bei der Wartung führen.
Die Qualität des Sourcecodes und der Dokumentation kann sehr leicht durch die Anwen-
dung von Reviews erhöht werden.

4.2.5 Reviews und Softwareunterstützung


Als gutes Mittel zur Qualitätssicherung sind Reviews auf mehreren Ebenen möglich, z.B.:
1. Auf der Ebene der fachlichen Anforderungen (sind diese vollständig und spezifisch ge-
nug, um ihr Problemfeld abzugrenzen?). Hier kann Software allerdings wenig Hilfestel-
lung bieten.
2. Auf der Ebene der Architektur und des Softwaredesigns (Verteilung der Komponenten,
Klassen, Pattern-Anwendung). An dieser Stelle empfiehlt sich die Verwendung von
Reverse Engineering, das heißt der Übertragung des Sourcecodes in visuelle Notatio-
nen, um einen schnellen Einblick in die Strukturen der Software zu gewinnen (siehe Ka-
pitel 3).
3. Auf der Ebene der erstellten Dokumentation (Artefakte). Es gibt zahlreiche Eclipse-
Plug-Ins, die Dokumentationen unterschiedlicher Natur zusammenführen oder aus
Sourcecodedokumenten eigene Ergebnisartefakte erstellen. Die Anwendung ist aber si-
cherlich sehr projektindividuell.
4. Auf der Ebene des Sourcecodes. Die Qualität kann z.B. durch entsprechende Restrik-
tionen erreicht werden (wie lang ist eine Zeile, wie sind Namenskonventionen, welche
Elemente muss ein Javadoc enthalten?). Dafür werden Tools verwendet, die den
Sourcecode prüfen (z.B. Checkstyle1), oder es werden die Restriktionen des Compilers
bereits entsprechend eingestellt, so dass dieser im Build-Prozess entsprechende Errors
oder Warnings auswirft. Eine andere Möglichkeit ist die Visualisierung der Sourcecode-
Qualität durch die Anwendung von Audits und Metriken. Beides wollen wir uns mittels

1. http://checkstyle.sourceforge.net/

123
eclipse_v01.book Seite 124 Montag, 30. Januar 2006 12:02 12

Eclipse zur Qualitätssicherung

entsprechender Tools erzeugen lassen. Auch die Prüfung der Sourcecode-Abdeckung


(wie viel von meinem Sourcecode wird überhaupt verwendet und wie viel ist toter
Code?) führt oft zu sehr interessanten Interpretationen.
Die beiden Themen Testen und Reviews werden oft etwas vernachlässigt und spielen in vie-
len Projektverläufen (und Büchern) zu Unrecht eine sehr untergeordnete Rolle. Aber gera-
de Produktqualität ist ein ganz wesentlicher Marketing- und Erfolgsfaktor bei der Soft-
wareerstellung.

4.3 Eclipse zur Qualitätssicherung


Eine recht gute Qualität lässt sich erreichen, wenn wir bereits während des Verlaufs der
Softwareentwicklung Techniken zu deren Sicherung anwenden und nicht erst dann, wenn
es zu spät ist. Eclipse bietet aufgrund der Refactoring- und Modellierungsmöglichkeiten so-
wie der Anwendung von Sourcecode-Stilrichtlinien und JUnit-Tests die Möglichkeit, qua-
litätssichernde Maßnahmen schon bei der Entwicklung vor allem im Team durchzusetzen
und nicht erst in der Endphase oder nach dem Projekt.

4.3.1 Testen mit JUnit


Der technische Einsatz eines JUnit-Tests ist nicht sehr schwierig. Ein Beispiel dafür findet
sich im Einführungskapitel 2 dieses Buchs. Schwieriger erscheint die Frage, wann und wo
JUnit-Tests verwendet werden sollen. JUnit eignet sich besonders gut für das Testen von
Klassen und deren Methoden. Es gibt eine sehr tiefe und feingranulare Ebene, aber je weiter
der Komponentenbegriff gespannt wird (Packages, Modules/Components, Application, ...),
desto mehr Implikationen mit bestimmten Testdaten gibt es und die Menge der Testfälle
vervielfacht sich.
Der Grund dafür findet sich an zwei Stellen:
1. Datenkonstellationen sind oft nur schwer reproduzierbar. Das erschwert die Möglich-
keit, JUnit im Deployment-Prozess z.B. im Ant-Build für komplexe Tests einzusetzen.
2. Beim Design der Komponenten wurden die Schnittstellen zu anderen Komponenten
möglicherweise überfrachtet. Selbstverständlich kann jede Komponente interne Fehler
haben, aber ein JUnit-Test wird normalerweise nur über eine Schnittstelle (Interface
bzw. public-Methoden von Klassen) angewendet. Je mehr public-Methoden existie-
ren, desto länger dauert das Erfinden von Testmethoden und Szenarien. Das heißt, ist
das Design einer Komponente ungünstig gewählt, kann der JUnit-Test zu einer schein-
bar unendlichen Prozedur der Definition von möglichen Testfällen führen.

Es sollten wiederholbare JUnit-Tests für Klassen bzw. Interfaces geschrie-


ben werden, die wiederum auch von anderen benutzt oder aufgerufen
werden sollten. Am Ende in der Kundentestphase oder auch schon vorher
kann für die Fehler, die als Bugs identifiziert wurden, oft schnell ein JUnit-

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.

4.3.2 Audits mit Checkstyle


Ein recht bekanntes Plug-In zur Prüfung von Sourcecode gegen entsprechende Richtlinien
heißt Checkstyle. Checkstyle1 selbst ist aber ein Standalone-Produkt, das sich u.a. sehr
leicht in einen Ant-Build-Prozess integrieren lässt. Für die Einbindung in IDEs gibt es ent-
sprechende Plug-Ins. Eines davon wollen wir uns an dieser Stelle näher ansehen.
Als Plug-In verwenden wir im Beispiel das Atlassw Eclipse Checkstyle2 für Checkstyle
(hier in Version 4.0.0 beta 6).
Nach dem Download der Datei und dem Entpacken ins Plug-Ins-Unterverzeichnis von
Eclipse starten wir Eclipse neu, um es nutzen zu können.
Checkstyle integriert in die Preferences von Eclipse (Menü WINDOW | PREFERENCES) eine ei-
gene Einstellungsseite (siehe Abb. 4.1), in der Checkstyle-Konfigurationen definiert wer-
den können. Das ist die Menge der Regeln/Regelprüfungen, die auf einen Satz von Java-
Dateien angewandt werden sollen.

Abb. 4.1: Checkstyle Preferences Page

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

Eclipse zur Qualitätssicherung

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).

Abb. 4.2: Checkstyle Check Configuration Editor

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

Prüfungen), Klassendesign (Interfaces, Final Classes, Sichtbarkeit), J2EE-Prüfungen (EJB-


Anwendungen, Returntypes, Exceptions) und Usage (unbenutzte Variablen, einmalige Zu-
weisungen), um nur einzelne Beispiele zu nennen.
Die erfassten Regelkonfigurationen lassen sich über die Preferences Page von Checkstyle
als interne oder externe XML-Konfigurationsdateien speichern und so auch in Eclipse-In-
stallationen anderer Projektmitglieder ohne Probleme erneut laden.
Das Checkstyle-Plug-In liefert zu den Regeln die recht ausführliche Checkstyle-Dokumen-
tation der bereits verfügbaren Regeln mit, die zum besseren Verständnis um eigene Kom-
mentare in Eclipse ergänzt werden können.
Nach der Zusammenstellung einer entsprechenden Konfiguration von Regeln wechselt
man in Eclipse in das auf diese Regeln zu prüfende Java-Projekt bzw. nach Selektion im
Package Explorer über die rechte Maustaste zu dessen Properties. In den Properties des
Projekts findet sich nun auch ein Unterpunkt mit der Bezeichnung Checkstyle, in welchem
die Konfigurationen mit zu definierenden „Datei-Sets“ assoziiert werden können. Im Bei-
spiel in Abb. 4.3 ist dies mit dem aus Kapitel 2 bekannten Jakarta ORO-Projekt unter Ver-
wendung der Sun Conventions getan worden.
Mehrere dieser Zuordnungen können parallel für ein Projekt erfasst und aktiviert oder
deaktiviert werden. Die Erstellung der Datei-Sets erfolgt über HINZUFÜGEN bzw. EDITIEREN
in einem eigenen DATEI-SET EDITOR.

Abb. 4.3: Zuordnung von Checkstyle Configuration zu Datei-Sets

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

Eclipse zur Qualitätssicherung

sind, da jede Einzelprüfung selbstverständlich einen Teil der Compile-/Build-Zeit in An-


spruch nimmt, und wie viele Verletzungen parallel geprüft werden sollen.
Nach Durchlauf des Build finden sich die Ergebnisse in der Problems View von Eclipse
wieder. Hierfür klicken wir auf das Toolbar-Icon für Filters (die drei nach rechts zeigenden
Pfeile) und wählen die Checkbox für Checkstyle an. Unter Umständen muss die Menge der
gleichzeitig anzeigbaren Fehler erhöht werden, weil (wie hier im Beispiel von Jakarta
ORO, siehe Abb. 4.4) das Plug-In über 6800 Verstöße gegen die Konventionen gefunden
hat. Dies zeigt deutlich, dass ein gewissenhafter Umgang mit dem Thema Stilrichtlinien
notwendig ist, auch um die Produktivität in der Teamarbeit nicht unnötig durch Konven-
tionen zu mindern und gleichzeitig die Sourcecode-Qualität bereits bei der Erstellung zu
sichern.
Bereits seit Eclipse 3.0 verfügt Eclipse über einen auf die Sun Code Conventions abge-
stimmten Formatter, der auch komplexere Formatierungsregeln unterstützt, so dass die
manuelle Nachpflege des Sourcecodes für die Einhaltung von Richtlinien weiter abnehmen
sollte.

Abb. 4.4: Checkstyle-Ergebnisse in der Problems View

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

4.3.4 Metrics 1.3.6


Ein frei verfügbares Tool zur Analyse des Sourcecodes ist Metrics von Frank Sauer, das
zum Erstellungszeitpunkt dieser Dokumentation in der Version 1.3.6 für Eclipse 3.1 zur
Verfügung stand. Das rund 1,8 MB große Programm kann von seiner Sourceforge-Herstel-
lerseite1 per automatischem Installations-Download heruntergeladen werden. Dazu müssen
wir in Eclipse in den Dialog HELP | SOFTWARE UPDATES | FIND AND INSTALL... wechseln und
als neue Remote-Seite die oben angegebene URL-Adresse eintragen. Nach Bestätigung
und Ausführung der Suche können wir das Produkt installieren und nach einem Neustart
der IDE ab jetzt in Eclipse 3.1 einsetzen.
Der Hersteller liefert eine kurze Hilfe in HTML-Form als Integration in die Eclipse-Hilfe
mit. Sie entspricht derzeit exakt dem Inhalt der Webseite, auf der dieses Programm vertrie-
ben wird. Die meisten Funktionen erschließen sich allerdings schnell auch von selbst. Der
Autor hat dabei sein auf dem CPL 1.0-Lizenzmodell basierendes Produkt u.a. mit der
Touchgraph2-Visualisierung ergänzt, was – wie wir später noch sehen werden – die Abhän-
gigkeiten zwischen einzelnen Klassen und Klassenverbänden sehr schön deutlich macht.
Nach der Installation findet sich in den Eclipse Preferences (Menü WINDOW | PREFERENCES)
ein Unterpunkt zum Thema METRICS PREFERENCES (siehe Abb. 4.5).

Abb. 4.5: Preferences-Metrics-Complexity

1. http://metrics.sourceforge.net/update
2. http://www.touchgraph.com/

129
eclipse_v01.book Seite 130 Montag, 30. Januar 2006 12:02 12

Eclipse zur Qualitätssicherung

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.

Abb. 4.6: Projekteigenschaften eines gemessenen Projekts

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.

Tabelle 4.1: Metrikwerte aus Metrics

Abkürzung Name Bedeutung

CA Afferent Coupling Anzahl der Klassen außerhalb eines Package, die


auf Klassen innerhalb eines Package verweisen.

CE Efferent Coupling Gegenteil von CA: Anzahl der Klassen innerhalb


eines Package, die auf andere außerhalb verwei-
sen. Die Werte von CA und CE kennzeichnen die
Geschlossenheit und Kapselung eines Package
gegenüber Einflüssen von außen und umgekehrt.

1. auch nochmal nachzulesen in der dem Produkt beiliegenden Hilfedokumentation

130
eclipse_v01.book Seite 131 Montag, 30. Januar 2006 12:02 12

4 – Qualitätssicherung in Eclipse

Tabelle 4.1: Metrikwerte aus Metrics (Forts.)

Abkürzung Name Bedeutung

DIT Depth of Inheritance Beschreibt die Anzahl der Vererbungslevel zwi-


Tree schen der aktuellen Klasse und java.lang.
Object.

LCOM* Lack of Cohesion Misst den Zusammenhalt einer Klasse nach der so
of Methods genannten Henderson-Sellors-Methode.

MLOC Method lines of Summe aller nicht leeren und Nicht-Kommentar-


code Zeilen innerhalb der Methodenblöcke.

NOC Number of Classes Gesamtzahl aller Klassen innerhalb des gewählten


Sichtbarkeitsbereichs.

NOF Number of Fields/ Gesamtzahl der Felder innerhalb des gewählten


Attributes Bereichs.

NOI Number of Gesamtzahl der Interfaces innerhalb des gewähl-


Interfaces ten Bereichs.

NOM Number of Methods Gesamtzahl der Methoden innerhalb des gewähl-


ten Bereichs.

NORM Number of Over- Gesamtzahl der von Elternteilen überschriebenen


ridden Methods Methoden innerhalb des gewählten Bereichs.

NSC Number of Children Gesamtzahl der direkten Sub-/Implementierungs-


klassen einer Klasse/von Interfaces.

RMA Abstractness Anzahl der abstrakten Typen (Klassen und Inter-


faces) geteilt durch die Anzahl aller Typen des
Package.

RMD Normalized Dis- | RMA + RMI - 1 | : Messwert, der bei gutem


tance from Main Package-Design nahe null liegen sollte.
Sequence

RMI Instability CE / (CA + CE)

TLOC Total lines of code Gesamtzahl der Codezeilen eines Typs ohne leere
und Kommentarzeilen.

VG McCabe Cyclo- Zyklomatische Komplexität nach McCabe, die die


matic Complexity Anzahl der potenziell unterschiedlichen möglichen
Programmflüsse und Äste innerhalb eines Source-
code-Teils bewertet.

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

Eclipse zur Qualitätssicherung

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.

Abb. 4.7: Schwellenwerte für Problemanzeige

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

4.3.5 Metrikreports und Graphen


Kommen wir nun von den Einstellungen des Programms zu deren konkreter Anwendung
für ein Java-Projekt in Eclipse.
Die Nutzung für ein Java-Projekt kann – wie bereits beschrieben – erfolgen, sobald die
entsprechende Funktion in den Projekteigenschaften aktiviert wurde. Die Anzeige der
zugehörigen Metrikwerte erfolgt über eigens dafür konzipierte Views. Sie sind über das
Menü WINDOW | SHOW VIEW | OTHER... im Baum unter dem Punkt METRICS zu finden (siehe
Abb. 4.8).

Abb. 4.8: Metrics Views

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

Eclipse zur Qualitätssicherung

Abb. 4.9: Metrik-Analysetabellen

Abb. 4.10: Abhängigkeitsgraph in Metrics

Abb. 4.11: Beispiel-XML aus Metrics

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.

4.3.7 Bleiben Sie kritisch


Bei der Metrikanalyse gilt der berühmte alte Satz aller Statistiken: „Trauen Sie keiner Sta-
tistik, die Sie nicht selbst gefälscht haben“.
Wer sich eine Weile intensiv mit Java, Java-Architekturen und Lösungsvarianten beschäf-
tigt hat, wird bemerken, dass es unendlich viele Lösungsmöglichkeiten zu geben scheint,
dass aber auch immer gleichartige Probleme dabei auftauchen.
Größtes Hindernis ist oft: Programme sind zu komplex und zu schwer zu verstehen.
Oder andersherum formuliert: Software mit weniger Sourcecode enthält potenziell weniger
Fehler. Ob wir einen solchen Kandidaten vor uns haben, lässt sich bereits schnell nach einer
Sichtung der Lines of Code ermitteln. Stellen wir noch die Anzahl der Vererbungshierar-
chieebenen, die Anzahl der Methoden und z.B. die zyklomatische Komplexität daneben,
wissen wir schnell, in welchen Bereichen der Software das Risiko von Fehlern am höchsten
ist. In einem Architekturbuch las ich einmal Folgendes: Fehler zeigen ein gruppendynami-
sches Verhalten. Dort wo viele auftauchen, finden sich zumeist noch mehr. Also wer eine
Aussage über die Qualität einer Softwarekomponente haben will, sollte vielleicht statt in
ein Metriktool hin und wieder mal in das zugehörige Bugtracking-Produkt schauen.
Zweites Problem: Mit fortschreitender Entwicklung werden Dokumentation und Test po-
tenziell vernachlässigt. Dies trifft besonders auf die Maintenance- (also die Betriebs-)Phase
zu, in der oft nicht mehr die ursprünglichen Entwickler fremden Source und fremde Mo-
delle ändern und anpassen müssen oder sollen. Das Verhältnis zwischen echten Lines of
Code und reiner Java-Klassenlänge lässt einen ganz guten Rückschluss darauf zu, wie viel
prozentual dokumentiert wurde. Aber Vorsicht, das sagt nicht aus, ob hier gut, angemessen
oder primitiv dokumentiert wurde. Es sagt auch nichts darüber aus, ob der Sourcecode
selbst sprechende Variablen enthält, die den Sinn der dort hinterlegten Logik gegebenen-
falls auch ohne expliziten Javadoc verständlich machen. Ebenfalls wichtig: Die Dokumen-
tation öffentlicher Schnittstellen ist gemeinhin wichtiger als die privater Klassen und

135
eclipse_v01.book Seite 136 Montag, 30. Januar 2006 12:02 12

Eclipse zur Qualitätssicherung

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

5 Build Management mit Eclipse

von Herbert Brückner

5.1 Aufgaben des Build Managements


Der Begriff Build Management wird in sehr unterschiedlichen Ausprägungen verwendet
und beschreibt meist Aufgaben in den Bereichen Kompilierung und Auslieferung von Re-
leases und Patches. Weiter ist er eng verknüpft mit den Themen Versionsverwaltung und
Konfigurationsmanagement. Wir wollen hier eine typische Situation und Fragestellungen
aufzeichnen, die im Rahmen des Build Managements behandelt werden. Dabei wird der
Begriff etwas weiter gefasst als der Begriff des eigentlichen Build, welcher häufig als Syn-
onym für ein intelligentes Kompilieren des Projekts oder Teile hiervon gesehen wird.
Nahezu jede professionelle Softwareentwicklung wird sich mit dem Build Management be-
schäftigen müssen, sobald die entwickelte Software auf einem anderen System betrieben
wird als dem, auf dem es entwickelt wurde. Üblicherweise findet schon die Softwareent-
wicklung auf mehreren Systemen statt: Auf einer oder mehreren Entwicklungsumgebun-
gen und Testumgebungen (z.B. je eine Umgebung pro Betriebssystem) oder auf einer oder
mehreren produktiv eingesetzten Umgebungen. Hieraus ergeben sich verschiedene Fragen:
쐌 Wie macht man aus Quelldateien und Konfigurationsdaten ein Stück Software? (Build)
쐌 Wie bringt man das Stück Software X auf die Umgebung Y? (Deployment)
쐌 Wie stellt man sicher, dass die Software X auch auf der Umgebung Y läuft? (Tests, Ver-
sionierung)
쐌 Was ist zu tun, wenn man die Software auf mehrere Systeme Y1, Y2, Y3 ... bringen
muss? (Build- und Konfigurationsmanagement)
쐌 Man will die Umgebung Y so aufbauen, wie sie am 03.12.1994 betrieben wurde. Wie
geht das? (Release-Management, Versionsverwaltung, Betrieb)
Wir wollen nun einen Vorschlag zur Struktur und den Prozessen im Build Management ma-
chen und aufzeigen, wie Eclipse dies technisch unterstützt.
Zunächst wird auf die direkt in Eclipse vorhandenen Hilfen und Werkzeuge eingegangen,
die insbesondere den Build-Prozess bei Java-Entwicklungen unterstützen. Im Anschluss
werden weitere Tools und Konzepte vorgestellt, die sich auf komplexere Prozesse beziehen,
und deren Unterstützung dargelegt. Dies zeigt auf, wie die bereits beschriebenen Funktio-
nen integriert genutzt werden können.
Zunächst noch zwei grundsätzliche Hinweise:
쐌 Sehr viele Arbeitsschritte im Build Management sind Standardschritte, die sich regel-
mäßig wiederholen. Sofern sie über die mitgelieferten automatischen Funktionen hin-
ausgehen, sollte man deshalb frühzeitig überlegen, ob und wie diese Schritte automati-
siert ausgeführt werden können!
쐌 Nachvollziehbarkeit ist oberstes Gebot! Es sollte immer klar sein, wie ein Stück Soft-
ware erstellt, eine Umgebung installiert und konfiguriert ist und wie dieser Zustand er-
reicht wurde.

137
eclipse_v01.book Seite 138 Montag, 30. Januar 2006 12:02 12

Vom Quellcode zum Programm: Build

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.

5.2 Vom Quellcode zum Programm: Build


Insbesondere in der Java-Programmierung unterstützt Eclipse die Arbeit durch automa-
tisches oder manuelles Kompilieren (Build) des Quellcodes. In Eclipse beziehen sich die
eingebauten Build-Funktionen auf den Kernbereich des Kompilierens und des Ablegens in
einem Zielbereich (Deployment/Launch) sowie der automatischen Erstellung der Doku-
mentation mittels JavaDoc.
Eclipse übernimmt hierbei die Prüfung, ob ein Kompilieren notwendig ist, ob Abhängig-
keiten zu anderen Dateien zu beachten sind und wie das Ergebnis abgelegt und eingebun-
den wird.
Es werden zwei Arten unterschieden:
쐌 Das komplette Build löst ein Löschen der vorherigen Kompilate aus und baut alle in
Frage kommenden Ergebnisse (z.B. die .class-Dateien) aus den Quelldateien neu auf.
Die Abhängigkeiten untereinander werden automatisch in der Reihenfolge des Kompi-
lierens berücksichtigt, können aber auch explizit verändert werden.
쐌 Das inkrementelle (teilweise) Build bearbeitet nur veränderte Dateien und solche, die
davon abhängig sind. Veränderungen des Codes werden also in der Regel auch in Da-
teien berücksichtigt, die selbst nicht angefasst wurden. Allerdings ist nicht völlig aus-
zuschließen, dass eine Abhängigkeit nicht erkannt wurde und somit das Kompilat in
sich inkonsistent geworden ist.
Beide Arten können entweder auf den gesamten Arbeitsbereich angewendet werden oder
auf eine bestimmte Teilmenge von Projekten. Die Vor- und Nachteile der beiden Arten lie-
gen auf der Hand: Während durch ein komplettes Build sichergestellt ist, dass die Abhän-
gigkeiten der Quellen erfüllt sind, hat das inkrementelle Build erheblich geringere Ausfüh-
rungszeiten.
Eclipse führt daher automatisch ein inkrementelles Build aus, wenn eine Datei gespeichert
wird, während ein komplettes Build manuell angestoßen werden muss. Die Modi, ob und
wann ein Build automatisch ausgeführt wird, sind konfigurierbar. Es kann z.B. sinnvoll
sein, das automatische Build abzuschalten, wenn eine große Anzahl von zusammenhängen-

1. vgl. http://ant.apache.org

138
eclipse_v01.book Seite 139 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

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.

5.3 Einstellungen des Eclipse-Build


Bevor ein Build ausgeführt werden kann, sind eine Reihe von Angaben notwendig, was al-
les dazugehören und aktualisiert werden soll. Diese Einstellungen werden in den Projekt-
eigenschaften vorgenommen und können auf verschiedene Arten geöffnet werden:
쐌 Reiter FILE | PROJECT PROPERTIES | JAVA BUILD PATH
쐌 (Bei aktivem Navigator-Fenster) Tastenkombination Ç-Æ
쐌 Im Navigator-Fenster durch rechte Maustaste auf PROJECT | PROPERTIES
In dem sich öffnenden Dialog findet man in der linken Navigationsleiste vier Einträge, die
für das Build von Interesse sind:
쐌 Unter BUILDERS kann man das Werkzeug bestimmen, mit dem das Build vorgenommen
werden soll. Neben dem internen Java Builder können hier auch externe (eigene) Tools
eingebunden und konfiguriert werden.
쐌 Unter JAVA BUILD PATH bestimmt man, welche Quelldateien, Projekte und Bibliotheken
verwendet werden sollen, und die Reihenfolge des Einbindens.
쐌 Unter JAVA COMPILER sind die Einstellungen bezüglich der Kompatibilität interessant.
Weiterhin kann hier festgelegt werden, wie mit speziellen Fehlersituationen umgegan-
gen werden soll.
쐌 Unter JAVADOC LOCATION schließlich kann man einstellen, was mit der Dokumentation
geschehen soll.

5.3.1 Build Path-Einstellungen


Beginnen wir mit dem zweiten Eintrag, der Einstellung des Build-Pfads. Diese Einstellun-
gen sind schon zu Projektbeginn erforderlich, wenn in dem Projekt externe Bibliotheken
verwendet werden, um z.B. Auto-Vervollständigung und die Syntaxprüfung nutzen zu kön-
nen. Die Einträge können praktisch jederzeit geändert werden, allerdings sollte dann neu
kompiliert werden und es können Fehler auftreten.
Nach Anklicken des Eintrags erscheinen im rechten Teil des Fensters vier Reiter: Der erste
trägt den Namen SOURCE. Hier können wie in Abb. 5.1 dargestellt die Quellverzeichnisse
und -dateien festgelegt werden:
Mit ADD FOLDER können wir aus dem Projekt-Verzeichnisbaum weitere Verzeichnisse aus-
wählen und dem Build-Pfad hinzufügen. Es öffnet sich ein Fenster mit einer Navigations-
leiste und dem ausgewählten Projekt. Hier können nun weitere Pakete (Verzeichnisse) hin-
zugefügt werden.

139
eclipse_v01.book Seite 140 Montag, 30. Januar 2006 12:02 12

Einstellungen des Eclipse-Build

Abb. 5.1: Hauptmenü der Einstellungen zum Build

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

5 – Build Management mit Eclipse

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

Einstellungen des Eclipse-Build

Abb. 5.2: Einstellung von Java-Variablen

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

5.3.2 Compiler und JavaDoc-Einstellungen


Wenn der Build Path definiert ist, sind bereits die wesentlichen Einstellungen getätigt. Es
kann jedoch sein, dass für das Build noch bestimmte Compiler-Optionen von Bedeutung
sind. Diese können unter dem dritten Menüpunkt eingestellt werden. Auch diese Einstel-
lung sollte schon zu Projektbeginn getroffen werden, um alle Möglichkeiten des Editors
und der Workbench nutzen zu können. Sie lässt sich aber jederzeit anpassen.
Zunächst können wir wieder bestimmen, ob die gewünschten Werte projektspezifisch oder
für den gesamten Arbeitsbereich festgelegt werden sollen. Die jeweilige Konfiguration er-
folgt dann analog. Für dieses Kapitel interessant sind die beiden letzten Reiter für Compi-
ler-Einstellungen:
Der Reiter COMPLIANCE AND CLASSFILES erlaubt die Einstellungen von Kompatibilitätsstufen.
Hier ist auszuwählen, ob das Ergebnis des Build gegebenenfalls auf einer anderen Maschi-

142
eclipse_v01.book Seite 143 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

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.

5.3.3 Automatische und manuelle Builds


Ein Build kann entweder manuell ausgelöst werden oder automatisch, z.B. bei Änderungen
an Quelldateien, erfolgen. Der manuelle Build lässt sich wie folgt starten.
Durch Auswahl in der Hauptmenüleiste:
쐌 Reiter PROJECT | BUILD ALL für ein Build aller Projekte
쐌 Reiter PROJECT | BUILD PROJECT für ein Build des aktuellen Projekts
쐌 Im Navigator-Fenster durch rechte Maustaste auf das PROJEKT-ICON|BUILD PROJECT (er-
scheint nur, wenn das automatische Build deaktiviert ist)
쐌 Durch die Tastenkombination Ÿ-B
Wichtig, weil sonst gerne vergessen, ist das Sichern aller offenen Dateien vor dem Ausfüh-
ren des Build. Dies kann durch die Einstellung im Menü WINDOW | PREFERENCES | WORK-
BENCH | SAVE ALL MODIFIED RESOURCES erreicht werden. Diese Auswahl ist deshalb wichtig,
weil beim Build nur die abgespeicherte Version einer Datei berücksichtigt wird. Die letzten
Änderungen, die gerade geprüft werden sollen, werden ohne Sichern nicht berücksichtigt.
Ein Build kann auch automatisch ausgelöst werden und zwar durch die Einstellung:

143
eclipse_v01.book Seite 144 Montag, 30. Januar 2006 12:02 12

Einstellungen des Eclipse-Build

Menü WINDOW|PREFERENCES|WORKBENCH|PERFORM BUILD AUTOMATICALLY


In diesem Fall führt das Speichern einer geänderten Datei zum Kompilieren. Diese Einstel-
lung ist meistens wünschenswert. Nur beim Ausführen von komplexeren Änderungen,
wenn nicht alle zu speichernden Zwischenstände wirklich fehlerfrei kompilierbar sind,
kann sie lästig werden.

5.3.4 Weitere Konfigurationen


Neben der Standardkonfiguration können noch weitere Konfigurationen definiert und be-
nutzt werden. Sie werden beim Programmstart verwendet und ergänzen bzw. überschreiben
die Standardkonfiguration. Auf diese Weise ist es leicht möglich, eine Anwendung in ver-
schiedenen Konstellationen, z.B. mit verschiedenen Versionen von Bibliotheken oder Java-
Umgebungen, zu betreiben. Dies kann zum einen dazu dienen, Unterschiede in verschiede-
nen Zielumgebungen, auf denen ein Deployment erfolgen soll, auf einer Umgebung nach-
zustellen, um Fehler im Build zu erkennen und zu analysieren. Zum anderen können die
Konfigurationen auch für die gemeinsame Nutzung in einem Team bereitgelegt werden, so
dass sich nicht jedes einzelne Teammitglied mit Konfigurationsfragen auseinander setzen
muss.
Die Konfigurationen können unter RUN|RUN ... oder gleichermaßen unter DEBUG|DEBUG...
erstellt werden. Man erhält ein neues Fenster mit Einstellungsmöglichkeiten wie in Abb.
5.3 zu erkennen ist.

Abb. 5.3: Einstellungen zum Programmstart

144
eclipse_v01.book Seite 145 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

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

Einstellungen des Eclipse-Build

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.

5.3.5 Erzeugung anderer Ausgabetypen


Bisher haben wir die Konfiguration und das Build in Bezug auf das Kompilieren der Quell-
dateien betrachtet, als Ergebnis sind .class-Dateien in einem oder mehreren Verzeichnis-
bäumen erstellt worden. Häufig soll jedoch der kompilierte Java-Code als portables Päck-
chen verfügbar sein, um auf anderen Umgebungen verwendet zu werden. Eclipse bietet
hierzu eine Exportfunktion an, durch die verschiedene portable Formate, z.B. als .jar-Datei
oder als komprimiertes Archiv (.zip-Datei), erzeugt oder bearbeitet werden können. Wir
wollen dies nun näher betrachten und beginnen mit der Erstellung einer .jar-Datei. Dazu
sind die folgenden Schritte notwendig:
Zunächst wählen wir in der Ansicht PACKAGE EXPLORER eine oder mehrere (Unter-)Ver-
zeichnisse aus, die in der .jar-Datei enthalten sein sollen. (Diese Auswahl kann auch später
getroffen oder korrigiert werden.)
Anschließend rufen wir die Exportfunktion auf, z.B. durch
Hauptmenü FILE | EXPORT... oder durch
Rechte Maustaste im PACKAGE EXPLORER|EXPORT ...
Es öffnet sich ein Fenster mit einer Menüführung (Wizard). Zunächst ist in der rechten Aus-
wahl das Zielformat JAR FILE anzuwählen und mit NEXT zu bestätigen.
Im nächsten Fenster kann die Auswahl des Inhalts der .jar-Datei bestimmt bzw. bearbeitet
werden. Im linken Fenster werden die Projekte angezeigt. Diese können als Ganzes oder in
Teilen ausgewählt werden. Wurde im ersten Schritt eine Auswahl vorgegeben, so sind die
Werte hier entsprechend vorbelegt. Im rechten Fenster kann die Auswahl jeweils auf Datei-
ebene weiter detailliert werden. Unter diesem Fenster lässt sich für die Quelldateien be-
stimmen, ob sie selbst und/oder die daraus generierten .class-Dateien eingebunden werden.

146
eclipse_v01.book Seite 147 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

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.

5.4 Build Management und Versionierung


Die bisherigen Ausführungen zum Thema Build Management betreffen jeden Entwickler,
auch wenn er nur kleinste Programme erstellt. Wenn jedoch die Programme größer werden,
sei es, dass mehrere Entwickler daran beteiligt sind oder dass verschiedene Anpassungen
und Entwicklungsstufen erstellt werden sollen, so kommen schnell Aspekte zum Build
Management hinzu, die ohne weitere Werkzeuge nur noch sehr mühsam zu behandeln sind.
Deshalb soll an dieser Stelle ein Exkurs zu dem Versionierungswerkzeug CVS („Concur-
rent Version System“) unternommen werden. CVS ist als Open Source Tool weit verbreitet
und etabliert, dessen Unterstützung durch Eclipse ist bereits als Standard eingebunden.
CVS unterstützt zwei Kernaufgaben, wie bereits aus dem Namen ersichtlich ist:
쐌 Concurrent: CVS ist ein Hilfsmittel, um das gleichzeitige Bearbeiten von Quellcode
durch mehrere Programmierer zu organisieren. Es hilft einerseits, das Team jeweils mit
dem neuesten Stand der Dateien zu versorgen, andererseits mögliche Konflikte bei der
Bearbeitung einer Datei durch verschiedene Teammitglieder zu erkennen und zu behe-
ben.
쐌 Version: CVS erlaubt es, auf alle älteren Versionen einer Datei wieder zurückzugreifen
sowie bestimmte Versionen der Dateien zu kennzeichnen, um deren Zuordnung zu Pro-
grammständen (z.B. „Beta-Release“, „Final Release“), Versionen („Eclipse 3.0“) oder
Entwicklungssträngen („Standard“, „Extended“, „additional features“) festzulegen.
Im folgenden Abschnitt soll auf die Einbindung von CVS in Eclipse und auf für das Build
Management relevante Aspekte eingegangen werden. Für allgemeine Informationen über
CVS möchten wir auf die entsprechende Literatur1 und Online-Quellen2 verweisen.

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

Build Management und Versionierung

5.4.1 Exkurs: Versionierung mit CVS in Eclipse


Ein CVS-System ist eine Client-Server-Architektur. Der Server dient als zentrale Ablage-
und Steuerungseinheit für alle Dateien, die der CVS-Verwaltung unterliegen. Eine Datei ist
die kleinste Verwaltungseinheit im CVS, die Dateien werden in einer Verzeichnisstruktur
abgelegt. Die Gesamtheit der von CVS verwalteten Dateien wird als Repository bezeichnet.
Weiterhin verwaltet der Server die Benutzer und ihre Zugriffsrechte.
Mit dem Server kommunizieren beliebig viele Clients, sie können Dateien oder Verzeich-
nisse abrufen, hinzufügen oder aktualisieren sowie bestimmte Kennzeichen (Tags) an den
Dateien vornehmen und abfragen. Üblicherweise werden Dateien zur Bearbeitung durch
den Client in die lokale Entwicklungsumgebung kopiert und nach der Bearbeitung wieder
zum Server übertragen. Es kann also mehrere Kopien einer Datei auf lokalen Rechnern ge-
ben, der jeweilige Client (bzw. dessen Benutzer, sprich Programmierer) ist dafür verant-
wortlich, jeweils mit der letztgültigen Fassung zu arbeiten bzw. seine Änderungen zum Ser-
ver zu übertragen, damit auch die anderen diese zur Verfügung haben.
Eclipse hat einen CVS-Client eingebunden, mit dessen Hilfe es möglich ist, eine Verbin-
dung mit einem Server zu erstellen, Dateien vom Server abzuholen und Änderungen sowie
neue Dateien auf dem Server abzulegen. Da es beim Einrichten und bei der Pflege des CVS-
Servers keine Eclipse-spezifischen Aspekte gibt, soll dessen Installation hier nicht be-
schrieben werden; es wird von einem verfügbaren Server ausgegangen.1

Verbindung zum CVS-Server


Wenn ein CVS-Server eingerichtet und erreichbar ist, kann die Verbindung zum Repository
in Eclipse eingerichtet werden. Die Verbindungen werden in der Perspektive CVS REPOSI-
TORY EXPLORING eingerichtet und verwaltet. Durch Rechtsklick im linken Fenster und Aus-
wahl von NEW|REPOSITORY LOCATION wird ein Wizard gestartet.
Hier werden die konkreten Verbindungsparameter eingestellt. Die ersten Einträge sind der
Name oder die IP-Adresse des Servers und der Pfad zum CVS-Repository. Die Authentifi-
zierung benötigt den Namen und das Passwort des Benutzers, der bereits auf dem CVS-Ser-
ver eingerichtet sein muss. Mit der Option VALIDATE CONNECTION ON FINISH wird sofort die
Korrektheit der Parameter geprüft, indem eine Verbindung aufgebaut wird. Schlägt der Ver-
bindungsaufbau fehl, gibt es eine Fehlermeldung und man kann entscheiden, ob die Para-
meter korrigiert werden sollen oder trotzdem verwendet werden (z.B. wenn der Server tat-
sächlich nicht verfügbar ist). Ferner besteht die Möglichkeit, das CVS-Benutzerpasswort
zu speichern, was bequem ist, aber gegebenenfalls als Sicherheitsrisiko angesehen wird.
Nach dem Erstellen der Verbindung wird diese im linken Fenster angezeigt, wobei sich der
Name aus den mitgegebenen Parametern zusammensetzt. Dies kann durch einen eigenen
Namen ersetzt werden. Mit einem Rechtsklick auf die Verbindung kann die Auswahl PRO-
PERTIES erreicht werden, hier lassen sich die Verbindungsdetails einsehen und verändern.

1. Zum Einrichten des Servers und allgemeiner Informationen s. z.B. http://ximbiot.com/cvs/cvshome/docs/

148
eclipse_v01.book Seite 149 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

Abb. 5.4: Anlegen einer Verbindung zum CVS-Server

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.

Projekt mit CVS-Unterstützung starten


Nach dem Aufbau der Verbindung gibt es üblicherweise zwei Möglichkeiten für den nächs-
ten Schritt: Entweder man möchte an einem bereits auf dem CVS-Server bestehenden Pro-
jekt mitarbeiten oder man möchte ein lokal begonnenes Projekt in das CVS-Repository
übertragen.
Ersteres wird durch Eclipse dadurch unterstützt, dass man durch Expandieren des Baums
zur Verbindung einen Einblick in das CVS-Repository erhält. Auf oberster Ebene enthält
der Baum vier Äste:
쐌 HEAD zeigt die bereits im CVS abgelegten Projekte an. CVSROOT ist der zentrale An-
kerpunkt jedes CVS-Repository, hier sind CVS-interne Dateien abgelegt, mit denen der
Programmierer im Normalfall nichts zu tun hat. Weiterhin wird hier die Verzeich-
nisstruktur des Repository angezeigt, wobei Dateinamen jeweils um letzte, aktuelle
Versionsnummern erweitert sind. Die oberste Ebene zeigt die CVS-Module an, typi-
scherweise entsprechen diese den vorhandenen Projekten.

149
eclipse_v01.book Seite 150 Montag, 30. Januar 2006 12:02 12

Build Management und Versionierung

쐌 BRANCHES gibt einen Überblick zu bestehenden Verzweigungen („Branch“). Darunter


versteht man eine Technik im CVS, welche parallele Entwicklungsstränge unterstützt.
쐌 VERSIONS erlauben einen Überblick zu mit einem Tag versehenen, d.h. gekennzeichneten
Versionen. Durch Vergleich der Versionsnummern von Dateien kann man erkennen,
dass es sich hierbei um ältere, fixierte Stände handelt.
쐌 DATES erlaubt einen Überblick über datumsbezogene Kennzeichnungen („Date Tags“).

Abb. 5.5: Properties und CVS-Struktur

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

5 – Build Management mit Eclipse

쐌 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

Build Management und Versionierung

Arbeiten mit CVS und Eclipse


Auf den ersten Blick dürfte man keinen Unterschied bei der Projektarbeit mit oder ohne
CVS feststellen. Dateien und Verzeichnisse können wie gehabt angelegt, editiert oder ge-
löscht werden und es ist auch nicht notwendig, ständig Verbindung zum CVS-Server zu be-
halten.
Allerdings ist CVS ein passives System, d.h., es geschieht nichts (sehr wenig) ohne Zutun
des Programmierers (was aber bei den meisten CVS-Systemen üblich ist). Jeder ist schon
selbst dazu angehalten, sich regelmäßig um einen Abgleich zu kümmern.
Wird im Navigator durch Rechtsklick auf ein Projekt, einen Ordner oder eine Datei die
Auswahl TEAM getroffen, so geben die oberen drei Punkte die wichtigsten bzw. häufigsten
Aktionen wieder. Diese sind:
쐌 UPDATE: Mit dieser Aktion wird die aktuelle Version vom CVS-Repository an den
Client übertragen und die von dem Programmierer durchgeführten Änderungen werden
eingefügt. Dies geschieht normalerweise automatisch, es können jedoch Konflikte auf-
treten, die sich durch den Algorithmus nicht auflösen lassen. In diesem Fall werden die
beiden Versionen im Vergleich angezeigt und der Programmierer ist gefragt, den Kon-
flikt selbst aufzulösen.
Mit UPDATE übernimmt ein Teammitglied die Änderungen, welche die anderen Mit-
glieder in das Repository übertragen haben. Dies sollte regelmäßig erfolgen, denn je
kürzer die Abstände zwischen den Update-Befehlen sind, desto geringer ist die Wahr-
scheinlichkeit von Konflikten.
쐌 COMMIT: Mit dieser Aktion überträgt der Programmierer seine Änderungen in das Re-
pository und es wird eine neue Version der Datei erzeugt. Zusätzlich muss ein Kommen-
tar zur Änderung gegeben werden.
Hierbei wird ebenfalls verglichen, ob nicht zwischenzeitlich eine andere Version auf
dem Server eingespielt wurde und ein Konflikt besteht. Der Befehl wird nur ausge-
führt, wenn die lokale Kopie auf der letzten Server-Version der Datei beruht. Deshalb
kann es ratsam sein, zuerst ein UPDATE aufzurufen und auftretende Konflikte zu bear-
beiten, bevor die eigenen Änderungen mit einem COMMIT übertragen werden.
Während ein UPDATE im Prinzip ungefährlich ist (sofern die anderen Teammitglieder keine
schwerwiegenden Fehler machen), ist das Ausführen des COMMIT-Befehls kritischer: Die
Änderungen können unvollständig sein oder Fehler enthalten und damit andere Teammit-
glieder in ihrer Arbeit behindern. Man kann daher als Faustregel „So oft wie möglich, so
selten wie nötig“ formulieren: Die Änderungen zwischen zwei COMMIT-Aufrufen sollten
nicht zu groß, vor allem aber in sich abgeschlossen und lauffähig (mindestens kompilier-
fähig, möglichst aber bereits in ihrer Funktion getestet) sein.
Diese beiden Befehle sind Kernbestandteil aller CVS-Clients. Eclipse bietet zusätzlich ei-
nen dritten Auswahlpunkt:
쐌 SYNCHRONIZE WITH REPOSITORY: Dies ist eine separate Perspektive, die eine Übersicht
und Details zu den Unterschieden der lokalen Kopie gegenüber den Versionen des Re-
pository bietet. Es handelt sich hierbei um eine Verbindung der beiden Kernaufgaben

152
eclipse_v01.book Seite 153 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

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.

Abb. 5.6: Synchronize Perspective

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

Build Management und Versionierung

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

5 – Build Management mit Eclipse

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

Build Management und Versionierung

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

5 – Build Management mit Eclipse

쐌 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.

Trennen der Verbindung


Schließlich sei noch vermerkt, dass man auch die lokale Kopie eines Projekts wieder von
der CVS-Verwaltung abtrennen kann. Dies kann zum endgültigen Abschluss der Arbeit er-
folgen oder wenn z.B. der Server, auf dem das CVS betrieben wird, gewechselt wird. CVS
erzeugt auf dem Client zusätzliche Dateien mit internen Informationen („Metadaten“), u.a.
auch über die Server-Verbindung, so dass ein Wechsel des Servers nicht einfach durch Än-
derung der Verbindungsdaten erfolgen kann.
Zum Trennen der Verbindung wird im Navigator oder Explorer mit Rechtsklick zum Pro-
jekt die Auswahl TEAM|DISCONNECT getroffen. Ein Popup fragt nach, ob die CVS-Metadaten
gelöscht oder beibehalten werden sollen. Werden die Daten beibehalten, so ist es recht ein-
fach möglich, zu einem späteren Zeitpunkt die Verbindung zum Server wieder herzustellen
und die Dateien zu synchronisieren. Umgekehrt haben diese Metadaten ohne den Server
keine Bedeutung bzw. behindern das Anbinden an einen anderen CVS-Server.
Mit diesen Ausführungen ist der Exkurs zum Thema CVS beendet. Es wurden die wesent-
lichen Arbeitsschritte für die Verwendung von CVS in Eclipse erläutert. Für weiterführende
Informationen stehen frei verfügbare Quellen und Fachliteratur zur Verfügung. Im Folgen-
den wird CVS im Rahmen des Build Managements weiter betrachtet. Diesen Exkurs möch-
ten wir aber mit folgenden Hinweisen abschließen:
쐌 Für jede Softwareentwicklung, selbst bei kleinen Projekten und einzelnen Entwicklern,
ist eine Versionsverwaltung sehr ratsam, wenn nicht fast überlebenswichtig! Egal, ob
man auf ältere Stände zurückgreifen möchte oder parallele Entwicklungen betreibt, ein
geeignetes Tool kann hier viel Zeit, Aufwand und Ärger ersparen. Mit CVS steht ein
etabliertes Open-Source-Werkzeug zur Verfügung, dessen Einbindung in Eclipse pro-
blemlos und komfortabel ist.
쐌 Für die tägliche Arbeit stellt die Verwendung von CVS einen marginalen Zusatzauf-
wand dar, der sehr schnell vom Nutzen (z.B. einfacher Abgleich der Dateien im Team)
übertroffen wird.
쐌 Dennoch ist CVS nur ein Werkzeug und kein Allheilmittel: Zu seiner effizienten Nut-
zung im Projekt bedarf es Spielregeln (z.B. „Was gehört ins CVS, was nicht?“ oder
„Wann wird ein COMMIT ausgeführt?“) und organisatorischer Regelungen (z.B. „Wer
bearbeitet welchen Programmteil?“, „Was gehört zu welcher Version?“, „Was wird
parallel entwickelt?“).

157
eclipse_v01.book Seite 158 Montag, 30. Januar 2006 12:02 12

Build Management und Versionierung

5.4.2 Versionierung und Build Management


Schon bei der Frage „Können wir das Programm noch einmal in der Version 2.1 erstellen?“
wird klar, dass Build Management und Versionierung eng miteinander verknüpft sind. Zu-
nächst soll deshalb beschrieben werden, welche Bedingungen sich aus der Kombination der
beiden Aspekte für die jeweilige Gestaltung der Versionierung und des Build Managements
ergaben.
Betrachten wir zunächst, welche Zusatzbedingungen sich aus dem Build Management
heraus für das CVS ergeben:
쐌 Zu einer Auslieferung eines Programms können wesentlich mehr Dateien gehören als
im zugehörigen Java-Projekt bearbeitet werden: Dies können Ergebnisse anderer Pro-
jekte sein, grafische Elemente oder auch Dokumente wie Handbücher und Anleitungen.
Hier ist zu entscheiden, ob diese ebenfalls im CVS abgelegt werden oder anderweitig
verwaltet werden sollen. Als einfache Faustregel kann hier gelten: Alles, was bestimm-
ten Versionen zugeordnet ist, gehört auch ins CVS.
쐌 Weiterhin stellt sich die Frage, wie mit verwendeten Bibliotheken oder Programmen
umgegangen wird. Einerseits sind dies binäre Dateien, die sich wohl kaum jemals ver-
ändern, andererseits kann (z.B. bei langlebigen Projekten) sehr wohl eine Abhängigkeit
zur Programmversion bestehen. Generell möchten wir empfehlen, alles, was zu einer
Auslieferung gehört, auch zusammenhängend (sprich in CVS) abzulegen und zu ver-
walten. Ausnahmen ergeben sich aus zu großen Datenmengen insbesondere in Hinblick
auf die Datenübertragung zwischen Server und Client. Ein möglicher Kompromiss
kann hier sein, solche Dateien an einem von allen Teammitgliedern erreichbaren Ort
(z.B. ein Netzwerkfilesystem) abzulegen und im CVS eine Konfigurationsdatei anzule-
gen und zu pflegen, die genau beschreibt, welche Dateien zu welcher Version gehören.
쐌 Schließlich ist es noch ratsam, auch die Eclipse-Projektdateien im CVS zu verwalten.
(Dies geschieht schon automatisch, wenn ein Eclipse-Projekt komplett als CVS-Modul
angelegt wird.) Insbesondere die oben beschriebenen Build-Einstellungen stehen dann
jeweils zur passenden Version zur Verfügung.
Umgekehrt hat die Benutzung von CVS auch Einfluss auf die Struktur und Prozesse im
Build Management:
쐌 So ist es ratsam, den Compiler Output Path auf ein Verzeichnis zu legen, das nicht unter
CVS-Kontrolle steht. Zum einen kann CVS nicht gut mit den binären Dateien umgehen,
zum anderen wird so vermieden, dass mögliche inkonsistente Stände von .class-Dateien
ins CVS übertragen und so „verewigt“ werden. Ähnliches gilt für JavaDoc-Stände, auch
wenn es sich um Textdateien handelt, die somit wesentlich effizienter verwaltet werden.
쐌 Alle Angaben wie Pfade oder Verweise (Links) müssen so erfolgen, dass sie auf allen
Clients gültig sind. Dies ist entweder durch eine verbindliche Vereinbarung sicherzu-
stellen oder es werden alle Angaben relativ zu einem Projekt-Hauptverzeichnis getrof-
fen. Letzteres ist in jeden Fall vorzuziehen: Es entspricht dem Eclipse-Workspace-Kon-
zept, ist flexibler und weniger fehleranfällig.
쐌 Für Dokumente wie Handbücher oder Anleitungen ist zu überlegen, ob ein Format ge-
wählt werden kann, welches in CVS effizient verwaltet wird: Während eine Word-Datei

158
eclipse_v01.book Seite 159 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

(normalerweise) als binär behandelt wird, werden HTML-Dateien wesentlich besser


unterstützt.
Sind diese Aspekte entsprechend geklärt und ist das Projekt so eingesetzt und konfiguriert,
dass es komplett im CVS-Repository enthalten ist, so besteht ein Build-Prozess im Prinzip
aus den folgenden Schritten:
1. CLEAR PROJECT: Die lokale Umgebung sollte für das Build möglichst frei sein. Am bes-
ten wird der vorhandene Stand des Projekts gesichert und das Projekt komplett gelöscht.
(Alternativ kann auch ein separater Workspace verwendet werden.)
2. CHECK OUT: Das Projekt wird in der gewünschten Version vom CVS-Repository ange-
fordert (siehe Seite 149).
3. BUILD: Mit der Auswahl PROJECT|BUILD ALL werden alle Dateien kompiliert und gege-
benenfalls JavaDoc erzeugt.
4. TEST: Die soeben erstellte Version wird, z.B. durch Aufrufen von JUnit-Tests, auf ihre
Korrektheit geprüft.
5. DEPLOY: Aus der lokalen Version wird ein Deployment-Paket zusammengestellt und zur
Auslieferung gebracht.
6. CLEAN UP: Mögliche Änderungen, z.B. Fehlerkorrekturen, werden an das CVS-Reposi-
tory übertragen. Anschließend wird die Umgebung wieder in den Ausgangszustand zu-
rückversetzt.
Mit den bisherigen Darstellungen zum Build Management kann dieser Prozess schon mit
den Eclipse-internen Mitteln aufgesetzt und zum Teil automatisiert durchlaufen werden.
Für kleine bis mittlere Projekte mit durchschnittlichen Anforderungen kann dies vollkom-
men ausreichen. Sollten jedoch die einzelnen Phasen komplexer werden oder zusätzliche
Anforderungen umgesetzt werden, kann der Einsatz von flexibleren und leistungsfähigeren
Build-Management-Werkzeugen sinnvoll werden. Dies wird von Eclipse schon durch die
Einbindung des Build-Management-Tool Ant aktiv vorbereitet und im nun folgenden Ab-
schnitt vorgestellt.

5.5 Exkurs: Build Management mit Ant


Nachdem bisher auf die Eclipse-interne Unterstützung des Build eingegangen wurde,
möchten wir nun die Tool-zentrierte Sicht etwas zurücknehmen und die Aufgaben des
Build Managements allgemein betrachten. Dabei soll der Praxisbezug nicht verloren ge-
hen, daher werden Beispiele und Anregungen auf Basis von Ant beschrieben und auch de-
ren Einbindung in Eclipse wird nicht vergessen.
Wenn das Programm, das wir in Eclipse bearbeiten, auf dem gleichen Rechner bzw. auf ei-
nem zugreifbaren Dateisystem betrieben wird, können wir das Build mit der Auslieferung
verbinden, indem wir in Eclipse als Zielverzeichnis des Build direkt das vorgesehene Ab-
lagesystem angeben. Dies ist nur dann ratsam, wenn wir das Programm praktisch allein ent-
wickeln und betreiben. Meist ist es die bessere Lösung, zunächst mit einer lokalen Instal-
lation zu arbeiten und die Übertragung auf das Zielsystem separat ausführen zu lassen.
Hierzu möchten wir Ant als Tool für das Build Management vorstellen.

159
eclipse_v01.book Seite 160 Montag, 30. Januar 2006 12:02 12

Exkurs: Build Management mit Ant

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

5 – Build Management mit Eclipse

쐌 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.

5.5.1 Ant Projects, Targets und Tasks


Um ein Build durch Ant ausführen zu lassen, muss eine Konfigurationsdatei erstellt werden,
welche alle notwendigen Informationen und Prozessschritte enthält. Diese Datei wird als
XML-Datei erstellt, deren Hauptelement (Root) ein Project in Ant definiert. Unter einem
Project in Ant können wir uns einfach die Build-Aufgaben zu einem Eclipse-Projekt vor-
stellen. Es besteht aus einer Reihe von Targets, welche ein bestimmtes Teilziel des Build-
Prozesses definieren, z.B. das Kompilieren eines Pakets oder das Erstellen eines JavaDoc-
Dokuments. Will man ein Build oder Teilaufgaben hiervon ausführen, so wird das entspre-
chende Target aufgerufen. Für das Project wird ein Target als Default ausgezeichnet, d.h.,
dieses Target wird ausgeführt, wenn keine weiteren Angaben erfolgen.
Die Targets ihrerseits bestehen aus Tasks, in denen einzelne Befehle zur Erreichung des
Ziels definiert sind. So kann z.B. ein Target die Erstellung einer .jar-Datei sein, welches aus
den Tasks zum Kompilieren von Quelldateien, zum Kopieren in ein Verzeichnis und zum
Zusammenfassen zur .jar-Datei besteht. Die Targets können untereinander durch Abhän-
gigkeiten verknüpft werden; wird also ein Target aufgerufen, so werden automatisch auch
die Targets ausgeführt, von denen es abhängt.
Zusätzlich können Variablen, so genannte Properties, definiert werden, die bestimmte Wer-
te wie Verzeichnisnamen enthalten. Diese können global oder innerhalb eines Target ge-
setzt werden.

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

Exkurs: Build Management mit Ant

Der folgende Code-Auszug zeigt die wesentliche Struktur einer Konfigurationsdatei:

<project name="MeinBeispiel" default="alles" basedir=".">


<description> Einfaches Beispiel zur Struktur einer
Konfiguration. Mit basedir wird das
Hauptverzeichnis definiert.
</description>
<!-- Hier werden einige globale Properties definiert -->
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<!-- Erzeuge ein Verzeichnis zum Erstellen des Builds und lese
das aktuelle Projekt aus dem CVS Repository -->
<mkdir dir="${build}"/>
<cvs cvsRoot=":pserver:herbert@localhost:/home/cvs"
package="myProject" dest="${build}"/>
</target>
<target name="compile" depends="init"
description="kompiliert den Code">
<!-- Kompiliert den Code aus ${src} und legt in ${build} ab -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile"
description="Erstellt eine Distribution">
<!-- Erstellt ein neues Verzeichnis fuer Distribution, legt das
Kompilat in einem .jar-File dort ab -->
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/MyProject.jar" basedir="${build}"/>
</target>
<target name="clean" depends="init"
description="Löscht alle erzeugten Verzeichnisse">
<delete dir="${build}"/>
<delete dir="${dist}/lib"/>
</target>
<target name="alles" depends="dist clean"
description="vollstaendige distribution">
<!-- Distribution wird durch Abhaengigkeit erstellt, hier wird
noch das temporaere Verzeichis aufgeraeumt -->
<delete dir="${build}"/>
<echo message="alles erstellt und build-Verzeichnis
aufgeraeumt!"/>
</target>
</project>

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

5 – Build Management mit Eclipse

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.

5.5.2 Typische Ziele


Wenn man eine Reihe von (unabhängig voneinander entstandenen) Ant-Skripten liest, fällt
schnell auf, welche Aufgaben sich immer wiederholen und welche Targets somit wieder-
kehren. Es ist daher zu Beginn eines Projekts sehr sinnvoll, darauf zu achten, dass diese Tar-
gets sauber konzipiert und formuliert sind. Häufig wird es im Laufe des Projekts auch nicht
bei einem Ant-Skript bleiben. Daher sollte auch an die Wiederverwendung oder das Bereit-
stellen von Templates für diese Standardaufgaben gedacht werden. Immer wiederkehrende
Aufgaben, welche wir durch typische Namen für ihre Targets markieren, sind:
쐌 INIT oder CONFIGURE: Hier werden globale Einstellungen getroffen wie das Festle-
gen von Quell- und Zielverzeichnissen, die Auswahl des Compilers usw. Häufig werden
auch temporäre Verzeichnisse angelegt, die im Laufe des Build verwendet werden. Dies
wird auch gerne benutzt, um einen Versionsnamen oder Zeitstempel für das Ergebnis
anzulegen.
쐌 CLEANUP: Diese Aufgabe ist in gewisser Weise das Gegenteil zu INIT. Hier werden
temporär verwendete Dateien und Verzeichnisse wieder gelöscht und das System in ei-
nen definierten Zustand zurückgesetzt.
쐌 PREPARE: Diese Aufgabe schafft den definierten Ausgangsstatus für das Ausführen
des Build. Ein typischer Task an dieser Stelle ist das Beziehen der Quelldateien z.B. aus
dem CVS Repository. Dieser Punkt kann recht heikel werden, wenn zum Beispiel meh-
rere Stufen des Versionsstatus („alpha“, „beta“, „final“ oder „experimentell“, „stabil“,
„freigegeben“) erstellt werden sollen. Hier setzt ein erfolgreiches Build Management
auf jeden Fall eine saubere Versionsverwaltung voraus.
쐌 COMPILE: Diese Aufgabe übernimmt die Kernarbeitsschritte zur Erzeugung der Ziel-
dateien, seien es Klassenverzeichnisse, Libraries oder andere Ausgabedateien.
쐌 DEPLOY: Diese Aufgabe führt das Bereitstellen zum Deployment oder das Deploy-
ment selbst auf einer Zielumgebung aus. Bei einer Bereitstellung kann hier auch eine
Benachrichtigung über den ausgeführten Schritt erfolgen. Wird ein Deployment auf ei-

163
eclipse_v01.book Seite 164 Montag, 30. Januar 2006 12:02 12

Exkurs: Build Management mit Ant

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.

5.5.3 Ein Ant-Beispielskript


Nachfolgend ein kurzes Skript, das die genannten Ziele mit einfachen Anweisungen gefüllt
enthält:

<project name="MeinBeispiel" default="all" basedir=".">


<description> Einfaches Beispiel zu einem vollstaendigen Build
und Deployment. Es wird eine Version aus CVS ausgecheckt
und eine Test- bzw. Auslieferungsversion erstellt.
Eine Nachricht wird mittels des MailLoggers abgeschickt.
Das Skript soll daher mit der Option
"-logger org.apache.tools.ant.listener.MailLogger"
gestartet werden.
</description>
<!-- Hier werden einige globale und zielabhaengige Properties
definiert -->
<target name="initForTest" if="forTest" unless="forDist">
<!-- Initialisierung fuer Testbetrieb. Diese wird ausgefuehrt,
wenn ANT mit der Option '-DforTest' aufgerufen wird-->
<property name="TARGET_NAME" value="TestUmgebung"/>
<property name="TEST_INIT" value="true" />
<echo message="Initialisierung Test-Version durchgefuehrt!"/>
</target>

164
eclipse_v01.book Seite 165 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

<target name="initForDist" if="forDist">


<!-- Initialisierung fuer Auslieferung. Diese wird ausgefuehrt,
wenn ANT mit der Option '-DforDist' aufgerufen wird-->
<property name="TARGET_NAME" value="Produktivumgebung"/>
<property name="DIST_INIT" value="true" />
<echo message="Initialisierung Auslieferung ausgefuehrt"/>
</target>
<target name="initReportForTest" if="TEST_INIT">
<!-- Initialisierung des Reports fuer Testbetrieb. Diese wird
ausgefuehrt, wenn ANT mit der Option
'-DforTest' aufgerufen wird-->
<property name="MailLogger.from" value="Ant Build Skript"/>
<property name="MailLogger.failure.to"
value="BuildManager@myproject.xxx, Programmer@myproject.xxx"/>
<property name="MailLogger.failure.subject"
value="Fehler beim Build der Testversion"/>
<property name="MailLogger.success.to"
value="BuildManager@myproject.xxx, Tester@myproject.xxx"/>
<property name="MailLogger.success.subject"
value="Neue Testversion erfolgreich erstellt"/>
<echo message="Initialisierung fuer Report der Test-Version
durchgefuehrt!"/>
</target>
<target name="initReportForDist" if="DIST_INIT">
<!-- Initialisierung des Reports fuer eine Distribution. Diese
wird ausgefuehrt, wenn ANT mit der Option
'-DforDist' aufgerufen wird-->
<property name="MailLogger.from" value="Ant Build Skript"/>
<property name="MailLogger.failure.to"
value="BuildManager@myproject.xxx, Programmer@myproject.xxx"/>
<property name="MailLogger.failure.subject"
value="Fehler beim Build der neuen Version"/>
<property name="MailLogger.success.to"
value="BuildManager@myproject.xxx, Nutzer@myproject.xxx"/>
<property name="MailLogger.success.subject"
value="Neue Version erfolgreich erstellt"/>
<echo message="Initialisierung fuer Report zur Distribution
durchgefuehrt!"/>
</target>
<target name="initReport"
depends="initReportForTest, initReportForDist">
<!-- Hier koennen fuer alle Versionen geltende Parameter, z.B.
die weiteren Mail-Parameter definiert werden -->
<echo message="Initialisierung fuer Report abgeschlossen!"/>
</target>
<target name="init"
depends="initForTest, initForDist, initReport">

165
eclipse_v01.book Seite 166 Montag, 30. Januar 2006 12:02 12

Exkurs: Build Management mit Ant

<!-- allgemeine Initialisierung, z.B. Setzen von Parametern,


die von der gewählten Version unabhängig sind.-->
<property name="src" location="temp/src"/>
<property name="build" location="temp/build"/>
<mkdir dir="${src}"/>
<mkdir dir="${build}"/>
<tstamp prefix="start">
<echo message="Initialisierung abgeschlossen!"/>
</target>
<target name="prepare" depends="init"
description="Vorbereitungen zum Kompilieren">
<!-- Bezieht den Code aus dem CVS Repository und legt ihn in
${src} ab -->
<cvs cvsRoot=":pserver:cvsname@cvs.projektserver.de:/home/cvs"
package="mypackage" dest="${src}" failonerror="false" />
<echo
message="Vorbereitung zur Versionserstellung abgeschlossen!"/>
</target>
<target name="compile" depends="prepare"
description="kompiliert den Code">
<!-- Kompiliert den Code aus ${src} und legt in ${build} ab -->
<javac srcdir="${src}" destdir="${build}"
failonerror="true" />
<available file="myProject/output.class"
property="Myclass.present"/>
<echo message="Kompilierung der Version abgeschlossen!"/>
</target>
<target name="javadoc" depends="prepare"
description="Erstellung der automatischen Dokumentation ">
<javadoc sourcepath="${src}" destdir="${build}" />
<echo message="Javadoc fuer Version erstellt!" />
</target>
<target name="failedTest" depends="compile"
unless="Myclass.present"
description="beendet die Ausfuehrung wenn das Kompilat
unvollständig ist">
<fail message="Build nach Kompilierfehler abgebrochen!"/>
</target>
<target name="test" depends="compile, failedTest"
description="testet das Kompilat">
<!-- Hier koennen z.B. JUnit-Tests gestartet und ausgewertet
werden -->
<echo message="Test der Version abgeschlossen!"/>
</target>
<target name="deployForTest" if="TEST_INIT"
description="Auslieferung einer Testversion">
<!-- Erstellt ein neues Verzeichnis fuer eine Test-Version, legt
das Kompilat in einem .jar-File dort ab -->

166
eclipse_v01.book Seite 167 Montag, 30. Januar 2006 12:02 12

5 – Build Management mit Eclipse

<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

Exkurs: Build Management mit Ant

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

5 – Build Management mit Eclipse

쐌 Im compile-Target ist die folgende Zeile gesetzt:


<available file="myProject/output.class"
property="Myclass.present"/>
Diese bewirkt das Setzen der Property Myclass.present auf den Wert true, falls
die genannte Datei gefunden wird. Hier wird diese Anweisung als einfache Fehler-
erkennung zum Kompiliervorgang verwendet (wobei es sicherlich bessere Methoden
gibt). Wenn diese Property nicht gesetzt wird, wird das Target failedTest ausge-
führt, das durch die Zeile
<fail
message="Build Prozess nach Kompilierfehler abgebrochen!"/>
das Build mit einer Nachricht abbricht.

5.5.4 Ant in Eclipse: externe Builds


Wir möchten diesen Ausflug zu Ant und zum Build Management mit der Zusammenfüh-
rung von Ant und Eclipse abschließen und zeigen, wie Eclipse die Verwendung von Ant als
„externes Build“ unterstützt.
Als externe Builds werden in Eclipse alle Werkzeuge und Methoden bezeichnet, die ein
Build auf eine andere als in Abschnitt 5.3 beschriebene Weise erzeugen. Eine Methode
hierzu haben wir bereits in Abschnitt 5.3.4 kennen gelernt. Wenn nämlich eine SHARED
CONFIGURATION erstellt wurde, d.h., eine Konfiguration zum Build für die gemeinsame Nut-
zung durch andere Teammitglieder bereitgestellt wurde, so kann diese von dem Team als
externes Build eingelesen und verwendet werden.

Abb. 5.7: Aufruf eines Ant Build-Skripts

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

Exkurs: Build Management mit Ant

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.

Abb. 5.8: Konfiguration eines Ant 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

5 – Build Management mit Eclipse

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

Exkurs: Build Management mit Ant

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 – Build Management mit Eclipse

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

6 GUI-Design mit Eclipse

von Dr. Birgit Schwartz-Reinken

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

Der Visual Editor für Java

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.

6.2 Der Visual Editor für Java


Das Eclipse-Projekt Visual Editor stellt ein Framework bereit, um GUI Builder für Eclipse
zu entwickeln. Es gibt Referenzimplementationen für Swing und SWT GUI Builder. Mit
dem Framework können aber auch GUI Builder für andere Programmiersprachen entwi-
ckelt werden. Wir betrachten im Folgenden die Referenzimplementation für Java.
Der Visual Editor für Java ermöglicht das visuelle Entwerfen von GUIs, die AWT- und
Swing- sowie SWT-Komponenten beinhalten. Er wurde als Subprojekt des Eclipse-Tools-
Projekts entwickelt und steht als Download auf www.eclipse.org/vep mit seinem gesamten
Funktionsumfang als Open-Source-Produkt zur Verfügung. Eine Dokumentation ist eben-
falls kostenlos verfügbar. Sie wird beim Installieren in die Eclipse-Hilfe integriert.
Im Folgenden wird die Version 1.1.0.1 betrachtet, die unter Eclipse 3.1 lauffähig ist.

6.2.1 Installation und Aufruf


Zum Installieren des Visual Editors muss für die hier betrachtete Version 1.1.0.1 die Datei
VE-runtime-1.1.0.1.zip in das Eclipse-Verzeichnis entpackt werden. Hierbei ist zu beach-
ten, dass die in der zip-Datei gespeicherten Pfadangaben verwendet werden. War die Instal-
lation erfolgreich, so erscheint nach dem Starten von Eclipse unter HELP | ABOUT ECLIPSE
SDK | PLUG-IN DETAILS das Visual Editor-Plugin. Sollten das Eclipse Modeling Framework
(EMF) und das Graphical Modeling Framework (GEF) nicht installiert sein, müssen darü-
ber hinaus noch die Dateien GEF-runtime-3.1.1.zip und emf-sdo-runtime-2.1.1.zip in das

176
eclipse_v01.book Seite 177 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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.

Abb. 6.1: Integration des Visual Editors in Eclipse

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 Visual Editor für Java

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.

6.2.2 Hinzufügen von Komponenten


Die mithilfe des Visual Editors einfügbaren Komponenten sind in der Palette in verschie-
denen Kategorien zusammengefasst. Wird bei der Erstellung einer Klasse für ein GUI
unter FILE | NEW | OTHER | JAVA | VISUAL CLASS | STYLE ein AWT- oder Swing-Eintrag aus-
gewählt, werden nur die vier Kategorien Swing Components, Swing Containers, Swing
Menus und AWT Controls angezeigt. Bei Auswahl eines SWT-Eintrags dagegen werden
zusätzlich die drei Kategorien SWT Controls, SWT Containers und SWT Menus zur Ver-
fügung gestellt.
Bevor wir eine Komponente einem Container hinzufügen können, müssen wir zunächst die
gewünschte Komponente in der Palette anwählen. Hierzu gehen wir mit der Maus auf die
Palette. Nach einem kurzen Moment wird diese aufgeklappt und wir müssen dann, falls die
Komponenten einer Kategorie nicht angezeigt werden, zuvor auf die Kategorie klicken –
nochmaliges Klicken klappt die Kategorie wieder zu –, bevor wir die gewünschte Kompo-
nente anwählen können. Darüber hinaus lässt sich auch in der Palette der Befehl CHOOSE
BEAN anwählen und im daraufhin erscheinenden Fenster der gewünschte Klassenname ein-
geben. Der Stern * als Platzhalter ist hierbei möglich. Die Eingabe Button* liefert z.B. eine
Liste aller Klassen, deren Name mit Button beginnt. Hier können wir dann eine Klasse
auswählen. Durch Klicken auf den OK-Button müssen wir anschließend die Wahl bestä-
tigen.
Die angewählte Komponente kann jetzt entweder in der Design View oder in der Java
Beans View einer bestehenden Komponente hinzugefügt werden. Zum Hinzufügen in der
Design View bewegen wir die Maus, ohne die linke Maustaste gedrückt zu halten, an die
Position in der Design View, an der die neue Komponente platziert werden soll, und fügen
sie durch einen Klick ein.
Zum Hinzufügen in der Java Beans View wird die Maus zunächst in den Baum bewegt. Die
aktuelle Position wird hierbei durch eine dicke horizontale Linie angezeigt, bei der der An-
fang der Linie die Hierarchieebene wiedergibt. Ist die gewünschte Position erreicht, wird
die linke Maustaste losgelassen.

178
eclipse_v01.book Seite 179 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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.

6.2.3 Entfernen von Komponenten


Alle Komponenten lassen sich in der Java Beans View entfernen, indem sie dort angeklickt
und mithilfe der ¢-Taste, über den DELETE-Button in der Werkzeugleiste oder den
DELETE-Befehl im Kontextmenü gelöscht werden. Die meisten Komponenten können wir
darüber hinaus auch direkt in der Design View entfernen. Hierzu wird die Komponente dort
angeklickt und mit der ¢-Taste gelöscht.

6.2.4 Ändern von Eigenschaften einer Komponente


Einige Eigenschaften von Komponenten lassen sich direkt in der Design View verändern.
So kann beispielsweise die Größe geändert werden, indem die Komponente angeklickt
wird und dann an den Markern gezogen wird. Die Position lässt sich dadurch ändern, dass
wir mit der Maus auf die Komponente gehen und dann bei gedrückt gehaltener linker Maus-
taste die Maus auf die gewünschte Position der Komponente bewegen. Für Beschriftungen
bei Buttons, Checkboxen usw. wird die Komponente, die eine Beschriftung erhalten soll
oder deren Beschriftung geändert werden soll, angeklickt und anschließend noch einmal
geklickt, um ein Texteingabefeld zu erhalten.
Alle Eigenschaften, auch die direkt in der Design View veränderbaren Eigenschaften, las-
sen sich in der Properties View einstellen. Hierfür gibt es drei verschiedene Möglichkeiten:
쐌 Für einige Eigenschaften können die Einstellungen direkt in der Spalte VALUE vorge-
nommen werden.
쐌 Bei einigen Eigenschaften können wir, wenn wir in die Spalte VALUE klicken, eine Liste
mit möglichen Einstellungen öffnen, von denen eine ausgewählt werden kann.
쐌 Für einige Eigenschaften lässt sich ein so genannter Java Property Editor öffnen. In die-
sem Fall muss für die gewählte Eigenschaft in der Spalte VALUE rechts das Symbol
erscheinen. Java Property-Editoren existieren für die Auswahl von Schriften, Farben,
Rahmen und Icons. In der Abb. 6.2 findet sich exemplarisch der Property Editor für
Schriften.

179
eclipse_v01.book Seite 180 Montag, 30. Januar 2006 12:02 12

Der Visual Editor für Java

Abb. 6.2: Der Property Editor für Schriften

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

6 – GUI-Design mit Eclipse

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.

Abb. 6.3: Ausrichtungsmöglichkeiten im Customize Layout-Fenster

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

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.

6.3 Besonderheiten bei der Erstellung eines GUI mit Swing-


Komponenten
Nachdem wir in den Abschnitten 6.2.1 bis 6.2.6 die allgemeine Funktionsweise des Visual
Editors erklärt haben, wollen wir im Folgenden diejenigen Punkte aufzeigen, die unter-
schiedlich sind, je nachdem ob ein GUI mit AWT- bzw. Swing-Komponenten oder ein GUI
mit SWT-Komponenten erstellt wird. Wir beginnen unsere Betrachtung mit den Besonder-
heiten für AWT/Swing.

182
eclipse_v01.book Seite 183 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

6.3.1 Unterstützte Komponenten


Die einem AWT- oder Swing-Container hinzufügbaren Komponenten sind in der Palette in
vier Kategorien zusammengefasst. Im Einzelnen beinhalten die vier Kategorien die folgen-
den Komponenten:
쐌 Swing Components
JButton, JCheckBox, JTextArea, JList, JTable etc.
쐌 Swing Containers
JFrame, JPanel, JScrollPane, JWindow, JApplet etc.
쐌 Swing Menus
JMenuBar, JToolBar, JMenu, JPopupMenu, JMenuItem etc.
쐌 AWT Controls
Frame, Panel, Button, Label, Checkbox, List, TextField etc.

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.

Abb. 6.5: Customize Layout-Fenster für GridLayout und GridBagLayout

183
eclipse_v01.book Seite 184 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.

Abb. 6.6: Hinzufügen einer Komponente beim GridBagLayout

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

6 – GUI-Design mit Eclipse

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.

private JPanel jContentPane = null;

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.

private JPanel getJContentPane() {


if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
}
return jContentPane;
}

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:

private void initialize() {


this.setSize(300, 200);
this.setContentPane(getJContentPane());
this.setTitle("JFrame");
}

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.

private JButton jButton = null;

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

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

private JButton getJButton() {


if (jButton == null) {
jButton = new JButton();
jButton.setText("OK");
}
return jButton;
}

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.

private JPanel getJContentPane() {


if (jContentPane == null) {
jLabel = new JLabel();
jLabel.setText("JLabel");
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.add(jLabel, java.awt.BorderLayout.NORTH);
jContentPane.add(getJButton(), java.awt.BorderLayout.CENTER);
}
return jContentPane;
}

Das Hinzufügen einer Komponente zu einer anderen Komponente erfolgt in der Getter-Me-
thode der anderen Komponente.

private JPanel getJPanel() {


if (jPanel == null) {
jLabel1 = new JLabel();
jLabel1.setText("JLabel");
jPanel = JPanel();
jPanel.add(jLabel1, null);
jPanel.add(getJSlider(), null);
}
return jPanel;
}

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

6 – GUI-Design mit Eclipse

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.

Abb. 6.7: Ereignisverarbeitung im Visual Editor

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.

Beschreibung des Beispiels


Bei dem Beispiel handelt es sich um ein Swing-Fenster mit Menüleiste und mehreren In-
ternal Frames. Die Menüleiste besitzt drei Menüs – DATEI, ANSICHT, EINSTELLUNGEN. Im
Menü DATEI befindet sich der Befehl BEENDEN zum Beenden der Anwendung. Das Menü
ANSICHT ermöglicht es zum einen, ein Internal Frame zur Dateneingabe zu erzeugen, und
zum anderen ein Internal Frame, welches die bisher eingegebenen Daten in einer tabellari-
schen Übersicht ausgibt.

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

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.

Einrichten des Projekts


Wir erstellen ein Projekt mit dem Namen com.entwickler.eclipsebuch.VEBeispiel. Da die
Quelltext- und die class-Dateien jeweils in einem eigenen Verzeichnis gespeichert werden
sollen, aktivieren wir unter PROJECT LAYOUT den Eintrag CREATE SEPARATE SOURCE AND OUT-
PUT FOLDERS. Nach dem Beenden des Wizards erstellen wir die beiden Packages gui und
daten.

Die Klasse Daten


Bevor wir mit der Implementation der Klassen für das GUI beginnen, erstellen wir im
Package daten eine Klasse Daten, die einen Datensatz repräsentiert. Im Java Editor legen
wir anschließend die Attribute der Klasse Daten fest, implementieren zwei Konstruktoren
und erzeugen über SOURCE | GENERATE GETTERS AND SETTERS die Zugriffsmethoden.

package daten;

public class Daten {


private String kundenNr, kundenName;
public Daten() {}
public Daten(String kundenNr, String kundenName) {
this.kundenNr = kundenNr;
this.kundenName = kundenName;
}
public String getKundenName() { return kundenName; }
public void setKundenName(String kundenName) {
this.kundenName = kundenName;
}

188
eclipse_v01.book Seite 189 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

public String getKundenNr() { return kundenNr; }


public void setKundenNr(String kundenNr) {
this.kundenNr = kundenNr;
}
}

Die Klasse HauptFenster


Die Implementation des GUI beginnen wir nun mit der Implementation der Klasse für das
Hauptfenster. Hierzu wählen wir im Package Explorer das Package gui an und starten über
FILE | NEW | OTHER | JAVA | VISUAL CLASS den New Visual Class Wizard. Als Klassennamen
geben wir im Wizard HauptFenster ein. Des Weiteren wählen wir unter STYLE | SWING
den Eintrag FRAME, so dass unsere Klasse aus der Klasse javax.swing.JFrame abgelei-
tet wird. Außerdem lassen wir uns eine main-Methode generieren.
Nach dem Beenden des Wizards wird automatisch der Visual Editor gestartet. In der Java
Beans View erscheint der Eintrag this für das aktuelle Fenster, in der Design View ein
Fenster mit Titelleiste und in der Properties View werden, wenn der Eintrag this in der
Java Beans View oder das Fenster in der Design View angeklickt worden ist, die Eigen-
schaften des Fensters angezeigt.
Da standardmäßig die Eigenschaft visible für das Fenster auf false gesetzt ist, müssen
wir sie auf true setzen, damit das Fenster auch angezeigt wird. Des Weiteren ändern wir
unter der Eigenschaft bounds die beiden letzten Einträge auf 600 und 400, um ein Fenster
der Größe 600x400 zu erhalten, und geben unter title Visual Editor Swing-Beispiel ein.
Anschließend fügen wir die Komponente JMenuBar aus der Kategorie SWING MENUS dem
Fenster hinzu, um unser Fenster mit einer Menüleiste zu versehen. Da wir die vom Visual
Editor automisch vergebenen Namen übernehmen wollen und bisher unter WINDOW | PRE-
FERENCES | JAVA | VISUAL EDITOR die Anzeige des Fensters zur Namensgebung nicht deakti-
viert haben, holen wir dies jetzt nach.
Die drei Menüs erhalten wir, indem wir jeweils aus der Kategorie SWING MENUS die Kom-
ponente JMenu wählen und dann in der Java Beans View die Komponente JMenuBar an-
klicken, um das Menü der Menüleiste hinzuzufügen. Anschließend können wir in der
Properties View über die Eigenschaft text oder direkt in der Design View über das Text-
eingabefeld den drei Menüs ihre Beschriftung – Datei, Ansicht, Einstellungen – geben.
Als Nächstes werden den Menüs die Befehle hinzugefügt und zwar dem Menü DATEI der
Befehl BEENDEN, dem Menü ANSICHT die Befehle EINGABE und TABELLE und dem Menü EIN-
STELLUNGEN die Befehle ALLGEMEIN und ANSICHT. Hierzu wählen wir in der Kategorie SWING
MENUS die Komponente JMenuItem und fügen sie jeweils in der Java Beans View durch
Klicken auf das gewünschte Menü diesem hinzu. Da die Menübefehle nur in der Java Beans
View angezeigt werden, klicken wir sie anschließend dort an, um in der Properties View bei
der Eigenschaft text die Beschriftung einzugeben.

189
eclipse_v01.book Seite 190 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.*;

public class HauptFenster extends JFrame {


private JMenuBar jJMenuBar = null;
private JMenu jMenu = null;
private JMenu jMenu1 = null;
private JMenu jMenu2 = null;
private JMenuItem jMenuItem = null;
private JMenuItem jMenuItem1 = null;
private JMenuItem jMenuItem2 = null;
private JMenuItem jMenuItem3 = null;
private JMenuItem jMenuItem4 = null;
private JDesktopPane jDesktopPane = null;

private JMenuBar getJJMenuBar() {


if (jJMenuBar == null) {
jJMenuBar = new JMenuBar();
jJMenuBar.add(getJMenu()); // Datei
jJMenuBar.add(getJMenu1()); // Ansicht
jJMenuBar.add(getJMenu2()); // Einstellungen
}
return jJMenuBar;
}

190
eclipse_v01.book Seite 191 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

private JMenu getJMenu() {


if (jMenu == null) {
jMenu = new JMenu();
jMenu.setText("Datei");
jMenu.add(getJMenuItem()); // Beenden
}
return jMenu;
}
private JMenu getJMenu1() {
if (jMenu1 == null) {
jMenu1 = new JMenu();
jMenu1.setText("Ansicht");
jMenu1.add(getJMenuItem1()); // Eingabe
jMenu1.add(getJMenuItem2()); // Tabelle
}
return jMenu1;
}
private JMenu getJMenu2() {
if (jMenu2 == null) {
jMenu2 = new JMenu();
jMenu2.setText("Einstellungen");
jMenu2.add(getJMenuItem3()); // Allgemein
jMenu2.add(getJMenuItem4()); // Ansicht
}
return jMenu2;
}
private JMenuItem getJMenuItem() {
if (jMenuItem == null) {
jMenuItem = new JMenuItem();
jMenuItem.setText("Beenden");
}
return jMenuItem;
}
private JMenuItem getJMenuItem1() {
if (jMenuItem1 == null) {
jMenuItem1 = new JMenuItem();
jMenuItem1.setText("Eingabe");
}
return jMenuItem1;
}
private JMenuItem getJMenuItem2() {
if (jMenuItem2 == null) {
jMenuItem2 = new JMenuItem();
jMenuItem2.setText("Tabelle");
}
return jMenuItem2;
}

191
eclipse_v01.book Seite 192 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

private JMenuItem getJMenuItem3() {


if (jMenuItem3 == null) {
jMenuItem3 = new JMenuItem();
jMenuItem3.setText("Allgemein");
}
return jMenuItem3;
}
private JMenuItem getJMenuItem4() {
if (jMenuItem4 == null) {
jMenuItem4 = new JMenuItem();
jMenuItem4.setText("Ansicht");
}
return jMenuItem4;
}
private JDesktopPane getJDesktopPane() {
if (jDesktopPane == null) {
jDesktopPane = new JDesktopPane();
}
return jDesktopPane;
}
public static void main(String[] args) {
new HauptFenster();
}
public HauptFenster() {
super();
initialize();
}
private void initialize() {
this.setJMenuBar(getJJMenuBar());
this.setTitle("Visual Editor Swing-Beispiel");
this.setContentPane(getJDesktopPane());
this.setBounds(new java.awt.Rectangle(0,0,600,400));
this.setVisible(true);
}
}

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

6 – GUI-Design mit Eclipse

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);
}
});

Die Klasse IFEingabe


Um eine erste Klasse für ein Internal Frame zu erstellen, wählen wir im Package Explorer
wiederum das Package gui an und rufen über FILE | NEW | OTHER | JAVA | VISUAL CLASS den
New Visual Class Wizard auf. Nachdem wir unter NAME für die neue Klasse IFEingabe
eingegeben haben, müssen wir, um unsere Klasse von der Klasse javax.swing.JInter-
nalFrame abzuleiten, unter STYLE | SWING den Eintrag INTERNAL FRAME wählen.
Wir erhalten damit ein Internal Frame mit einer ContentPane. Der automatisch erzeugte
Quelltext lautet:

package gui;

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JInternalFrame;

public class IFEingabe extends JInternalFrame {


private JPanel jContentPane = null;
public IFEingabe() {
super();
initialize();
}
private void initialize() {
this.setSize(300, 200);
this.setContentPane(getJContentPane());
}
private JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();

193
eclipse_v01.book Seite 194 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.

Abb. 6.11: Die Properties View für die Klasse IFEingabe

Im Quelltext werden daraufhin in der Methode initialize die entsprechenden Setter-


Methoden aufgerufen.

private void initialize() {


this.setBounds(new java.awt.Rectangle(0,0,290,350));
this.setTitle("Dateneingabe");
this.setClosable(true);
this.setVisible(true);
this.setContentPane(getJContentPane());
}

194
eclipse_v01.book Seite 195 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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.

private JLabel jLabel = null;


private JTextField jTextField = null;
private JLabel jLabel1 = null;
private JTextField jTextField1 = null;
private JButton jButton = null;
private JButton jButton1 = null;

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

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

private JPanel getJContentPane() {


if (jContentPane == null) {
jLabel1 = new JLabel();
jLabel1.setText("Kundenname");
jLabel = new JLabel();
jLabel.setText("Kundennummer");
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(3);
gridLayout.setHgap(50);
gridLayout.setVgap(50);
gridLayout.setColumns(2);
jContentPane = new JPanel();
jContentPane.setLayout(gridLayout);
jContentPane.add(jLabel, null);
jContentPane.add(getJTextField(), null);
jContentPane.add(jLabel1, null);
jContentPane.add(getJTextField1(), null);
jContentPane.add(getJButton(), null);
jContentPane.add(getJButton1(), null);
}
return jContentPane;
}

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.

private JButton getJButton() {


if (jButton == null) {
jButton = new JButton();
jButton.setText("Übernehmen");
}
return jButton;
}

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

6 – GUI-Design mit Eclipse

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.

private java.util.LinkedList daten = null;

private void initialize() {


// ...
daten = new java.util.LinkedList();
}
public java.util.LinkedList getDaten() { return daten; }
public void setDaten(java.util.LinkedList daten) {
this.daten = daten;
}

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.

private HauptFenster parent = null;

Weiterhin kopieren wir im Quelltext den Standardkonstruktor und ändern die Kopie, indem
wir als Parameter das Hauptfenster übergeben.

public IFEingabe(HauptFenster fenster) {


super();
parent = fenster;
initialize();
}

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

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.

final IFEingabe jIF = this;


jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
jIF.dispose();
}
});

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.

private IFEingabe iFEingabe = null;

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.

final HauptFenster fenster = this;


jMenuItem1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e) {
iFEingabe = new IFEingabe(fenster);
jDesktopPane.add(iFEingabe);
}
});

Die Klasse IFTabelle


Als Nächstes implementieren wir im Package gui die Klasse IFTabelle zur Darstellung
der eingegebenen Daten in einer Tabelle. Für das Internal Frame stellen wir die in der Abb.
6.12 dargestellten Eigenschaften ein.

198
eclipse_v01.book Seite 199 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

Abb. 6.12: Die Properties View für die Klasse IFTabelle

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.

private JPanel getJContentPane() {


if (jContentPane == null) {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(2);
gridLayout.setHgap(50);
gridLayout.setVgap(50);
gridLayout.setColumns(1);
jContentPane = new JPanel();
jContentPane.setLayout(gridLayout);
jContentPane.add(getJScrollPane(), null);
}
return jContentPane;
}
private JScrollPane getJScrollPane() {
if (jScrollPane == null) {
jScrollPane = new JScrollPane();
jScrollPane.setViewportView(getJTable());
}
return jScrollPane;
}

199
eclipse_v01.book Seite 200 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

private JTable getJTable() {


if (jTable == null) {
jTable = new JTable();
}
return jTable;
}

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.

private javax.swing.table.DefaultTableModel getTableModel() {


daten.Daten datSatz = new Daten();
String[] modUeberschrift = {"Kundennummer","Kundenname"};
String[][] modDaten = new String[parent.getDaten().size()][2];
for (int i=0; i<parent.getDaten().size(); i++) {
datSatz = (daten.Daten)parent.getDaten().get(i);
modDaten[i][0] = datSatz.getKundenNr();
modDaten[i][1] = datSatz.getKundenName();
}
return new
javax.swing.table.DefaultTableModel(modDaten,modUeberschrift);
}

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

6 – GUI-Design mit Eclipse

Die Klasse IFAllgemein


Nachdem die beiden Internal Frames, die beim Aufruf der Befehle im Menü ANSICHT ange-
zeigt werden sollen, implementiert worden sind, erstellen wir nun die Klasse für das Inter-
nal Frame, welches die Wahl der Fenstergröße und der Hintergrundfarbe des Hauptfensters
ermöglicht. Die Klasse soll sich ebenfalls im Package gui befinden. Als Namen geben wir
im New Visual Class Wizard IFAllgemein ein. Darüber hinaus erstellen wir analog zu den
Klassen IFEingabe und IFTabelle einen zweiten Konstruktor und definieren das Haupt-
fenster als Attribut des Internal Frame. In der Properties View stellen wir für das Internal
Frame die in der Abb. 6.13 dargestellten Eigenschaften ein.

Abb. 6.13: Die Properties View für die Klasse IFAllgemein

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

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

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.

// Combobox für Fenstergröße


private JComboBox getJComboBox() {
if (jComboBox == null) {
jComboBox = new JComboBox();
jComboBox.addItem("600x400");
jComboBox.addItem("750x500");
jComboBox.addItem("900x600");
}
return jComboBox;
}
// Liste für Hintergrundfarbe
private JList getJList() {
if (jList = null) {
jList = new JList();
Object[] items = {"grau","blau","weiß","rot","grün","gelb"};
jList.setListData(items);
}
return jList;
}

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

6 – GUI-Design mit Eclipse

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.

Die Klasse IFAnsicht


Als letzte Klasse erstellen wir mithilfe des New Visual Class Wizard im Package gui die
Klasse IFAnsicht, welche wiederum die Klasse javax.swing.JInternalFrame er-
weitert. Auch hier definieren wir das Hauptfenster als Attribut des Internal Frame und er-
stellen einen zweiten Konstruktor.

203
eclipse_v01.book Seite 204 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten

Abb. 6.14: Die Properties View für die Klasse IFAnsicht

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

6 – GUI-Design mit Eclipse

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);
}
}
}

6.4 Das SWT


Das Standard Widget Toolkit (SWT) ist eine Grafikbibliothek, die mit dem Ziel entwickelt
worden ist, einerseits portable Anwendungen erstellen zu können, andererseits jedoch auch
eine große Betriebssystemnähe zu haben.
Die erste zur Verfügung stehende Grafikbibliothek, das Abstract Window Toolkit (AWT),
erlaubt zwar ebenfalls die Entwicklung portabler Anwendungen mit großer Betriebssys-
temnähe. Allerdings umfasst sie nur Klassen für diejenigen GUI-Elemente, die auf allen
Plattformen zur Verfügung stehen. Hierbei handelt es sich um einfache GUI-Elemente, wie
Buttons, Textfelder oder Listen. Komplexere GUI-Elemente wie Trees oder Tabellen feh-
len.
Das Swing Toolkit beinhaltet zwar Klassen für komplexere GUI-Elemente. Allerdings wer-
den die meisten GUI-Elemente emuliert, so dass beispielsweise ein Button in einer Swing-
Anwendung anders aussieht als unter dem jeweiligen Betriebssystem.
Im SWT sind nun die Vorteile beider Grafikbibliotheken vereint. Allerdings darf nicht ver-
schwiegen werden, dass auch einige Nachteile bestehen. So laufen SWT-Anwendungen nur
auf Plattformen, für die SWT zur Verfügung steht. Des Weiteren sind der Portabilität dort
Grenzen gesetzt, wo Dialogelemente auf verschiedenen Plattformen ein unterschiedliches
Verhalten zeigen.

6.4.1 Aufbau einer SWT-Applikation


Um eine Applikation mit SWT-Komponenten zu implementieren, müssen auf jeden Fall
Klassen aus den Packages org.eclipse.swt und org.eclipse.swt.widgets impor-
tiert werden. Der Einfachheit halber können wir alle Klassen dieser Packages importieren.

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.

Display display = Display.getDefault();


Shell shell = new Shell(display);

206
eclipse_v01.book Seite 207 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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.

Button button = new Button(shell, SWT.PUSH);

SWT-Komponenten besitzen analog zu AWT- und Swing-Komponenten Eigenschaften. Ei-


nige dieser Eigenschaften können bzw. müssen beim Erzeugen der Komponente festgelegt
werden und können zum Teil nachträglich nicht mehr verändert werden. Für die verschie-
denen Ausprägungen der Eigenschaften existieren in diesem Fall so genannte Stilkonstan-
ten. Diese sind in der Klasse org.eclipse.swt.SWT definiert.
Bei der Festlegung mehrerer Eigenschaften für eine Komponente über Stilkonstanten wer-
den diese über ein bitweises Oder | zu einem Stilparameter zusammengefasst.

Shell shell = new Shell(SWT.CLOSE | SWT.RESIZE);

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.

Die Klasse Widget


Die verschiedenen GUI-Elemente von SWT werden durch Klassen repräsentiert, die sich in
einer Vererbungshierarchie befinden. Die Superklasse aller Klassen ist hierbei die Klasse
Widget. Sie ist eine abstrakte Klasse, in der einige grundlegende Methoden implementiert
sind, wie z.B. die Methode dispose, die durch ein Objekt genutzte Ressourcen wieder
freigibt. Sie besitzt keine Stilkonstanten.

Die Klasse Control


Eine direkte Subklasse der Klasse Widget ist die ebenfalls abstrakte Klasse Control. Sie
repräsentiert GUI-Elemente, die beliebigen anderen GUI-Elementen hinzugefügt werden
können, und stellt eine Vielzahl von Methoden zur Verfügung, mit denen die verschiedenen
Eigenschaften der GUI-Elemente gesetzt und abgefragt werden, wie z.B. die Methoden
setVisible und setSize. Darüber hinaus verfügt sie über die Stilkonstante SWT.BOR-
DER, die ein GUI-Element mit einem Rahmen versieht.

208
eclipse_v01.book Seite 209 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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

Die Klasse Composite


Widgets werden in der Regel nicht direkt auf einer Shell platziert, sondern auf einem so ge-
nannten Composite. Ein Composite ist ein Widget, das andere Widgets aufnehmen kann
und somit das Gruppieren von Widgets ermöglicht. Repräsentiert wird ein Composite
durch die Klasse Composite. Im Gegensatz zu Swing wird ein Widget einem Composite

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.

Composite composite = new Composite(shell, SWT.NONE);


Button button = new Button(composite, SWT.NONE);

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.

Die Klasse Group


Die Klasse Composite besitzt als eine Subklasse die Klasse Group. Diese zeichnet um das
Composite zusätzlich einen Rahmen und kann optional einen Titel, der in den Rahmen
gesetzt wird, aufweisen. Das Aussehen der Linie kann über die Stilkonstanten SWT.
SHADOW_ETCHED_IN, SWT.SHADOW_ETCHED_OUT, SWT.SHADOW_IN, SWT.SHADOW_OUT
und SWT.SHADOW_NONE festgelegt werden. Diese werden jedoch nicht von allen Betriebs-
systemen unterstüzt. Für die Definition des Titels stellt die Klasse Group die Methode
setText zur Verfügung.

Die Klasse Canvas


Die Klasse Canvas dient als Zeichenfläche für Grafikoperationen und erlaubt es, eigene
GUI-Elemente zu implementieren. Über die aus der Klasse Composite geerbten Stilkon-
stanten lassen sich einige grundsätzliche Einstellungen vornehmen.

Die Klasse Label


Für Beschriftungen existiert die Klasse Label. Neben einer Beschriftung in Form von Text
ermöglicht es die Klasse Label auch, eine Grafik bzw. eine horizontale oder vertikale Linie
(Separator) abzubilden. Der Einsatzzweck und das Aussehen eines Labels werden über
Stilkonstanten gesteuert. In der folgenden Übersicht und auch den weiteren Übersichten
schließen sich die Stilkonstanten innerhalb einer Zelle gegenseitig aus, d.h., es kann nur je-
weils eine gewählt werden.

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

6 – GUI-Design mit Eclipse

SWT.WRAP Automatischer Umbruch bei Textlabels


SWT.SEPARATOR Label in Form einer horizontalen oder vertikalen Linie
(Separator)
SWT.HORIZONTAL
Orientierung der Linie im Fall eines Separators
SWT.VERTICAL

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.

Label textLabel = new Label(composite, SWT.LEFT);


textLabel.setText("Textlabel");
Label bildLabel = new Label(composite, SWT.CENTER);
bildLabel.setImage("bild.gif");
Label separator = new Label(composite, SWT.SEPARATOR |
SWT.VERTICAL);

Die Klasse Button


Während im AWT und in Swing für die unterschiedlichen Arten von Buttons auch ver-
schiedene Klassen existieren, besitzt das SWT nur eine Klasse Button, in der die verschie-
denen Arten zusammengefasst sind. Welche Art jeweils realisiert werden soll, wird beim
Erzeugen des Button-Objekts über eine Stilkonstante im Konstruktor gesteuert.

SWT.ARROW Button mit einem kleinen Pfeil

SWT.CHECK Checkbox

SWT.PUSH Button mit Beschriftung oder Grafik

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

SWT.FLAT Button wird nur zweidimensional dargestellt.

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.

Die Klasse Text


Textfelder werden repräsentiert durch die Klasse Text. Über Stilkonstanten lassen sich das
Aussehen und das Verhalten eines Textfelds steuern.

SWT.CENTER Inhalt des Textfelds wird zentriert ausgerichtet.


SWT.LEFT Inhalt des Textfelds wird linksbündig ausgerichtet.
SWT.RIGHT
Inhalt des Textfelds wird rechtsbündig ausgerichtet.
SWT.SINGLE Einzeiliges Textfeld
SWT.MULTI Mehrzeiliges Textfeld
SWT.PASSWORD Passwortfeld
SWT.READ_ONLY Inhalt des Textfelds kann nicht vom Benutzer verändert werden.
SWT.WRAP Automatischer Zeilenumbruch

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.

Text textFeld = new Text(composite, SWT.H_SCROLL | SWT.MULTI |


SWT.V_SCROLL | SWT.WRAP);

212
eclipse_v01.book Seite 213 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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.

Append Fügt Text an den im Textfeld bereits vorhandenen Text an.


clearSelection Entfernt die Auswahl.
Copy Kopiert den im Textfeld ausgewählten Text in die Zwischen-
ablage.
cut Schneidet den im Textfeld ausgewählten Text aus. Er steht in
der Zwischenablage zur Verfügung.
getCaretLineNumber Liefert für die Cursorposition die Zeilennummer. Die Zählung
beginnt bei 0.
getCaretPosition Liefert für die Cursorposition die Nummer des Zeichens. Die
Zählung beginnt bei 0.
getCharCount Liefert die Anzahl eingegebener Zeichen.
getSelectionCount Liefert die Anzahl ausgewählter Zeichen.
getSelectionText Liefert den ausgewählten Text.
getText Liefert den im Textfeld eingegebenen Text.
insert Fügt Text an der Cursorposition ein.
paste Fügt Text aus der Zwischenablage an der Cursorposition
ein.
selectAll Wählt den gesamten im Textfeld eingegebenen Text aus.
setSelection Wählt im Textfeld eingegebenen Text in einem vorgegebe-
nen Bereich aus.
setText Gibt Text im Textfeld ein.
showSelection Markiert ausgewählten Text.

Die Klasse List


Für Listen existiert im SWT die Klasse List. Über die Stilkonstanten SWT.SINGLE und
SWT.MULTI kann gesteuert werden, ob ein oder mehrere Einträge aus einer Liste ausge-
wählt werden können. Analog zum Textfeld kann auch eine Liste über die Stilkonstanten
SWT.H_SCROLL und SWT.V_SCROLL mit Scrollleisten versehen werden. Für das Hinzufü-
gen von Elementen zu einer Liste stehen die Methoden add, setItem bzw. setItems zur
Verfügung. Die Methode add fügt hierbei ein Listenelement immer am Ende der Liste an,
die Methode setItems fügt die angegebenen Elemente am Anfang der Liste ein und mit
der Methode setItem kann festgelegt werden, in welcher Zeile ein Listenelement einge-
fügt werden soll. Zu beachten ist, dass die Zählung bei 0 beginnt.

213
eclipse_v01.book Seite 214 Montag, 30. Januar 2006 12:02 12

Das SWT

// Liste mit Rahmen


List list = new List(composite, SWT.BORDER);
list.setItems(new String[] {"item 1", "item 2", "item 3"});
list.add("item 4");
list.setItem(1,"item 5");

Für die Ermittlung der ausgewählten Listenelemente sowie die programmseitige Auswahl
von Listenelementen stehen die folgenden Methoden zur Verfügung:

getSelection Liefert ein String-Array zurück, welches die Beschriftung


der ausgewählten Listenelemente enthält.
getSelectionIndex Liefert den Index des ersten ausgewählten Listenelements
zurück.
getSelectionIndices Liefert die Indizes aller ausgewählten Listenelemente
zurück.
setSelection Wählt Listenelemente aus.

Die Klasse Combo


Comboboxen werden im SWT repräsentiert durch die Klasse Combo und erlauben sowohl
eine Listenauswahl als auch die Texteingabe. Es werden folgende Stilkonstanten unter-
stützt:

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:

getItems Liefert ein String-Array zurück, welches die Beschriftung der


ausgewählten Listenelemente enthält.
getSelectionIndex Liefert den Index des ausgewählten Listenelements zurück.
getText Liefert den im Textfeld eingegebenen Text.
select Wählt ein Listenelement aus.
setText Gibt Text im Textfeld ein.

214
eclipse_v01.book Seite 215 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

Die Klasse Spinner


Für die Eingabe von numerischen Werten existiert ab der Version 3.1 von Eclipse die Klasse
Spinner. Die Eingabe kann hierbei direkt in einem Eingabefeld erfolgen oder durch Be-
tätigen von Pfeil-nach-oben- bzw. Pfeil-nach-unten-Buttons, die sich rechts neben dem
Eingabefeld befinden. Als Stilkonstante steht SWT.READ_ONLY zur Verfügung, die steuert,
ob der Inhalt des Spinners vom Benutzer verändert werden kann.

Abb. 6.16: Spinner

Für die Ermittlung der eingegebenen Zahl und die Gestaltung des numerischen Eingabe-
felds existieren folgende Methoden:

getDigits Liefert die eingegebene Zahl.


setDigits Gibt eine Zahl ein.
setIncrement Setzt Schrittweite für die Pfeil-nach-oben- bzw. Pfeil-nach-
unten-Buttons.
setMaximum Setzt Maximalwert.
setMinimum Setzt Minimalwert.

Die Klassen Table, TableColumn und TableItem


Die Klasse Table dient zur Darstellung von Tabellen. Sie besitzen im SWT standardmäßig
eine Spalte. Soll eine Tabelle mehr als eine Spalte aufweisen, muss ihr die gewünschte An-
zahl Spalten hinzugefügt werden. Für Tabellenspalten existiert die Klasse TableColumn.
Hierbei erfolgt das Hinzufügen einer Spalte zu einer Tabelle, indem beim Erzeugen des
TableColumn-Objekts das Table-Objekt im Konstruktor angegeben wird.

Table table = new Table(composite, SWT.BORDER);


TableColumn tableColumn = new TableColumn(table, SWT.NONE);

Um Tabelleneinträge zu definieren, müssen einer Tabelle Tabellenzeilen hinzugefügt wer-


den. Tabellenzeilen werden repräsentiert durch die Klasse TableItem. Das Hinzufügen ei-
ner Tabellenzeile zur Tabelle geschieht analog zum Hinzufügen von Tabellenspalten.

TableItem tableItem = new TableItem(table, SWT.NONE);

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

TableItem tableItem1 = new TableItem(table, SWT.NONE);


TableItem tableItem2 = new TableItem(table, SWT.NONE);
TableItem tableItem3 = new TableItem(table, SWT.NONE,1);

Die Tabelleneinträge werden den TableItem-Objekten mithilfe der Methode setText


hinzugefügt. Hierbei existieren verschiedene Möglichkeiten.

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");

Die Klasse Table besitzt folgende Stilkonstanten:

SWT.SINGLE Der Benutzer kann nur eine Tabellenzeile auswählen.


SWT.MULTI Der Benutzer kann mehrere Tabellenzeilen auswählen.
SWT.FULL_SELECTION Die gesamte Tabellenzeile ist selektierbar (plattform-
abhängig).
SWT.HIDE_SELECTION Die Tabellenzeilen sind nicht selektierbar (plattform-
abhängig).
SWT.CHECK Vor jeder Tabellenzeile wird eine Checkbox abgebildet.

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

6 – GUI-Design mit Eclipse

Die Klassen Slider und Scale


Für die Eingabe eines numerischen Werts mittels eines Schiebereglers existieren die beiden
Klassen Slider und Scale. Im Gegensatz zur Klasse Slider verfügt die Klasse Scale
über eine Skaleneinteilung.

Abb. 6.17: Slider und Scale

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:

setIncrement Setzt Schrittweite.


setMaximum Setzt Maximalwert.
setMinimum Setzt Minimalwert.
setPageIncrement Setzt Schrittweite.
setSelection Setzt aktuelle Position.

Die Klasse Slider weist darüber hinaus noch folgende Methoden auf:

setThumb Setzt die Größe des Handgriffs.


setValues Setzt alle Werte in einer Methode.

Die aktuelle Position kann mit der Methode getSelection abgefragt werden.

Die Klasse ProgressBar


Fortschrittsbalken werden durch die Klasse ProgressBar repräsentiert. Sie weist die fol-
genden Stilkonstanten auf:

SWT.HORIZONTAL Horizontale Anordnung


SWT.VERTICAL Vertikale Anordnung
SWT.SMOOTH Bewirkt, dass der Fortschrittsbalken nicht durchbrochen
gezeichnet wird.
SWT.INDERMINATE Bewirkt, dass der Fortschrittsbalken endlos durchläuft.

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.

ProgressBar progBar = new ProgressBar(shell, SWT.SMOOTH);


progBar.setMinimum(10);
progBar.setMaximum(20);
shell.open();
for (int i=progBar.getMinimum(); i<= progBar.getMaximum(); i++) {
progressBar.setSelection(i);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {}
}

Die Klasse ScrollBar


Die für Scrollleisten im SWT vorhandene Klasse ScrollBar wird bei einer Reihe von
Widgets realisiert, die von vornherein mit Scrollleisten ausgestattet werden können, wie
z.B. ein Textfeld oder eine Tabelle. Die Klasse ähnelt stark der Klasse Slider, ist aber im
Gegensatz zur Klasse Slider keine Subklasse der Klasse Control, so dass Scrollleisten
nicht beliebigen anderen GUI-Elementen hinzugefügt werden können. Scrollleisten kön-
nen nur GUI-Elementen hinzugefügt werden, die über die Stilkonstanten SWT.H_SCROLL
und SWT.V_SCROLL verfügen. Das Hinzufügen erfolgt in diesem Fall über den Aufruf der
Stilkonstanten im Konstruktor.

Table table = new Table(composite, SWT.V_SCROLL);

Die Klassen Tree und TreeItem


Für die Darstellung von Bäumen und deren Baumknoten verfügt das SWT über die Klassen
Tree und TreeItem. Die Baumknoten der ersten Hierarchieebene werden einem Baum
hinzugefügt, indem beim Erzeugen des TreeItem-Objekts im Konstruktor das Tree-Ob-
jekt angegeben wird. Bei den Baumknoten tieferer Hierarchieebenen wird das übergeord-
nete TreeItem-Objekt angegeben.
Die Funktionsweise und das Aussehen werden durch die Stilkonstanten der Klasse Tree
festgelegt.

SWT.SINGLE Der Benutzer kann nur einen Baumknoten auswählen.


SWT.MULTI Der Benutzer kann mehrere Baumknoten auswählen.

218
eclipse_v01.book Seite 219 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

SWT.CHECK Vor jedem Baumknoten wird eine Checkbox abgebildet.


SWT.FULL_SELECTION Die gesamte Zeile eines Baumknotens wird markiert.

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.

Tree tree = new Tree(composite, SWT.BORDER | SWT.SINGLE);


TreeItem treeItem1 = new TreeItem(tree, SWT.NONE);
treeItem1.setText("Knoten 1");
TreeItem treeItem2 = new TreeItem(tree, SWT.NONE);
treeItem2.setText("Knoten 2");
TreeItem treeItem11 = new TreeItem(treeItem1, SWT.NONE);
treeItem11.setText("Knoten 1.1");

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.

Die Klassen Sash und SashForm


Im SWT kann man ein Composite über Trennleisten in mehrere Bereiche aufteilen, wobei
sich die Trennleisten verschieben lassen. Hierfür existiert die Klasse Sash. Da nach einem
Verschieben die neue Position der Trennleiste und der Nachbarelemente nicht automatisch
angezeigt wird, muss bei der Verwendung der Klasse Sash eine aufwändige Ereignisver-
arbeitung implementiert werden.
Daher empfiehlt es sich, stattdessen die Klasse SashForm zu verwenden. Diese repräsen-
tiert ein Composite, das in zwei Bereiche aufgeteilt ist. Die Anordnung der beiden Bereiche
– horizontal oder vertikal – wird hierbei über die Stilkonstanten SWT.HORIZONTAL und
SWT.VERTICAL gesteuert.

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

Die Klassen TabFolder und TabItem


Die Klasse TabFolder implementiert zunächst einen Registerkartenbereich. Diesem müs-
sen dann die einzelnen Register hinzugefügt werden, indem Objekte der Klasse TabItem
erzeugt werden. Die Beschriftung der Registerkarten erfolgt mithilfe der Methode set-
Text. Um bei Wahl eines Registers spezifische GUI-Elemente anzeigen zu können, muss
für jedes Register ein Composite oder eine Group erstellt und über die Methode setCon-
trol dem Register zugeordnet werden. Neben der aus der Klasse Control geerbten Stil-
konstante SWT.BORDER verfügt die Klasse TabFolder über die beiden Stilkonstanten
SWT.TOP und SWT.BOTTOM, über die festgelegt werden kann, ob die Registerkarten oben
oder unten angeordnet werden sollen.

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.

Die Klassen ToolBar und ToolItem


Für die Implementation von Werkzeugleisten stehen die Klassen ToolBar und ToolItem
zur Verfügung. Jedes ToolBar-Objekt ist hierbei ein Composite, welches ein oder mehrere
Buttons beinhaltet. Die Buttons werden hierbei durch ToolItem-Objekte repräsentiert.
Das Erscheinungsbild von Werkzeugleisten lässt sich mithilfe der folgenden Stilkonstanten
festlegen:

SWT.FLAT Zweidimensionale statt dreidimensionale Darstellung (platt-


formabhängig)
SWT.WRAP Automatischer Umbruch

220
eclipse_v01.book Seite 221 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

SWT.RIGHT Rechtsbündige Anordnung


SWT.HORIZONTAL Horizontale Anordnung
SWT.VERTICAL Vertikale Anordnung

Das Aussehen der Buttons wird ebenfalls über Stilkonstanten festgelegt.

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.

Die Klassen CoolBar und CoolItem


Die Klasse CoolBar ermöglicht die Implementation einer verschiebbaren Werkzeugleiste.
Hierzu wird ein ToolBar-Objekt mithilfe der Methode setControl in ein CoolItem-
Objekt eingebettet. Das CoolItem-Objekt wiederum wird einem CoolBar-Objekt hinzu-
gefügt, indem beim Erzeugen des CoolItem-Objekts im Konstruktor das CoolBar-Objekt
angegeben wird. Zu beachten ist, dass für das CoolItem-Objekt eine minimale Größe ge-
setzt werden muss.

Die Klassen Menu und MenuItem


Für Menüs existieren die Klassen Menu und MenuItem. Um eine Menüleiste mit Menüs
und Menübefehlen aufzubauen, muss zunächst die Menüleiste als Objekt der Klasse Menu
erzeugt werden. Hierbei ist als Typ SWT.BAR anzugeben und als übergeordnetes Composite
die Shell. Dann muss die Menüleiste mithilfe der Methode setMenuBar aktiviert werden.

Menu menuBar = new Menu(shell,SWT.BAR);


shell.setMenuBar(menuBar);

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.

Menu menuDateiTit = new Menu(shell, SWT.DROP_DOWN);


MenuItem menuDatei = new MenuItem(menuBar, SWT.CASCADE);
menuDatei.setText("Datei");
menuDatei.setMenu(menuDateiTit);

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:

SWT.CHECK Menüeintrag mit Check-Symbol


SWT.PUSH Normaler Menüeintrag
SWT.RADIO
Menüeintrag mit gegenseitiger Auslösung
SWT.SEPARATOR
Passive Trennlinie

Für die Definition der Beschriftung ist wiederum die Methode setText zuständig.

MenuItem menuDateiBeenden = new MenuItem(menuDateiTit, SWT.PUSH);


menuDateiBeenden.setText("Beenden");

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

6 – GUI-Design mit Eclipse

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:

Layoutoption Beschreibung Voreinstellung


marginHeight Größe des Randbereichs oben und unten in Pixel 0
marginWidth Größe des Randbereichs oben rechts und links in 0
Pixel
spacing Zwischenraum zwischen GUI-Elementen in Pixel 0
(für alle GUI-Elemente gleich)
type Anordnung horizontal (SWT.HORIZONTAL) / verti- SWT.HORIZON-
kal (SWT.VERTICAL) TAL

Der Zugriff auf die Attribute marginHeight, marginWidth, space und type erfolgt
hierbei direkt und nicht über eine Setter-Methode.

FillLayout fillLayout = new FillLayout();


fillLayout.type = SWT.VERTICAL;
composite.setLayout(fillLayout);

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:

Layoutoption Beschreibung Voreinstellung


fill Wird die Einstellung auf true gesetzt, haben false
alle GUI-Elemente bei horizontaler Anordnung
die gleiche Höhe und bei vertikaler Anordnung
die gleiche Breite.
justify Wird die Einstellung auf true gesetzt, werden false
alle GUI-Elemente gleichmäßig über den ver-
fügbaren Platz verteilt.
marginBottom Größe des Randbereichs unten in Pixel 3
marginHeight Größe des Randbereichs oben und unten in 0
Pixel
marginLeft Größe des Randbereichs links in Pixel 3
marginRight Größe des Randbereichs rechts in Pixel 3
marginTop Größe des Randbereichs oben in Pixel 3
marginWidth Größe des Randbereichs links und rechts in 0
Pixel
pack Wird die Einstellung auf true gesetzt, werden true
alle GUI-Elemente in ihrer natürlichen Größe
und so weit links wie möglich dargestellt. Bei
false füllen sie das Composite aus.

spacing Zwischenraum zwischen GUI-Elementen in 3


Pixel
type Anordnung horizontal (SWT.HORIZONTAL) / SWT.HORIZONTAL
vertikal (SWT.VERTICAL)
wrap Wird die Einstellung auf true gesetzt, erfolgt true
bei Bedarf ein Zeilenumbruch.

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

6 – GUI-Design mit Eclipse

RowLayout rowLayout = new RowLayout(SWT.VERTICAL);


rowLayout.wrap = false;
rowLayout.pack = false;
rowLayout.justify = true;
rowLayout.marginLeft = 15;
rowLayout.marginTop = 10;
rowLayout.marginRight = 15;
rowLayout.marginBottom = 10;
rowLayout.spacing = 7;
composite.setLayout(rowLayout);

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);

Abb. 6.19: Fenster mit RowLayout in verschiedenen Größen

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:

Layoutoption Beschreibung Voreinstellung


horizontalSpacing Zwischenraum zwischen den Spalten in 5
Pixel
makeColumnsEqualWidth Wird die Einstellung auf true gesetzt, false
wird allen Spalten die gleiche Breite
zugeordnet.
marginBottom Größe des Randbereichs unten in Pixel 0
marginHeight Größe des Randbereichs oben und 5
unten in Pixel
marginLeft Größe des Randbereichs links in Pixel 0
marginRight Größe des Randbereichs rechts in 0
Pixel
marginTop Größe des Randbereichs oben in Pixel 0
marginWidth Größe des Randbereichs links und 5
rechts in Pixel
numColumns Anzahl der Spalten. Die Anzahl der Zei- 1
len ergibt sich automatisch aus der
Anzahl der GUI-Elemente und der
Spalten.
verticalSpacing Zwischenraum zwischen den Zeilen in 5
Pixel

Die allgemeinen Einstellungsmöglichkeiten werden analog zum RowLayout gesetzt, wobei


die Layoutoptionen numColumns und makeColumnsEqualWidth auch beim Erzeugen
des GridLayout-Objekts im Konstruktor angegeben werden können.

226
eclipse_v01.book Seite 227 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

GridLayout gridLayout = new GridLayout(3, true);


gridLayout.marginHeight = 10;
composite.setLayout(gridLayout);

Neben den allgemeinen Einstellungsmöglichkeiten für die GUI-Elemente existieren eine


Reihe von individuellen Layoutoptionen.

Layoutoption Beschreibung Voreinstellung


exclude Wird die Einstellung auf true false
gesetzt, erhält das GUI-Element
Position und Größe nicht durch
den Layoutmanager und wird
auch nicht für die Bestimmung
der Position und Größe der
anderen GUI-Elemente heran-
gezogen.
grapExcessHorizontalSpace Wird die Einstellung auf true false
gesetzt, passt sich das GUI-Ele-
ment horizontal der Zellgröße
an.
grapExcessVerticalSpace Wird die Einstellung auf true false
gesetzt, passt sich das GUI-Ele-
ment vertikal der Zellgröße an.
heightHint Höhe des GUI-Elements in Pixel SWT.DEFAULT

horizontalAlignment Horizontale Ausrichtung des GridData.


GUI-Elements: BEGINNING
GridData.BEGINNING
GridData.CENTER
GridData.END
GridData.FILL

horizontalIndent Linker Einzug eines GUI-Ele- 0


ments in Pixel
horizontalSpan Gibt an, wie viele Zellen das GUI- 1
Element in horizontaler Richtung
benötigt.
minimumHeight Minimale Höhe eines GUI-Ele- 0
ments in Pixel (nur wirksam,
wenn grapExcessVertical-
Space=true)

227
eclipse_v01.book Seite 228 Montag, 30. Januar 2006 12:02 12

Das SWT

Layoutoption Beschreibung Voreinstellung


minimumWidth Minimale Breite eines GUI-Ele- 0
ments in Pixel (nur wirksam,
wenn grapExcessHorizontal-
Space=true)

verticalAlignment Vertikale Ausrichtung des GUI- GridData.


Elements: CENTER
GridData.BEGINNING
GridData.CENTER
GridData.END
GridData.FILL

verticalIndent Oberer Einzug eines GUI-Ele- 0


ments in Pixel
VerticalSpan Gibt an, wie viele Zellen das 1
GUI-Element in vertikaler Rich-
tung benötigt.
WidthHint Breite des GUI-Elements in SWT.DEFAULT
Pixel

Die Layoutoptionen werden nach dem Erzeugen eines GridData-Objekts gesetzt:

Button button = new Button(composite, SWT.PUSH);


GridData gridData = new GridData();
gridData.widthHint = 100;
gridData.heightHint = 50;
button.setLayoutData(gridData);

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

6 – GUI-Design mit Eclipse

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);

Zu beachten ist, dass im Gegensatz zu Swing, wo beim GridBagLayout ein GridBagCon-


straints-Objekt für verschiedene GUI-Elemente verwendet werden kann, im SWT jedes
GUI-Element sein eigenes GridData-Objekt benötigt.

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

formData.top = new FormAttachment(50,-5);

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

formData.top = new FormAttachment(100,200,5);

bewirkt, dass das GUI-Element vertikal an der Position (100/200)*Höhe+5 angeordnet


wird.

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

6 – GUI-Design mit Eclipse

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:

Layoutoption Beschreibung Voreinstellung


marginHeight Größe des oberen und unteren Randbereichs 0
in Pixel
marginWidth Größe des linken und rechten Randbereichs in 0
Pixel
topControl Das sichtbare GUI-Element 0

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:

Button button = new Button(composite, SWT.PUSH);


button.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Button wurde angeklickt!");
}
public void widgetDefaultSelected(SelectionEvent e) {}
});

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.

Button button = new Button(composite, SWT.PUSH);


button.addSelectionListener(new SelectionAdapter () {
public void widgetSelected(SelectionEvent e) {
System.out.println("Button wurde angeklickt!");
}
});

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

6 – GUI-Design mit Eclipse

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

MenuListener / Tritt auf, wenn Menüs ein- oder ausgeblendet werden.


MenuEvent

ModifyListener / Tritt auf, wenn Text modifiziert wurde.


ModifyEvent

MouseListener / Tritt auf, wenn die Maustasten betätigt werden.


MouseEvent

MouseMoveListener / Tritt auf, wenn die Maus bewegt wird.


MouseEvent

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

Ereignistyp Methoden für die Ereignisse GUI-Elemente, für die die


Ereignisse eintreten können

Arm widgetArmed MenuItem

Control controlMoved, Control, TableColumn


controlResized

Dispose widgetDisposed Widget

Focus focusGained, focusLost Control

Help helpRequested Control, Menu, MenuItem

Key keyPressed, keyReleased Control

Menu menuHidden, Menu


menuShown

Modify modifyText Combo, Spinner, Text

Mouse mouseDoubleClick, Control


mouseDown, mouseUp

MouseMove mouseMove Control

MouseTrack mouseEnter, Control


mouseExit, mouseHover

Paint paintControl Control

Selection widgetDefaultSelected, Button, Combo, CoolItem, List,


widgetSelected MenuItem, Sash, Scale, Slider,
ScrollBar, Spinner, TabFolder,
Table, TableColumn, Text, Tool-
Item, Tree

Shell shellActivated, Shell


shellClosed,
shellDeactivated,
shellDeiconified,
shellIconified

Traverse keyTraversed Control

Tree treeCollapsed, Tree


treeExpanded

Verify verifyText Text

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 – GUI-Design mit Eclipse

Klasse java.util.EventObject das das Ereignis auslösende GUI-Element. Des Weite-


ren verfügen einige Ereignistyp-Klassen über Attribute, auf die direkt zugegriffen werden
kann, wie beispielsweise das Attribut character der Klasse KeyEvent, welches das ein-
gegebene Zeichen liefert, oder die Attribute x und y der Klasse MouseEvent, die die Posi-
tion liefern, an der die Maus gedrückt worden ist.

6.5 Besonderheiten bei der Erstellung eines GUI mit


SWT-Komponenten
Nachdem in Abschnitt 6.3 die Besonderheiten bei der Entwicklung eines GUI mit Swing-
Komponenten betrachtet worden sind, werden nach der Beschreibung der Grafikbibliothek
SWT in diesem Abschnitt die Besonderheiten des Visual Editors für SWT vorgestellt.

6.5.1 Unterstützte Komponenten


Wird bei der Erstellung einer Klasse für ein GUI unter FILE | NEW | OTHER | VISUAL CLASS |
STYLE ein SWT-Eintrag gewählt, stehen in der Palette neben den vier Kategorien für AWT-
und Swing-Komponenten auch drei Kategorien mit den folgenden SWT-Komponenten zur
Verfügung:
쐌 SWT Controls
Button, CheckBox, RadioButton, Label, CLabel, Link, Text, TextArea,
StyledText, List, Combo, CCombo, Progress Bar, Spinner, Slider, Scale,
Table, TableColumn, Tree, ToolBar, ToolItem.Push, ToolItem.Check, Tool-
Item.Radio, ToolItem.Dropdown, ToolItem.Separator, Browser
쐌 SWT Containers
Shell, Composite, Group, TabFolder, CTabFolder, CoolBar, CBanner, Sash-
Form, ViewForm, Canvas, ScrolledComposite
쐌 SWT Menus
MenuBar, MenuItem.Push, MenuItem.Submenu, MenuItem.Separator, Menu-
Item.Check, MenuItem.Radio

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

Besonderheiten bei der Erstellung eines GUI mit SWT-Komponenten

Abb. 6.23: Customize Layout-Fenster für allgemeine Einstellungen FillLayout und


RowLayout

Abb. 6.24: Customize Layout-Fenster für allgemeine und individuelle Einstellungen


GridLayout

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 – GUI-Design mit Eclipse

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;

public class Fenster {


private Shell sShell = null;

private void createSShell() {


sShell = new Shell();
sShell.setText("Shell");
sShell.setSize(new Point(300, 200));
}
}

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:

public static void main(String[] args) {


Display display = Display.getDefault();
SWTFenster thisClass = new SWTFenster();
thisClass.createSShell();
thisClass.sShell.open();
while (!thisClass.sShell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}

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

Besonderheiten bei der Erstellung eines GUI mit SWT-Komponenten

private void createComposite() {


gridLayout=new GridLayout();
gridLayout.numColumns = 2;
composite = new Composite(sShell, SWT.NONE);
composite.setLayout(gridLayout);
composite.setBounds(
new org.eclipse.swt.graphics.Rectangle(15,9,262,142));
}

Der Aufruf der createComposite-Methode erfolgt in der Methode createSShell.


Das Hinzufügen einer Komponente zum Composite in der Design View oder der Java
Beans View bewirkt, dass die Komponente als Attribut der Klasse mit dem Zugriffsrecht
private deklariert und in der Methode createComposite instanziiert und dem Compo-
site hinzugefügt wird. Änderungen von Eigenschaften eines GUI-Elements in der Proper-
ties View werden als Anweisungen ebenfalls in der createComposite-Methode reali-
siert.

private Button button = null;


// …
private void createComposite() {
// …
button = new Button(composite, SWT.NONE);
button.setText("OK");

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 – GUI-Design mit Eclipse

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.

Beschreibung des Beispiels


Es soll ein SWT-Fenster mit zwei Textfeldern und einem Label unter Verwendung des
GridLayouts erstellt werden. Hierbei soll sich das Label horizontal über zwei Zellen erstre-
cken und diese ausfüllen. Weiterhin sollen folgende Ereignisse implementiert werden:
쐌 Als Erstes soll beim Anzeigen des Fensters, also beim shellActivated-Ereignis, der
Text „Hello“ in das erste und „World“ in das zweite Textfeld eingetragen werden.
쐌 Beim focusGained-Ereignis der Textfelder soll der Inhalt des entsprechenden Text-
felds markiert werden und beim focusLost-Ereignis der Text aus dem ersten mit dem
aus dem zweiten Textfeld zusammengesetzt und in das Label ausgegeben werden.
쐌 Beim mouseDown-Ereignis des Labels soll die Schriftgröße um jeweils zwei Punkt ver-
größert werden.

Implementation des Beispiels


Wir erstellen zunächst ein neues Projekt mit dem Namen com.entwickler.eclipsebuch.VE-
BeispielSWT. Da die Quelltext- und die class-Dateien jeweils in einem eigenen Verzeichnis
gespeichert werden sollen, aktivieren wir, nachdem wir im New Java Project Wizard den
Namen für das Projekt eingegeben haben, unter PROJECT LAYOUT den Eintrag CREATE SEPA-
RATE SOURCE AND OUTPUT FOLDERS. Anschließend klicken wir rechts daneben auf CONFIGURE
DEFAULT und aktivieren im daraufhin erscheinenden Fenster unter SOURCE AND OUTPUT FOL-
DER den Eintrag FOLDERS. Die dort vorgeschlagenen Verzeichnisnamen src und bin überneh-
men wir.
Nach dem Beenden des New Java Project Wizard klicken wir als Nächstes im Package Ex-
plorer auf das Quelltextverzeichnis und wählen FILE | NEW | OTHER | JAVA | VISUAL CLASS.
Nach dem Klicken auf NEXT geben wir im Fenster des VE New Class Wizard der Klasse
den Namen SWTFenster, wählen unter STYLE | SWT den Eintrag SHELL und aktivieren unter
WHICH METHOD STUBS WOULD YOU LIKE TO CREATE? den Eintrag PUBLIC STATIC VOID
MAIN(STRING[] ARGS). Es wird daraufhin der in Abschnitt 6.5.3 beschriebene Quelltext er-
zeugt. Damit das als Nächstes der Shell hinzuzufügende Composite diese komplett ausfüllt,
wählen wir als Layout für die Shell in der Properties View unter der Eigenschaft layout
das FillLayout.
Zum Hinzufügen des Composite klicken wir in der Palette in der Kategorie SWT Contai-
ners auf den Eintrag COMPOSITE und anschließend einfach in der Design View in die Shell.
Für das Composite stellen wir anschließend das GridLayout ein und geben, nachdem wir
auf das +-Zeichen vor layout geklickt haben, unter numcolumns als Spaltenanzahl 2 ein.
Die beiden Textfelder und das Label werden nun dem Composite hinzugefügt, indem in der
Palette unter der Kategorie SWT Controls der Eintrag TEXT bzw. LABEL gewählt und an-
schließend in das Composite geklickt wird. Wenn unter WINDOW | PREFERENCES | JAVA |

239
eclipse_v01.book Seite 240 Montag, 30. Januar 2006 12:02 12

Besonderheiten bei der Erstellung eines GUI mit SWT-Komponenten

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:

GridData gridData = new org.eclipse.swt.layout.GridData();


gridData.horizontalSpan = 2;
gridData.horizontalAlignment =
org.eclipse.swt.layout.GridData.FILL;
lblAusgabe.setLayoutData(gridData);

Um unserer Beispielanwendung Leben einzuhauchen, implementieren wir jetzt noch die


oben beschriebenen Ereignisse, und zwar als Erstes das shellActivated-Ereignis.
Dazu klicken wir in der Java Beans View auf die Shell und wählen im Kontextmenü den Be-
fehl EVENTS | ADD EVENTS. Im daraufhin erscheinenden Dialogfenster klicken wir auf den
Eintrag SHELLACTIVATED. Dadurch wird in der Methode createSShell der Listener mit-
hilfe der Methode addShellListener der Shell hinzugefügt. Die Ereignismethode
shellActivated wird in eine anonyme Klasse geschrieben. In dieser implementieren
wir, dass im ersten Textfeld der Text „Hello“ und im zweiten der Text „World“ erscheinen
soll.

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

6 – GUI-Design mit Eclipse

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();
}
});

Die Methode lblAusgabeTextSetzen enthält lediglich eine Befehlszeile:

private void lblAusgabeTextSetzen() {


lblAusgabe.setText(txtEingabe1.getText()+" "+
txtEingabe2.getText());
}

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);
}
});

Damit ist die Programmierung unserer Beispielanwendung abgeschlossen.

6.6 Der WindowBuilder


Der WindowBuilder ermöglicht das visuelle Entwerfen von GUIs, die Swing- und SWT-
Komponenten beinhalten. Er wurde von der Firma Instantiations entwickelt und besteht aus
den beiden Komponenten SWT Designer und Swing Designer. Eine Download-Möglich-
keit besteht unter www.windowbuilderpro.com, wobei eine Free Edition und eine Profes-
sional Edition existieren. Eine Dokumentation kann in jedem Fall kostenlos herunterge-
laden werden. Die Free Edition besitzt einen eingeschränkten Funktionsumfang. Eine
Übersicht der Unterschiede zwischen Free und Professional Edition findet sich ebenfalls
unter www.windowbuilderpro.com.
Die Grundlage für die folgende Beschreibung ist die Version 4.2.0 Professional Edition, die
14 Tage kostenlos getestet werden kann. Obwohl ab der Version 2.0.0 auch die Entwick-
lung von GUIs mit Swing-Komponenten (Swing Designer) möglich ist, beschränken wir
uns auf die Verwendung von SWT-Komponenten (SWT Designer), da mit dem Visual Edi-
tor bereits ein Designer für die Entwicklung von GUIs mit Swing-Komponenten vorgestellt
worden ist.

6.6.1 Installation und Aufruf


Zum Installieren der hier betrachteten Version des WindowBuilder muss zunächst die Datei
Designer_v4.2.0_for_Eclipse3.1.zip in das Eclipse-Verzeichnis entpackt werden. Es ist
darauf zu achten, dass die in der zip-Datei gespeicherten Pfadangaben verwendet werden.
War die Installation erfolgreich, so erscheint nach dem Starten von Eclipse unter HELP |
ABOUT ECLIPSE SDK | PLUG-IN DETAILS das WindowBuilder-Plugin. Dieses ist leicht am Fir-
mennamen Instantiations in der Spalte PROVIDER zu erkennen. Soll auch die Hilfe zur Ver-
fügung stehen, muss des Weiteren noch die Datei Designer_v4.2.0_docs.zip ebenfalls in
das Eclipse-Verzeichnis entpackt werden. Sie wird – wie auch beim Visual Editor – in die

242
eclipse_v01.book Seite 243 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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.

Abb. 6.25: Erstellen einer neuen SWT-Applikation im WindowBuilder

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.

Abb. 6.26: Eclipse mit dem Designer-Fenster des WindowBuilder

Unter WINDOW | PREFERENCES | DESIGNER | EDITOR LAYOUT lassen sich alternative Anordnun-
gen der einzelnen Bestandteile festlegen.

6.6.2 Hinzufügen von Komponenten


Die mithilfe des WindowBuilder einfügbaren SWT-Komponenten sind in der Control-
Palette in drei Kategorien zusammengefasst:
쐌 SWT Composites
Composite, Group, SashForm, TabFolder, TabItem etc.

244
eclipse_v01.book Seite 245 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

쐌 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.3 Entfernen von Komponenten


Eine Komponente lässt sich entfernen, indem sie im Control Tree oder der Content Pane an-
geklickt wird und anschließend mit der ¢-Taste oder dem DELETE-Befehl aus dem Kon-
textmenü gelöscht wird.

6.6.4 Ändern von Eigenschaften einer Komponente


Um die Eigenschaften einer Komponente zu ändern, müssen wir sie in der Content Pane
oder dem Control Tree anklicken. Im Inspector werden daraufhin die Eigenschaften ange-
zeigt. Wenn wir im Inspector entweder in der linken Spalte den Namen einer Eigenschaft
anwählen oder in der rechten Spalte den Wert einer Eigenschaft, können wir den Wert än-
dern. Um die Änderung zu bestätigen, muss bei vielen Eigenschaften anschließend Æ ge-
drückt werden.
Bei einigen Eigenschaften handelt es sich um komplexe Eigenschaften. Diese sind erkenn-
bar an dem Zeichen vor dem Namen der Eigenschaft in der linken Spalte. Erscheint ein
+-Zeichen, muss auf dieses geklickt werden, um weitere Eigenschaften zu der gewählten
Eigenschaft anzuzeigen. Bei einem Minuszeichen werden die weiteren Eigenschaften be-
reits angezeigt.

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.

Abb. 6.27: Layoutassistent für GridLayout und FormLayout

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

6 – GUI-Design mit Eclipse

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

Abb. 6.28: Die Anzeige eines Ereignisses im Inspector

Ü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.

Abb. 6.29: Einstellungsmöglichkeiten für Codegenerierung

248
eclipse_v01.book Seite 249 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

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;

public class Fenster {


protected Shell shell;
public static void main(String[] args) {
try {
Dummy window = new Dummy();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
public void open() {
final Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
}
protected void createContents() {
shell = new Shell();
shell.setSize(500, 375);
shell.setText("SWT Application");
}
}

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

public class Fenster {


private Text text;
// ...
{
final Button button = new Button(shell, SWT.NONE);
button.setText("button");
}
{
text = new Text(shell, SWT.BORDER);
}

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.

protected void createContents() {


shell = new Shell();
shell.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent e) {}
});
// ...

250
eclipse_v01.book Seite 251 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

final Button button = new Button(composite, SWT.NONE);


button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {}
});

Wird die Option CREATE INNER CLASS aktiviert, erfolgt die Implementation statt als anonyme
Klasse als innere Klasse.

public class Fenster


// ...
private class ShellMouseMoveListener implements
MouseMoveListener {
public void mouseMove(MouseEvent e) {}
}
private class ButtonSelectionListener extends SelectionAdapter {
public void widgetSelected(SelectionEvent e) {}
}

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.

public class Fenster implements


MouseMoveListener, SelectionListener {
// ...
public void mouseMove(MouseEvent e) {}
public void widgetSelected(SelectionEvent e) {}
public void widgetDefaultSelected(SelectionEvent e) {}

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.

Beschreibung des Beispiels


Bei dem Beispiel handelt es sich um ein SWT-Fenster, welches in vier Bereiche aufgeteilt
ist. Der obere linke Bereich dient zur Dateneingabe. Im unteren linken Bereich werden die
bisher eingegebenen Daten in einer tabellarischen Übersicht ausgegeben. Der obere rechte
Bereich ermöglicht es, die Fenstergröße und die Hintergrundfarbe der beiden oberen Berei-
che zu verändern. Der untere rechte Bereich weist zwei Register auf. In einem ersten Re-
gister kann über einen Schieberegler die Schriftgröße verändert werden. Das zweite Regis-
ter ermöglicht es, die Tabelle mit oder ohne Gitternetzlinien darzustellen.

251
eclipse_v01.book Seite 252 Montag, 30. Januar 2006 12:02 12

Der WindowBuilder

Abb. 6.30: Das Beispielfenster

Einrichten des Projekts


Wir erstellen zunächst ein neues Projekt mit dem Namen com.entwickler.eclipse-
buch.SWTDesignerBeispiel. Hierzu rufen wir FILE | NEW | OTHER | DESIGNER | SWT/JFACE
JAVA PROJECT auf. Im nächsten Fenster können wir dann für das neue Projekt den Namen
eingeben. Da die Quelltext- und die class-Dateien jeweils in einem eigenen Verzeichnis ge-
speichert werden sollen, aktivieren wir, nachdem wir im New SWT/JFace Java Project
Wizard den Namen für das Projekt eingegeben haben, unter PROJECT LAYOUT den Eintrag
CREATE SEPARATE SOURCE AND OUTPUT FOLDERS. Anschließend klicken wir rechts daneben auf
CONFIGURE DEFAULT und aktivieren im daraufhin erscheinenden Fenster unter SOURCE AND
OUTPUT FOLDER den Eintrag FOLDERS. Die dort vorgeschlagenen Verzeichnisnamen src und
bin übernehmen wir. Nach dem Beenden des New SWT/JFace Java Project Wizard klicken
wir als Nächstes im Package Explorer auf das Quelltextverzeichnis und erstellen ein
Package gui und ein Package daten.

Die Klasse Daten


Bevor wir jetzt mit der Implementation der Klasse für das GUI beginnen, erstellen wir zu-
nächst eine Klasse, die einen Datensatz repräsentiert. Hierzu generieren wir im Package
daten eine neue Klasse mit dem Namen Daten. Als Attribute definieren wir kundenNr
und kundenName vom Typ String und erzeugen die zugehörigen Getter- und Setter-Metho-
den. Weiterhin implementieren wir den Standardkonstruktor mit leerem Methodenrumpf
und einen Konstruktor für die Initialisierung der beiden Attribute.

package daten;

public class Daten {


private String kundenNr, kundenName;

// Konstruktoren ...

// Getter- und Setter-Methoden ...


}

252
eclipse_v01.book Seite 253 Montag, 30. Januar 2006 12:02 12

6 – GUI-Design mit Eclipse

Die Klasse Fenster


Bevor wir mit der Implementation der Klasse Fenster beginnen, deaktivieren wir unter
WINDOW | PREFERENCES | DESIGNER | CODE GENERATION den Eintrag CREATE EVERY COMPONENT
IN ITS OWN BLOCK.

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.

Abb. 6.31: Einstellungen für das Beispielfenster im Inspector

Diese werden sofort im Quelltext berücksichtigt.

package gui;

import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Fenster {


// ...
protected void createContents() {
shell = new Shell();
shell.setLayout(new FillLayout());
shell.setSize(600, 400);
shell.setText("SWT Designer Beispiel");
}
// ...

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.

protected void createContents() {


// ...
shell.setText("SWT Designer Beispiel");
final SashForm sashForm = new SashForm(shell, SWT.NONE);
final Composite compLi = new Composite(sashForm, SWT.NONE);
compLi.setLayout(new FillLayout());
final SashForm sashFoLi = new SashForm(compLi, SWT.VERTICAL);
final Composite compLo = new Composite(sashFoLi, SWT.NONE);
final Composite compLu = new Composite(sashFoLi, SWT.NONE);
sashFoLi.setWeights(new int[] { 1, 1 });
final Composite compRe = new Composite(sashForm, SWT.NONE);
compRe.setLayout(new FillLayout());
final SashForm sashFoRe = new SashForm(compRe, SWT.VERTICAL);
final Group compRo = new Group(sashFoRe, SWT.NONE);
final Composite compRu = new Composite(sashFoRe, SWT.NONE);
sashFoRe.setWeights(new int[] { 1, 1 });
sashForm.setWeights(new int[] { 1, 1 });
}// ...

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

6 – GUI-Design mit Eclipse

final Label kundennummerLabel = new Label(compLo, SWT.NONE);


final GridData gridData = new GridData(GridData.BEGINNING,
GridData.CENTER, true, true);
gridData.horizontalIndent = 5;
kundennummerLabel.setLayoutData(gridData);
kundennummerLabel.setText("Kundennummer");

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.

text = new Text(compLo, SWT.BORDER);


final GridData gridData_1 = new GridData(GridData.FILL,
GridData.CENTER, true, true);
gridData_1.horizontalIndent = 5;
text.setLayoutData(gridData_1);

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.

final Button button = new Button(compLo, SWT.NONE);


final GridData gridData_4 = new GridData(GridData.BEGINNING,
GridData.CENTER, true, true);
gridData_4.horizontalIndent = 5;
button.setLayoutData(gridData_4);
button.setText("Übernehmen");

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

table = new Table(compLu, SWT.BORDER);


table.setLinesVisible(true);
table.setHeaderVisible(true);

final TableColumn newColumnTableColumn = new TableColumn(table,


SWT.NONE);
newColumnTableColumn.setWidth(100);
newColumnTableColumn.setText("Kundennummer");

final TableColumn newColumnTableColumn_1 = new TableColumn(table,


SWT.NONE);
newColumnTableColumn_1.setWidth(100);
newColumnTableColumn_1.setText("Kundenname");

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.

final Label label = new Label(compRo, SWT.NONE);


label.setText("Fenstergröße");
combo = new Combo(compRo, SWT.NONE);
combo.setItems(new String[] {"600x400", "750x500", "900x600"});
final Label hintergrundfarbeLabel = new Label(compRo, SWT.NONE);
hintergrundfarbeLabel.setText("Hintergrundfarbe");
list = new List(compRo, SWT.BORDER);
list.setItems(new String[] {"grau", "blau", "weiß",
"rot", "grün", "gelb"});

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

6 – GUI-Design mit Eclipse

final TabFolder tabFolder = new TabFolder(compRu, SWT.NONE);


final TabItem eingabeTabItem = new TabItem(tabFolder, SWT.NONE);
eingabeTabItem.setText("Eingabe");
final TabItem tabelleTabItem = new TabItem(tabFolder, SWT.NONE);
tabelleTabItem.setText("Tabelle");

Um in den einzelnen Registern GUI-Elemente platzieren zu können, müssen wir beiden


TabItems noch jeweils ein Composite bzw. eine Group hinzufügen. Hierzu müssen wir zu-
nächst in der Control-Palette den Eintrag COMPOSITE anwählen. Anschließend wählen wir
dann entweder in der Content Pane oder in dem Inspector das gewünschte TabItem an. Im
Quelltext wird daraufhin ein Composite-Objekt erzeugt und mithilfe der Methode set-
Control dem angewählten TabItem zugewiesen.

final Composite composite = new Composite(tabFolder, SWT.NONE);


eingabeTabItem.setControl(composite);
final Group tabelleGroup = new Group(tabFolder, SWT.NONE);
tabelleTabItem.setControl(tabelleGroup);

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.

final Scale scale = new Scale(composite, SWT.NONE);


scale.setSelection(8);
scale.setPageIncrement(2);
scale.setMinimum(8);
scale.setMaximum(16);

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;

public class Fenster {


private java.util.LinkedList daten = null;
// ...
protected void createContents() {
daten = new java.util.LinkedList();

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

6 – GUI-Design mit Eclipse

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

6 – GUI-Design mit Eclipse

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

7 Eclipse und J2EE

von Dr. Kai Brüssau

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.

Abb. 7.1: Architektur einer J2EE-Anwendung

J2EE-Anwendungen können auf unterschiedlichen Systemen ablaufen. Es gibt eine Viel-


zahl von Applikations- und Webservern, die den J2EE-Standard unterstützen. In dem vor-
liegenden Buch werden wir den Tomcat Webserver als Webserver und den JBoss Server als
Server für EJB-Komponenten verwenden. Die beiden Server stehen kostenlos zur Verfü-
gung.1

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.

1. Der MySQL-Datenbankserver steht unter http://www.mysql.com/ kostenlos zur Verfügung.

264
eclipse_v01.book Seite 265 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

In diesem Kapitel verwenden wir XML-Dokumente vorwiegend als Deployment-Deskrip-


toren, die einem Server die Informationen zu einer Komponente oder einer Anwendung be-
reitstellen. Daneben werden die Informationen zur Konfiguration von Servern zumeist auch
als XML-Dokument gespeichert.

7.1.2 Bestandteile eines XML-Dokuments

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.:

<?xml version="1.0" encoding="UTF-8"?>

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.

Document Type Declaration/Document Type Definition


Die XML Document Type Declaration steht immer zu Beginn eines XML-Dokuments und
gibt im Wesentlichen die Document Type Definition (DTD) an. Die DTD beschreibt die
Struktur einer Klasse von XML-Dokumenten mit Hilfe einer Textdatei in einem bestimm-
ten Format. Ein Beispiel für eine Document Type Declaration kann wie folgt aussehen.

<!DOCTYPE Kundenliste SYSTEM ’kundenliste.dtd’>

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:

<?xml version="1.0" encoding="UTF-8"?>


<!ELEMENT Kundenliste (Kunde)*>
<!ELEMENT Kunde (Name, Adresse?, Telefon*)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Adresse (#PCDATA)>
<!ELEMENT Telefon (#PCDATA)>
<!ATTLIST Telefon
Typ (mobil | privat | geschäftlich) #REQUIRED
>

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:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE Kundenliste SYSTEM ’kundenliste.dtd’>
<Kundenliste>
<Kunde>
<Name>Hans Muster</Name>
<Telefon Typ="mobil">0171 987</Telefon>
<Telefon Typ="privat">040 555</Telefon>
<Telefon Typ="geschäftlich">040 428</Telefon> </Kunde>
<Kunde>
<Name>Heidi Muster</Name>
<Adresse>Goetheallee 12, 20123 Hamburg</Adresse>
<Telefon Typ="mobil">0171 123</Telefon>
</Kunde>
</Kundenliste>

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70101XML-DTD


2. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70101XML-DTD

266
eclipse_v01.book Seite 267 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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">

Üblicherweise wird der Namensraum http://www.w3.org/2001/XMLSchema im XML-


Schema mit xsd bezeichnet. Die Definition erfolgt in dem Bereich:

<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.

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70102XML-Schema

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:

<xsd:element name="Kundenliste" type="tns:myKundenliste"/>

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>

Elemente vom Typ tns:myKundenliste bestehen aus 0 (minOccurs="0") oder beliebig


vielen (maxOccurs="unbounded") Elementen mit dem Namen Kunde, die wiederum
vom Typ tns:myKunde sind.
Demnach ist noch der Typ tns:myKunde zu definieren. Dieser besteht aus den drei Ele-
menten Name, Adresse und Telefon, die alle vom Typ xsd:string sind. Das Element
Name muss immer innerhalb des Kunde-Elements vorhanden sein, wohingegen die Adresse
und die Telefonnummer weggelassen werden können. Bei der Telefonnummer soll die
Möglichkeit bestehen, dass sie mehrfach vorkommt, wenn z.B. unterschiedliche Telefon-
nummern eines Kunden gespeichert werden. Die Telefonnummer soll zusätzlich ein Attri-
but erhalten, das mit Typ bezeichnet wird. Attribute können aber nicht für Elemente, die
einen einfachen Datentyp wie z.B. xsd:string besitzen, definiert werden. Aus diesem
Grund erzeugen wir einen <xsd:complexType> und legen dort das Attribut fest.
Das Attribut gibt in unserem Beispiel an, ob es sich um die private, mobile oder geschäft-
liche Telefonnummer handelt. Aus diesem Grund definieren wir eine Enumeration, die wir
mit myTelefontypen bezeichnen. Von diesem Typ ist das Attribut mit dem Namen Typ,
was bedeutet, dass das Attribut nur die Werte privat, mobil oder geschäftlich anneh-
men darf:

<xsd:attribute name="Typ" type="tns:myTelefontypen"/>

268
eclipse_v01.book Seite 269 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

Die gesamte XML Schema-Datei sieht wie folgt aus:

<?xml version="1.0" encoding="Cp1252"?>


<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://eclipsebuch.entwickler.com"
xmlns:tns="http://eclipsebuch.entwickler.com"
elementFormDefault="qualified">

<xsd:element name="Kundenliste" type="tns:myKundenliste"/>


<xsd:complexType name="myKundenliste">
<xsd:sequence>
<xsd:element name="Kunde" type="tns:myKunde"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>

<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:

<?xml version="1.0" encoding="UTF-8"?>


<Kundenliste
xmlns="http://eclipsebuch.entwickler.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://eclipsebuch.entwickler.com
kundenliste.xsd">

<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.

7.1.3 Plug-Ins für das Bearbeiten von XML-Dokumenten


Für die Erstellung oder Bearbeitung von XML-Dokumenten sind XML-Editoren hilfreich.
Sie bieten eine übersichtliche Darstellung, prüfen die Gültigkeit in Bezug auf eine DTD
oder ein XML Schema und zeigen Fehler an.

Sample XML Editor


Eclipse beinhaltet den Sample XML Editor, der mit Hilfe eines Assistenten als Eclipse-
Plug-In erzeugt und in die Entwicklungsumgebung integriert werden kann. Dazu erzeugen
wir ein neues Projekt als Plug-In Project (Menü: FILE | NEW | PROJECT  PLUG-IN DEVELOP-
MENT | PLUG-IN PROJECT).

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).

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70102XML-Schema

270
eclipse_v01.book Seite 271 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

Abb. 7.2: Plug-In-Erstellung des Sample XML Editors

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.

1. Siehe auch beiliegende CD ../Kapitel07/Kap70103SampleXMLEditor

271
eclipse_v01.book Seite 272 Montag, 30. Januar 2006 12:02 12

XML

Abb. 7.3: Projektverzeichnis des Sample XML Editors

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

7 – Eclipse und J2EE

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.

1. Das Plug-In XMLBuddy steht unter http://xmlbuddy.com/ zur Verfügung.

273
eclipse_v01.book Seite 274 Montag, 30. Januar 2006 12:02 12

XML

Abb. 7.5: Darstellung einer XML-Datei mit dem Editor XMLBuddy

Erzeugen einer DTD-Datei


Existiert noch keine DTD-Datei, so können wir über den Menüpunkt XML | GENERATE
DTD eine neue erzeugen. Diese ist für das XML-Dokument gültig, welches wir gerade be-
arbeiten. Weil diese DTD aber in der Regel nicht unseren Ansprüchen genügt, sollte sie nur
als Grundlage dienen und weiter bearbeitet werden.
Code-Assistent
XMLBuddy unterstützt uns auch beim Schreiben eines XML-Dokuments. Wenn eine gül-
tige DTD oder ein XML Schema angegeben ist, so werden jeweils die Elemente angezeigt,
die innerhalb eines Elements verwendet werden dürfen. Außerdem erscheinen die Attribute
zu einem Tag, wenn es gerade bearbeitet wird. Dieser Code-Assistent erleichtert das
Schreiben und reduziert mögliche Tippfehler.
Bewertung
Der XML Editor XMLBuddy genügt den Ansprüchen, die wir im Folgenden benötigen, um
beispielsweise Deployment-Deskriptoren und andere Konfigurationsdateien zu erzeugen.
Vor allem die Gültigkeitsüberprüfung und der Code-Assistent sind nützliche Features, die
in dem integrierten Editor von Eclipse nicht vorhanden sind. Auf diesem Gebiet gibt es wei-
tere Plug-Ins von Drittanbietern, die ähnliche Funktionalitäten besitzen. Wir wollen diese
aber an dieser Stelle nicht im Einzelnen betrachten.

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

7 – Eclipse und J2EE

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.

Abb. 7.6: Kommunikation zwischen Browser und Webserver

275
eclipse_v01.book Seite 276 Montag, 30. Januar 2006 12:02 12

Webanwendungen

7.2.2 Beispiel einer Webanwendung mit Servlets


Wir wollen uns zunächst einem sehr einfachen Beispiel widmen, um die einzelnen Schritte
im Ablauf von Webanwendungen nachzuvollziehen. In diesem Beispiel kann ein Benutzer
auf einem HTML-Dokument zwei Zahlen eingeben und auf einen Button klicken. Damit
wird eine Anfrage an einen Webserver gesendet, der diese Anfrage bearbeitet, die beiden
Zahlen addiert und ein neues HTML-Dokument mit der Summe der beiden Zahlen zurück-
sendet.
Um eine Webanwendung ausführen zu können benötigen wir einen Webserver. In diesem
Buch verwenden wir den Tomcat Webserver1 in der Version 5.5. Wir werden die Anwen-
dung zunächst in einem beliebigen Verzeichnis entwickeln und anschließend das Deploy-
ment auf den Webserver vornehmen.

Erstellung eines Projekts für eine Webanwendung mit Eclipse


Im ersten Schritt erzeugen wir ein neues Java-Projekt in Eclipse mit dem Projektnamen My-
Calculator2.
Ein Servlet ist eine Java-Klasse. Die kompilierte Version dieser Klasse (.class-Datei) muss
in einem bestimmen Unterverzeichnis des Webservers stehen, damit dieser darauf zugreifen
kann. Um nicht später die Dateien in ein anderes Verzeichnis kopieren zu müssen, geben wir
für dieses Projekt als DEFAULT OUTPUT FOLDER das Verzeichnis WEB-INF/classes vor.
Weiterhin wird die externe Bibliothek servlet-api.jar (bzw. servlet.jar bei älteren Versionen
des Tomcat Servers) benötigt, um Servlets entwickeln zu können. Diese liegt im Verzeich-
nis common/lib der Tomcat-Installation und im Klassenpfad unseres Projekts eingebunden.

Erstellung des Servlets


Nachdem wir nun ein neues Java-Projekt generiert haben, fügen wir diesem ein neues Pack-
age mit dem Namen com.entwickler.eclipsebuch.web hinzu. Als Servlet erzeugen
wir eine neue Java-Klasse, die von der abstrakten Klasse javax.servlet.http.Http-
Servlet abgeleitet ist. Wir bezeichnen sie mit Rechenmaschine und ordnen sie dem
Package com.entwickler.eclipsebuch.web zu. Das Servlet soll zwei Zahlen, die in
einem Browser eingegeben worden sind, addieren und das Ergebnis an den Browser zu-
rückschicken.
Die Servlet-Klasse erbt unter anderem die Methoden doGet bzw. doPost von HttpServ-
let. Je nach Art des Request (Get Request oder Post Request) wird eine der beiden Me-
thoden ausgeführt. Aus diesem Grund sollte zumindest eine überschrieben werden, so dass
ein Servlet auf eine Anfrage reagieren kann. Informationen einer Anfrage werden mit Hilfe
des so genannten Request-Objekts übermittelt, das als Parameter an die Methoden überge-
ben wird. Das Request-Objekt ist eine Instanz der Klasse javax.servlet.http.Http-
ServletRequest und kapselt die Daten, die vom Browser gesendet werden.

1. Download unter http://jakarta.apache.org/tomcat


2. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70201MyCalculator

276
eclipse_v01.book Seite 277 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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;

public class Rechenmaschine extends HttpServlet{


protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
PrintWriter out = response.getWriter();
out.print("<!DOCTYPE HTML PUBLIC ");
out.println("'-//W3C//DTD HTML 4.0 Transitional//EN'>");
out.println("<HTML><HEAD><TITLE>Addition: ");
out.println("</TITLE></HEAD><BODY>");
int x = Integer.parseInt(request.getParameter("x"));
int y = Integer.parseInt(request.getParameter("y"));
out.println("Berechnung: "+x+" + "+y+" = " + (x+y));
out.println("</BODY></HTML>");
}
}

HTML-Dokument zur Eingabe der Daten


Die Funktionalität des Servlets soll aus einem HTML-Dokument aufgerufen werden. Auf
diesem sollen zwei Zahlen eingegeben und bei Klick auf einen Button die Berechnung ge-
startet sowie das Ergebnis auf einem zweiten Dokument ausgegeben werden. Dazu fügen
wir dem Projekt eine neue Datei mit dem Namen eingabe.html hinzu. Der HTML-Code für
die Eingabemaske sieht wie folgt aus:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


<HTML>
<HEAD>
<TITLE>My Calculator</TITLE>
</HEAD>
<BODY>
<FORM action="calculator" method="get">
X: <INPUT type="text" name="x">

277
eclipse_v01.book Seite 278 Montag, 30. Januar 2006 12:02 12

Webanwendungen

Y: <INPUT type="text" name="y">


<INPUT type="submit" value="Berechnen" >
</FORM>
</BODY>

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:

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>rechner</servlet-name>
<servlet-class>
com.entwickler.eclipsebuch.web.Rechenmaschine
</servlet-class>
</servlet>

<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

7 – Eclipse und J2EE

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.

Abb. 7.7: Verzeichnisstruktur einer Webanwendung im Package Explorer / Navigator

In Eclipse gehen wir beim manuellen Deployment folgendermaßen vor:


쐌 Auswahl des Menüpunkts FILE | EXPORT
쐌 Auswahl der Exportart FILE SYSTEM
쐌 Markieren des gesamten Projekts und Auswahl des Verzeichnisses webapps der Tom-
cat-Installation als DESTINATION DIRECTORY oder Markieren des gesamten Verzeichnisses
WEB-INF sowie der Datei eingabe.html. Das DESTINATION DIRECTORY muss ein Unterver-
zeichnis des webapps-Verzeichnisses mit Namen MyCalculator sein.

Starten der Webanwendung


Nach dem Export der Dateien kann der Tomcat Webserver gestartet werden. Dazu ist die
Datei startup aus dem bin-Verzeichnis der Tomcat-Installation aufzurufen. Wir starten den
Browser und geben als URL http://localhost:8080/MyCalculator/eingabe.html an. In den
folgenden Beispielen gehen wir davon aus, dass Client und Server auf demselben Rechner
ausgeführt werden, und verwenden localhost als Rechnernamen. In realen Anwendungen
liegen Client und Server auf unterschiedlichen Rechnern und es muss die IP-Adresse oder
ein Alias angegeben werden.
Nach Eingabe der URL sehen wir im Browser die Eingabemaske (siehe Abb. 7.8).

279
eclipse_v01.book Seite 280 Montag, 30. Januar 2006 12:02 12

Webanwendungen

Abb. 7.8: Eingabemaske der ersten Webanwendung

Nach Klick auf den Button mit der Beschriftung BERECHNEN erscheint das HTML-Doku-
ment aus Abb. 7.9.

Abb. 7.9: Ausgabe der ersten Webanwendung

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>");
}

Weiterhin erweitern wir den Deployment-Deskriptor web.xml um das Tag <welcome-


file-list>. Mithilfe dieses Elements werden Dateien bzw. Dokumente festgelegt, die
standardmäßig ergänzt werden, wenn die Webanwendung ohne explizite Angabe eines
Dokuments aufgerufen wird. Durch die folgenden Zeilen kann eingabe.html in der URL
ausgelassen werden.

<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

7 – Eclipse und J2EE

Textfeldern keine gültigen Zahlen, erscheint nach Klick auf den Button BERECHNEN die
Meldung, die in Abb. 7.10 angezeigt wird.

Abb. 7.10: Ausgabe der Fehlermeldung

7.2.3 Beispiel einer Webanwendung mit Java Server Pages


Eine Java Server Page (JSP) ist ein Dokument, welches HTML-Befehle und Java-Code
trennt. Im Gegensatz zu den Servlets, bei denen die HTML-Tags etwas unübersichtlich im
Java-Code enthalten sind, gibt es bei den JSP-Dokumenten Bereiche für HTML-Tags und
welche für Java-Code. Das JSP-Dokument wird vom Webserver in Java-Code, also in ein
Servlet übersetzt und anschließend kompiliert. Danach erfolgt die Verarbeitung wie bei den
selbst erstellten Servlets.

Erstellen des JSP-Dokuments


Um die Technologie im Detail zu untersuchen, legen wir in Eclipse ein neues Projekt mit
dem Namen MyCalcultorJSP1 an und erzeugen direkt im Projektverzeichnis eine Datei mit
dem Namen ausgabe.jsp. Der Code dieses Dokuments sieht dann wie folgt aus:

<%@ page language="java" %>

<%-- Java-Code (Skriptlet) --%>


<%
String ausgabe;
try{
int x = Integer.parseInt(request.getParameter("x"));
int y = Integer.parseInt(request.getParameter("y"));
ausgabe = "Berechnung: "+x+" + "+y+" = " + (x+y);
}
catch(Exception ex) {
ausgabe = "Bitte geben Sie gültige ganze Zahlen ein.";
}
%>

<%-- HTML-Code --%>


<html>
<head>
<title>Calculator</title>
</head>

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70202MyCalculatorJSP

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:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web


Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<welcome-file-list>
<welcome-file>eingabe.html</welcome-file>
</welcome-file-list>
</web-app>

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.

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70202MyCalculatorJSP

282
eclipse_v01.book Seite 283 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

Nach Eingabe von http://localhost:8080/MyCalculatorJSP/ in einem Browser auf demsel-


ben Rechner ist der für den Benutzer sichtbare Ablauf der Anwendung identisch zu dem des
vorherigen Beispiels. Allerdings wird beim ersten Aufruf des JSP-Dokuments aus diesem
ein Servlet generiert und kompiliert. Die entsprechenden Dateien liegen im work-Verzeich-
nis der Tomcat-Installation.
Nachdem wir nun gesehen haben, welche einzelnen Schritte für die Generierung einer
Webanwendung notwendig sind, untersuchen wir im Folgenden, wie uns ein Plug-In bei
der Entwicklung unterstützen kann.

7.3 Eclipse-Projekt Web Tools Platform (WTP)

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

Eclipse-Projekt Web Tools Platform (WTP)

7.3.2 Editoren

Structured Source Editor


Auf einem JSP-Dokument gibt es in der Regel unterschiedliche Teile, die in verschiedenen
Sprachen wie HTML, Java Script, Java etc. geschrieben sind. Die Möglichkeit, innerhalb
eines Dokuments die verschiedenen Sprachen zu vereinen, basiert auf dem Structured
Source Editor (SSE) Framework. SSE erweitert den Eclipse Editor auf den Gebieten, die
über den Java Editor hinausgehen. Die Web Tools Platform bietet Unterstützung bei der Er-
stellung von Dokumenten mit XML, JSP, HTML, XHTML, CSS, DTD oder JavaScript.
Die SSE-basierten Editoren sind so entwickelt, dass sie miteinander verknüpft werden kön-
nen. So ist das Editieren von HTML und Java Code auf einem JSP-Dokument identisch
zum Editieren von HTML in einem HTML-Dokument bzw. von Java Code im gewöhnli-
chen Java Editor.
SSE bietet dabei in Abhängigkeit von der Umsetzung für eine Sprache unter anderem fol-
genden Features:
쐌 Highlighting
쐌 Refactoring
쐌 Content Assist
쐌 Quick Fix/Assist
쐌 Parameter/Attribute Hints
쐌 Property Sheet
쐌 Document/Element Formatting
쐌 Outline View
쐌 Hover Info
쐌 Toggle Comment
쐌 Delimiter Highlighting (bracket matching)

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

7 – Eclipse und J2EE

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

1. Download unter www.eclipse.org.

285
eclipse_v01.book Seite 286 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekt Web Tools Platform (WTP)

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).

Abb. 7.11: Project Explorer View in der J2EE-Perspektive der WTP

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.

1. Download von XDoclet unter http://www.xdoclet.net/xdoclet/index.html.


Es ist wichtig, die bin-Version zu verwenden.

286
eclipse_v01.book Seite 287 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

Wie neue Server konfiguriert und in die WTP eingebunden werden, wird in Kapitel 7.6 aus-
führlich beschrieben.

7.3.5 Entwicklung einer Webanwendung


In diesem Kapitel wird gezeigt, wie wir eine Webanwendung mithilfe der WTP erzeugen.
Wir verwenden wiederum das einfache Beispiel von oben, bei dem lediglich zwei Zahlen
addiert werden.

Dynamic Web Project


Zunächst erzeugen wir ein neues Projekt und gehen dabei wie folgt vor:
쐌 Auswahl von FILE | NEW | DYNAMIC WEB PROJECT
쐌 Festlegen des Projektnamens mit WTP-Web011
쐌 Erweitern der Eingabemöglichkeiten durch Klick auf den Button SHOW ADVANCED <<
쐌 Als TARGET RUNTIME soll der Tomcat-Server in der Version 5.5 eingetragen werden.
Dazu klicken wir auf den Button NEW, wählen bei APACHE den entsprechenden Server
aus und geben das Projektverzeichnis an (siehe Abb. 7.12).

Abb. 7.12: Festlegen des Tomcat Server v.5.5 als Webserver

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).

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70301WTP-Web01

287
eclipse_v01.book Seite 288 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekt Web Tools Platform (WTP)

Abb. 7.13: Dynamic Web Project in der Project Explorer View

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

7 – Eclipse und J2EE

Abb. 7.14: WTP-Projekt, Erstellen eines Servlets

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.

protected void doGet(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException{

289
eclipse_v01.book Seite 290 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekt Web Tools Platform (WTP)

PrintWriter out = response.getWriter();


out.print("<!DOCTYPE HTML PUBLIC ");
out.println("'-//W3C//DTD HTML 4.0 Transitional//EN'>");
out.println("<HTML><HEAD><TITLE>Addition: ");
out.println("</TITLE></HEAD><BODY>");
int x = Integer.parseInt(request.getParameter("x"));
int y = Integer.parseInt(request.getParameter("y"));
out.println("Berechnung: "+x+" + "+y+" = " + (x+y));
out.println("</BODY></HTML>");
}

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:

<form action="Calculator" method="get">


<p>Geben Sie zwei Zahlen ein:</p>
<p>x: <input type="text" name="x" value="0"></p>
<p>y: <input type="text" name="y" value="0"></p>
<p><input type="submit" name="submit" value="Senden"></p>
</form>

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

7 – Eclipse und J2EE

Abb. 7.15: Einbinden des Tomcat Webservers in Eclipse

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

Eclipse-Projekt Web Tools Platform (WTP)

7.3.6 Beispielanwendung Kreditkartenprüfer


Nachdem wir anhand von einfachsten Beispielen die Technologie und die Struktur einer
Webanwendung betrachtet haben, wollen wir uns jetzt mit den Möglichkeiten von Web-
anwendungen beschäftigen. Häufig müssen Anwendungen Anfragen (Requests) eines Be-
nutzers (Browsers) verarbeiten und dazu mit anderen Systemen außerhalb des Webservers
kommunizieren. Eine große Rolle spielen dabei Datenbanken, aus denen bestimmte Infor-
mationen gelesen oder in die Daten gespeichert werden sollen.
Wir wollen nun eine Webanwendung entwickeln, bei der der Benutzer die Gültigkeit einer
Kreditkartennummer überprüfen kann. Dazu sollen auf einer Webseite Name und Kredit-
kartennummer eingegeben werden. Nach dem Senden der Informationen an den Webserver
wird in einer Datenbank überprüft, ob der Kunde mit dem angegebenen Namen und der
Nummer existiert. Zurückgegeben wird die Information, ob die Karte gültig ist oder nicht.
Für diese Beispielanwendung benötigen wir eine Datenbank. Prinzipiell können wir auf
jede beliebige Datenbank zugreifen, für die ein entsprechender JDBC-Treiber existiert. Wir
verwenden die Datenbank MySQL, die mit einem JDBC-Treiber kostenlos zur Verfügung
gestellt wird1.

Anlegen einer neuen Datenbank in MySQL


Zuerst müssen wir die Datenbank anlegen, auf die wir zugreifen wollen. In dieser Beispiel-
anwendung besteht die Datenbank lediglich aus der Tabelle Kunden:

CREATE TABLE Kunden (


kkNummer varchar(20) NOT NULL PRIMARY KEY,
kName varchar(50) NOT NULL,
aktiv tinyint(1) NOT NULL default 0
);

Mithilfe der Batch-Datei kkp.sql2 kann die Datenbank erzeugt werden. Dazu starten wir die
MySQL-Konsole und geben folgende Zeile ein:

mysql> source ../kkp.sql

Erstellen des Eclipse-Projekts zur Beispielanwendung


Wir erstellen ein neues DYNAMIC WEB PROJECT für unsere Beispielanwendung. Dieses Pro-
jekt bezeichnen wir mit KKP und wählen als TARGET RUNTIME den Tomcat Webserver. An-
schließend testen wir die Datenbankverbindung, indem wir den Database Explorer als neue
View einfügen und dort im Kontextmenü über NEW CONNECTION eine neue Verbindung zur
Datenbank kkp herstellen. Für diese Verbindung benötigen wir einen JDBC-Treiber. Wir
verwenden MySQL Connector/J in der Version 3.1.11.

1. Der Download von MySQL ist unter http://www.mysql.com/ möglich.


2. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70303KKP-SQL

292
eclipse_v01.book Seite 293 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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)

Abb. 7.16: Spezifikation der Parameter für eine Datenbankverbindung

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.

Herstellen einer Datenbankverbindung


Für die Herstellung einer Datenbankverbindung wird jeweils ein entsprechender JDBC-
Treiber benötigt. Dieser muss im Classpath einer Anwendung existieren, damit diese An-
wendung ihn verwenden kann. Bei einer J2EE-Anwendung bzw. einer Webanwendung
muss der Treiber dem Server bekannt sein. Wollen wir in einer Webanwendung beispiels-
weise die MySql-Datenbank ansprechen, dann können wir die Treiberdatei (mysql-connec-
tor-java-3.1.11-bin.jar) in das Verzeichnis WEB-INF/lib der Webanwendung kopieren.
Eine andere Möglichkeit besteht darin, die Treiberdatei in das shared/lib-Verzeichnis der
Tomcat-Installation zu kopieren.

293
eclipse_v01.book Seite 294 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekt Web Tools Platform (WTP)

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 class Pruefung {


private Connection conn;
private PreparedStatement ps;

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 = ?";

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70304KKP

294
eclipse_v01.book Seite 295 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

ps = conn.prepareStatement(sql);
} catch (Exception e) {
System.out.println("Es ist ein Fehler aufgetreten.");
}
}

public boolean gueltig(String name, String nummer){


try {
ResultSet rs;
ps.setString(1,nummer);
ps.setString(2,name);
rs = ps.executeQuery();
if (rs.next()){
if (rs.getBoolean("aktiv")){
return true;
}
}
return false;
} catch (Exception e) {
return false;
}
}
}

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.

Eingabeseite der Webanwendung


Die Seite zur Eingabe der Kreditkartennummer und des Kundennamens besteht aus reinem
HTML. Auf ihr sind ein Formular mit den beiden Textfeldern für die Eingabe sowie ein
SUBMIT-Button definiert. Mithilfe des action-Attributs des <form>-Tags ist vorgegeben,
dass bei Klick auf den Button die Seite pruefung.jsp aufgerufen wird. Wir erzeugen die
HTML-Seite über das Kontextmenü des WebContent-Verzeichnisses des Projekts (NEW |
HTML) und bezeichnen sie mit index.html. Die Eingabeseite sieht folgendermaßen aus:

<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

Eclipse-Projekt Web Tools Platform (WTP)

<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>

Integration der Java Bean in ein JSP-Dokument


Von der Eingabeseite aus kann das JSP-Dokument pruefung.jsp aufgerufen werden. Das
JSP-Dokument dient zur Überprüfung der eingegebenen Daten zu einer Kreditkarte. An-
schließend ist eine entsprechende Ausgabe zur Gültigkeit der Karte anzuzeigen. Auf dem
JSP-Dokument wird aus diesem Grund zunächst ein Objekt der Klasse Pruefung instan-
ziiert. Das Objekt ist eine Java Bean, deren Lebensdauer mit angegeben wird. Es gibt fol-
gende Gültigkeitsbereiche
쐌 Page: Die Bean gilt nur auf der aktuellen Seite.
쐌 Request: Die Bean gilt für den gesamten Request.
쐌 Session: Die Bean gilt für einen Benutzer während seiner Sitzung.
쐌 Application: Die Bean gilt während der gesamten Anwendung. Alle Benutzer grei-
fen auf dieselbe Bean zu. Wenn sie einmal instanziiert ist, wird sie erst bei Beendigung
der Anwendung zerstört.
Wir erzeugen das JSP-Dokument, indem wir im Kontextmenü des Verzeichnisses WebCon-
tent NEW | JSP auswählen. Bei Verwendung des TEMPLATES NEW JSP FILE (HTML) erhalten
wir ein JSP-Dokument, welches im Wesentlichen aus HTML-Tags besteht. Da wir von die-
sem Dokument eine Java Bean ansprechen werden, müssen wir diese instanziieren. Dazu
vergeben wir eine ID, also einen (Objekt-)Namen, unter dem wir die Bean im JSP-Doku-
ment ansprechen wollen. Weiterhin sind der Gültigkeitsbereich und der Klassenname mit
Package-Bezeichner anzugeben, von dem die Bean abgeleitet werden soll. Diese Angaben
zur Instanziierung sollten am Anfang des JSP-Dokuments stehen:

<%@ page language="java" contentType="text/html;


charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<jsp:useBean id="pruefungBean" scope="application"
class="com.entwickler.eclipsebuch.kartenpruefer.Pruefung" />

296
eclipse_v01.book Seite 297 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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.

<%@ page language="java" contentType="text/html;


charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<jsp:useBean id="pruefungBean" scope="application"
class="com.entwickler.eclipsebuch.kartenpruefer.Pruefung" />

<%
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>

Die Klasse com.entwickler.eclipsebuch.kartenpruefer.Pruefung muss im


Verzeichnis WEB-INF/classes der Webanwendung stehen, damit der Tomcat Webserver
diese findet. Außerdem muss der JDBC-Treiber in dem entsprechenden lib-Verzeichnis der
Anwendung stehen. Bei Verwendung der WTP wird im Verzeichnis .deployables das Web-
projekt automatisch erzeugt (siehe Abb. 7.17).

297
eclipse_v01.book Seite 298 Montag, 30. Januar 2006 12:02 12

Eclipse-Projekt Web Tools Platform (WTP)

Abb. 7.17: Darstellung der Webanwendung

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.

Deployment auf den Webserver


Das Deployment auf den Webserver ist im vorherigen Abschnitt 7.3.5 detailliert beschrie-
ben. Es besteht die Möglichkeit, über die Servers View den Webserver (Apache Tomcat 5.5)
zu starten und das Projekt zu veröffentlichen.
Eine alternative Vorgehensweise sieht vor, das Webprojekt aus dem Verzeichnis .deploy-
ables in das webapps-Verzeichnis des Webservers zu kopieren und den Server direkt zu
starten.
Zum Entwickeln und Testen einer Anwendung ist sicherlich die erste Variante geeignet,
wohingegen die zweite für das Deployment auf den realen Webserver verwendet werden
sollte.

7.3.7 Server Debugging


Beim Starten des Webservers aus Eclipse heraus gibt es die Möglichkeit, den Debug-
Modus zu wählen. Auf diese Weise können wir die Java Beans, die auf dem Webserver ab-
laufen, debuggen. Dazu setzen wir wie gewohnt einen oder mehrere Haltepunkte (Break-
points) und starten die Webanwendung, indem wir im Kontextmenü der Startseite DEBUG
AS | DEBUG ON SERVER auswählen. Beim Erreichen des ersten Haltepunkts wird der Pro-
grammablauf unterbrochen und in einzelnen Schritten oder bis zum nächsten Haltepunkt
etc. fortgeführt.
Es besteht ebenfalls die Möglichkeit, innerhalb der Scriptlets auf einem JSP-Dokument
Haltepunkte zu setzen (Toggle Breakpoints). Dadurch ist es möglich, den Ablauf inner-
halb des JSP-Dokuments näher zu untersuchen und dabei die Werte der Variablen, Re-
quest-, Response-Objekte etc. zu überwachen.

298
eclipse_v01.book Seite 299 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

7.3.8 Lomboz Plug-In und WTP


Das Lomboz Plug-In, das von ObjectWeb zur Verfügung gestellt wird, basiert auf der WTP.
Da ObjectWeb den Programmcode des ehemaligen Lomboz Plug-In eingebracht hat, gehen
dessen Funktionalitäten mit in die WTP ein. Es gibt nach wie vor eine Installation des Lom-
boz Plug-In neben WTP. Allerdings bietet dieses keine nennenswerten zusätzlichen Funk-
tionalitäten im Vergleich zur WTP. Aus diesem Grund wird Lomboz nicht weiter unter-
sucht.

7.4 J2EE-Anwendungen mit Enterprise Java Beans


Nachdem wir uns mit Webanwendungen beschäftigt haben, wollen wir die Architektur um
eine weitere Schicht erweitern. Dazu untersuchen wir, wie Teile einer Anwendung auf ei-
nem Applikationsserver ablaufen können. Ein J2EE-Applikationsserver ist eine Ablauf-
umgebung für Java-Komponenten (Enterprise Java Beans). Eine Anwendung kann von au-
ßen auf diese Komponenten zugreifen. Der J2EE-Applikationsserver berücksichtigt dabei
Zugriffsrechte und andere Sicherheitsaspekte, beinhaltet ein Transaktionsmanagement und
ermöglicht das persistente Speichern von Daten. Im Folgenden werden wir Enterprise Java
Beans (EJB) bei einem J2EE-fähigen Applikationsserver (z.B. JBoss) registrieren, um dann
aus einer Java-Anwendung darauf zugreifen zu können. Zur Entwicklung von J2EE-An-
wendungen, insbesondere EJBs, benötigen wir außerdem das J2EE SDK1 von Sun.

7.4.1 Grundlegende Begriffe


Ein Applikationsserver stellt verschiedene Dienste (Services) zur Verfügung. Für ein bes-
seres Verständnis der Konfiguration von EJB-Komponenten für diese Dienste wollen wir
diese zunächst im Einzelnen betrachten.

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.

1. Das J2EE SDK steht unter http://java.sun.com/j2ee/ kostenlos zur Verfügung.

299
eclipse_v01.book Seite 300 Montag, 30. Januar 2006 12:02 12

J2EE-Anwendungen mit Enterprise Java Beans

쐌 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.

Namensdienst (Naming Service)


Ein Namensdienst verwaltet Zuordnungen von Namen zu bestimmten Datenobjekten. Alle
Datenobjekte werden nach einem standardisierten Namen angesprochen. Der Client ver-
wendet einen Namensdienst, um ein Objekt zu identifizieren. Häufig verwendete Namens-
dienste sind beispielsweise:
쐌 Domain Name Service (DNS): Dieser Namensdienst wird im Internet verwendet, um
die Zuordnung eines Domain Name auf eine IP-Adresse vorzunehmen. Es handelt sich
hierbei um einen verteilten Namensdienst, weil die zugrunde liegende Datenbank auf
vielen verschiednen Servern liegt, die sich gegenseitig aktualisieren können.
쐌 Common Object Service (COS) Naming: Dieser Namensdienst wird von CORBA ver-
wendet, um die Referenzen auf CORBA-Objekte zu verwalten.
Die Namensdienste speichern in der Regel nicht direkt die Objekte, sondern lediglich die
Referenzen auf diese. Beim DNS wird beispielsweise die IP-Adresse gespeichert, über die
auf den entsprechenden Webserver zugegriffen werden kann. Die Daten selber werden vom
Namensdienst nicht bereitgestellt.

300
eclipse_v01.book Seite 301 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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.

Verzeichnisdienst (Directory Service)


Ein Verzeichnisdienst ist eine Art Datenbank, die für den Lesezugriff optimiert ist. Die In-
formationen werden in einem hierarchischen Informationsmodell gespeichert. Die in einem
Namensdienst definierten Namen können von einem Verzeichnisdienst gespeichert wer-
den. Der Verzeichnisdienst übernimmt dann das Auffinden des Namens und der Namens-
dienst liefert die Referenz auf ein Objekt.
Der Domain Name Service ist ebenfalls ein Directory Service. Der Directory Service DNS
hat die so genannten Domain Names gespeichert. Bei einer Anfrage wird der entsprechende
Eintrag gesucht und die korrespondierende IP-Adresse zurückgegeben. Der Dienst ist
hochgradig für diese Aufgabe spezialisiert und besitzt sehr effiziente Indizierungen, Such-
und Caching-Verfahren. Weitere Verzeichnisdienste sind:
쐌 Network Information Services (NIS)
쐌 Novell Directory Service (NDS)
쐌 Windows NT Domains/Active Directory Service
Diese Verzeichnisdienste verwalten zusätzlich Zugriffsrechte für Benutzer und Benutzer-
gruppen sowie für Computer oder bestimmte IP-Adressen.

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

J2EE-Anwendungen mit Enterprise Java Beans

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.

Abb. 7.18: Interaktion JNDI/LDAP und Namensdienste

7.4.2 Enterprise Java Bean (EJB)


Enterprise Java Beans (EJBs) sind Komponenten, die nach einem von Sun Microsystems
entwickelten Standard spezifiziert werden. Sie werden in verteilten J2EE-Anwendungen
eingesetzt und basieren auf der Programmiersprache Java. Es werden folgende Arten von
EJBs unterschieden:
쐌 Stateless Session Beans
쐌 Stateful Session Beans
쐌 Entity Beans (Container Managed/Bean Managed Persistence)
쐌 Message Driven Beans

302
eclipse_v01.book Seite 303 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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.

Stateless Session Beans


Die statuslosen Session Beans können für einfache Methodenaufrufe verwendet werden. Es
werden keinerlei Informationen gespeichert, so dass jede Anfrage unabhängig von der vor-
herigen bearbeitet wird. Prinzipiell genügt es, ein Objekt zu instanziieren, auf das alle
Clients zugreifen können. Eine solche Session Bean wird in der Regel verwendet, um eine
Funktionalität abzubilden, die mit einer Anfrage bearbeitet werden kann und das Ergebnis
zurückliefert. Beispielsweise kann für die Kreditkartenprüfung eine statuslose Session
Bean eingesetzt werden, da vom Client aus alle Informationen zu einer Anfrage an den Ser-
ver gesendet, dort verarbeitet und die Ergebnisse zurückgesendet werden. Bei einer weite-
ren Anfrage benötigt der Server keine Statusinformationen der vorherigen Anfrage. Neh-
men wir aber an, dass die Kreditkartenprüfung nur bestimmte Clients nutzen dürfen, so ist
beispielsweise eine Authentifizierung erforderlich. Wenn wir weiterhin mit statuslosen
Session Beans arbeiten wollen, muss der Client sich bei jeder Anfrage neu authentifizieren.
Da keine Informationen zu einer Anfrage gespeichert werden, hat der Server bei einer wei-
teren Anfrage „vergessen“, dass der Client sich schon einmal authentifiziert hat.

Stateful Session Beans


Bei den Stateful Session Beans bleiben hingegen Statusinformationen zu einer Sitzung er-
halten. Das bedeutet, dass bei mehreren Anfragen eines Clients während einer Sitzung auf
bestimmte Daten zugegriffen werden kann. Es können natürlich mehrere Sitzungen von un-
terschiedlichen Clients gleichzeitig verarbeitet werden, wobei für jede Session ein eigenes
Objekt erzeugt wird.
Eine Stateful Session Bean können wir beispielsweise nutzen, wenn wir die Kreditkarten-
prüfung mit Authentifizierung des Clients so realisieren wollen, dass der Client sich ledig-
lich einmal zu Beginn einer Sitzung authentifizieren muss und anschließend beliebig viele
Kreditkartenprüfungen durchführen kann.
Eine detaillierte Betrachtung der Session Beans und ihrer Verwendung erfolgt in Abschnitt
7.5.

303
eclipse_v01.book Seite 304 Montag, 30. Januar 2006 12:02 12

J2EE-Anwendungen mit Enterprise Java Beans

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.

Message Driven Beans


Message Driven Beans (MDB) verwenden den Java Messaging Service (JMS). Über den so
genannten Message Listener empfangen sie Nachrichten. Abhängig von der Kommunika-
tionsart (Queue oder Topic) werden die Nachrichten an die Bean weitergeleitet oder von der
Bean abgeholt. Liegt eine Nachricht bei der Bean vor, wird ein Ereignis ausgelöst und eine
vordefinierte Methode aufgerufen.
Ein Client kann mit einer MDB demnach nur kommunizieren, indem er Nachrichten ver-
sendet. Direkte Methodenaufrufe sind vom Client nicht möglich. Die Kommunikation er-
folgt anonym und damit statuslos. Die Besonderheit der MDBs liegt aber vor allem darin,
dass bei der Kommunikation über eine Queue diese asynchron und zeitunabhängig erfolgen
kann. Bei der Kommunikation über ein Topic können dagegen mehrere MDBs dieselben
Nachrichten abonnieren und empfangen, so dass vom Client diese nicht mehrfach gesendet
werden müssen.
Der Abschnitt 7.12 beschäftigt sich detailliert mit den Kommunikationsvarianten Topic und
Queue sowie den Message Driven Beans.

7.4.3 Zugriff eines Clients auf eine EJB

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

7 – Eclipse und J2EE

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

Abb. 7.19: Vereinfachte Darstellung des Zugriffs auf EJBs

7.5 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.

1. Download unter http://java.sun.com/j2ee/

306
eclipse_v01.book Seite 307 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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.*;

public class WarenkorbBean implements SessionBean {


private String kName;
private String kNr;
private Vector<String> inhalt;

// ejbCreate-Methoden
public void ejbCreate(String name) throws CreateException {
this.ejbCreate(name,"0");
}

public void ejbCreate(String name, String nr)


throws CreateException {
kName = name;
kNr = nr;
inhalt = new Vector();
}

// Geschäftsmethoden
public void hinzufuegen(String artikel) {
inhalt.addElement(artikel);
}

public void entfernen(String artikel) {


inhalt.removeElement(artikel);
}

public Vector<String> getInhalt() {


return inhalt;
}

// Konstruktor
public WarenkorbBean() {}

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70501Warenkorb

307
eclipse_v01.book Seite 308 Montag, 30. Januar 2006 12:02 12

Session Beans

// Methoden des implementierten Interfaces SessionBean


public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext sc) {}
}

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

7 – Eclipse und J2EE

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:

public interface WarenkorbHome extends javax.ejb.EJBHome{

public Warenkorb create(String name)


throws javax.ejb.CreateException,java.rmi.RemoteException;
public Warenkorb create(String name , String nr)
throws javax.ejb.CreateException,java.rmi.RemoteException;
}

Das Local Home Interface ist ähnlich aufgebaut:

package com.entwickler.eclipsebuch.warenkorb;

public interface WarenkorbLocalHome extends javax.ejb.EJBLocalHome


{
public void create(String name)
throws javax.ejb.CreateException;

public void create(String name, String nr)


throws javax.ejb.CreateException;
}

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;

public interface Warenkorb extends javax.ejb.EJBObject {


public void hinzufuegen(String artikel)
throws java.rmi.RemoteException;

309
eclipse_v01.book Seite 310 Montag, 30. Januar 2006 12:02 12

Session Beans

public void entfernen(String artikel)


throws java.rmi.RemoteException;
public java.util.Vector<String> getInhalt()
throws java.rmi.RemoteException;
}

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;

public interface WarenkorbLocal extends javax.ejb.EJBObject {


public void hinzufuegen(String artikel);
public void entfernen(String artikel);
public java.util.Vector<String> getInhalt();
}

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:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.
//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">

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

7 – Eclipse und J2EE

쐌 <enterprise-beans> (Die Angabe von mindestens einer EJB ist notwendig.)


Hier werden die EJBs angegeben, die in der jar-Datei zum Deskriptor vorhanden sein
müssen. Innerhalb dieses Elements werden die Tags <entity>, <session> oder
<message-driven> verwendet, um die speziellen EJBs festzulegen.
쐌 <assembly-descriptor> (optional)
Hier wird definiert, wie eine EJB in einer Anwendung verwendet wird. Es werden Rol-
len, Zugriffsrechte für einzelne Methoden angegeben oder das Transaktionsverhalten
definiert.
Der Rumpf des Deployment-Deskriptors sieht für das Warenkorb-Beispiel mit der einzigen
EJB WarenkorbBean wie folgt aus.

<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>

<!-- Assembly Descriptor -->


<assembly-descriptor >
</assembly-descriptor>
</ejb-jar>

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

Konfiguration der WTP für einen neuen Server

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:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" "http://
www.jboss.org/j2ee/dtd/jboss_3_0.dtd">

<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.

7.6 Konfiguration der WTP für einen neuen Server


In Kapitel 7.3.8 haben wir bei der Entwicklung von Webanwendungen gesehen, wie wir die
Web Tools Platform für das Deployment auf den Tomcat Webserver konfigurieren müssen.
Um das Deployment auf einen Server vorzunehmen, der noch nicht vorkonfiguriert ist, be-

312
eclipse_v01.book Seite 313 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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.

7.6.1 Server-Definitionsdatei jboss4.serverdef


Im Unterverzeichnis servers des Plug-In-Projekts com.entwickler.eclipsebuch.jboss4 er-
zeugen wir eine XML-Datei mit dem Namen jboss4.serverdef. Diese enthält die Konfigu-
rationsdaten des JBoss-Applikationsservers der Version 4.0.2. Für welchen Server die Kon-
figuration vorgenommen wird, ist dabei grundsätzlich unerheblich. Die entsprechenden
Daten müssen jeweils für andere Server angepasst werden.

Definition der Namespaces


Der Kopf der Datei jboss4.serverdef ist wie folgt aufgebaut. Hier erfolgt die Festlegung der
Kodierung des XML-Dokuments und der Namespaces:

<?xml version="1.0" encoding="UTF-8"?>


<tns:ServerRuntime
xmlns:tns=
"http://eclipse.org/jst/server/generic/ServerTypeDefinition"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://eclipse.org/jst/server/generic/
ServerTypeDefinition ServerTypeDefinitionSchema.xsd"
name="JBOSS 4.0.2" version="v4.0.2">

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70701WTPKonfiguration

313
eclipse_v01.book Seite 314 Montag, 30. Januar 2006 12:02 12

Konfiguration der WTP für einen neuen Server

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

7 – Eclipse und J2EE

<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

Konfiguration der WTP für einen neuen Server

<classpath id="jboss.project" >


<archive path="${classPath}/client/jbossall-client.jar" />
<archive path=
"${classPath}/server/default/lib/javax.servlet.jar" />
</classpath>

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:

<classpath id="jboss" >


<archive path="${javaHome}/lib/tools.jar"/>
<archive path="${javaHome}/jre/lib"/>
<archive path="${classPath}/server/${serverConfig}/conf"/>
<archive path="${classPath}/bin/run.jar" />
<archive path=
"${classPath}/server/${serverConfig}/lib/log4j.jar"/>
</classpath>

Angaben zum Starten und Stoppen des JBoss Servers


Zum Starten und Stoppen des JBoss Servers existieren im bin-Verzeichnis die beiden
Bibliotheken run.jar bzw. shutdown.jar. In run.jar gibt es die Klasse org.jboss.Main,
die zum Starten des Servers dient. Dabei kann beispielsweise mit –c die Startkonfiguration
(z.B. –c default) übergeben werden.
In der shutdown.jar dient die Klasse org.jboss.Shutdown zum Stoppen des Servers.
Dabei ist das Argument –S zu übergeben.
In der Konfigurationsdatei sind die beiden Elemente start und stop dazu da, diese An-
gaben zu speichern. Folgende Elemente stehen für die Konfiguration zur Verfügung:
쐌 mainClass: Klasse für das Starten bzw. Stoppen des Servers
쐌 workingDirectory: Verzeichnis der jar-Dateien run.jar bzw. shutdown.jar
쐌 programArguments: Argumente für den Aufruf der Programme
쐌 vmParameters: Parameter für die Virtuelle Maschine

316
eclipse_v01.book Seite 317 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

쐌 classpathReference: verwendeter Classpath


쐌 debugPort: Port, den der Eclipse Debugger im Debug-Modus verwendet
쐌 external: Anwendung oder Skript, auf die bzw. das verwiesen wird
In der Datei jboss4.serverdef wird das Element wie folgt definiert:

<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

Konfiguration der WTP für einen neuen Server

Diese so genannten Ant-Skripte können für unterschiedliche Aufgaben geschrieben und


aus Eclipse heraus gestartet werden. Für das Deployment und das Undeployment von EJBs,
Web- und Enterprise-Anwendungen auf den JBoss Server wird im Unterverzeichnis build-
files die Datei jboss4.xml definiert:

<project name="deployextension" default="deploy.j2ee.web"


basedir=".">
<target name="deploy.j2ee.web">
<jar destfile="${project.working.dir}/${module.name}.war">
<zipfileset dir="${module.dir}">
<include name="**/*.*"/>
<exclude name="**/*.war"/>
</zipfileset>
</jar>
<move file="${project.working.dir}/${module.name}.war"
todir="${server.publish.dir}"/>
</target>
<target name="deploy.j2ee.ejb"> ... </target>
<target name="deploy.j2ee.ear"> ... </target>

<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>

Ant Publisher des Plug-In org.eclipse.jst.server.generic.core


In der Datei jboss4.serverdef werden die so genannten Publisher definiert. Diese verweisen
auf die Build Files (z.B. buildfiles/jboss4.xml) bzw. auf die darin enthaltenen Targets (z.B.
deploy.j2ee.web). Auf diese Weise wird der Aufruf der jeweiligen Ant-Skripte von der
Eclipse Web Tools Platform aus gesteuert. Diese Steuerung übernimmt das Plug-In org.
eclipse.jst.server.generic.core, welches den Extension Point genericpublisher besitzt.
Für den ist wiederum org.eclipse.jst.server.generic.antpublisher als ID für
diesen Extension Point angegeben. Dieser verwendet die Klasse AntPublisher aus dem
Package org.eclipse.jst.server.generic.core.internal, die die Verarbeitung
der Ant-Skripte zum Deployment und Undeployment übernimmt.1
In der plugin.xml des Plug-In org.eclipse.jst.server.generic.core erfolgt die Festlegung in
den Zeilen:

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

7 – Eclipse und J2EE

...
<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>
...

In diesem Plug-In (org.eclipse.jst.server.generic.core) müssen wir keine Änderungen vor-


nehmen. Wir lesen hier nur die ID ab, die wir im Folgenden für die Definition der Publisher
in der Server-Definitionsdatei jboss4.serverdef benötigen.
Angabe des Ant Publisher im Element publisher von jboss4.serverdef
In der jboss4.serverdef wird das Element publisher definiert. Hier wird als id der Exten-
sion Point genericpublisher des Plug-In org.eclipse.jst.server.generic.core verwendet.
Weiterhin erfolgt die Angabe, wo das Build File mit den Ant-Skripten liegt. Anschließend
werden den Befehlen des Ant Publisher die Bezeichnungen der Targets des Ant-Skripts zu-
geordnet.

<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

Konfiguration der WTP für einen neuen Server

<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

7 – Eclipse und J2EE

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>

7.6.2 7.6.2 Konfiguration der plugin.xml


Neben der Definition des XML-Dokuments jboss4.serverdef und des Build Files
jboss4.xml müssen zusätzlich noch Einstellungen in der plugin.xml des Plug-Ins gemacht
werden. Dabei sind die folgenden Elemente zu definieren:
쐌 Extension Point org.eclipse.wst.server.core.runtimeTypes, Element runtimeType
In diesem Bereich werden allgemeine Angaben für den Server gemacht, z.B. Name und
Beschreibung für die Ausgabe in Eclipse oder die Gruppe, unter der der Server ange-
zeigt wird (JBoss). Außerdem wird festgelegt, für welche Art von Modulen der Server
verwendet werden kann:

321
eclipse_v01.book Seite 322 Montag, 30. Januar 2006 12:02 12

Konfiguration der WTP für einen neuen Server

<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, Element serverType


In diesem Bereich werden spezielle Angaben für eine Instanz eines Servers gemacht,
Startkonfiguration, Timeout-Variablen etc.:

<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

7 – Eclipse und J2EE

쐌 Extension Point org.eclipse.wst.server.ui.serverImages, Element image


In diesem Bereich werden die Dateinamen der Icons referenziert:

<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, Element fragment


Die Angabe des Wizards in dem Element fragment führt dazu, dass der entsprechende
Server bei der Auswahl der Server mit dem angegebenen Icon angezeigt wird (siehe
Abb. 7.20):

<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,


Element serverdefinition
Angabe des Ortes der Serverdefinitionsdatei jboss4.serverdef:

<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

Konfiguration der WTP für einen neuen Server

쐌 Extension Point org.eclipse.wst.common.project.facet.core.runtimes


Hier werden die von dem Server unterstützten Versionen für Web-, J2EE-Anwendun-
gen etc. angegeben:

<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


Die Angabe ist notwendig, damit der Server im Assistenten zur Erstellung eines neuen
EJB-Projekts erscheint:

<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

7 – Eclipse und J2EE

쐌 Extension Point org.eclipse.wst.common.project.facet.ui.images


Angabe des Icon im Projekterstellungsassistenten:

<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>

Abb. 7.20: Assistent zur Auswahl einer Server-Instanz (GenericServerWizardFragment)

7.6.3 Konfiguration der plugin.properties


Da in den Dateien plugin.xml und jboss4.serverdef an vielen Stellen die Beschriftungstexte
nicht direkt, sondern mithilfe von Variablen definiert worden sind, müssen wir in der Datei
plugin.properties noch die Werte für diese Variablen setzen.
Dies erfolgt durch Zuordnungen von Beschriftungstexten zu den Variablen:

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

Erstellung eines EJB-Projekts

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

7.7 Erstellung eines EJB-Projekts

7.7.1 Anlegen des Projekts


Nach der Konfiguration des Plug-In für den JBoss Server erstellen wir ein neues Projekt
und gehen dabei wie folgt vor1:
쐌 Auswahl von FILE | NEW PROJECT und EJB à EJB PROJECT
쐌 Festlegen des Projektnamens Warenkorb
쐌 Festlegen der TARGET RUNTIME mit JBoss 4.0.x. Falls die Runtime nicht zur Auswahl
steht, muss durch Klick auf NEW die entsprechende Runtime erstellt werden. Dazu wer-
den der Applikationsserver und sein Installationsverzeichnis ausgewählt.
쐌 Als SOURCE FOLDER geben wir ejbModule an.
Nach Beendigung des Assistenten wird ein neues Projekt erzeugt, welches neben den J2SE-
Bibliotheken noch Bibliotheken aus dem Verzeichnis des JBoss Servers einbindet. Dabei
handelt es sich um die Bibliotheken, die in der jbsoo4.serverdef-Datei als Classpath mit der
ID jboss.project definiert worden sind.
Außerdem gibt es das Verzeichnis ejbModule. In diesem Verzeichnis werden die EJB mit
ihren zugehörigen Interfaces gespeichert. Im Unterverzeichnis META-INF steht beispiels-
weise der Deployment-Deskriptor ejb-jar.xml.

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70701Warenkorb

326
eclipse_v01.book Seite 327 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

7.7.2 Erzeugen des EJB


Zum Erzeugen einer EJB-Klasse wählen wir FILE | NEW | OTHER und EJB à XDOCLET EN-
TERPRISE JAVABEAN. Auf der zweiten Maske wählen wir die Art der Bean aus (Session Bean)
und geben als ANNOTATION PROVIDER XDoclet an. Durch Klick auf den Link PREFERENCES
kann das Installationsverzeichnis von XDoclet angegeben werden. Dabei sollte auch bei
EJBDOCLET der Punkt JBOSS angekreuzt werden.

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.

Abb. 7.22: Erstellen einer Session Bean

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

Erstellung eines EJB-Projekts

7.7.3 Bean-Klasse und XDoclet


In der neu erzeugten Klasse steht zu Beginn ein XDoclet-Bereich. Dieser beinhaltet die
Informationen für den Deployment-Deskriptor und für die Generierung der weiteren not-
wendigen Klassen und Interfaces:

/**
*
* <!-- 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.

7.7.4 Einfügen einer neuen Methode in die Bean-Klasse


Zum Erzeugen von Methoden gibt es in der aktuellen Version der WTP keinen Assistenten.
Vor die Methode müssen wir daher den XDoclet-Bereich selber schreiben oder von einer
anderen Methode kopieren.
In der Klasse WarenkorbBean existieren nach dem Erzeugen der Klasse die beiden Me-
thoden ejbCreate und foo. Vor der Methode ejbCreate steht im XDoclet-Bereich:

328
eclipse_v01.book Seite 329 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

/**
*
* <!-- 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

Erstellung eines EJB-Projekts

Weiterhin werden in diesem Beispiel drei so genannte Business-Methoden programmiert,


die zum Hinzufügen bzw. Entfernen eines Artikels aus dem Warenkorb sowie zum Ausle-
sen des Inhalts des gesamten Warenkorbs dienen. Die Methoden heißen hinzufuegen,
entfernen und getInhalt. Vor dem Java-Code der Methoden ist wiederum ein XDoc-
let-Bereich erforderlich, damit die Methoden automatisch in das Local und Remote Inter-
face aufgenommen werden. Dieser Bereich enthält keine methodenspezifischen Daten und
ist für jede Methode gleich:

/**
*
* <!-- 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

7 – Eclipse und J2EE

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:

<!-- Session Beans -->


<session >
<description><![CDATA[]]></description>
<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.WarenkorbSession
</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>

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).

Abb. 7.23: Design View des Deployment-Deskriptors ejb-jar.xml

331
eclipse_v01.book Seite 332 Montag, 30. Januar 2006 12:02 12

Client für den Remote-Zugriff auf eine EJB

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.

[org.jboss.deployment.MainDeployer] Starting deployment of


package: file:/C:/Programme/jboss-3.2.3/server/default/deploy/
WarenkorbEJB.jar
[org.jboss.ejb.EjbModule] Creating
[org.jboss.ejb.EjbModule] Deploying Warenkorb
...
[org.jboss.ejb.EJBDeployer] Deployed: file:/C:/Programme/jboss-
3.2.3/server/default/deploy/WarenkorbEJB.jar
[org.jboss.deployment.MainDeployer] Deployed package: file:/C:/
Programme/jboss-3.2.3/server/default/deploy/WarenkorbEJB.jar

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.

7.8 Client für den Remote-Zugriff auf eine EJB

7.8.1 Herstellung einer Verbindung zum JBoss-Namensdienst


Der JBoss Server stellt in seinem Naming Service Modul (JBossNS) eine Implementierung
des Java Naming and Directory Interface (JNDI) zur Verfügung. Der Namensdienst nutzt
das JNP-Protokoll (Java Naming Provider), welches standardmäßig auf den Port 1099
horcht. Soll ein Client von außen (remote) auf den Namensdienst zugreifen, so muss eine
Verbindung zu dem Server und dem entsprechenden Port aufgebaut werden.
Für den Verbindungsaufbau benötigt der Client ein Objekt der Klasse InitialContext
aus dem Package javax.naming. Beim Instanziieren eines Objekts dieser Klasse muss
dem Konstruktor ein Hashtable-Objekt übergeben werden, in dem Informationen für den

332
eclipse_v01.book Seite 333 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

Verbindungsaufbau gespeichert sind. Im Hashtable-Objekt werden die Einstellungen un-


ter bestimmten Namen gesetzt. Folgende Eigenschaften können angegeben werden:
쐌 java.naming.factory.initial oder Context.INITIAL_CONTEXT_FACTORY
Diese Eigenschaft spezifiziert den Namen der initial context factory. Der Name der
Klasse lautet org.jnp.interfaces.NamingContextFactory für den JBoss-Na-
mensdienst. Dieser Name wird der Eigenschaft zugeordnet.
쐌 java.naming.provider.url oder Context.PROVIDER_URL
Mit dieser Eigenschaft wird der Ort des JBoss-Namensdienst-Providers angegeben, den
der Client verwendet. Die Klasse NamingContextFactory benötigt diese Informati-
on, um eine Verbindung zum Namensdienst aufzubauen. Der Wert der Eigenschaft ist
eine URL und kann wie folgt angegeben werden:
jnp://<host>:<port>/[<jndi_path>]
Der Ausdruck jnp: bezeichnet das Protokoll. Da JNP standardmäßig verwendet wird,
kann die Angabe entfallen. Der Teil <host> ist die Server-Adresse und kann als IP-
Adresse angegeben werden. Danach folgt der Port, der standardmäßig auf 1099 gesetzt
ist und ebenfalls nicht angegeben werden muss. Der Wert von <jndi_path> ist optional
und beschreibt das Verzeichnis, in dem die EJBs liegen. Zur besseren Strukturierung
unserer Komponenten im Applikationsserver könnten wir beispielsweise festlegen,
dass die JNDI-Namen für die EJB stets mit ejb/… beginnen. Dann würden wir das Ver-
zeichnis ejb als <jndi_path> angeben.
Liegt der Server auf demselben Rechner wie der Client, dann kann die Eigenschaft
Context.PROVIDER_URL den Wert localhost oder aber auch jnp://localhost:1099
annehmen.
쐌 java.naming.factory.url.pkgs oder Context.URL_PKG_PREFIXES
Der Wert dieser Eigenschaft spezifiziert die Liste von Package-Präfixen, die verwendet
werden, wenn die Context Factories geladen werden. Für den JBoss-Namensdienst lau-
ten die Präfixes org.jboss.naming:org.jnp.interfaces.
쐌 jnp.socketFactory
Diese Eigenschaft besitzt als Wert standardmäßig den Namen der Klasse org.jnp.
interfaces.TimedSocketFactory. Diese Klasse ermöglicht die Spezifikation von
Timeout-Daten.
쐌 jnp.timeout
Angabe der Dauer in Millisekunden, nach der der Versuch, eine Verbindung aufzubau-
en, abgebrochen wird. Standardmäßig ist der Wert 0. Das bedeutet aber nicht, dass keine
Zeit abgewartet wird, bis die Verbindung aufgebaut ist. Da die Kommunikation über
TCP/IP läuft, wird der dort eingestellte Timeout verwendet und die Dauer des
jnp.timeout gegebenenfalls dazu addiert.
쐌 jnp.sotimeout
Diese Eigenschaft gibt den Timeout bei der Kommunikation an und besitzt ebenfalls
standardmäßig den Wert 0. Hierbei handelt es sich wiederum um die Dauer, die zusätz-
lich zur Timeout-Dauer des TCP/IP-Protokolls eingestellt ist.

333
eclipse_v01.book Seite 334 Montag, 30. Januar 2006 12:02 12

Client für den Remote-Zugriff auf eine EJB

7.8.2 Beispiel eines Java-Client


Für den Java-Client erzeugen wir in Eclipse ein Java-Projekt1, das eine Klasse (Waren-
korbClient) mit main-Methode enthält. Zum Verbindungsaufbau mit dem JBoss-
Namensdienst schreiben wir eine Methode getContext, in der das dafür benötigte Objekt
der Klasse InitialContext instanziiert wird.

private InitialContext getContext() throws NamingException {


Hashtable props = new Hashtable();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
props.put("jnp.socketFactory",
"org.jnp.interfaces.TimedSocketFactory");
props.put("jnp.timeout","0");
props.put("jnp.sotimeout","0");
InitialContext context = new InitialContext(props);
return context;
}

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.

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70306WarenkorbClient

334
eclipse_v01.book Seite 335 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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.

private WarenkorbHome getHome() throws NamingException {


Context ctx = getContext();
Object ref = ctx.lookup(WarenkorbHome.JNDI_NAME);
WarenkorbHome wkh = (WarenkorbHome)
PortableRemoteObject.narrow(ref,WarenkorbHome.class);
return wkh;
}

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:

public void testBean() {


try {
Warenkorb myBean = getHome().create("Meier");
myBean.hinzufuegen("Saft");
myBean.hinzufuegen("Bier");
myBean.hinzufuegen("Wurst");
Vector v = myBean.getInhalt();
for (int i=0;i<v.size();i++){
System.out.println(v.elementAt(i));
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}

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

Webclient für den Zugriff auf eine EJB

In der main-Methode derselben Klasse erzeugen wir ein Objekt vom Typ Warenkorb-
Client und rufen die testBean-Methode auf:

public static void main(String[] args) {


WarenkorbClient test = new WarenkorbClient();
test.testBean();
}

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

7.8.3 WTP zur Erstellung eines Java-Clients


Für die Erstellung eines Java-Clients bietet die WTP einen Assistenten. Allerdings wird mit
dessen Hilfe lediglich ein Java-Projekt erstellt, welches einige Bibliotheken einbindet. Eine
Unterstützung bei der Entwicklung der Methoden für den Zugriff auf die EJB existiert in
der zugrunde liegenden Version nicht. Aus diesem Grund werden die in der Web Tools Plat-
form als Application Client Projects bezeichneten Projekte nicht näher untersucht.

7.9 Webclient für den Zugriff auf eine EJB


Der Zugriff eines Webclients bzw. Browsers auf eine EJB erfolgt über einen Webserver. In
Kapitel 7.2 haben wir gesehen, wie von einem Browser aus auf einen Webserver zugegrif-
fen werden kann. Wir haben JSP-Dokumente entwickelt, in denen Java-Skriptlets ausge-
führt werden. Außerdem konnten wir auf einfache Java Beans zugreifen. In diesem Ab-

336
eclipse_v01.book Seite 337 Montag, 30. Januar 2006 12:02 12

7 – Eclipse und J2EE

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

In der Beispielanwendung werden in einer Browser-Oberfläche Bezeichnungen von Arti-


keln eingegeben. Anschließend soll die Möglichkeit bestehen, die Liste der Artikel anzuse-
hen und eine Bestellung aufzugeben.
Wir entwickeln diese Anwendung nach dem Model View Controller (MVC) Pattern.
Als Model dient die in Kapitel 0 bereits entwickelte Session Bean Warenkorb.
Für die View benötigen wir HTML- und JSP-Dokumente, die die Eingabe der Bestellung
verarbeiten und den Inhalt des Warenkorbs ausgeben.
Außerdem verwenden wir ein Servlet, welches die Kommunikation mit dem Applikations-
server bzw. mit dem Model und dem Browser bzw. mit der View übernimmt. Dieses be-
zeichnen wir als Controller Servlet.
Die Architektur ist in Abb. 7.25 dargestellt.

Web Server EJB Container

View
JSP / HTML

Model
Session Bean

C o n tr o l l e r
Controller Servlet

Abb. 7.25: Model View Controller-Architektur der Anwendung

337
eclipse_v01.book Seite 338 Montag, 30. Januar 2006 12:02 12

Webclient für den Zugriff auf eine EJB

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.

7.9.1 Lokaler Zugriff innerhalb derselben virtuellen Maschine


Wenn in einer Webanwendung eine EJB aufgerufen wird, dann fungiert der Webserver als
Client beim Applikationsserver. Im folgenden Beispiel werden wir aus einer Java Bean
(dem Controller Servlet) heraus, die im Kontext des Tomcat Webservers ausgeführt wird,
auf eine Enterprise Java Bean, die im EJB-Container des JBoss Servers im selben Kontext
ablaufen soll, zugreifen.

Local Interface und Local Home Interface


Beim lokalen Zugriff innerhalb derselben virtuellen Maschine erfolgt der Zugriff nicht über
das RMI-Protokoll. Wir verwenden das Local Interface und das Local Home Interface1.

package com.entwickler.eclipsebuch.warenkorb;

public interface WarenkorbLocal extends javax.ejb.EJBLocalObject


public void hinzufuegen(String artikel ) ;
public void entfernen(String artikel ) ;
public java.util.Vector getInhalt( ) ;
}

Das Local Home Interface ist wie folgt aufgebaut:

package com.entwickler.eclipsebuch.warenkorb.WarenkorbLocal;

public interface WarenkorbLocalHome


extends javax.ejb.EJBLocalHome{

public static final String


COMP_NAME="java:comp/env/ejb/WarenkorbBean";
public static final String JNDI_NAME="WarenkorbLocal";

1. Siehe auf der beiliegenden CD im Verzeichnis ../Kapitel07/Kap70901WarenkorbWebClient

338
eclipse