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:
[email protected] Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; 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 (Fotokopie, Nachdruck, Mikrofilm, Erfassung auf elektronischen Datenträgern oder andere Verfahren) nur mit schriftlicher Genehmigung des Verlags. Jegliche Haftung für die Richtigkeit 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
2
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
1.1 1.2 1.3 1.4 1.5 1.6 1.7
Was ist Eclipse? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Warum ein Buch über Eclipse?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An wen richtet sich dieses Buch? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was erwartet Sie in diesem Buch? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was benötigen Sie?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anforderungen an eine moderne IDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . Open Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13 13 14 14 15 15 16
Wegweiser durch Eclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.1
19 19 19 20 21 21 23 23 24 25 26 27 31 35 36 40 43 43 44 46 48 50 51 51 56 57 59
2.2 2.3
2.4
2.5
2.6
Perspektiven und Views von Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Perspektiven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2 Perspektiven auswählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.3 Die Java-Perspektive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.4 Neues Java-Projekt erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.5 Package Explorer und View-Funktionen . . . . . . . . . . . . . . . . . . 2.1.6 Das Eclipse-Editorfenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.7 Outline View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.8 Tasks/Problems View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.9 To be done – Arbeiten mit Tasks. . . . . . . . . . . . . . . . . . . . . . . . . 2.1.10 Eigene Tasks definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hilfe in Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eclipse-Projekte individuell konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 Vorhandenen Sourcecode ins Projekt Link to Source . . . . . . . . . 2.3.2 Projekteigenschaften definieren . . . . . . . . . . . . . . . . . . . . . . . . . Sourcecode-Editor-Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Quick Fix auf Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.2 Automatische Getter/Setter-Erzeugung . . . . . . . . . . . . . . . . . . . 2.4.3 Sourcecode-Vervollständigung (Code completion) . . . . . . . . . . 2.4.4 Try-Catch-Block-Generierung . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.5 Sourcecode-Templates verwenden . . . . . . . . . . . . . . . . . . . . . . . 2.4.6 Gimmicks des Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.7 Immer ein Undo für die Vergangenheit. . . . . . . . . . . . . . . . . . . . Refactoring mit Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Überschreiben/Implementieren von Methoden. . . . . . . . . . . . . . 2.5.2 Auslagern von Zeichenketten/Mehrsprachigkeit . . . . . . . . . . . . Erstellung eines JUnit-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
eclipse_v01.book Seite 6 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
2.7
2.8
2.9
2.10
2.11
2.12 3
Eclipse als Modellierungswerkzeug. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 3.1 3.2
3.3
4
Einleitung ins Thema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . OMONDO EclipseUML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 Versionen von EclipseUML . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Download und Installation von Omondo EclipseUML . . . . . . . 3.2.3 Klassendiagramme erstellen. . . . . . . . . . . . . . . . . . . . . . . . . . . . EMF/GEF und UML2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Eclipse Modeling Framework (EMF) . . . . . . . . . . . . . . . . . . . . 3.3.2 Graphical Editing Framework (GEF). . . . . . . . . . . . . . . . . . . . . 3.3.3 UML2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
109 110 110 111 111 118 118 119 120
Qualitätssicherung in Eclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 4.1
6
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 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 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 Java 5 – Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 2.10.1 Java 5 on board. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 2.10.2 Migration Java 1.4 nach 5.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Customizing Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 2.11.1 Customizing perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 2.11.2 Eclipse individuell starten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Eclipse Preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Einführung ins Thema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
eclipse_v01.book Seite 7 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
4.2
4.3
5
121 121 122 122 123 123 124 124 125 128 129 133 135 135
Build Management mit Eclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 5.1 5.2 5.3
5.4
5.5
5.6 6
Wie äußert sich ein Mangel an Qualität? . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Mangelnde Sourcecodetests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2 Mangelnde Tests der fachlichen Funktionalität . . . . . . . . . . . . . 4.2.3 Eingeschränkte Funktionalität. . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.4 Begrenzte Sourcecode-Qualität. . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5 Reviews und Softwareunterstützung. . . . . . . . . . . . . . . . . . . . . . Eclipse zur Qualitätssicherung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 Testen mit JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 Audits mit Checkstyle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.3 Sourcecode-Metrics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.4 Metrics 1.3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.5 Metrikreports und Graphen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.6 Ant-Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.7 Bleiben Sie kritisch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufgaben des Build Managements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vom Quellcode zum Programm: Build. . . . . . . . . . . . . . . . . . . . . . . . . . . Einstellungen des Eclipse-Build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1 Build Path-Einstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.2 Compiler und JavaDoc-Einstellungen. . . . . . . . . . . . . . . . . . . . . 5.3.3 Automatische und manuelle Builds . . . . . . . . . . . . . . . . . . . . . . 5.3.4 Weitere Konfigurationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.5 Erzeugung anderer Ausgabetypen . . . . . . . . . . . . . . . . . . . . . . . Build Management und Versionierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Exkurs: Versionierung mit CVS in Eclipse. . . . . . . . . . . . . . . . . 5.4.2 Versionierung und Build Management . . . . . . . . . . . . . . . . . . . . Exkurs: Build Management mit Ant. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 Ant Projects, Targets und Tasks . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 Typische Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.3 Ein Ant-Beispielskript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.4 Ant in Eclipse: externe Builds . . . . . . . . . . . . . . . . . . . . . . . . . . Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
137 138 139 139 142 143 144 146 147 148 158 159 161 163 164 169 173
GUI-Design mit Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 6.1 6.2
Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Visual Editor für Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Installation und Aufruf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.2 Hinzufügen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.3 Entfernen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.4 Ändern von Eigenschaften einer Komponente . . . . . . . . . . . . . .
175 176 176 178 179 179
7
eclipse_v01.book Seite 8 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
6.3
6.4
6.5
6.6
7
180 181 182 183 183 184 187 206 206 208 222 232 235 235 235 237 239 242 242 244 245 245 245 247 248 251
Eclipse und J2EE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 7.1
7.2
7.3
8
6.2.5 Layouteinstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.6 Ereignisverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Besonderheiten bei der Erstellung eines GUI mit Swing-Komponenten 6.3.1 Unterstützte Komponenten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.2 Layoutmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.3 Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.4 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das SWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.1 Aufbau einer SWT-Applikation . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.2 SWT-Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.3 Layoutmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.4 Ereignisverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Besonderheiten bei der Erstellung eines GUI mit SWT-Komponenten . 6.5.1 Unterstützte Komponenten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5.2 Layoutmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5.3 Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5.4 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der WindowBuilder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.1 Installation und Aufruf. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.2 Hinzufügen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.3 Entfernen von Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.4 Ändern von Eigenschaften einer Komponente. . . . . . . . . . . . . . 6.6.5 Layouteinstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.6 Ereignisverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.7 Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.8 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.2 Bestandteile eines XML-Dokuments . . . . . . . . . . . . . . . . . . . . . 7.1.3 Plug-Ins für das Bearbeiten von XML-Dokumenten . . . . . . . . . Webanwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.1 Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.2 Beispiel einer Webanwendung mit Servlets. . . . . . . . . . . . . . . . 7.2.3 Beispiel einer Webanwendung mit Java Server Pages . . . . . . . . Eclipse-Projekt Web Tools Platform (WTP) . . . . . . . . . . . . . . . . . . . . . . 7.3.1 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.2 Editoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.4 Einstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
264 264 265 270 275 275 276 281 283 283 284 285 286
eclipse_v01.book Seite 9 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
7.4
7.5
7.6
7.7
7.8
7.9
7.10
7.11
7.12
7.3.5 Entwicklung einer Webanwendung. . . . . . . . . . . . . . . . . . . . . . . 7.3.6 Beispielanwendung Kreditkartenprüfer . . . . . . . . . . . . . . . . . . . 7.3.7 Server Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.8 Lomboz Plug-In und WTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . J2EE-Anwendungen mit Enterprise Java Beans. . . . . . . . . . . . . . . . . . . . 7.4.1 Grundlegende Begriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.2 Enterprise Java Bean (EJB). . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.3 Zugriff eines Clients auf eine EJB . . . . . . . . . . . . . . . . . . . . . . . Session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5.1 Bean-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5.2 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5.3 Deployment-Deskriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konfiguration der WTP für einen neuen Server . . . . . . . . . . . . . . . . . . . . 7.6.1 Server-Definitionsdatei jboss4.serverdef . . . . . . . . . . . . . . . . . . 7.6.2 7.6.2 Konfiguration der plugin.xml . . . . . . . . . . . . . . . . . . . . . . . 7.6.3 Konfiguration der plugin.properties . . . . . . . . . . . . . . . . . . . . . . Erstellung eines EJB-Projekts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.7.1 Anlegen des Projekts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.7.2 Erzeugen des EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.7.3 Bean-Klasse und XDoclet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.7.4 Einfügen einer neuen Methode in die Bean-Klasse . . . . . . . . . . Client für den Remote-Zugriff auf eine EJB . . . . . . . . . . . . . . . . . . . . . . 7.8.1 Herstellung einer Verbindung zum JBoss-Namensdienst . . . . . . 7.8.2 Beispiel eines Java-Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.8.3 WTP zur Erstellung eines Java-Clients. . . . . . . . . . . . . . . . . . . . Webclient für den Zugriff auf eine EJB . . . . . . . . . . . . . . . . . . . . . . . . . . 7.9.1 Lokaler Zugriff innerhalb derselben virtuellen Maschine . . . . . 7.9.2 Zugriff bei unterschiedlichen virtuellen Maschinen . . . . . . . . . . Datenbankzugriff aus einer EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.10.1 Einstellungen für den Zugriff auf die MySQL-Datenbank . . . . . 7.10.2 Beispiel Onlineshop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Entity Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.11.1 Grundlagen und Persistenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.11.2 Finder-Methoden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.11.3 Entity Bean (Container Managed Persistence) . . . . . . . . . . . . . . 7.11.4 Entity Bean (BMP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Messaging Service und Message Driven Beans . . . . . . . . . . . . . . . . 7.12.1 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.12.2 Message Driven Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.12.3 Senden einer Nachricht an eine Message Driven Bean . . . . . . .
287 292 298 299 299 299 302 304 306 306 308 310 312 313 321 325 326 326 327 328 328 332 332 334 336 336 338 344 345 345 347 352 352 353 354 370 379 379 381 383
9
eclipse_v01.book Seite 10 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
8
Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 8.1 8.2
8.3
9
389 390 390 391 391 392 392 397 404 405
Plug-In-Entwicklung für die Eclipse Workbench . . . . . . . . . . . . . . . . . . . . . 411 9.1 9.2 9.3
9.4
9.5 9.6 9.7 9.8
9.9 9.10
9.11
10
Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Begriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.2 WSDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.3 JAX. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Entwicklung eines Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.1 Aufbau eines WSDL-Dokuments . . . . . . . . . . . . . . . . . . . . . . . 8.3.2 Erzeugen eines Web Service aus einem WSDL-Dokument. . . . 8.3.3 Entwicklung eines Clients für den Web Service . . . . . . . . . . . . 8.3.4 Erzeugen eines WSDL-Dokuments aus einer Java-Klasse . . . . Everything is a plug-in. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . In die Tiefen der Oberfläche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Outline View für den Texteditor . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.1 Adapter: Dynamische Erweiterung von Klassen . . . . . . . . . . . . 9.3.2 Ein eigener Adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.3 Alternative 1: Überschreiben der Methode getAdapter . . . . . . . 9.3.4 Alternative 2: der Adapter Manager. . . . . . . . . . . . . . . . . . . . . . 9.3.5 Ein Extension Point wird geboren . . . . . . . . . . . . . . . . . . . . . . . 9.3.6 Schritt 1: Definition des Interface für den Extension Point . . . . 9.3.7 Schritt 2: Definition des Extension Point. . . . . . . . . . . . . . . . . . 9.3.8 Schritt 3: Implementierung des Extension Point . . . . . . . . . . . . 9.3.9 Eine Extension für den neuen Extension Point . . . . . . . . . . . . . Der eigene Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.1 Nichts einfacher als ein eigener Texteditor . . . . . . . . . . . . . . . . 9.4.2 Wir erweitern den Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Und Action ...: Actions in der Eclipse Workbench (Teil 1). . . . . . . . . . . ... Einschub: Aufbau der Eclipse-Oberfläche . . . . . . . . . . . . . . . . . . . . . Und Action ...: Actions in der Eclipse Workbench (Teil 2). . . . . . . . . . . 9.7.1 Ein Button mit persistentem Status . . . . . . . . . . . . . . . . . . . . . . Page Book View: ein Buch mit sieben Seiten . . . . . . . . . . . . . . . . . . . . . 9.8.1 Action Delegates oder „Wie kommt man von außen in das Buch?“ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Markers und Annotations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.9.1 Marker für Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . OSGi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.10.1 Bundles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.10.2 Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.10.3 Die Benutzung eines Service . . . . . . . . . . . . . . . . . . . . . . . . . . . Fazit und Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
411 411 412 413 415 423 425 441 442 442 448 450 452 452 458 464 469 487 488 495 497 511 518 537 538 545 550 555
eclipse_v01.book Seite 11 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
10
Plug-In-Entwicklung für das JDT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557 10.1 10.2
10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 10.11 10.12 10.13 10.14 10.15 10.16 10.17 10.18 10.19 10.20 11
Soap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Apache Axis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1 Installation von Tomcat. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.2 Installation von Axis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Web Service Deployment Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . Den Rahmen erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Funktionalität implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eingabe der Konfigurationsparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6.1 Speichern und Laden der Konfigurationsparameter . . . . . . . . . . Generierung von service.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Generierung eines Ant-Skripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausführen des Ant-Skripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das fertige Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Extension Point für die Generierung von Clients . . . . . . . . . . . . . . . Einschub: Code-Analyse über AST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine View zur Anzeige des Syntaxbaums . . . . . . . . . . . . . . . . . . . . . . . . Die Erzeugung von Java-Code über AST. . . . . . . . . . . . . . . . . . . . . . . . . Ein Extension Point für die Generierung von Clients (Fortsetzung) . . . . Die Implementierung des Extension Point . . . . . . . . . . . . . . . . . . . . . . . . Ein Generator für SWT Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das SWT-Client-Generator-Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Erzeugung von Java Code über das Java Element API . . . . . . . . . . . So ganz nebenbei zum Schluss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
557 559 559 561 562 563 569 574 583 586 589 592 592 596 597 598 608 611 613 621 629 629 633
Eclipse als Rich Client Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635 11.1
11.2
11.3
Kapitelüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Themenüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Kapitelstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.3 Ziele des Kapitels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anwendungen auf Basis der Plug-In-Technologie . . . . . . . . . . . . . . . . . . 11.2.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 Sidebar: Bundles versus Plug-Ins . . . . . . . . . . . . . . . . . . . . . . . . 11.2.3 Hello World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.4 Strukturierung von Anwendungen . . . . . . . . . . . . . . . . . . . . . . . 11.2.5 Tipps, Tricks und mögliche Fallen . . . . . . . . . . . . . . . . . . . . . . . Die Eclipse Rich Client Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.2 Hello World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.3 Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.4 Menüs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.5 Views und Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
635 635 635 635 636 636 637 637 641 642 645 645 645 649 650 653
11
eclipse_v01.book Seite 12 Montag, 30. Januar 2006 12:02 12
Inhaltsverzeichnis
11.4
11.5 12
Weitere Themen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.1 Swing und/oder SWT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.2 Eclipse im Client-Server-Umfeld. . . . . . . . . . . . . . . . . . . . . . . . 11.4.3 Eclipse in der Projektpraxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.4 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
655 655 656 657 659 659
Refactoring to Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 12.1
12.2 12.3
12.4
12.5
12.6
12.7
12.8
12.9
Kapitelüberblick. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.1 Themenüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.2 Kapitelstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Refactorings im Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Refactoring: Konvertiere Standalone-Anwendung in eine Single-Plug-In-Eclipse-Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Refactoring: Extrahiere Bibliotheks-Plug-In . . . . . . . . . . . . . . . . . . . . . . 12.4.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Refactoring: Extrahiere Erweiterungs-Plug-In . . . . . . . . . . . . . . . . . . . . 12.5.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.5.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.5.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Refactoring: Verallgemeinere Extension-Point . . . . . . . . . . . . . . . . . . . . 12.6.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Refactoring: Konvertiere Anwendung in RCP-Anwendung . . . . . . . . . . 12.7.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.7.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.7.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Refactoring: Ersetze Swing-Fenster durch RCP-View . . . . . . . . . . . . . . 12.8.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.8.2 Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.8.3 Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
661 661 661 662 662 663 663 663 666 666 666 667 667 668 668 668 671 671 672 672 673 673 673 674 675 676 676 676 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 zusammengeschlossen, 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-Entwicklungsumgebung verlassen. Immer mehr Entwickler in Unternehmen oder hobbymäßig zu Hause entdeckten Eclipse und mit Eclipse teilweise auch erstmalig die Programmiersprache Java. Als im Januar 2005 die erste Auflage dieses Buchs mit großem Erfolg eine interessierte 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 vorstellen (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 professionellen Umfeld erlauben. Eines der herausragendsten Merkmale der Version 3.1 ist zweifelsohne 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 Entwicklungsplattform, aber auch im produktiven Umfeld einsetzen. Manchmal werden auch kommerzielle Produkte vorgestellt. In diesen Fällen muss entschieden werden, ob der zusätzliche 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 Wesentlichen in größeren Projekten, d.h. zumeist im Unternehmen, einsetzen oder darüber nachdenken, dies zu tun. Wir gehen davon aus, dass bereits eine grobe Vorstellung von Eclipse vorhanden 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 Unterschied 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 angebotenen 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 benutzt 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 EclipseWebseite.
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 unterschiedlichen 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 vorgestellt. 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 UMLModellierung, 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 Eigenentwicklung an Eclipse kommen. Wir untersuchen, wie man Eclipse als „Startframework“ für eigene 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 Entwicklung 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 Dokumentation 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 jedoch 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 kompletten Entwicklungszyklus vor Augen. Dazu zählen die Analysephase und die Dokumentation (soweit dies das Tool unterstützen kann), das objektorientierte Design bis hin zur Programmierung sowie die Themen Qualitätssicherung oder Deployment. Am besten positionieren 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-InKonzept) 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 Funktionen 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, berü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 jeweiligen Bedürfnisse anpassen lassen sollen, ist Eclipse sicherlich ein Kandidat der engeren Wahl. Die Anforderungen an eine moderne IDE hängen primär von den ganz persönlichen Bedürfnissen ab und ob ein Produkt alles können soll oder ob Medienbrüche (Wechsel zwischen 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-Deployment hinaus für das eigene Vorgehen noch benötigt werden. Wenn dies mit einer kostenlosen IDE (wie Eclipse) funktioniert, umso besser.
1.7
Open Source
Entgegen der Meinung vieler Projektverantwortlicher sind nicht unbedingt immer die teuersten Produkte die besten. Besonders die unter der Apache Group laufenden Jakarta-Subprojekte1 sprechen eine ganz andere Sprache und haben Produkte wie LOG4J, Struts, Hivemind 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 weiterhilft, kann die Untersuchung des Sourcecodes Support-Anfragen auch zuweilen ersetzen. Für Unternehmen ist oft der Zeitfaktor im Projektmanagement erheblich drängender als der Kostenfaktor. Beide lassen sich ganz erheblich reduzieren, wenn eine Open SourceLö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 Stadium ihres Lebenszyklus noch nicht ausgereift sind. Das Risiko besteht dabei, dass die Weiterentwicklung 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 SourceEntwicklungsumgebung, 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 erscheinen. Nach dem Start von Eclipse fragt dieses nach einem Workspace-Verzeichnis für seine eigenen Dateien. Wir klicken die Checkbox an, um das vorgeschlagene Verzeichnis zum Defaultdirectory zu erklären, und wählen danach OK. Sollten Sie eine alte Eclipse-Version installiert 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 kennen 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-Perspektive wechseln.
2.1 2.1.1
Perspektiven und Views von Eclipse Perspektiven
Das Aussehen von Eclipse bzw. dessen Erscheinungsbild bei der Arbeit hängt im Wesentlichen 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 Sourcecodes, das Debuggen, aber auch das Installieren von weiteren Plug-Ins sein. Grundsätzlich können eigene Perspektiven wie in einer Art Baukasten zusammengestellt, angeordnet 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 betrachtete Beispiel wählten wir die Java-Perspektive. Die jeweils aktuelle Perspektive ist dabei mit einem schwarzen Kreis markiert. Weitere Perspektiven (auch jene, die gegebenenfalls 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 einzelnen 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 wesentlichen Funktionen – die Arbeit mit Projekten, Sourcecode-Modifikationen, Suchalgorithmen, die Konfiguration der kompletten Oberfläche, das Hilfesystem und der WelcomeBildschirm, 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 Reihe von ihnen sind auch über entsprechende Kontextmenüs oder eine spezielle Tastenkombination, 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 geben 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 Elemente 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 fällt“.
ALL
– schließt die aktuelle Baumansicht, indem der Baum in sich „zusammen-
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önlichen Bedürfnisse anzupassen (Ein/Ausblenden bestimmter Inhalte, Wechsel der Strukturdarstellungen, ...).
Abb. 2.3: Fensterfunktionen
Mit einem Rechtsklick auf das Fenster-Icon können die Fensterfunktionen angezeigt werden (Abb. 2.3), wobei die Features (egal ob View oder nicht) stets gleichbleibend sind. Neben 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 Register 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 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.
VIEW
2.1.6
Das Eclipse-Editorfenster
Im Zentrum von Eclipse befindet sich der Editor bzw. das Editorfenster. Pro geöffneter Datei existiert ein Editierfenster (siehe Abb. 2.5), wobei jeweils eines aktiv ist. In allen nachfolgenden 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 visualisiert 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 angezeigten Klasse
——
2.1.8
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 verbleibenden.
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 Informationselemente wichtig sind.
24
eclipse_v01.book Seite 25 Montag, 30. Januar 2006 12:02 12
2 – Wegweiser durch Eclipse
——
2.1.9
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 SourcecodeDebugging nicht verzichtet werden soll oder kann, in eigene Eclipse-Projekte 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 Anwendung. Darüber hinaus besteht die Möglichkeit, durch die Definition von so genannten Working-Sets (Arbeitsmengen) die Menge der Klassen nochmals wesentlich einzuschränken. Nur kann dies auch schnell zu Verwirrungen führen.
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-Kommentare 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. zwischen 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 gegebenenfalls auch modifiziert werden, was sich gleich wieder auf den Sourcecode auswirkt. Eclipse selbst bedient sich dieser Funktionalität auch gerne und erzeugt künstlich Kommentare mit dem Hinweis „To do“, wenn es beispielsweise Methoden automatisch generiert und daher Javadoc und Implementierung nicht vollständig sein können.
——
2.1.10
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 leider 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“.
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 eingestellt (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 PROPERTIES | JAVA COMPILER | JAVA TASK TAGS – siehe Abb. 2.8).
Abb. 2.8: Erstellen eigener Tasks über Project-Properties
——
26
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 JakartaUmfeld importiert wird, an welchen Hotspots die dortigen Autoren noch nicht gedreht haben.
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 Tutorials 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 zahlreichen 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 Benutzer durch eine Sequenz von definierten Schritten führt. Nach dem Abschluss jedes einzelnen 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-Beispiels 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 HelloWorld-Beispiel an, das einen zwischen ein paar Minuten Aufwand und mehreren Anrufen beim entsprechenden Support Zeit kosten kann (eben auch je nach Sprache und Entwicklungsumgebung). 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 Folgenden 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 EclipseGrundkenntnisse 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 Textmuster verarbeiten soll und was zu tun ist, wenn dieses Muster gefunden wird. Das OROFramework prüft unter Verwendung unterschiedlicher Methoden, inwieweit andere Zeichenketten 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 einige 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 erzeugen. 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.entwickler.eclipsebuch.kapitel2.analyzer ein und klicken auf FINISH. Auf dem erzeugten 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.analyzer.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ückliefert. Zunächst erzeugen wir die Methodensignatur. Hierzu tippen wir den folgenden Sourcecode in die ExpressionAnalyzer-Klasse ein: public Vector 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ündung in einem so genannten Hover an. Eclipse benutzt Hovers an vielen Stellen zur Anzeige 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. Zunä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 Compile-Fehlers und schließlich finden sich in der Problems View darunter noch einmal die Fehler mit Beschreibung, Resource, Ordner und Angabe der Zeilennummer. Ein Doppelklick 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 inkrementell, das heißt, nur jene Sourcecodeteile, auf die Änderungen Auswirkungen 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 selektierten 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 generieren, 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 hierfür Voraussetzung. Haben Sie dies noch nicht getan, können Sie weitere JREs über das Menü WINDOW | PREFERENCES | JAVA | INSTALLED JREs nachholen. 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 stellen Sie den JAVA COMPLIANCE LEVEL entsprechend ein.
Dafür weist Eclipse nun darauf hin, dass wir zwar ein getyptes Vector-Objekt zurückgeben 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 returnStatement.
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, indem wir im Menü FILE | NEW | PROJECT | JAVA PROJECT | NEXT wählen und im daraufhin erscheinenden Fenster als Projektnamen ORO eingeben. Wir aktivieren den Radiobutton CREATE PROJECT FROM EXISTING SOURCE und wählen das Verzeichnis, in dem wir ORO entpackt 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 einbezogen 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 MULTIPLE 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 Preferences definiert werden kann, siehe Kapitelabschnitt 2.12). Eclipse zieht zusätzlich zum Sourcecode auch die jakarta-oro-2.0.8-JAR-Bibliothek mit heran. 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-Verzeichnis für die Classfiles definieren. Zu diesem Zweck wird die Checkbox ALLOW OUTPUT FOLDERS 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 generierten Classfiles außerhalb noch weiterbearbeitet werden sollen (z.B. in einer Ant-Task) kann es sinnvoll sein, Teile des Sourcecodes von anderen örtlich 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 aussehen sollte.
Abb. 2.15: ORO-Projektstruktur
Möglicherweise (je nach Version, die von ORO vorliegt) erscheinen eine Reihe von Warndreiecken, 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-Workspace 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 angelegt 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 vorliegt, sondern in einem Jar-File, er aber trotzdem gesehen werden soll, oder wenn die ursprü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ändige Bytecode bereits vorliegt, werden in das Projekt die entsprechenden Class- bzw. JarFiles importiert und Eclipse wird durch Doppelklick auf dem entsprechenden Classfile mitgeteilt, 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 abhängiger Libraries benötigt, dafür kann man nicht vernünftig durch diese Klassen debuggen. Wird der komplette Sourcecode über die Import-Funktion (rechte Maustaste auf dem JavaProjekt 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 debuggen. Der Nachteil bei der Variante ist, dass alle abhängigen Libraries vorhanden sein müssen, 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
——
2.3.2
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 Hintergrund 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.
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 Unterpunkt 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 zugeordneten 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 Bildhä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 Konfiguration 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önnen Sie nun auch nochmals – falls noch nicht geschehen – den Compiler-Level auf 5.0-Unterstützung umschalten. Neben der separaten Einzeleinstellung der generierten Class-FileVersionen 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 Debuggens auftreten, sollte an diesen Einstellungen möglichst wenige Modifikationen vornehmen. 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, aktivieren 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 Libraries 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 PROBLEMS und NAME SHADOWING AND CONFLICTS helfen schnell und einfach, bereits bei der Kodierung 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 Vorhandensein 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-Projekt 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 JavaCompiler in Beziehung stehen.
——
Die Einstellungen im Bereich BUILDING sind besonders dann interessant, wenn man beispielsweise mit vielen separaten Source- und unterschiedlichen Ausgabe-Compile-Verzeichnissen arbeiten möchte. Hier lässt sich nun konfigurieren, ob Eclipse auf unvollständige oder „kaputte“ BuildPfade (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 Ausgabeverzeichnisse für einen Recompile löscht (Scrub output folders when cleaning projects). 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 Abschnitt 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 Abschnitt 2.3). Java Code Style Unter dem Unterpunkt JAVA CODE STYLES lassen sich individuelle Einstellungen für die Kodierungsrichtlinien dieses Projekts vornehmen. Dies ist besonders in größeren Projekten mit klar formulierten Design- und Coderichtlinien sehr hilfreich, wenn zahlreiche Einstellungen bereits während der Programmierphase geprüft oder bei der Erstellung entsprechend 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 vorgenommen, sollte das Projekt selbst jetzt fehlerfrei kompilieren. Fremde Projekte referenzieren Wir öffnen nun noch einmal die PROPERTIES des RegExtTest-Projekts über die Tastenkombination Ç+Æ 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 assoziierende ORO-Projekt. Klicken Sie dann auf OK, damit das Projekt in den BUILD PATHEigenschaften 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, JARFiles 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, MethodNotFound-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 Beispiels betrachtet werden sollen. Grundsätzlich kann der Sourcecode vollkommen ohne weitere Unterstützung über die üblichen Tastenkombinationen, wie z.B. Cut and Paste, bearbeitet 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 Anlegen expliziter Java-Dateien in Eclipse zu integrieren und zu kompilieren. Wir ergänzen den Sourcecode der ExpressionAnalyzer-Klasse, so dass er wie folgt aussieht (die Kommentare können dabei wahlweise ignoriert werden, die Fehler im Sourcecode werden wir im Folgenden beseitigen): package com.entwickler.eclipsebuch.kapitel2.analyzer; import java.util.Vector; /** * ExpressionAnalyzer Test-Klasse */ public class ExpressionAnalyzer { public Vector getAllOccurrencesOfPattern(final String originalContent,final String patternString) { // Erzeugen eines Ergebnisvectors: Vector results = new Vector(); // 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 „zusammengefaltet“ 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 eingestellt 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 Speichern. 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-Kontextmenü 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 markierten 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-Kommentar 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 eindeutig, 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 Unterklassen und dem Erzeugen von Getter- und Setter-Methoden (Abschnitt 2.4.2). Für eine detailliertere 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 DefaultKonstruktors kann dabei wahlweise ausgespart werden (OMIT CALL TO DEFAULT CONSTRUCTOR).
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 Instanzvariablen 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 regexpCompiler nutzen, um die fehlende Variable zu generieren und Getter- und Setter-Methoden 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 Methodenaufrufs 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 Instanzvariablennamen im PACKAGE EXPLORER und wählen über die rechte Maustaste im Kontextmenü SOURCE den Unterpunkt GENERATE GETTERS UND SETTERS. Die automatische Generierung 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 Methodenkommentare erzeugen. In den Generierungsschritt von Kommentar und Methodenname können Sie allerdings über entsprechende CODE TEMPLATES separat eingreifen. Klicken Sie zur Konfiguration hier auf den Link für die Code Templates. Sie werden aus den Workbench Preferences 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 stattdessen 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ändigen. Zu bekannten Klassen zeigt Eclipse gleichzeitig daneben den Javadoc-Kommentar zur Hilfestellung an. Die Auswahl einer Klasse führt implizit auch zur Generierung eines zugehö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-Kommentars. 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ändigung von Methoden- oder Variablennamen – bei den Variablen sogar bezogen auf Instanzoder lokale Variablen, die in der jeweiligen Methode verfügbar sind. Wurde noch keine Eingabe 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 import import import import
java.util.Vector; org.apache.oro.text.regex.PatternCompiler; org.apache.oro.text.regex.PatternMatcherInput; org.apache.oro.text.regex.Perl5Matcher; org.apache.oro.text.regex.Perl5Pattern;
public class ExpressionAnalyzer { private PatternCompiler regexpCompiler; public Vector getAllOccurrencesOfPattern( final String originalContent, final String patternString) { Vector results = new Vector(); // 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 markieren 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 unterschiedlichen 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 markierten 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 java.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 informiert 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 BusinessException-Klasse forciert werden. Eclipse geht dabei davon aus, dass die neue BusinessException-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 anzuklicken, 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 gewü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öchte 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 machen 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 Vervollstä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 Konstrukte wie Try-Catch-Blöcke oder Kommentare besitzt die IDE Vorlagen. Bei der Definition von Vorlagen werden bestimmte Freiheitsgrade offen gelassen. Dazu zählen beispielsweise 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-Dialog den Begriff „code templates“ eingeben, um schnell zur gewünschten Eigenschaftenseite zu gelangen. —
Wir beginnen die Zeile hinter dem PatternMatcherInput und vor dem returnStatement mit der Eingabe des Befehls while. Danach drücken wir Ÿ+Leertaste, um die Kontexthilfe aufzurufen. Eclipse bietet drei verschiedene While-Schleifen an. Wir begnü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 ConditionAusdruck. Wir geben als logischen Ausdruck die Buchstaben occ ein und drücken Ÿ+Leertaste. Der Begriff wird auf occurrencesMatcher automatisch vervollständigt. 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 Parameterreihenfolge 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 completion übernimmt. Allerdings ist dies nur selten nützlich. Wir ergänzen die While-Condition 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 weitertippen (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 results = new Vector(); 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-Statement 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 MatchResult 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 entspricht dies dem gesuchten Ergebnisstring. Diesen fügen wir in unseren Result-Vektor result ein und erhalten so die fertige Ergebnismenge.
2.4.6
Gimmicks des Editors
Über Sinn und Unsinn komplexer Tastenkombinationen zum Fingerbrechen lässt sich zuweilen 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)) bereit. 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-spezifische 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 Informationen über Vererbungshierarchien zur Verfügung stellt. Eine einfache Version (Quick type hierarchy view) lässt sich über die Tastenkombination Ÿ+T anzeigen, wenn der Cursor zuvor auf einer Variablen positioniert wird. Mittels der gleichen Tasten lässt sich zwischen 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 Indikatorstreifen 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 zurü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-Speicher noch ein Sourcecode-Management-System existiert, das die langfristige Versionierung 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 gespeicherten REPLACE WITH – Ersetzen der aktuellen Source-Version mit einer gespeicherten RESTORE FROM – Wiederherstellung bereits gelöschter Elemente (Methoden, Felder, ...) aus der lokalen Historie
—
2.5
Kleiner Tipp für Löschexperten: Wenn Sie versehentlich einmal eine JavaKlasse gelöscht haben sollten, was ohne Source Control ManagementSystem 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 einfach wieder rekonstruieren.
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. Improving 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 Modellierung, macht sich Gedanken über abstrakte Inhaltsbeschreibungen, konkrete Implementierungen, 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 Komponenten 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 Vielzahl 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 setRegExpCompiler 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 Ausnahmen beeinflussen. Tipp: Das kleine Lämpchen neben der Tabellenzeile zeigt an, dass Ihnen die Vervollständigungsfunktion von Eclipse zur Verfügung steht, so dass man mittels Ÿ-Leertaste unvollständige Klassennamen vervollständigen lassen kann. Interessant ist die PREVIEW-Möglichkeit, bei der Eclipse anzeigt, an welchen Klassen Änderungen vorgenommen werden. Müssen größere Refactoring-Aktionen durchgeführt werden, 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 (REPLACE X DUPLICATE CODE FRAGMENTS) und hilft so, mehrere Codestellen gleichzeitig zu refactoren.
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 Previews 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 to Nested
Wandelt eine anonyme innere Klasse in eine eingebettete, benannte Subklasse um
Convert Nested Type to Top Level
Wandelt eine eingebettete Unterklasse in eine eigenständige Klasse um und erzeugt für diese eine eigene Java-Datei
Move Member Type to New File
Extraktion einer Unterklasse in eine eigene Datei
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 Unterklasse 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 Possible
Ersetzt das Auftreten einer Klasse im Sourcecode durch dessen Superklasse, wo immer dieser Austausch syntaktisch möglich ist
Infer Generic Type Arguments
Ersetzt Raw types durch generische Typen ab Java 5
Inline
Gegenteil des Extrahierens einer Methode. Fügt den Sourcecode 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 AccessorMethoden (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ändig. Andere IDEs bieten unter Umständen noch mehr Möglichkeiten. Betrachtet man jedoch 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 Methoden 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 mindestens von java.lang.Object als Root-Klasse erbt, können zumindest Methoden wie toString 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, bietet Eclipse an, jene zu implementierenden Methoden, die jetzt zum Syntaxfehler führen, automatisch 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 halber 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. Dabei werden alle Superklassen der Hierarchie samt implementierten Interfaces aufgelistet. Auch hier (wie in bereits vorangegangenen Beispielen) lassen wir uns den Methodenkommentar 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 Sourcecode. Entsprechende Hinweissymbole finden sich zudem in der Outlineview 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 Fehlermeldung, die in unserer BusinessException weitergereicht wird, im Sourcecode auslagern. Dies ist ein erster Schritt zur Implementierung einer Mehrsprachigkeit, die wir damit umsetzen 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 ihnen 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 ersetzen die Key-Namen der ersten beiden Values durch ERROR_PATTERN_COMPILE1 bzw. ERROR_PATTERN_COMPILE2. Die Namen dürfen hierbei keine Leerzeichen aufweisen. 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 vornimmt, 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 ausgelagert 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 unterschiedliche 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 getAllOccurrencesOfPattern 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 liegende Klammer, die die Test Cases strukturiert.
—
Ab einer gewissen Phase und unter entsprechendem Zeitdruck des Projekts 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 aktivieren. 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 Checkbox 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 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 Inhalt 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 jeweils 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 suchen 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 2.7.1
Debuggen in Eclipse 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önnen, 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 versehen sein, wenn der Classloader der VM die Klasse geladen hat. Über die Breakpoint-Properties, die über die rechte Maustaste auf einem Breakpoint erreicht werden können, können wir die Aktivierung des Breakpoints mit zusätzlichen Eigenschaften einschränken (siehe Abb. 2.31) und beispielsweise vorgeben, wie viele Male der Breakpoint übersprungen wird, bevor er greifen soll. Bei Breakpoints innerhalb von Schleifenkonstrukten ist das von Vorteil, aber auch die Vorgabe einer expliziten zusätzlichen Bedingung kann in den Properties erfasst werden. Für unsere Zwecke können wir z.B. erfassen, 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 Breakpoint 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 vorkommen, 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 Zustand 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 virtuelle Maschine auswählen usw. So können wir den Build bzw. den Compile-Lauf vollkommen 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önnen 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 Klassen in unterschiedlichen Projekten wiederfinden. Besonders dann muss bei der Konfiguration sehr aufgepasst werden, weil eine Klasse n-fach vorkommen 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 einem Projekt bzw. Package oder Source-Verzeichnis gestartet werden (siehe Radiobutton). Mittels des Punkts REMOTE JAVA APPLICATION können wir uns an entfernte, virtuelle Maschinen „attachen“. Das heißt, wir sind potenziell in der Lage, auch produktive Java-Applikationen, so diese im Debug-Modus gestartet wurden, über eine TCP/IP-Verbindung und einen 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 keine 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 debuggenden Sourcecode-Stellen müssen auf beiden Seiten den gleichen Versionsstand aufweisen, 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 existiert. 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 übergeben 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 JavaUmgebungsvariablen zu übergeben (-Dproperty=) 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 Projektname, 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 Libraries 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 jederzeit wieder aufrufen. In der Classpath-Ansicht wird zwischen den USER ENTRIES und den BOOTSTRAP ENTRIES unterschieden. 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 virtuellen 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 Konfiguration 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 Anwendung 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 DebugZeitpunkt 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 Funktionen 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 Umgebungsvariablen 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 diesem Fall kann die erarbeitete Variante in einer Datei gespeichert und wiederverwendet (shared) werden und es lässt sich gleichzeitig vorgeben, welche Perspektive zum Startzeitpunkt dieser Launch Configuration geöffnet werden soll. Es empfiehlt sich hier, die entsprechende 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 vorgeben. 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 normalen 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 umgelenkt 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 Debugger angehalten hat. Im Sourcecode verankerte Breakpoints sind durch den kleinen runden Kreis und ein Häkchen daneben gekennzeichnet. Da davon ausgegangen wird, dass bereits Erfahrungen mit dem Debuggen in den unterschiedlichsten IDEs vorliegen, wird im Folgenden lediglich eine kurze Liste der wichtigsten 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 markierte Objekt deklariert ist
Open Declaration Type Hierarchy
Öffnen der 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 weitergehen
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 Funktion wird allgemein bei Remotedebugging von Java-Anwendungen außerhalb der Eclipse-Umgebung verwendet.
Use Step Filter / Edit Step Filter / Filter Type / Filter Package
Mit Step Filtering lassen sich einzelne Klassen oder Packages beim Debug-Durchlauf ausblenden. Diese Funktion kann einund ausgeschaltet werden. Filter Type/Package beziehen den aktuellen Typ und das aktuelle Package in den Filter mit ein.
2.7.5
Vererbungshierarchieanzeige
des
aktuellen
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 Korrektheit 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 werden (remote debugging). Dies wird in Eclipse dadurch realisiert, dass Eclipse per Zufall einen 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 komplett 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-Prozess) 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 Sourcecode- 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ühren 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 Funktionen fehlen, startet man die Debugsession häufig mit einer moderneren. Zu beachten ist hierbei 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 allerdings 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-Configuration 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 angezeigt. Des Weiteren wird die Startklasse und die Port-Adresse für die Kommunikation zwischen 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 ...). Weitere 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 Verschachtelung 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 Sourcecode vorhanden ist) im Editor angezeigt. Über die rechte Maustaste können die oben beschriebenen 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ückzuspringen. 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 allerdings 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 gegangen, welche Parameter in welcher Reihenfolge übergeben wurden und wie Eclipse den Klassenpfad zusammengebaut hat, dann empfiehlt sich ein Blick zu den Startup-Parametern. 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 Startkonfiguration 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 lokalen 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 Namen 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 Objektklasse und die Hashcode-Adresse.
Abb. 2.35: Variables View
—
Besonders das Debuggen komplexer Objekte stellte in den vorangegangenen 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öglichkeiten: 1. uninteressante Membertypen wegblenden (über das Menü in der Variables View lassen sich Konstanten und statische Elemente einund 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 logische Baumstruktur des jeweiligen Objekts anpasst. Er ist über das Kontextmenü 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 werden. 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 komplexen 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äsentation 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 Baumelemente in die Zwischenablage z.B. zum Anzeigen in einem Editor.
Change Variable Value
Öffnet ein Fenster zum Ändern des Variableninhalts. Dies geht nur bei primitiven Datentypen nicht jedoch bei komplexen. Um komplexe 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 Formatter
Öffnet einen Dialog, in dem durch einen Code Snippet vorgegeben werden kann, wie der Inhalt des Objekts in der Detailanzeige angezeigt werden soll. Dies ist dann hilfreich, wenn die toStringMethode nicht implementiert wurde bzw. werden konnte (fremder Bytecode) und kurzfristig die Ansicht geändert werden soll.
Open Declared Type
Öffnet ein Fenster mit dem Sourcecode des Objekttyps.
Open Declared Type Hierarchy
Öffnet ein Fenster mit der Vererbungshierarchieansicht des Objekttyps.
Instance Breakpoints
Zeigt alle Breakpoints innerhalb des selektierten Objekts an, die definiert sind, und erlaubt es, diese zu begrenzen.
Toggle Watchpoint
Fügt einem Objekt einen Watchpoint hinzu oder entfernt diesen. 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 anzuhalten. 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 Watchpoint 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 Variables 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 NullPointerException 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 Übersicht zu verlieren, oder erst über die Checkbox vor dem Breakpoint-Eintrag 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 zuschlagen 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.
—
76
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.
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 erscheint, 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 bedeutet nicht, dass nur java.lang.Exception oder alle davon abgeleiteten Klassen zum Breakpoint definiert werden können, auch Throwable bzw. alle Error und Runtimeexceptions können auf diese Art und Weise abgefangen werden. Im sich öffnenden Dialog ist der gewünschte Exception-Typ auszuwählen und zu konfigurieren, 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“ Nullpointerexceptions als Breakpoints zu aktivieren, denn dadurch taucht sehr schnell die erste Exception in manchen Frameworks auf und wird abgefangen, 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 „normalen“ 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 BREAKPOINT 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 Breakpoint-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. Hilfreich 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 kopiert 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 Namen 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 ausgewertet 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 sinnvollerweise 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 transformiert. 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 Expression 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 angezeigt werden. Wenn wir also analyzer.toString() markieren und mit INSPECT ansehen wollen, wird die Methode auf der Analyzer-Instanz aufgerufen und das Rückgabeobjekt (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 Neuerungen 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 Objektvariable 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 Zusammenhang deutlich wird. Alle hier vorgestellten Aktionen (Inspect, Display, Execute und Watch) können auch über das Kontextmenü der jeweiligen Objekte im Editor aufgerufen 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 Arbeit 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 tauglich erweist, muss man austesten oder beim entsprechenden Hersteller erfragen. Eclipse erlaubt in begrenztem Maße, zur Laufzeit den Sourcecode einer Methode zu ändern. 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 Hotswap 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 Beispielprojekt betrachtet werden. Sollte dieser Fehler nicht behoben sein, muss an die SourcecodeStelle 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 Debugger 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 Instanzvariablen, die vom Classloader während des Debug-Vorgangs schon in die VM geladen worden 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 unterstü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 produktiven 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 Methoden ü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 objektorientierter Lösungen in Klassen und Interfaces populär wurde. Ein komplexes Beziehungsgeflecht zwischen diesen beiden kann bei einer großen Anzahl eben solcher Elemente allerdings 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 stellen 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 scrollen. 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 Toolbar, ü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 einen entsprechenden Menüeintrag (im Menü NAVIGATE) oder eine Tastenkombination erreichbar. 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. Zumeist ist man als Entwickler aber weniger daran interessiert, alle Schritte, die man bei seiner „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 markiert wurden, an denen es Probleme gibt – sei es, dass ein Compile- bzw. Syntaxfehler vorliegt oder durch den Build-Vorgang eine Warnung erzeugt wurde. Welche Arten von Fehlern (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) geben 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 Dateien. Erwartungsgemäß steigt die Ergebnisanzahl mit der Größe des Suchbereichs (hier als Scope bezeichnet). Der Scope kann neben der selektierten Ressource oder dem WorkingSet auch die durch dieses Projekt eingeschlossenen Projekte (siehe Abschnitt 2.3.1) umfassen. 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 Verzeichnis gesucht werden soll, kann im Scope auch ein so genanntes Working Set definiert werden. Über den CHOOSE-Button wird mittels eines logischen Namens konfiguriert, welche Projekttypen, welche Verzeichnisse und welche Projekte durchsucht werden sollen. Gleichzeitig lassen sich Inhalte auch sofort ersetzen, dazu dient der REPLACE-Button bei der Dateisuche. 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 weiter 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 entsprechenden 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 normalerweise 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öglichkeit 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 (Neubeginn der Suche am Anfang der Datei nach dem Erreichen von dessen Ende) und INCREMENTAL 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 suchenden 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, bevor der FIND-Button angeklickt wird.
2.8.4
Open-Funktionen
Die folgenden Aktionen sind zumeist nach Selektion des Elements über einen entsprechenden 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 Verbindungen 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 Projekten. 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 gefundene 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 keinen Typ, so wird die Typhierarchie des umgebenden Sourcecode-Elements (Klasse bzw. Interface) 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 positioniert wird, die überschrieben worden ist, und dann die Aktion OPEN SUPER IMPLEMENTATION ausgeführt wird, führt diese in die noch nicht überschriebene Originalimplementierung. 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 anhand einer Baumdarstellung schnell nachvollzogen werden, wer dort welche Methode aufruft.
—
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-Konvention) 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-Zugriff) 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 getAllOccurrencesOfPattern-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 Suchergebnisse 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 2.9.1
Weitere Views 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 beschrieben, die Vererbungs- und Implementierungshierarchie vom jeweils ausgewählten Java-Typ aus betrachtet (siehe Abb. 2.41). Im oberen Teil wird ein Hierarchiebaum angezeigt. Abhängig davon, welche Toolbar-Einstellung aktiv ist, zeigt dieser entweder die Hierarchie vom aktuellen Element aufwärts (von welcher Klasse erbt meine Klasse, welche Interfaces werden von meiner Klasse implementiert?) oder abwärts (wer erweitert oder implementiert den aktuellen Typ?) oder eingeschränkt sogar beides (ganz linker ToolbarMenü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 Aussehen 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 entsprechendes 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. Letztendlich werden alle Aktionen, egal ob Java-Elemente editieren oder XML-Strukturen erzeugen, 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 Navigator 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 infrastructure). 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 Laufbandsymbol 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 abgefragt 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, weisen allerdings Java 5 schon als Basisplattform für die Entwicklung aus. Einige dieser oftmals sanft eingeführten Neuerungen haben wir beim Streifzug durch unser Anwendungsbeispiel mit Regular Expressions bereits erstmalig kennen gelernt. Da an dieser Stelle genügend Grundlagen geschaffen sein sollten, um mit Eclipse zu arbeiten, 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 aktivieren. 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 optionales 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 RuntimeBibliothek – eben die von JRE-Hersteller – mitgeliefert, in der diese Konzepte umfangreich angewandt werden. Insofern ist es ratsam, die hier von Eclipse vorgeschlagenen WarningMeldungen 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 Formatierung des Sourcecodes, der sich zumindest inhaltlich leicht von seinem Vorgänger abhebt. In den Preferences der Workbench oder pro Java-Projekt finden sich die individuellen Einstellungen 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 beispielsweise 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 Annotation spezielle Wizards an, die die Erstellung beschleunigen sollen (siehe Abb. 2.45). Wir wollen hier testhalber eine Enumeration, eine Annotation und eine normale Java-Klasse 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.eclipsebuch.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 Kunden herausgreifen und prüfen, ob er der erste Kunde ist1. Hierfür benötigen wir zwei Klassen. Zum einen die JavaExamples-Klasse und eine „dumme“ 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
Auch wenn hier nichts Wesentliches passiert, kann dieser Code bereits in Ant geladen werden. Dazu wird er in einer Datei gespeichert, die üblicherweise mit build.xml als Standardbezeichnung 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 dieses Target ausführen, bevor die Tasks in alles ausgeführt werden. Dieses hängt aber seinerseits 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 dieses Target jedoch schon ausgeführt wurde, kommt es nun nicht mehr zum Einsatz. Innerhalb 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 werden 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 wiederkehren. Es ist daher zu Beginn eines Projekts sehr sinnvoll, darauf zu achten, dass diese Targets 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 Bereitstellen 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 Festlegen 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 einen 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 mehrere 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 Zieldateien, seien es Klassenverzeichnisse, Libraries oder andere Ausgabedateien. 쐌 DEPLOY: Diese Aufgabe führt das Bereitstellen zum Deployment oder das Deployment 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 Abschluss 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 reagieren 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übersichtlichen Menge von Status-, Warn- und Fehlermeldungen einige Kernaussagen zu extrahieren 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. ratsam, 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: 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.
164
eclipse_v01.book Seite 165 Montag, 30. Januar 2006 12:02 12
5 – Build Management mit Eclipse
165
eclipse_v01.book Seite 166 Montag, 30. Januar 2006 12:02 12
Exkurs: Build Management mit Ant
166
eclipse_v01.book Seite 167 Montag, 30. Januar 2006 12:02 12
5 – Build Management mit Eclipse
Die einzelnen Aufgaben sind hier natürlich sehr einfach. Die Struktur kann als Gerüst genutzt 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-Target 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 enthalten 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 COMPILE 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 versionsunabhä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 Erstellung von Versionen mit unterschiedlichen Parametern weitestgehend ausgeschlossen. Für REPORT wurde in diesem Skript auf die eingebaute Funktion MailLogger zurückgegriffen, um eine Benachrichtigung der betroffenen Personen (Programmierer, Tester, Nutzer) 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 -Zeichen vor einer Eigenschaft zeigt, dass diese Eigenschaft geändert worden ist.
Abb. 6.11: Die Properties View für die Klasse IFEingabe
Im Quelltext werden daraufhin in der Methode initialize die entsprechenden SetterMethoden 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 layout 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 beginnen 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 gewechselt. 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. Alternativ 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 importiert und das Dialogelement selbst als Attribut deklariert und mit null initialisiert. private private private private private private
JLabel jLabel = null; JTextField jTextField = null; JLabel jLabel1 = null; JTextField jTextField1 = null; JButton jButton = null; JButton jButton1 = null;
Des Weiteren erfolgt in der Getter-Methode für die ContentPane das Hinzufügen der Dialogelemente 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 erzeugt, welche dem Quelltext ebenfalls automatisch hinzugefügt werden. Der folgende Quelltext enthält die Implementation für den ersten Button. Für die weiteren Dialogelemente wird ein analoger Quelltext generiert, wobei für die beiden Textfelder der Aufruf der Methode 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 ÜBERNEHMEN-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ändigen Klassennamen angeben oder alternativ die Klasse importieren. Das Datensatzobjekt fügen wir anschließend einer Liste daten hinzu. In der Liste daten werden alle eingegebenen 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 ausgibt, auf die Daten zugreifen kann, wird die Liste daten als Attribut des Hauptfensters definiert. Hierzu wird in der Klasse HauptFenster das Attribut daten als vom Typ java.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 Implementation 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 ANSICHT | 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 mithilfe 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üssen wir noch vor der Implementation des Listener eine Konstante definieren, die eine Referenz 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 GridLayout. Als Spaltenanzahl geben wir 1 und als Zeilenanzahl 2 ein. Der horizontale und vertikale Abstand soll jeweils 50 betragen. Anschließend wird eine scrollbare Tabelle der ContentPane 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ückliefert. Das Objekt wird in der Methode erzeugt und mit den Daten aus der Liste daten initialisiert. Da auch hierbei, genau wie bei der Klasse IFEingabe, auf das Hauptfenster zugegriffen 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