Diplomarbeit

  • 5,637 views
Uploaded on

Meine Diplomarbeit zum Thema "Entwicklung eines webbasierten CORBA-Clients mit Java Servlets im Umfeld betrieblicher Standardsoftware". …

Meine Diplomarbeit zum Thema "Entwicklung eines webbasierten CORBA-Clients mit Java Servlets im Umfeld betrieblicher Standardsoftware".

Vorgelegt dem Fachbereich Wirtschaftsinformatik der Universität-Gesamthochschule Siegen zum Erlangen des Grades Diplom Wirtschaftsinformatiker im Jahr 2002.

More in: Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
5,637
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
8
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. DiplomarbeitEntwicklung eines webbasierten CORBA-Clients mit Java Servlets im Umfeld betrieblicher Standardsoftware vorgelegt dem Fachbereich Wirtschaftsinformatik der Universit¨t-Gesamthochschule Siegen a zum Erlangen des Grades Diplom Wirtschaftsinformatiker von Markus M¨ller o Hagener Str. 404 57223 Kreuztal Matrikelnummer 539623 Betreuender Professor: Prof. Dr. Bernd Freisleben Betreuende Firma: Varial Software AG, Hauptstrasse 18, 57074 Siegen Bearbeitungszeitraum: 2.5.2002 - 2.9.2002
  • 2. INHALTSVERZEICHNIS iInhaltsverzeichnis1 Einleitung 32 Technologie 5 2.1 Java Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.1 Entstehungsgeschichte . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.2 Alternative Ans¨tze . . . . . . . . . a . . . . . . . . . . . . . . . . . . . 5 2.1.3 Die Zukunft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2 CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.1 Die OMG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.2 Object Management Architecture . . . . . . . . . . . . . . . . . . . . . 12 2.2.3 Interface Definition Language . . . . . . . . . . . . . . . . . . . . . . . 15 2.2.4 Alternative Ans¨tze . . . . . . . . . a . . . . . . . . . . . . . . . . . . . 16 2.2.5 Vorteile von CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.3 Verbindung von Java Servlets und CORBA . . . . . . . . . . . . . . . . . . . 253 Varial World Edition 26 3.1 Leistungsumfang VWE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3 Das Web-Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 Anforderungen an das Web-Interface 31 4.1 Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.2 Internationalisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 ¨ 4.2.1 Ubersetzung der sprachlichen Inhalte . . . . . . . . . . . . . . . . . . . 38 4.2.2 Zeichens¨tze . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . 40 4.2.3 L¨nderspezifische Formate . . . . . . a . . . . . . . . . . . . . . . . . . . 41 4.2.4 Lokalisierung der fachlichen Inhalte . . . . . . . . . . . . . . . . . . . . 41 4.3 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 4.3.1 Verteiltes Rechnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 4.3.2 Verteilung von Server-Last . . . . . . . . . . . . . . . . . . . . . . . . 42 4.3.3 Komprimierte Inhalte . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.3.4 Zwischenspeicherung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4.4 Anpassbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4.4.1 Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4.4.2 Corporate Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 4.5 Analogie zu bestehender VWE-Oberfl¨che . a . . . . . . . . . . . . . . . . . . . 475 Konzeptioneller Neuentwurf eines Web-Interfaces 50 5.1 Multi-Tier-Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 5.2 Das MVC-Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 5.2.1 Model – Das Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 5.2.2 View – Die Ansicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 5.2.3 Controller – Die Steuerung . . . . . . . . . . . . . . . . . . . . . . . . 52 5.2.4 Zusammenspiel der Komponenten . . . . . . . . . . . . . . . . . . . . 52
  • 3. INHALTSVERZEICHNIS ii 5.2.5 Vorteile von MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 5.3 HTTP und das Session-Problem . . . . . . . . . . . . . . . . . . . . . . . . . 52 5.4 Business-Objekt und Enumerations . . . . . . . . . . . . . . . . . . . . . . . . 55 5.5 Das Callback-Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 5.5.1 Daten sammeln und erst komplett an Browser ubergeben¨ . . . . . . . 68 5.5.2 Server Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 5.5.3 Client Pull . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 5.5.4 Client Pull + DHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 5.5.5 Daten ungepuffert schreiben . . . . . . . . . . . . . . . . . . . . . . . . 70 5.5.6 Daten ungepuffert schreiben + viele kleine Tabellen . . . . . . . . . . 70 5.5.7 Daten ungepuffert schreiben + Tabelle imitieren . . . . . . . . . . . . 71 5.5.8 Asynchrones Warten . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 5.6 Tabsheets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 5.7 Multimedia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.7.1 MIME-Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.7.2 Bilderzeugung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.7.3 Excel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 5.7.4 WAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 5.8 Darstellung mit verschiedenen Browsern . . . . . . . . . . . . . . . . . . . . . 796 Die VWE-Web-API 82 6.1 Das Packet com.varial.base . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.1.1 VServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.1.2 VListServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 6.1.3 VDetailServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 6.1.4 VSelectServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.1.5 VChartServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.1.6 VState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 6.1.7 VListState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 6.1.8 VDetailState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 6.1.9 VSelectState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 6.1.10 VContext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 6.1.11 Instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.1.12 BO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.1.13 VBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.1.14 VException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.1.15 TempData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.1.16 AbstractCallback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 6.1.17 VListStateThread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 6.1.18 ExceptionHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 6.1.19 StringMapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 6.1.20 VCurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 6.1.21 VNumber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 6.1.22 VDate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 6.2 Das Packet com.varial.translation . . . . . . . . . . . . . . . . . . . . . . . . . 110
  • 4. INHALTSVERZEICHNIS iii 6.2.1 Translator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 6.2.2 TranslatorCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 6.3 Das Packet com.varial.gui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 6.3.1 GuiHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 6.3.2 VGuiBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 6.3.3 LabeledTextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 6.3.4 LabeledNumberField . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 6.3.5 LabeledCurrencyField . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 6.3.6 LabeledTextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 6.3.7 LabeledMemo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 6.3.8 LabeledButtonTextField . . . . . . . . . . . . . . . . . . . . . . . . . . 129 6.3.9 LabeledCheckBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 6.3.10 LabeledRadioButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 6.3.11 LabeledComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 6.3.12 LabeledEditableComboBox . . . . . . . . . . . . . . . . . . . . . . . . 130 6.3.13 LabeledListBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 6.3.14 LabeledListBoxButtons . . . . . . . . . . . . . . . . . . . . . . . . . . 131 6.3.15 LabeledGrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 6.3.16 GridBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 6.3.17 DivGridBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 6.3.18 GraphBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 6.3.19 ImageBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 6.3.20 TabSheetBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 6.3.21 MenuBarBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 6.3.22 MenuEntryTreeBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 6.3.23 MenuEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 6.3.24 MenuBarComponentInterface . . . . . . . . . . . . . . . . . . . . . . . 139 6.3.25 SelectCompanyBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 6.3.26 SelectOkCancelButtonBean . . . . . . . . . . . . . . . . . . . . . . . . 140 6.3.27 SelectSearchBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 6.3.28 JavaScriptBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 6.3.29 JavaScriptHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 6.3.30 Theme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 6.4 Das Packet com.varial.taglib . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 6.4.1 varial.tld . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 6.4.2 VComponent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 6.4.3 VTextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 6.4.4 VNumberField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 6.4.5 VCurrencyField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 6.4.6 VDateField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.4.7 VMemo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.4.8 VButtonTextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.4.9 VCheckBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.4.10 VRadioButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.4.11 VComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
  • 5. INHALTSVERZEICHNIS iv 6.4.12 VEditableComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.4.13 VListBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.4.14 VGrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.4.15 VGraph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.4.16 VImage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.4.17 Empty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.4.18 Vspacer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 6.4.19 TabSheetControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 6.4.20 TabSheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 6.4.21 MenuBar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.4.22 SelectOkCancel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.4.23 SelectSearch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.4.24 HeadLine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.4.25 LastChange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 6.4.26 JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 6.4.27 CssLink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 6.4.28 HiddenField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 6.4.29 HiddenExtraField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 6.4.30 Translator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 6.4.31 LanguageString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1607 Beispiel f¨r die Verwenung der VWE-Web-API u 163 7.1 Vorbereitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 7.1.1 Die IDL-Beschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 7.1.2 Die Server-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 7.1.3 Die Client-BOs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 7.1.4 Die Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 7.2 Listen-Ansicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 7.2.1 Das ListServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 7.2.2 Der ListState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 7.2.3 Die JSP-Listen-Seite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 7.2.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 7.3 Detail-Ansicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 7.3.1 Das DetailServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 7.3.2 Die JSP-Detail-Seite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 7.3.3 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 7.4 Auswahl-Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 7.4.1 Das SelectServlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 7.4.2 Der SelectState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 7.4.3 Die JSP-Auswahl-Seite . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 7.4.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 7.5 Abschluss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1958 Aufbau und Bedienung der Web-Oberfl¨che a 196
  • 6. INHALTSVERZEICHNIS 19 Zusammenfassung und Ausblicke 197A Anhang 199 Tabellenverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 A.1 Abbildungsverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 A.2 Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
  • 7. VorwortDie vorliegende Diplomarbeit beschreibt die Entwicklung einer Internet-Schnittstelle f¨r udas ERP-System Varial World Edition“. Angefertigt wurde die Arbeit bei der Varial ”Software AG in Kaan Marienborn, bei der ich bereits zuvor als Werkstudent besch¨ftigt awar. Aus meinem Interesse sowohl an modernen Internet-Technologien als auch an der Java- ¨Programmierung und den strategischen Uberlegungen des Unternehmens Varial entstanddie Idee, eine Anbindung der World Edition f¨r das World Wide Web zu konstruieren. Der uGrundstein f¨r VWE-Web war gelegt. u Die Arbeit ist schließlich recht umfangreich ausgefallen, da sie neben den verwendetenTechnologien sowohl die Bedienung des Web-Interfaces als auch dessen Entwicklung be-schreibt. Durch die Dokumentation aller wichtigen Klassen und die beispielhafte Umsetzungeiner Anwendung, soll es dem Leser erm¨glicht werden, die entwickelte API selbstst¨ndig zu o averwenden und mit ihrer Hilfe weitere Funktionalit¨ten der World Editon zu implementieren. a Danken m¨chte ich Herrn Prof. Freisleben f¨r die Betreuung der Diplom-Arbeit. Ein o ubesonderer Dank geht ebenso an meine Kolleginnen und Kollegen der Varial Software AG,die mir mit Rat und Tat zu Seite standen und die durch ihr freundliches Miteinander einsehr gutes Arbeitsklima f¨r das Heranreifen des Projekts schufen. u Weiterhin ist es mir ein Bed¨rfnis, Ina daf¨r zu danken, dass sie ihre Freizeit f¨r das u u uKorrekturlesen der Arbeit opferte. Auch bei meinen Kommilitonen Maik, der neben derKorrektur f¨r viele interessante fachliche Diskussionen zur Stelle war, und Tobi f¨r seine u uErkl¨rungen zu DCOM, SOAP & Co m¨chte ich mich an dieser Stelle herzlich bedanken. a oIhr wart mir eine große Hilfe. Ebenfalls haben die vielen unz¨hligen User diverser Internet-Foren, wie vorzugweiße dem aSELFHTML-Forum, zum Gelingen dieser Arbeit beigetragen. Danke f¨r die vielen guten uRatschl¨ge, Meinungen und Kritiken. a Außerdem sei meinen Mitmenschen gedankt, die mich in den letzen Monaten unterst¨tzt, ugelobt, ertragen und getr¨stet haben und mit ihrem Verst¨ndnis den n¨tigen Freiraum f¨r o a o udie Erstellung der Arbeit gegeben haben und damit deren Realisierung erst erm¨glichten. Zu oguter Letzt gilt mein besonderer Dank nat¨rlich Julia, die mir nicht nur in Zeiten technischer uSchwierigkeiten die n¨tige Hardware zur Verf¨gung stellte, sondern auch mit einem Mix o u u u u ¨aus R¨cksicht und Zuneigung entscheidende Motivationssch¨be f¨r das Uberwinden mancherTiefphase und f¨r die Fertigstellung der Arbeit lieferte. Danke! u
  • 8. 1 EinleitungDie Industrie befindet sich zur Zeit im Wandel. Die traditionelle Wirtschaft bewegt sichhin zur Digital Economy“, einem System, in dem alle Teilnehmer der Wertsch¨pfungskette o ”auf digitalem Wege, mit Hilfe des Internets, kommunizieren und ihre Transaktionen uber ¨das World-Wide-Web ausf¨hren. Das Internet etabliert sich immer mehr als das globale uInformations- und Kommunikationsmedium schlechthin. W¨hrend vor Jahren das Internet lediglich statische Inhalte zur Verf¨gung stellte, nimmt a umittlerweile mehr und mehr dynamischer Content das Netz ein. Das Potential reicht jedochweit uber die M¨glichkeiten eines einfachen eShops oder eines G¨stebuchs hinaus. So bieten ¨ o asich auch einem modernen ERP-System interessante M¨glichkeiten, das Internet f¨r eine o uunternehmens- und weltweite Abwicklung von Gesch¨ftsf¨llen zu nutzen. a a Diese Diplomarbeit beschreibt hierzu die Entwicklung eines Systems, mit dessen Hilfewebbasierte Benutzerschnittstellen f¨r das ERP-System Varial World Edition“ (VWE) u ”erstellt werden k¨nnen. o VWE ist eine von dem Unternehmen Varial Software AG entwickelte ERP-Software.Hierbei handelt es sich um eine verteilte Anwendung, die mit CORBA realisiert wird. DerServer wird in Java implementiert, w¨hrend clientseitig C++ zum Einsatz kommt. aIm Rahmen der Diplomarbeit wird die Software um die M¨glichkeit erweitert, auf aus- ogew¨hlte Datenbest¨nde mittels Web-Browser zugreifen zu k¨nnen. Auf diese Weise wird a a oes dem Benutzer erm¨glicht, VWE via Intra-, Extra- oder Internet von jedem beliebigen oArbeitsplatz zu nutzen. Hierbei kommen Java Servlets zum Einsatz. Die Arbeit gliedert sich in neun Abschnitte. Nach dieser Einf¨hrung werden im zweiten uKapitel zun¨chst die beiden Techniken CORBA und Java Servlets vorgestellt. Hierbei werden ainsbesondere Alternativen zu diesen Technologien aufgezeigt und diskutiert. Die Vorteile desverwendeten L¨sungsansatzes werden herausgestellt und die Entscheidung f¨r CORBA und o uJava Servlets begr¨ndet. u Kapitel 3 beschreibt das ERP-System VWE. Es wird ein Einblick in den Leistungsumfangund den Aufbau von VWE gegeben. Außerdem wird gezeigt, wie ein Web-Interface diebestehenden Funktionalit¨ten sinnvoll erweitern bzw. erg¨nzen kann. a a Das vierte Kapitel fasst anschließend alle Anforderungen, die an eine Browser-Oberfl¨che agestellt werden, zusammen. Kapitel 5 zeigt, wie diese Anforderungen umgesetzt wurden undwelche Fragestellungen und Probleme sich bei der Entwicklung ergaben. Kapitel 6 erl¨utert die Komponenten, die zur Realisierung entwickelt wurden. Zentrale aPackete werden aufgef¨hrt und die Funktionen der Klassen im Einzelnen erl¨utert. u a Im siebten Kapitel wird aufgezeigt, wie die entwickelten Komponenten zur Realisierungeines Use-Cases eingesetzt werden k¨nnen. Hier wird eine kleine Anwendung beispielhaft o
  • 9. 4umgesetzt. Kapitel 8 widmet sich der Bedienung der Web-Oberfl¨che. Der Aufbau sowie die aHandhabung des Web-Interfaces werden erl¨utert. a Das abschließende neunte Kapitel fasst noch einmal alle gewonnenen Erkenntnissezusammen und bietet einen Ausblick auf zuk¨nftige Entwicklungen. u
  • 10. 2 Technologie2.1 Java ServletsServlets sind Java-Programme, die auf einem Web-Server laufen.W¨hrend Java urspr¨nglich f¨r den Einsatz in Embedded-Systemen entwickelt wurde, wuchs a u usp¨ter das Interesse an Java durch den Einsatz als Applets. Bei Applets handelt es sich um aJava-Code, der in einem Web-Umfeld clientseitig, also im Browser, ausgef¨hrt wird. Dank uJavas Plattformunabh¨ngigkeit ist der Byte-Code auf jedem Betriebssytem ausf¨hrbar. Dies a uf¨hrte zusammen mit der Tatsache, dass eine solche Funktionalit¨t im Browser bislang u aunbekannt war, zu einem regelrechtem Java-Boom. Mit Java-Servlets halten Java und seine Vorteile nun auch Einzug auf der Serverseite.Was Applets f¨r den Browser sind, sind Servlets f¨r den Web-Server. Prinzipiell sind Servlets u ukeinesfalls auf die Behandlung von HTTP-Anfragen beschr¨nkt. Denkbar w¨re auch, ein a aServlet in einen Mail- oder FTP-Server einzubetten, um dessen Funktionalit¨t zu erweitern. aIn der Praxis bilden solche Einsatzm¨glichkeiten jedoch eher die Ausnahme, so dass Servlets ouberwiegend f¨r HTTP-Anfragen verwendet werden.¨ u2.1.1 EntstehungsgeschichteUrspr¨nglich bestand die Aufgabe des Internets darin, Informationen in Form von statischen uSeiten zur Verf¨gung zu stellen. Der Web-Server konnte die Anfrage eines Clients durch u ¨die einfache Ubermittlung vorgefertigter Dokumente befriedigen. Mittlerweile hat sich dasInternet jedoch stark gewandelt, so dass die Bereitstellung statischer Seiten u.U. nicht mehrausreichend ist, sondern dass f¨r jede Anfrage eine andere Seite generiert werden muss. Es ugibt mehrere Gr¨nde f¨r die Generierung dynamischer Seiten: u u • Die Web-Seite basiert auf Benutzereingaben Die Ergebnisseiten von Suchmaschinen sind hierf¨r ein typisches Beispiel. Je nach Such- u begriff wird dem Benutzer eine andere Seite pr¨sentiert. a • Die Web-Seite beinhaltet Daten, die sich oft ¨ndern a Ein Beispiel hierf¨r ist eine Unternehmensseite, die den aktuellen Aktienkurs angibt, u oder die Web-Seite einer Zeitung, die die neusten Schlagzeilen und den Wetterbericht darstellt. • Die Web-Seite verwendet Informationen aus serverseitigen Quellen Typisches Beispiel hierf¨r w¨re ein eCommerce-Seite, die eine Liste von Produkten und u a deren Preise aus einer Datenbank generiert.Auf Grund der neuen Anforderungen wurde nach neuen L¨sungsans¨tzen, die dem Wunsch o anach dynamischen Web-Seiten entsprachen, gesucht.2.1.2 Alternative Ans¨tze aCommon Gateway Interface Das Common Gateway Interface (CGI) war die erste Techno-logie, die das Erzeugen von dynamischen Web-Seiten erm¨glichte. o 5
  • 11. 2.1 Java Servlets 6Bei CGI nimmt der Web-Server wie gewohnt eine Client-Anfrage entgegen, startet dann aberein externes Programm und leitet die Bearbeitung an dieses Programm weiter. Das Programmgeneriert daraufhin die Antwortseite. Diese Seite kann nun vom Web-Server an den Clientgesendet werden.Mit CGI k¨nnen dynamsiche Seiten in fast jeder Programmiersprache erzeugt werden. CGI oruft lediglich ein Programm auf und erwartet eine R¨ckgabe, die an den Browser geschickt uwird. In welcher Sprache das Programm geschrieben ist spielt hierbei keine Rolle. Allerdingshat sich Perl als Programmiersprache durchgestetzt, da Perl m¨chtige Befehle zur Verar- abeitung von Texten bereitstellt (u.a. Regular Expressions), die sich im Umfeld von CGI alsgroße Hilfe herausstellen. Auf diese Weise war es erstmals m¨glich, dynamsiche Seiten zu oerzeugen. Schnell verbreitete sich CGI und immer mehr Web-Server stellten dieses Interfacezur Verf¨gung. uDer Nachteil von CGI ist jedoch, dass nicht gerade sparsam mit Serverresourcen umgegangenwird. F¨r jede Anfrage wird das verarbeitende Programm als eigener Prozess gestartet. Bei uhochfrequentierten Servern kann es somit vorkommen, dass viele Prozesse gleichzeitig laufen,was schnell zu einer hohen Serverlast f¨hren kann. Um z.B. ein Perl-Skript auszuf¨hren, muss u ubei CGI jedesmal der Perl-Interpreter gestartet werden. Abbildung 1 zeigt die Funktionsweisevon CGI. Abbildung 1: Web-Server mit CGI Ein anderer Nachteil von CGI ist, dass CGI-Programme nicht mit dem Server intera-gieren k¨nnen, da sie in einem eigenen Prozess gestartet werden. Ein CGI-Skript kann so obeispielsweise nicht in das Logfile des Servers schreiben. Außerdem k¨nnen CGI-Skripte nur orecht schwer Daten untereinander austauschen oder zwichen zwei Anfragen persistent halten,da der Prozess nach Abarbeitung der Anfrage beendet wird.Um die Performance von CGI zu verbessern wurden mehrere L¨sungsans¨tze entwickelt: o aDie Firma Open Market entwickelte eine Alternative namens FastCGI, die im Gegensatz zuCGI ein Programm immer im selben Prozess laufen l¨sst. So wird nur noch ein Prozess pro aProgramm, und nicht mehr pro Anfrage gestartet. Dies f¨hrt zwar zu einer Performance- uVerbesserung, erzeugt u.U. aber immer noch eine Reihe von Prozessen auf dem Server. Ab-bildung 2 zeigt einen Web-Server mit FastCGI-Unterst¨tzung. u
  • 12. 2.1 Java Servlets 7Speziell f¨r Perl-Skripte auf dem Apache-Server wurde mod perl entwickelt. Bei mod perl u Abbildung 2: Web-Server mit FastCGIhandelt es sich um ein Modul f¨r den Apache-Server, das den Perl-Interpreter direkt in den uServer einbettet. Perl-Skripte laufen so wesentlich schneller als zuvor. Dieser Ansatz ist jedochausschließlich f¨r Perl-Skripte, die auf dem Apache-Server laufen, geeignet. uServer-Extension-API Einige Serverhersteller entwickelten sog. Extension-APIs f¨r ihre uWeb-Server. Auf diese Weise k¨nnen Server um weitere Funktionalit¨ten erweitert werden. o aBeispiele hierf¨r sind ISAPI f¨r Microsofts Internet Information Server (IIS) oder WAI (ur- u uspr¨nglich ver¨ffentlicht unter der Bezeichnung NSAPI) von iPlanet/Netscape f¨r deren Ser- u o uver. Abbildung 3 stellt die Funktionsweise der Server-Extensions dar. Diese Erweiterungen sind i.d.R. in C++ geschrieben, was eine hohe Performance zur Folgehat. Jedoch hat auch diese L¨sung einige Nachteile: Durch die enge Verbindung mit dem Web- oServer kann eine abgest¨rzte Server-Erweiterung den kompletten Server lahm legen. Außer- u ¨dem sind Erweiterungen immer auf einen bestimmten Servertyp festgelegt. Eine Ubertragungauf andere Server ist somit nicht m¨glich. oServer Side Includes Mit Hilfe von Server Side Includes (SSI) k¨nnen dynamische Infor- omation direkt innerhalb von HTML-Dateien eingebunden werden. Server Side Includes sindgenerell dazu gedacht, kleinere Teile einer HTML-Seite dynamisch einzubinden. Ein typisches ¨Beispiel ist die Angabe des letzten Anderungsdatums einer Seite.SSI wird von sehr vielen Servern unterst¨tzt und ist deshalb meist von Server zu Server uubertragbar. Jedoch ist der Funktionsumfang recht beschr¨nkt, so dass SSI nicht f¨r gr¨ßere¨ a u oProjekte geeignet ist.ASP, PHP, SSJS Eine weitere M¨glichkeit zum Erstellen dynamischer Web-Seiten bieten odie Technologien ASP (Active Server Pages), PHP (benannt nach einem Vor¨ngerprodukt anamens Personal Homepage) oder auch SSJS (Server Side JavaScript).Bei dieser Technik werden Code-Fragmente in HTML-Seiten eingebettet. Wird eine Seite
  • 13. 2.1 Java Servlets 8 Abbildung 3: Web-Server mit Server-Extension-APIangefordert, wird der eingebettete Code zuerst vom Web-Server ausgef¨hrt, bevor er zum uClient geschickt wird.Diese Technik ist vor allem hilfreich bei Seiten, die nur sehr wenig dynamischen Inhalt bietenund uberwiegend aus statischen Teilen bestehen, da hier lediglich ein paar zus¨tzliche Zeilen ¨ ain den bestehenden HTML-Code eingef¨gt werden m¨ssen. Ein Beispiel ist ein Seite, die den u uBesucher namentlich begr¨ßt, sonst aber keine benutzerabh¨ngigen Informationen enth¨lt. u a aEin anderes Beispiel ist ein Besucherz¨hler auf einer sonst statischen Seite. aBesteht die Seite jedoch aus sehr vielen dymanischen Teilen, zeigen sich die Schw¨chen dieser aTechnologie. Durch die Vermischung von statischen Inhalt und Funktionalit¨t ist eine Pflege a ¨des Codes recht schwierig, da die Ubersichtlichkeit stark leidet. Außerdem ist es so nur schwer,wenn uberhaupt m¨glich, die Arbeit von Entwicklern und Designern zu trennen. ¨ oAußerdem sind ASP und SSJS serverabh¨ngig. So verwendet ASP in der Regel VBScript aoder JScript und l¨uft nur auf Microsofts IIS. Zwar gibt es bereits kommerzielle Software wie az.B. InstantASP von Halcyon Software oder OpenASP von ActiveScripting.org, die ASP auchauf anderen Servern m¨glich macht, jedoch ist dies mit großem Aufwand verbunden und bis oheute nicht vollkommen ausgereift. SSJS wurde von iPlanet/Netscape entwickelt und bettetJavaScript-Fraktmente in HTML ein. SSJS l¨uft jedoch ausschließlich auf iPlanet/Netscape- aServern.Lediglich PHP, das sich stark an dem vielen CGI-Programmiern bekannte Perl anlehnt, l¨uft aauf nahezu allen Servern. So verwundert es auch nicht, dass PHP die verbreitetste dieserdrei Sprachen ist. Der Nachteil, dass große Projekte schnell un¨bersichtlich werden, bleibt uallerdings auch hier bestehen.ColdFusion Das Unternehmen Allaire entwickelte eine Alternative zur Erzeugung dynami-scher Inhalte: ColdFusion. Bei diesem Ansatz werden HTML/XML-¨hnliche Elemente, ge- a
  • 14. 2.1 Java Servlets 9nannt ColdFusion Markup Language (CFML), in die Web-Seite eingebettet. War der Funk-tionsumfang von ColdFusion zu Beginn noch recht beschr¨nkt, bieten sich dem Entwickler amittlerweile viele n¨tzliche Features, die jedoch in ihrer M¨chtigkeit der Java-API deutlich u aunterlegen sind.Die neuste Version von ColdFusion er¨ffnet jedoch die M¨glichkeit, benutzerdefinierte Ele- o omente zu entwickeln, die mit JavaServlets kommunizieren k¨nnen. ColdFusion bietet sich osomit als Erg¨nzung von Servlets an, wobei allerdings zu abzuw¨gen ist, ob die Verwendung a avon JavaServer Pages, die sp¨ter beschrieben werden, nicht die bessere Alternative ist. aServlets Ein Java Servlet l¨uft ¨hnlich wie Server-Extensions im Web-Server und erweitert a adessen Funktionalit¨t. Jedoch laufen Servlets als Java-Programme in einer Java Virtual Ma- achine (JVM), so dass sie erstens sicher sind und zweitens, dank Byte-Code, leicht auf anderePlattformen ubertragen werden k¨nnen. Servlet-Unterst¨tzungen sind bereits f¨r viele Web- ¨ o u uServer erh¨ltlich. aDer große Vorteil von Servlets besteht darin, dass Client-Anfragen nicht zu einer Unmengevon Prozessen f¨hren. Vielmehr ist es mit Servlets m¨glich, separate Threads zu erzeugen, u odie in ein und dem selben Prozess laufen. Abbildung 4 zeigt diese Vorgehensweise. Denkbar Abbildung 4: Web-Server mit Servlet-Unterst¨tzung uw¨re auch die Verteilung von Threads auf mehrere Prozesse, die auf verschiedenen Rechnern a(sog. Backend Server) laufen.Diese Technik erm¨glicht eine schnelle und resourcenschonende Verarbeitung von Anfragen. oGleichzeitig ist es Servlets m¨glich, eng mit dem Web-Server zusammen zu arbeiten, da sie odirekt in diesen eingebettet werden. Eine solche Art der Kommunikation w¨re beispielsweise amit CGI nicht m¨glich. oDies alles f¨hrt zu den folgenden entscheidenden Vorteilen: u
  • 15. 2.1 Java Servlets 10 Effizienz Servlets laufen im Gegensatz zu CGI-Skripts nicht als schwergewichtigerBetriebssystem-Prozess, sondern als resourcenschonender Thread. CGI-Progamme m¨ssten ubei N parallelen Anfragen N mal in den Arbeitsspeicher geladen werden. Bei Servlets g¨be aes zwar auch N Threads, aber lediglich ein Exemplar der Servlet-Klasse.Servlets verweilen als einfache Instanz im Speicher. Im Gegensatz zu CGI, wo f¨r jede An- ufrage der (Perl-)Interpreter erneut geladen werden muss, kann ein Servlet somit, wenn es ersteinmal geladen wurde, jede weiter Anfrage quasi unmittelbar ausf¨hren. Weiterhin ist es Serv- ulets m¨glich, einen Zustand uber mehrere Anfragen hinweg bei zu behalten. Daten k¨nnen o ¨ oals Klassenvariablen zwischengespeichert werden, vorangegangene Berechnungen k¨nnen ge- ocachet werden oder externe Resourcen, wie z.B. eine Datenbank-Verbindung, k¨nnen gehalten owerden, was sonst bei jeder Anfrage erneut einige Zeit in Anspruch nehmen w¨rde. u M¨chtigkeit Java Servlets k¨nnen den kompletten Java Sprachumfang nutzen. a oDatenbank-Verbindungen mit JDBC, Multithreading, Datenkomprimierung, Internationali-sierung, Grafikerzeugung oder Serialisierung sind nur einige Beispiele f¨r die M¨glichkeiten, u odie sich Servlets bieten. Kommuniziert ein Servlet mit einem Applet, k¨nnte auf die M¨glich- o okeit von Remote Method Invokation (RMI) zur¨ckgegriffen werden. Zus¨tzlich zu den auf- u agef¨hrten Gebieten decken Klassen von Drittanbietern fast jedes andere Einsatzgebiet ab. uDas Parsen von XML, die Verwendung von regul¨ren Ausdr¨cken oder das Erzeugen von a uDiagrammen seien als Beispiel genannt.Alles in allem bietet die Java-API eine M¨chtigkeit, die kaum oder nur schwer von CGI- aProgrammen oder Skriptsprachen erreicht werden kann. Portierbarkeit Da Servlets in Java geschrieben sind, k¨nnen sie problemlos zwischen overschiedenen Plattformen portiert werden. Der Quellcode wird dazu wie gewohnt kompiliert.Der erzeugte Byte-Code in Form einer .class-Datei kann nun auf jeder JVM laufen. Servlets,die unter dem IIS von Microsoft entwickelt wurden, k¨nnen somit ohne Ver¨nderungen auf o aeinen Apache-Server ubertragen werden. ¨ Sicherheit Java Servlets sind sehr sicher. Da Java bereits beim Kompilieren eine Typ-Pr¨fung vornimmt, k¨nnen klassische Sicherheitsl¨cken, wie beim typenlosen Perl gar nicht u o uerst entstehen.Javas Garbage Collector und das Fehlen von Zeigern stellt sicher, dass Speicherprobleme wiebeispielsweise Memory Leaks, ung¨ltige oder gar b¨swillig ver¨nderte Pointer, nicht m¨glich u o a osind. In C++ k¨nnte beispielsweise auf die 1000-te Position eines Arrays mit nur 200 Ein- otr¨gen zugegriffen werden. Dies w¨rde dazu f¨hren, dass so in Bereiche des Arbeitsspeichers a u ugeschrieben w¨rde, auf die sonst kein Zugriff best¨nde. Tats¨chlich ist dies eine oft benutzte u u aHintert¨r f¨r Angriffe. Servlets bieten diese M¨glichkeit nicht, da automatsich Array-Grenzen u u ouberpr¨ft werden.¨ uFehler zur Laufzeit, wie z.B. eine Division durch Null, die bei Server Extensions oft als Sicher-heitsl¨cke f¨r Angriffe genutzt wurden um den Server lahmzulegen, werfen bei Java Servlets u ueine Exception, die entweder vom Servlet selbst oder aber vom Server abgefangen werden.Ein Absturz des Servers ist nicht mehr m¨glich. oZu guter Letzt werden bei Servlets keine externen Programme ausgef¨hrt, wie es bei CGI u
  • 16. 2.1 Java Servlets 11der Fall ist. Oftmals ist es m¨glich einem CGI-Skript Daten zu ubergeben, um dadurch die o ¨Ausf¨hrung von anderen Programmen zu erzwingen. So werden bei Perl-Skripten oft Mails uverschickt, indem das Unix-Programm sendmail verwendet wird. Auf den ersten Blick istes ausreichend, die Adresse, die der Benutzer in ein Formular eingegeben hat, an sendmailweiter zu reichen. Da jedoch auch mehrere Befehle in einer Unix-Shell mit einem Semikolongetrennt werden k¨nnen, kann ein Angreifer als Adresse so etwas wie mmo@varial.de;rm o-rf / angeben. W¨rde dies ungepr¨ft an sendmail weitergegeben, erg¨be dies: sendmail u u ammo@varial.de;rm -rf /. Resultat w¨re neben dem Senden einer Mail auch die Ausf¨hrung a udes rm-Befehls, der die Festplatte des Servers l¨schen w¨rde. o uDies ist nur eines von vielen Beispielen, das zeigt, dass die Ausf¨hrung von externen Pro- ugrammen ein erhebliches Sicherheitsrisiko darstellt. Servlets hingegen verwenden keine Shell,selbst dann nicht, wenn ein Remote-Systemaufruf ausgef¨hrt wird. uMan sieht, dass Java Servlets uber einen umfangreichen Sicherheitsmechanismus verf¨gen. ¨ u Serverintegration Dadurch, dass Servlets direkt in den Web-Server integriert werden,k¨nnen sie eng mit ihm zusammenarbeiten. Sie k¨nnen direkt in Logfiles schreiben, relative o oURLs in absolute Pfadangaben ubersetzen oder auch Benutzerberechtigungen uberpr¨fen. ¨ ¨ uCGI-Programme laufen hingegen getrennt vom eigentlichen Server, so dass eine solche Artder Zusammenarbeit dort unm¨glich ist. oJavaServerPages JavaServer Pages oder kurz JSP verbinden die Vorteile von Servlets, Cold-Fusion und eingebetteten Skript-Sprachen. JavaServer Pages ¨hneln vom Aufbau recht stark adem ASP- oder PHP-Ansatz. In statischen HTML-Code 1 werden Elemente f¨ r dynamischen uInhalt eingef¨gt. Seiten, die nur wenig dynamische Teile beinhalten, k¨nnen so ohne großen u oAufwand erstellt werden.Sollte der dynamische Inhalt einen gr¨ßeren Teil der Seite ausmachen, k¨nnen JSP-Seiten o oleicht mit Servlets zusammen arbeiten. Hierzu k¨nnen sog. Taglibs entwickelt werden. Dies osind Bibliotheken mit benutzerdefinierten Elementen. Dem Entwickler wird es auf diese Weiseerm¨glicht, eigene Tags zu entwerfen. Die Funktion der Tags wird von einer Java-Klasse im- oplementiert. Der Vorteil dieser Vorgehensweise ist, dass Ausgabe (JSP) und Funktion (Java-Klasse) klar voneinander getrennt sind. Die JSP-Seite unterscheidet sich vom Aufbau herkaum von herk¨mmlichen HTML-Seiten, da alle Elemente der XML-Syntax folgen. So k¨nnen o oWeb-Designer, die mit dem Umgang mit HTML-Seiten vertraut sind, fast ohne Einarbei-tungszeit komplexe Seiten gestallten. Die Funktionalit¨t wird hingegen von Programmierern aubernommen, die sich ihrerseits nicht mit dem Seitenlayout belasten m¨ssen. Beide Parteien¨ uerstellen so gemeinsam ein Projekt, arbeiten aber unabh¨ngig von einander. aMit JSP und Taglibs kann so spielend einfach das Seitenlayout ge¨ndert werden, ohne dass adie Programmlogik angepasst werden muss und umgekehrt. Dies macht auch die Pflege einesProjekts denkbar einfach.Der JSP-Ansatz beinhaltet dar¨ber hinaus auch alle Vorteile von Servlets, da es sich bei JSP- uSeiten nur um eine andere Darstellung von Servlets handelt. JSP-Code wird bei erstmaligerAusf¨hrung2 in ein Java Servlet ubersetzt und kompiliert. Mit JSP erstellte Seiten werden u ¨ 1 JSP ist keinesfalls auf HTML beschr¨nkt, sondern kann theoretisch in jede Art von Text eingebettet awerden. Denkbar w¨ren ebenso XML- oder L TEX-Dokumente. a A 2 JSP-Code kann auch vorkompiliert werden.
  • 17. 2.2 CORBA 12vom Server somit als Servlet betrachtet, sie sind also genauso effizient, m¨chtig, portierbar aund sicher wie Servlets.2.1.3 Die ZukunftMit Java Servlets setzt die Programmiersprache Java ihren Siegeszug der letzen Jahre weiterfort. Java besticht durch die M¨chtigkeit und Eleganz der Sprache, die eine saubere, objek- atorientierte, modulare und einfache Programmierung erm¨glicht. Mit Java Servlets k¨nnen o odiese Vorteile nun auch auf Web-Servern genutzt werden.Immer mehr Hersteller bieten Servlet-Unterst¨tzung f¨r ihre Web-Server, so dass Java Serv- u ulets auf lange Sicht auf Grund ihrer Performance-Vorteile und Portierbarkeit den weitverbrei-teten CGI-Ansatz abl¨sen werden. o2.2 CORBADie Common Object Request Broker Architecture oder kurz CORBA ist eine Spezifikation,die von der Object Managment Group (OMG) entwickelt wurde. CORBA unterst¨tzt die uRealisierung verteilter Objekte. So k¨nnen Objekte zusammen agieren ohne voneinander zu owissen, wo sich das Gegen¨ber befindet, oder in welcher Sprache es implementiert wurde. uCORBA ist in der letzten Zeit immer mehr zu dem Standard f¨r die Entwicklung von Middle- uware geworden. Die OMG umfasst mittlerweile mehr als 800 Firmen, die das ganze Spektrumder Computerindustrie repr¨sentieren. Die einzige bemerkenswerte Ausnahme bildet Micro- asoft mit einem eigenen konkurierenden Objektbus namens Distributed Component ObjectModel (DCOM).2.2.1 Die OMGOMG ist die Abk¨rzung f¨r Object Managment Group. Sie wurde im April 1989 gegr¨ndet u u uund bestand urspr¨nglich aus 11 Firmen, darunter u.a. 3Com Corporation, American Air- ulines, Canon Inc., Data General, Hewlett-Packard, Philips Telecommunications N.V., SunMicrosystems und Unisys Corporation. Mittlerweile umfasst die OMG uber 800 Mitglieder. ¨Auf der Basis eines Vorschlags, Request for Comment (RFC) genannt, wird zun¨chst disku- atiert, was standardisiert werden soll. Dann k¨nnen zu einem festgelegten Anforderungsprofil, oals Request for Proposal (RFP) bezeichnet, Technologien zur Standardisierung vorgeschlagenwerden. Ziel der OMG ist es, herstellerunabh¨ngige, technisch ausgereifte und kommerziell aerfolgreiche Spezifikationen zu erarbeiten und zu standardisieren. Diese Spezifikationen sollenes erm¨glichen, objektorientierte Modelle unter Abstraktion von der verwendeten Hardware ound des Betriebsystems zu gestalten.2.2.2 Object Management ArchitectureDie OMG ver¨ffentlichte im Herbst 1990 die Object Management Architecture (OMA) im oRahmen des sog. OMA Guides, der im September 1992 nochmals uberarbeitet wurde. Drei ¨Jahre sp¨ter wurde OMA dann schließlich ein weiteres Mal erweitert. Im Januar 1995 wurden aEinzelheiten der sog. Common Facilities hinzugef¨gt. Der endg¨ltige Stand der Spezifikation u uist in Abbildung 5 dargestellt. Das Bild zeigt den Aufbau der OMA. Die Architektur gliedert
  • 18. 2.2 CORBA 13 Abbildung 5: Aufbau der Object Management Architecturesich in vier Teile:Application Objects Die Application Objects (oft auch als Application Interfaces bezeich-net) stellen die eigentliche Anwendung dar, die CORBA nutzt. Mit anderen Worten bezeich-net der Begriff Application Objects die Objekte, die durch CORBA verteilt werden sollen.Diese Objekte repr¨sentieren gem¨ß dem Grundsatz der objektorientierten Programmierung a aDinge des realen Lebens. Wichtige Einzelheiten werden mit entsprechenden Attributen mo-deliert, unwichtige Details wegabstrahiert. Im Folgendem werden diese Objekte, bzw. dieJava-Klassen, die diese implementieren, als Business-Objekte (BO) bezeichnet.Die Business-Objekte werden speziell f¨r die jeweilige Anwendung programmiert. Folglich uwerden diese von der OMG nicht n¨her spezifiziert. Die Business Object Task Force der aOMG definiert lediglich, dass ein BO eine Komponente der Applikationsebene ist, die sichentsprechend des Prinzips der Wiederverwendbarkeit, vielseitig einsetzen l¨ßt. aCommon Facilities Mit Common Facilities oder, wie sie von der OMG genannt werden,CORBAfacilities stellt CORBA bereits einige n¨tzliche Dienste f¨r die Verwendung mit BOs u uzur Verf¨gung. Dazu z¨hlen beispielsweise grafische Benutzeroberfl¨chen, Drucker- und Da- u a atenbankdienste, mobile Agenten oder auch Frameworks f¨r Internationalisierung. Das Reper- utoire an CORBAfacilities wird laufend weiterentwickelt und wird in Zukunft praktisch jedenverteilten Dienst anbieten.Common Object Services Die Common Object Services, die von der OMG als CORBA-services bezeichnet werden, bieten das Fundament f¨r die CORBAfacilities. CORBAservices usind Sammlungen von elementare Diensten auf Systemebene, die f¨r die Entwicklung von u
  • 19. 2.2 CORBA 14verteilten Anwendungen ben¨tigt werden. Die OMG definiert insgesamt 15 CORBAservices: o • Lifecycle Service ¨ Ubernimmt das Erzeugen, Kopieren, Verschieben unf L¨schen von Objekten. o • Persistence Service Einheitliche Schnittstelle f¨r das dauerhafte Speichern der Objekte auf unterschiedli- u chen physikalischen Datentr¨gern. a • Naming Service Dienst f¨r das Auffinden von Objekten anhand ihres Namens. u • Event Service Registriert und verwaltet Objekt-Ereignisse, so dass Objekte zusammenarbeiten k¨nnen. o • Concurrency-Control Service Verwaltet als Lock-Manager die Sperren f¨r Transaktionen und Threads. u • Transaction Service Koordiniert ein Zwei-Phasen-Protokol zwischen wiederherstellbaren Komponenten. • Relationship Service Erm¨glicht das Verkn¨pfen von Objekten. Erm¨glicht weiterhin referentielle Integrit¨t. o u o a • Externalization Service Importiert bzw. exportiert Daten uber eine Stream-Mechanismus in eine Komponente. ¨ • Query Service Stellt Abfrageoperationen f¨r Objekte bereit. u • Licensing Service Bietet Operationen um die Nutzungsdauer einer Komponente zu messen. • Properties Service Ordnet Objekten Schl¨ssel-Wert-Paare zu. u • Time Service Synchronisiert Zeitangaben in verteilten Umgebungen. • Security Service Regelt die Sicherheit von verteilten Objekten. Unterst¨tzt Identifizierung, Zugriffskon- u trollen, Vertraulichkeit und Unwiderlegbarkeit der Daten. • Trader Service Verwaltet die Dienste, die Objekte bereitstellen in einem zentralen Verzeichnis. • Collection Service Erm¨glicht CORBA-Schnittstellen, allgemeine Collections zu erzeugen und zu manipu- o lieren.
  • 20. 2.2 CORBA 15Object Request Broker Die OMG definiert mit CORBA einen offenen Standard, liefertselbst jedoch keine Implementierung. Software, die die CORBA-Spezifikation implementiert,heißt Object Request Broker (ORB). Als Beispiele seien hier VisiBroker von Visigenic, Orbixvon Iona oder Suns Java IDL genannt.Der ORB trennt die Anfrage eines Services (Client) von dessen Bereitstellung (Server). DerORB ist das Herzst¨ck der CORBA-Technologie. Alle Aufrufe von Objekten (ob lokal oder uentfernt) werden durch den ORB gemanagt (Abbildung 6). Genauer gesagt ist dies Aufgabe Abbildung 6: Aufruf verteilter Objekte uber den ORB ¨des Objektadapters. Er sorgt daf¨r, dass bei Anfragen das richtige Serverobjekt aktiviert uwird und leitet Auftr¨ge an diese Objekte weiter. Dies geschieht automatisch, ohne dass sich ader Entwickler Gedanken dar¨ber machen muss, wo und ob ein Serverobjekt zur Zeit aktiv uist. Der Objektadapter sorgt daf¨r, dass aus Sicht des Clients alle Serverobjekte aktiv und ulokal zu sein scheinen.CORBA legt fest, dass jeder ORB einen Standardadapter namens Basic Objekt Adapter(BOA) unterst¨tzen muss. Da der BOA bei CORBA 1.1 noch nicht ausreichend spezifiziert uwar, entwickelten sich viele herstellerabh¨ngige BOAs, die zwar alle den CORBA-Standard aerf¨llten, jedoch u.U. nicht richtig zusammen arbeiteten. Aus diesem Grunde wurde CORBA u2.0 um den Portable Object Adapter (POA) erweitert. Durch zus¨tzliche Spezifikationen der aOMG ist nun sichergestellt, dass POAs zueinander kompatibel sind, w¨hrend das bei BOAs anicht unbedingt der Fall sein muss.Da die ORB-Implementierungen an die Spezifikation der OMG gebunden sind, k¨nnen ORBs overschiedener Hersteller problemlos ausgetauscht werden. Seit CORBA 2.0 und der Verab-schiedung des Internet Inter-ORB-Protocols (IIOP) ist dar¨ber hinaus auch sicher gestellt, udass ORBs verschiedener Hersteller miteinander kooperieren (Abbildung 7). Bei IIOP han-delt es sich im Wesentlichen um TCP/IP, erg¨nzt um einige CORBA-spezifische Nachrichten, adie als gemeinsames Backbone-Protokoll dienen.2.2.3 Interface Definition LanguageCORBA ist ein selbstbeschreibendes System. Damit Objekte sprachenunabh¨ngig mitein- aander agieren k¨nnen, wird klar zwischen Schnittstellenbeschreibung und Implementierung ounterschieden. Hierzu dient die Interface Definition Language (IDL). Mit dieser neutralenSprache, deren Syntax an C++ angelehnt ist, werden CORBA-Objekte mit ihren Attributen
  • 21. 2.2 CORBA 16 Abbildung 7: ORB-Verbindung mit IIOP ¨und Funktionen (inkl. Uber- und R¨ckgabe-Parameter und Fehlerbehandlungen) beschrieben. uKomponenten, die in IDL geschrieben sind, sollten zu anderen Sprachen, Betriebssystemenund Netzwerken hin kompatibel sein (Abbildung 8). Hierzu generiert der Compiler aus der Abbildung 8: Sprachunanh¨ngigkeit durch IDL aIDL-Beschreibung f¨r die jeweilige Programmiersprache passende Interfaces. Diese Interfa- uces heißen serverseitig Skeletons, w¨hrend sie clientseitig als Stubs bezeichnet werden. Diese aInterfaces k¨nnen dann von Client und Server implentiert werden. o Auf diese Weise ist es z.B. m¨glich, dass ein in IDL beschriebenes Objekt als C-Client ound Java-Server implementiert und auf verschiedenen Rechnern platziert wird. Die IDL stellthierf¨r die programmiersprachenunabh¨ngige Verbindung her, der ORB sorgt f¨r die Loka- u a ulisierung der verteilten Objekte. F¨r den Programmierer gestaltet sich das Szenario dank uCORBA v¨llig transparent. o2.2.4 Alternative Ans¨tze aSockets Sockets stellen die wohl primitivste Art der Netzwerkkommunikation dar. EinSocket ist ein Peer-to-Peer-Kommunikationsendpunkt uber TCP/IP. 1981 wurden Sockets ¨
  • 22. 2.2 CORBA 17im Rahmen von Unix BSD 4.2 als Interface f¨r interprocess communications“ (IPC) auf u ”Unix-Systemen vorgestellt. Mittlerweile sind Sockets auf nahezu allen Betriebssystemen im-plementiert. Java selbst unterst¨tzt Socket durch einige Klassen in dem java.net-Packet. uEin Socket besteht aus einem Namen und einer Netzwerkadresse und l¨ßt sich in eine von adrei Klassen einteilen. • Datagram Sockets a u ¨ UDP (User Datagram Protocol): unabh¨ngige Packet¨bertragung, keine Ubertragungs- garantie. • Stream Sockets TCP/IP (Transmission Control Protocol / Internet Protocol), verbindungsorientiertes Protokoll. • Raw Sockets ICMP (Internet Control Message Protocol), low-level Protokoll.Durch ihren Low-Level-Charakter sind Sockets zwar sehr schnell, haben hingegen aber aucheinige Nachteile. So bieten Sockets weder Parameter Marshaling noch dynamische Service-Bindung. Der Entwickler muss eigene Protokolle entwickeln, die die Methodenaufrufe desClients den Methoden des Servers zuordnen. Bedenkt man, dass große Systeme leicht einigehundert Funktionen umfassen, k¨nnte dies zu einem gewaltigen Aufwand f¨hren. Die Pflege o uund Wartung der Software w¨rde schnell eine un¨berschaubare Aufgabe. Folglich stellen u uSockets f¨r die Anforderung moderner Systeme keine ausreichende L¨sung dar. u oRMI Remote Method Invocation oder kurz RMI ist eine von der Firma Sun Microsystemsentwickelte Technik zur Realisierung verteilter Anwendungen mit Java. Genauer gesagt er-laubt RMI einer Java-Applikation, Methoden anderer Java-Anwendungen, die in unterschied-lichen JVMs und sogar auf anderen Systemen laufen k¨nnen, aufzurufen. Das Ziel bei der oEntwicklung von RMI war es, ein verteiltes Objektmodel in Java zu integrieren, ohne dabeidas bestehende Sprach- und Objektmodell zu zerreißen. RMI ist seit der Version 1.1 ein fe-ster Bestandteil des JDKs (java.rmi-Packet) und erm¨glicht die einfache Entwicklung einer oClient-Server-Architektur, die sich f¨r den Entwickler fast vollkommen transparent gestaltet. uRMI baut auf Socketverbindungen auf, verbirgt aber alle Low-Level-Einzelheiten. Der Ent-wickler muss keine Protokolle definieren oder sich uber Details der Verbindung Gedanken ¨machen. Java-Klassen kommunizieren mit RMI uber ein wohldefiniertes und standardisiertes ¨Protokoll. Die Entwicklung einer verteilten Anwendung gestaltet sich dadurch recht einfach.Die Arbeitsweise von RMI l¨ßt sich folgendermaßen skizzieren: a • Erstellen eines Remote-Interfaces Bei einem Remote-Interface handelt es sich um ein normales Java-Interface, das von dem Interface java.rmi.Remote abgeleitet wurde. Dieses Interface muss immer als public deklariert werden. Alle Funktionen, die ein verteiltes Objekt zur Verf¨gung stel- u len sollen, m¨ssen in diesem Interface angegeben werden. Hierbei ist zu beachten, dass u die Methoden die Ausnahme vom Typ java.rmi.RemoteException werfen m¨ssen. u Verbindungsst¨rungen und Netzwerkprobleme w¨hrend eines Methodenaufrufs werden o a hiermit angezeigt.
  • 23. 2.2 CORBA 18 • Entwurf einer Serverklasse, die das Remote-Interface implementiert Eine Java-Klasse implementiert die Methoden des erstellten Remote-Interfaces und er- zeugt eine oder mehrere Instanzen. • Registrierung bei einem Name-Service Nachdem mindestens eine Instanz der Server-Klasse erzeugt wurde (sog. Remote- Objekte), muss diese bei einem Name-Service registriert werden. Das RMI-Packet stellt hierzu bereits einen simplen Name-Service mit der Bezeichnung RMI-Registry zur Verf¨gung. u • Aufruf entfernter Methoden Clients verschaffen sich mittels des Name-Services Referenzen auf die Remote-Objekte. Durch solche Remote-Referenzen lassen sich nun Methoden von entfernten Objekten ¨ aufrufen. Zu beachten ist hierbei, dass Ubergabeparamter serialisierbar sein m¨ssen, u indem sie das Interface Serializable implementieren. Der Grund daf¨r ist, dass RMI u Parameter-Objekte in irgendeiner Form uber das Netzwerk schicken muss. Hierzu stellt ¨ Java mit der Objekt-Serialisierung bereits die notwendige Technologie zur Verf¨gung, u auf die RMI zur¨ckgreift. uGenau wie bei CORBA kommunizieren Client- und Server-Klassen nur scheinbar direkt mit-einander. Tats¨chlich dienen auch hier Stubs und Skeletons als Platzhalter, die die Kom- amunikation transparent erscheinen lassen. Der Client hat Zugriff auf eine Stub-Klasse, diedas Server-Interface implementiert. Methodenaufrufe des Stubs werden uber das Netzwerk ¨ubertragen und von dem Gegenst¨ck auf der Serverseite, dem Skeleton, an das jeweilige¨ uServer-Objekt weitergeleitet (Abbildung 9). Abbildung 9: Verteilte Anwendung mit RMI Der RMI-Ansatz unterscheidet sich demnach nicht viel von der CORBA-Architektur.Dementsprechend muss bei der Planung zun¨chst die Frage gestellt werden, welcher Ansatz aden Anforderungen besser gerecht wird. RMI stellt eine wesentlich einfachere Architektur alsCORBA zur Verf¨gung, was dazu f¨hrt, dass RMI besonders f¨r kleinere Projekte geeignet ist. u u uDar¨ber hinaus ist es einfacher zu erlernen und direkt in neueren JDK-Versionen eingebettet. u
  • 24. 2.2 CORBA 19Der Nachteil gegen¨ber CORBA ist allerdings, dass gerade große Projekte durch verschie- udene CORBA-Features (CORBAservices und CORBAfacilities) besser mit die Technologieder OMG umsetzbar sind. Außerdem k¨nnen mit RMI nur reine Java-Projekte implementiert owerden. Eine Kommunikation zwischen Objekte, die in unterscheidlichen Programmierspra-chen geschrieben wurden, ist im Gegensatz zu CORBA nicht m¨glich. RMI stellt folglich bei oheterogenen Projekten keine Alternative dar.DCOM Das Distributed Component Object Model (DCOM) ist Microsofts Antwort auf denOMG-Standard. Mit DCOM stellt Microsoft eine weitere M¨glichkeit zur Realisierung verteil- oter Anwendungen zur Verf¨gung. Dabei gehen die Wurzeln von DCOM weit in die Vergangen- uheit zur¨ck. Strenggenommen wurde 1987 mit Einf¨hrung der Zwischenablage in Windows u uder Grundstein f¨r DCOM gelegt (Abbildung 10). Mit der Zwischenablage war es erstmals u Abbildung 10: Entwicklung von DCOM aus COM und RPCm¨glich, Texte aus einem Programm zu kopieren und in anderen Applikationen einzusetzen. o1992 wurde diese Technik erweitert und als OLE (Object Linking & Embedding) ver¨ffent-olicht. Nun war es nicht nur m¨glich, Texte zwischen zwei Applikationen auszutauschen, son- odern es wurde gar erm¨glicht, komplexere Objekte durch die Zwischenablage zu kopieren. oEin oft zitiertes Beispiel ist das Einbinden einer Excel-Tabelle in einem Word-Dokument. BeiDoppelklick des Benutzers auf die eingebettete Tabelle, startet die Excel-Applikation auto-matisch im Hintergrund und ubernimmt die Kontrolle uber die grafische Oberfl¨che. Da beide ¨ ¨ aAnwendungen jedoch unabh¨ngig von einander entwickelt werden, bedarf es einem standar- adisierten Verfahrens, das die Kommunikation zwischen den Windows-Applikationen regelt.OLE bot mit DDE (Dynamic Data Exchange) die grundlegende Kommunikationsschicht f¨r uden Datenaustausch. Da sich DDE jedoch schon schnell als zu langsam und unflexibel her-ausstellte, konnte sich die Technologie nicht wie gew¨nscht durchsetzen. uMicrosoft entwickelte daraufhin OLE 2. Die Fragestellung, wie zwei Windows-Programmemiteinander Daten austauschen k¨nnen, wurde jetzt ein wenig ausgeweitet. Als zentrales Ziel owurde definiert, dass eine Applikation die Funktionalit¨t beliebiger bin¨rer Komponenten in a aeiner objektorientierten Art und Weise nutzen solle. Dies unabh¨ngig von den verwendeten a
  • 25. 2.2 CORBA 20Implementierungssprachen und ebenso vom Aufenthaltsort der beteiligten Akteure. Das Re- ¨sultat der Uberlegung war 1993 OLE 2, eine Technologie, die schon bald die Grundlage f¨r uCOM bilden sollte.COM ist die Kurzbezeichnung f¨r Component Object Model und definiert einen Standard f¨r u udie Entwicklung von Software-Komponenten. Eine Software-Komponente stellt in der COM-¨Uberlegung eine Art Black-Box dar, die ihre Funktionalit¨ten nach Außen durch beschriebene aSchnittstellen zur Verf¨gung stellt. Bei der Verwendung der Komponente ist es hierbei v¨llig u oegal, wie und in welcher Programmiersprache sie geschrieben ist. Mit Hilfe der Interfaceskann die Komponente von anderen Anwendungen genutzt werden ohne den inneren Aufbauzu kennen (Abbildung 11). Schnell fand ein neues Zauberwort Einzug in die Windows-Welt: ActiveX. ActiveX beinhaltet Abbildung 11: Software-Komponente nach COM: Aufbau und Zugriffdabei lediglich COM. Der Grund f¨r die babylonische Sprachverwirrung, in der auch VBX, udas Software-Komponenten f¨r Visual-Basic-Steuerelemente beschreibt, und das allgemeinere uOCX, Platz finden, ist weniger in technischen Weiterentwicklungen, als in marketingtechni- ¨schen Uberlegungen zu finden.ActiveX war mit COM wesentlich schneller als DDE und dar¨ber hinaus viel flexibler als die ualte Technologie. Mit Windows NT und einer Version f¨r Windows 95 fand ActiveX schnell uerste Einsatzgebiete in der Windows-Welt. Fortan sollte das Component Object Model bzw.ActiveX eine entscheidende S¨ule in der Entwicklung von Windows-Applikationen spielen. aW¨hrend COM lediglich das Zusammenspiel von Software-Komponenten auf dem selben aRechner erlaubt, hebt DCOM als verteiltes COM diese Grenzen auf. DCOM erm¨glicht nun oauch die netzweite Kommunikation zwischen Komponenten und damit die Entwicklung ver-teilter Systeme (Abbildung 12). DCOM-Objekte entsprechen hierbei weitgehend den gewohn-ten COM-Komponenten. Die Kommunikation zwischen den Objekten regelt das DCE (Distri-buted Computing Enviroment), das in Abbildung 13 dargestellt ist. Es basiert im Grunde aufRPC. Clients rufen Server-Methoden auch hier uber die Stellvertreter, die Stubs, auf. Eine ¨ ¨weitere Ahnlichkeit zu CORBA ist, dass DCOM ebenfalls die Beschreibung von Diensten vonderen Implementierung trennt. Hierzu definiert DCOM eine eigene IDL, die allerdings keine¨Ahnlichkeit zu der CORBA-Systax hat. Die neuste Entwicklung der COM bzw. DCOM Technik wurde unter der Bezeichnung COM+ver¨ffentlicht. COM+ ist dabei nichts anderes als die Kombination von DCOM und dem oMicrosoft Transaction Server (MTS). Der MTS, der die Entwicklung von Middleware verein-fachen soll (Abbildung 14 und 15), wurde zuvor als optionales und eigenst¨ndiges Produkt averkauft. COM+ bezeichnet somit keine wirkliche Neuentwicklung des Standards, sondernnur ein neu zusammengestelltes Microsoft Produkt.
  • 26. 2.2 CORBA 21 Abbildung 12: Verteilte Anwendung mit DCOMDer propriet¨re DCOM-Standard stellt eine f¨r Windows-Produkte optimierte Technik f¨r a u udie Umsetzung verteilter Systeme dar. Dementsprechend einfach gestaltet sich die Entwick-lung auf der Microsoft-Plattform. Auf der anderen Seite bietet DCOM keine oder kaumUnterst¨tzung f¨r andere Betriebssysteme. Die Firma Software AG portierte ActiveX un- u uter dem Namen EntireX zwar auf verschiedene Plattformen wie Linux, Sun Solaris, DigitalUnix, HP-UX oder OS/390, eine komplette Kompatibilit¨t wurde hingegen noch nicht er- areicht. Außerdem ist DCOM ein Bin¨rstandard. Die Folge ist eine enge Bindung an die ax86-Prozessorarchitektur. ¨Alle diese Uberlegungen zeigen, dass DCOM in einem reinen Windows-System sicherlich einegute L¨sung darstellt. F¨r die Verwendung in heterogenen Systemen stellt CORBA jedoch o udie bessere Wahl dar.SOAP Das Simple Open Access Protocol oder kurz SOAP ist die neuste Entwicklung ausdem Hause Mircrosoft und definiert ein Transportprotokoll, das die wesentlichen Merkmalevon XML und HTTP in sich vereinigt. SOAP stellt einen wichtigen Pfeiler in Microsofts.NET-Strategie dar. Ziel der .NET-Architektur und damit auch von SOAP ist es, die direkteBindung von Anwendungen an Microsoft Windows und an die x86-Prozessorarchitektur auf-zuheben und eine Kommunikation uber die Grenzen des Microsoft Betriebssystems hinaus ¨zu erm¨glichen. SOAP dient als Grundlage f¨r diese plattformunabh¨ngige Kommunikation o u ain heterogenen Systemen.SOAP beruht im Prinzip auf der Verwendung von sog. Remote Procedure Calls (RPC). Wieder Name bereits andeutet, werden mit dieser Technik entfernte Funktionsaufrufe erm¨glicht. oDurch gestiegene Sicherheitsbed¨rfnisse in Netzwerken bzw. dem Internet werden aber immer umehr Netzwerke durch Firewalls gesichert. Diese Firewalls sch¨tzen an das WWW angeschlos- usene Netzwerke, indem sie Ports blockieren und Anfragen filtern. In der Regel werden nurAnfragen auf den Ports der Standard-Protokolle wie HTTP (Port 80), FTP (Port 21) oder
  • 27. 2.2 CORBA 22 Abbildung 13: Aufbau des DCE Abbildung 14: Kommunikation von COM-Objekten ohne MTS Abbildung 15: Kommunikation von COM-Objekten mit MTS
  • 28. 2.2 CORBA 23SMTP (Port 25) zugelassen. Die Folge ist, dass RPC-Aufrufe des Clients von der Firewallblockiert werden. Zur L¨sung dieses Problems verwendet SOAP den offenen Port 80, indem oRPC-Aufrufe uber HTTP verschickt werden. Hierzu bedient sich SOAP der Datenaustausch- ¨sprache XML. Methodenaufrufe werden mit XML verpackt und dann uber HTTP verschickt. ¨Eine SOAP-Nachricht definiert hierzu einen sog. SOAP Envelope (Abbildung 16). Dieser un- Abbildung 16: Aufbau der SOAP Envelopeterteilt sich wiederum in einen SOAP Header und einen SOAP Body. Der Header enth¨lt aInformationen dar¨ber, was f¨r eine Art von Nachricht vorliegt, den Empf¨nger der Nach- u u aricht und welche Bestandteile der Nachricht optional bzw. obligatorisch sein m¨ssen, um ueine g¨ltige SOAP-Nachricht darzustellen. Der SOAP-Body enth¨lt den eigentlichen Inhalt u ader Nachricht. Außerdem kann eine SOAP-Nachricht noch einen Block mit der BezeichnungFault beinhalten. Dieser kann Fehlermeldungen enthalten, die Transport-Knoten w¨hrend der a¨Ubertragung erzeugt haben.Der eigentliche RPC-Aufruf wird als Nachricht in den SOAP-Body integriert. Um eine ent-fernte Methode mit SOAP aufzurufen, sind die folgenden Angaben notwendig: • Die URL des Zielknotens • Der Name der aufzurufenden Methode ¨ • Ubergabe-Parameter f¨r die Methode u • Evtl. weitere Header-InformationenMit diesen Angaben wird eine SOAP-Nachricht im XML-Format erstellt und uber das Netz- ¨werk verschickt. Dies geschieht normalerweise uber HTTP. SOAP kann jedoch auf jedem ¨anderen Netzwerkprotokoll aufsetzen, das den Austausch von XML-Dokumenten erlaubt.Die Verwendung von XML als kleinster gemeinsamer Nenner erm¨glicht es einerseits, SOAP oauf prinzipiell jeder Plattform auszuf¨hren. Andererseits entstehen gerade bei komplexen uAnwendungen u.U. schnell sehr große Datenmengen, da XML-Dateien neben den reinen In-formationen große Mengen von Formatierungs- bzw. Gliederungsanweisungen in Form vonTags besitzen. Beachtet man weiterhin den Aufwand f¨r das Parsen des Dokuments, erfolgt udie Verarbeitung dementsprechend langsamer als bei CORBA oder DCOM. SOAP bietet
  • 29. 2.2 CORBA 24daf¨r jedoch eine einfachere Zusammenarbeit mit Firewalls. Zusammenfassend l¨ßt sich sa- u agen, dass Microsoft bei der Entwicklung von SOAP eher die Verwendung im Internet im Augehatte, w¨hrend DCOM in kleineren, homogenen LANs St¨rken offenbart. a aAls Erg¨nzung sei an dieser Stelle ein ¨hnliches Verfahren genannt, dass unter der Bezeich- a anung XML-RPC bekannt geworden ist. Auch hier werden RPC-Anweisungen in XML ver-packt. Diese Technologie ist im Gegensatz zu SOAP jedoch nicht in diesem Mase ausgereiftund findet deshalb nur in kleineren Projekten Anwendung.2.2.5 Vorteile von CORBAStellt man CORBA und andere Techniken f¨r die Entwicklung verteilter Anwendungen ge- ugen¨ber, zeigen sich schnell die St¨rken des OMG-Standards. Die reine Socket-Verbindung u abietet zwar eine schnelle Kommunikation, allerdings auf einer denkbar niedrigen Abstrakti-onsebene. So sind neben vielen Verbindungseigenschaften ein eigenes Protokoll zu definieren.Sockets finden demzufolge nur Verwendung in sehr kleinen Systemen. Bereits bei der Umset-zung mittelgroßer Software zeigt sich schnell, dass Socket eine viel zu niedrige Abstraktionbieten.RMI bietet bereits eine sehr hohe Abstraktionsebene. Die Kommunikation erfolgt in einemstandardisieren Protokoll und Verbindsdetails werden f¨r den Entwickler verborgen, so dass udieser sich keine Gedanken uber Einzelheiten der Kommunikation machen muss. RMI ist Teil ¨der Programmiersprache Java und l¨uft deshalb mit der passenden JVM auf sehr vielen Platt- aformen. Bei der Verteilung von Java-Applikationen stellt RMI sicherlich die beste L¨sung dar. oAllerdings erm¨glicht RMI nicht das Zusammenspiel zwischen verschiedenen Programmier- osprachen.Microsofts DCOM-Architekur erm¨glicht im Gegensatz zu RMI zwar eine Kommunikati- oon zwischen Software-Komponenten, die in verschiedenen Sprachen implementiert werdenk¨nnen. Zugleich wurde auch hier eine hohe Abstraktionsebene erreicht. Der Nachteil von oDCOM ist hingegen die enge Bindung an das Microsoft-Betriebssystem und die Prozessor-Architektur. In einer reinen Windows-Applikation bietet DCOM somit eine gute Alternativezu CORBA. In heterogenen Systemen offenbart DCOM aber seine Schw¨chen. aSOAP als neuste Entwicklung von Microsoft hebt die Bindung von DCOM auf. Die Kommu-nikation uber XML ist nicht nur plattformunabh¨ngig, sondern erlaubt auch die Verbindung ¨ auber Port 80 und somit die Zusammenarbeit mit Firewalls. Die Unabh¨ngigkeit von XML¨ awird jedoch mit einem hohen Mass an Overhead f¨r Strukturierungsbefehle bezahlt. Dadurch, udass die XML-Beschreibungen gerade in großen Projekten sehr groß werden, und dass dieseDokumente vor der Verarbeitung entsprechend geparst werden m¨ssen, zeigen sich deutliche uPerformance-Schw¨chen bei SOAP. Mit dem selben Problem ist auch XML-RPC behaftet. aAußerdem bietet sich hier ein geringerer Funktionsumfang.Mit CORBA l¨ßt sich Middleware auf einer sehr hohen Abstraktionsebene realisieren. aDar¨ber hinaus bietet CORBA ein Optimum an Unabh¨ngigkeit. Der Standard ist weder u aan Betriebssysteme, noch an Programmiersprachen gebunden. Außerdem stellt CORBA mitden CORBAfacilities und den CORBAservices viele sehr n¨tzliche Dienste zur Verf¨gung. u uDie OMG vereinigt das Know-How vieler Experten und definiert einen offenen Standard.Resultat ist ein st¨ndig weiterentwickelter und verbesserter CORBA-Standard. a
  • 30. 2.3 Verbindung von Java Servlets und CORBA 252.3 Verbindung von Java Servlets und CORBA Multi-Tier“ ist zu einem der wichtigsten Schlagworte in der modernen Software-Entwicklung”geworden. Durch die Verbindung von Java Servlets und CORBA wird es m¨glich, saubere ovierschichtige webbasierte Anwendungen zu bauen.Mit Java Servlets steht eine effiziente und m¨chtige M¨glichkeit zur Verf¨gung, mit der die a o uVorteile von Java nun auch auf Web-Servern genutzt werden k¨nnen. CORBA erm¨glicht o owiederum die Entwicklung leistungsf¨higer Middleware. aDie Verbindung beider Technologien ist geradezu optimal. Java Servlets sind von Natur ausplattformunabh¨ngig. CORBA ist dar¨ber hinaus nicht nur unabh¨ngig vom Betriebssystem, a u asondern auch von der Programmiersprache. So l¨ßt sich ein Servlet-CORBA-System nicht nur abeliebig auf andere Betriebssysteme ubertragen, sondern es ist auch m¨glich, Servlets mit je- ¨ odem beliebigen CORBA-Server zusammen arbeiten zu lassen, gleichg¨ltig in welcher Sprache udieser geschrieben ist oder auf welchem Betriebssystem er l¨uft. aZusammen stellen CORBA und Servlets ein Optimum an Leistungsf¨higkeit und Unabh¨ngig- a akeit dar.
  • 31. 3 Varial World Edition3.1 Leistungsumfang VWEDie Varial World Edition ist ein neu entwickeltes ERP-System der Firma Varial SoftwareAG. Neben der Personalwirtschaft bietet VWE u.a. auch L¨sungen f¨r das Finanzwesen und o uControlling. VWE wurde erstmalig auf der CeBIT 2000 vorgestellt und liegt momentan ineiner deutschen und einer englischen Version vor. Seit September 2001 befindet sich VWEbei einem Pilotkunden, der britischen Firma Espera Scales Ltd. aus Dorking, s¨dlich von uLondon, im Testbetrieb.VWE wurde speziell f¨r den Einsatz in international operierenden Unternehmen entwickelt. uDabei k¨nnen Firmengruppen (Holdings) problemlos mehrere Firmen getrennt in einem Pro- ogramm verwalten. VWE ist nicht nur mehrsprachen-, sondern auch mehrw¨hrungsf¨hig. D.h. a aim System k¨nnen Buchungen in mehreren W¨hrungen vorgenommen werden. Umrechnungen o afinden zu fixen oder auf Basis tagesgenauer Umrechungskurse aus dem Internet statt. Auch dieAnpassung an landesspezifische Formate ist gew¨hrleistet. Selbst fachliche Besonderheiten, awie beispielsweise unterschiedliche gesetzliche Bestimmungen, k¨nnen mit VWE verwaltet owerden. Hierzu wurde eine spezielle Berechnungslogik entwickelt, die einfache Anpassung, oft-mals sogar vom Anwender selbst, ohne Programmieraufwand, erm¨glicht. L¨nder-, branchen- o aoder unternehmensspezifische Versionen lassen sich somit schnell und effektiv umsetzen.Auf Grund des Vertriebsmodels mit OEM-Partnern wurde bereits bei dem Entwurf von VWEdarauf geachtet, dass ein hohes Maß an Integration erreicht wird. VWE l¨ßt sich leicht an ein abestehendes Design anpassen und in vorhandene Systeme integrieren. Durch einen modularenAufbau, bei dem Funktionalit¨ten bzw. Use-Cases in Programmbausteinen gekapselt sind, ist aes m¨glich, nur einzelne Funktionen zur Verf¨gung zu stellen. Auf diese Weise k¨nnen indi- o u oviduelle ERP-Systeme zusammengestellt werden, die den Anforderungen des Endanwendersgerecht werden. Ein Varial Verkaufsprospekt titelt: Varial Software solutions are accordin- ”gly best-of-breed products”. Best of breed“ bedeutet hierbei, dass der Anwender die Freiheit ”hat, Software-Bausteine nach seinen Bed¨rfnissen zusammenzustellen. u3.2 ArchitekturNeben dieser Komponentenbauweise basiert VWE auf der Basis einer Multi-Tier-Architektur,die mit CORBA realistiert wurde. Abbildung 17 zeigt den dreischichtigen Aufbau der Soft-ware. Varial spricht bei den drei Schichten auch von Presentation Layer“, Application ” ”Layer“ und Persistency Layer“, die jeweils f¨r Darstellung, fachliche Funktionalit¨t und u a ”Datenhaltung zust¨ndig sind. aDer Presentation Layer ist die Oberfl¨che der VWE und ist f¨r die Darstellung der fachlichen a uInhalte verantwortlich. Neben der ergonomischen Gestaltung zeichnet sich die Oberfl¨che adurch die Integration von Office Standards und der M¨glichkeit der flexiblen Anpassung oan bestehendes Corporate Design aus. OEM-Partnern wird mit dem Varial Client SDK(Software Development Kit) eine vollst¨ndige und nahtlose Integration mit anderen Produk- aten erm¨glicht. Ein einheitliches Look and Feel“ mit gleichen Symbolen, Oberfl¨chen und o a ”ergonomischen Prinzipien ist sichergestellt. Beim Anwender treten Wiedererkennungseffekteauf, der Schulungsaufwand reduziert sich.Auch durch die Nutzung von Resource Bundles und die getrennte Haltung von l¨nderspezi- a 26
  • 32. 3.2 Architektur 27 Abbildung 17: Der dreischichtige Aufbau von WVEfischen Formaten vereinfacht sich die Anpassung an andere Sprachen und L¨nder.aZusammenfassend l¨ßt sich sagen, dass der Presentation Layer eine sehr flexible Oberfl¨chen- a agestaltung zul¨ßt. Diese Entwicklungsweise bewahrt vor monolithischen Strukturen, deren aAdaption an andere Sprachen und reginale Sonderheiten massive Ver¨nderungen erfordern aw¨rde. uBeim Application Layer handelt es sich um das Kernst¨ck der VWE. In ihm ist die uFunktionalit¨t aller Anwendungen realisiert. Er stellt eine fachliche Korrektheit, also eine aordnungsgem¨ße kaufm¨nnische Buchf¨hrung, sicher und deckt auch technische Erfordernisse a a uwie Transaktionsicherheit und Performance ab.Der Application Layer folgt einem modularen Aufbau, bei dem alle verwendeten Entit¨ten in asog. Business Objekten gekapselt sind, die den Regeln der objektoriertierten Programmierungentsprechen. Diese modulare Bauweise vereinfacht sowohl die Wartung und Erweiterungenals auch die Anpassung der Software.Ferner sorgt der Application Layer f¨r Transaktionssicherheit und optimalen Datendurchsatz uin Richtung Persistency und Presentation Layer. Dabei wird die Verarbeitung durch denEinsatz von Callbacks, einem Mechanismus, bei dem Daten asynchron geliefert werden, auchgroßen Datenmengen gerecht.Der Persitency Layer sorgt f¨r die Datenhaltung in VWE. Obgleich er den kleinsten Anteil uam Gesamtcode des Systems ausmacht, entscheidet er uber Stabilit¨t und Anwendungsbreite ¨ ader Varial World Edition. Seine Aufgabe ist es, die im Application Layer verwendeten Busi-ness Objekte in relationalen Strukturen abzubilden und in einer Datenbank zu speichern.Mit der Verwendung von JDBC wird hier eine Standardisierung erreicht, so dass VWE mitallen Datenbanken auf SQL-92-Basis kommunizieren kann. Datenbankunterschiede werdenvom Persistency Layer ausgeglichen, damit die Datenhaltung in den verschiedensten RDBSm¨glich ist. Derzeit l¨uft VWE mit Oracle, Interbase, Informix, Sybase und dem SQL-Server o avon Microsoft. Durch die Verwendung von CORBA und die klare Trennung der Schichten, insbesondere
  • 33. 3.3 Das Web-Interface 28des Presentation und Application Layers, wurde es nicht nur m¨glich, die Gesch¨ftslogik von o ader Darstellung zu trennen, sondern es konnte bei der Realisierung auch auf unterschied-liche Programmiersprachen zur¨ckgegriffen werden. Der Presentation Layer (Client) wurde uin C++ geschrieben, w¨hrend auf der Serverseite im Application Layer Java zum Einsatz akommt. Im Rahmen der Diplomarbeit wird nun zus¨tzlich zum bestehenden Client eine wei- atere Anwendung entwickelt, mit der es m¨glich ist, VWE uber das Internet zu nutzen. o ¨3.3 Das Web-InterfaceEin Web-Interface erm¨glicht es dem Anwender, VWE mit einem Browser von nahezu ojedem beliebigen Arbeitsplatz aus zu nutzen. Hierdurch ergeben sich ein Reihe von neuenAnwendungsm¨glichkeiten der Varial World Edition. Zu Beginn muss erst einmal gekl¨rt o awerden, welche Funktionalit¨ten die zu entwickelnde Anwendung zur Verf¨gung stellen soll. a uEs soll also der Frage nachgegangen werden, welche Daten welchem Benutzer zug¨nglich agemacht werden sollen, welche Gesch¨ftsprozesse im Umfeld einer Internet-Anwendung asinnvoll sind und welche eher nicht.Prinzipiell lassen sich alle Benutzer in zwei Gruppen unterteilen: Betriebsinterne undbetriebsexterne Anwender. Als betriebsintern gilt beispielsweise der Vorstand, der Buchhal-ter oder Mitarbeiter im Außendienst. Zur Gruppe der betriebsexternen Anwender z¨hlen az.B. die Kunden, der Steuerberater oder der Wirtschaftspr¨fer. Um nun die verschiedenen uM¨glichkeiten eines Web-Interfaces zu demonstrieren, seien hier beispielhaft einige Use-Cases oaufgef¨hrt: uEin Vorstandsmitglied geh¨rt, wie bereits oben erw¨hnt, zu den betriebsinternen Anwendern, o ahat somit tendenziell mehr Zugriffsrechte als externe Anwender. Es hat Zugriff auf s¨mtliche aDaten. Jedoch ist man eher daran interessiert, schnell Daten in aggregierter Form, wiez.B. Bilanzen, Jahresstatistiken etc, geliefert zu bekommen. Einzelheiten sind hier nichtvon Interesse, behindern zuweilen sogar bei der Auswertung der Daten. Eine denkbareAnwendung des Web-Interfaces w¨re, dass der Vorstandschef auf Dienstreise im Hotelzimmer adie aktuellen Umsatzergebnisse einsieht oder einen Blick auf die neusten Bilanzzahlen wirft.Etwas anders verh¨lt es sich beim Mitarbeiter im Verkauf. Hier sind die Daten, auf die azugegriffen werden kann, deutlich eingeschr¨nkter, beinhalten daf¨r aber mehr Einzelheiten. a uDer Außendienst kann uber das Web-Interface s¨mtliche Kundendaten auswerten und auf ¨ aeinzelne schreibend zugreifen. Beispielsweise kann hier im Außendienst direkt der Name desAnsprechpartners einer Firma ge¨ndert werden. Schließlich ist der Außendienstmitarbeiter a ¨einer der Ersten, die von dieser Anderung erfahren.Zugriffsrechte des Sachbearbeiters lassen sich nat¨rlich weiter einschr¨nken. So betreut z.B. u aein Mitarbeiter nur alle Kunden von A“ bis M“ und hat dementsprechend auch nur Zugriff ” ”zu diesen Informationen.Ein weiteres Beispiel daf¨r, dass eine Internet-Anbindung die bestehende World Editi- uon sinnvoll erg¨nzen kann, findet sich im Bereich Personalwirtschaft. Den Mitarbeitern ades Unternehmens k¨nnen pers¨nliche Daten zur Verf¨gung gestellt werden. Auf diese o o uWeise k¨nnen Arbeiter und Angestellte z.B. die Anzahl der Resturlaubstage einsehen, o ¨die Anderung ihrer Daten wie Anschrift, Telefonnummer, etc. veranlassen oder in Erwei-terung zu einem Mitarbeiter-Portal Vorschl¨ge f¨r das betriebliche Vorschlagswesen abgeben. a u
  • 34. 3.3 Das Web-Interface 29 Rechte von externen Usern sind im Gegensatz hierzu deutlich eingeschr¨nkter. So sollten aDaten nur gelesen, diese aber nicht ver¨ndert werden d¨rfen. Einem externen User wird des- a uhalb in der Regel nur ein sog. Pr¨ferarbeitsplatz eingerichtet. uSo k¨nnte z.B. einem Steuerberater Daten uber eine Browser-Oberfl¨che zur Verf¨gung ge- o ¨ a u ¨stellt werden. Interessant ist in diesem Zusammenhang auch die Anderungen in der Ab-gabenordnung zum 01. Januar 2001 und die damit verbundenen Zugriffsm¨glichkeiten der oBetriebspr¨fer des Finanzamtes: u §147 Absatz 6 Satz 1 AO: Sind die Unterlagen nach Absatz 1 mit Hilfe eines Datenverarbeitungssystems erstellt worden, hat die Finanzbeh¨rde im Rahmen einer Außenpr¨fung das Recht, o u Einsicht in die gespeicherten Daten zu nehmen und das Datenverarbeitungssystem zur Pr¨fung dieser Unterlagen zu nutzen. uEinem Wirtschaftspr¨fer kann ubers Internet Zugang zu Informationen gew¨hrt werden, u ¨ adie f¨r Pr¨fungen notwendig sind. Weitere Daten sollten aber selbstverst¨ndlich verborgen u u ableiben. Ein Web-Interface w¨rde diesen neuen Anforderungen gerecht werden. uWeiterhin k¨nnen Kunden die Software dazu nutzen, um offene Rechnungsbetr¨ge einzu- o asehen. Kunden des Unternehmens k¨nnen sich so von jedem Browser aus ansehen, welche oRechnungen noch bezahlt werden m¨ssen. Eine Bonit¨tseinsch¨tzung hingegen sollte dem u a aKunden nicht gezeigt werden. Man sieht, dass es eine Reihe von Einsatzm¨glichkeiten und Anwendungsf¨llen f¨r ein o a uWeb-Interface im Rahmen eines modernen ERP-Systems gibt, bei dem jedem Benutzer einean die entsprechende Rolle angepasste Datensicht zur Verf¨gung gestellt wird. u Dadurch, dass bei VWE klar zwischen der Darstellung und Verarbeitung von fachlichenInhalten unterschieden und getrennt wird, kann die Multi-Tier-Architektur um einen wei-teren CORBA-Client und, wie sich zeigen wird, um eine weitere Schicht erg¨nzt werden. aAbbildung 18 zeigt den neuen vierschichtigen Aufbau der Software mit Webanbindung. DieAufgabe, die den normalen Desktop-Client zukommt, wird von einem Java Servlet ubernom- ¨men, das auf einem Web-Server (beispielsweise Apache Tomcat, JRun von Macromedia oderBEA WebLogic Server) l¨uft. Da das Servlet selbst jedoch nur die Ausgabe erzeugen bzw. avorbereiten kann, diese aber selbst nicht dargestellen kann, wird ein Browser ben¨tigt. Dieser ostellt die vierte Schicht im Modell dar. Die vom Servlet erzeugten Daten werden mit HTTPbzw. HTTPS an den Browser geschickt. Dieser stellt sie dann f¨r den Anwender dar und udient zur Bedienung der Anwendung.
  • 35. 3.3 Das Web-Interface 30 Abbildung 18: Der vierschichtige Aufbau von WVE-Web
  • 36. 4 Anforderungen an das Web-Interface4.1 Sicherheit ¨Da das Internet immer mehr zur Ubertragung sensibler Daten verwendet wird, ist die Sicher-heitsbetrachtung zu einem der wichtigsten Themen in der Web-Programmierung geworden.Insbesondere ist darauf zu achten, dass nur authoristierte Benutzer Zugriff auf sensible Datenhaben. Im Einzelnen sind folgende vier Punkte sicherzustellen: • Authentizit¨t a Wie k¨nnen die Verbindungspartner eindeutig identifiziert werden? o • Genehmigungen Wie k¨nnen Zugriffsrechte einzelner Benutzer / Benutzergruppen beschr¨nkt werden? o a • Vertraulichkeit Wie kann gew¨hrleistet werden, dass Daten vertraulich behandelt werden und nur von a berechtigten Benutzern empfangen werden k¨nnen? o • Echtheit ¨ Wie kann sichergestellt bzw. nachgewiesen werden, dass die Daten w¨hrend der Uber- a tragung nicht ver¨ndert wurden? a Die erste Stuffe, die die Sicherheit des Systems gew¨hrleistet, ist ein Passwortschutz. Vor ader Benutzung muss sich der Anwender mit einem Login und dem dazugeh¨rigen Passwort oanmelden. Ein Zugriff auf die Applikation wird nur dann gew¨hrt, wenn der Benutzerna- ame g¨ltig ist und das Passwort korrekt eingegeben wurde. Unter der Annahme, dass das uPasswort geheim gehalten wird, ist gew¨hrleistet, dass ausschließlich authorisierte Benutzer aZugang zum System erhalten. Da das Passwort f¨r jeden Anwender unterschiedlich ist, ist es uweiterhin nicht m¨glich, sich f¨r jemand anderes auszugeben. Ein erfolgreicher Login ist des- o uhalb ein relativ sicheres Zeichen daf¨r, dass es sich bei dem Anwender um die Person mit der uangegebenen Benutzerkennung handelt. Die Authentizit¨t des Benutzers ist sichergestellt. aDiese Art der Benutzerverwaltung ist weiterhin hilfreich, um Genehmigungen zu definieren.Da der Benutzer eindeutig identifiziert wurde, k¨nnen ihm Zugriffsrechte gegeben bzw. die- ose eingeschr¨nkt werden. So ist es m¨glich, dass verschiedene Benutzer auf unterschiedliche a oProgrammteile zugreifen d¨rfen. Der VWE-Administrations-Modus bietet hier eine rollen- ubasierte Zugriffskontrolle. Zum einen werden Benutzer angelegt, indem ihnen eine Benutzer-kennung und ein Passwort zugewiesen werden. Zus¨tzlich k¨nnen pers¨nliche Angaben wie a o oName, Adresse, Funktion, Abteilung, Durchwahl etc. angegeben werden. Weiterhin kann einBenutzer als Administrator kenntlich gemacht werden. Er kann dann selbst auf den VWE-Administrations-Modus zugreifen. Ein Benutzer kann zus¨tzlich gesperrt werden (er ist dann anoch nicht gel¨scht, aber zwischenzeitlich aus dem System genommen) oder die G¨ltigkeit o udes Passworts kann festgelegt werden. So kann beispielsweise angegeben werden, dass dasPasswort alle 14 Tage ge¨ndert werden muss. a Ist ein solcher Benutzer angelegt, k¨nnen ihm Rechte zugewiesen werden. Dies geschieht ojedoch nicht unmittelbar, sondern uber sog. Rollen. Eine Rolle beschreibt die Funktion des ¨Benutzers und legt dar¨ber die Zugriffsrechte fest. Angenommen, es wurde ein Benutzer mit u 31
  • 37. 4.1 Sicherheit 32 Abbildung 19: Anlegen eines Benutzersder Kennung meier“ angelegt, der im Vrkauf f¨r die Kunden mit den Anfangsbuchstaben u ” A“ bis M“ zust¨ndig ist. Zuerst muss eine Rolle Verkauf“ definiert werden. Hierzu bietet a” ” ”der VWE-Adininistrations-Modus eine Rollen-Verwaltung. Hier k¨nnen Benutzerrollen oangelegt und verwaltet werden. Nach Erzeugung der Verkauf-Rolle k¨nnen ihr die n¨tigen o oRechte zugewiesen werden. VWE stellt hierzu eine detaillierte Liste mit Rechten, die in derApplikation vergeben werden k¨nnen, zur Verf¨gung. Der erzeugten Rolle wird beispielsweise o udas Recht Anlegen neuer Kunden“ zugeteilt. Einer Rolle k¨nnen beliebig viele Rechte o ”zugeteilt werden.Als n¨chsten Schritt wird dem Benutzer meier“ die Rolle Verkauf“ zugewiesen. Dies a ” ”geschieht immer in Verbindung mit einer oder mehreren Firmen. So kann der Benutzer beider Verwaltung mehrere Firmen beispielsweise nur die Mitarbeiter einer speziellen Firmabearbeiten. Nun kann Benutzer meier“ alle Kundendaten einsehen. Als letzter Schritt muss ”nun nur noch das Recht eingeschr¨nkt werden. In der Benutzerverwaltung kann dazu die aEinschr¨nkung code LIKE ’A%’ AND code LIKE ’M%’“ angegeben werden. Der Benutzer a ”hat somit nur Zugriff auf die von ihm ben¨tigten Daten. oIm Zusammenhang mit der Zugriffskontrolle ist das sog. AccessToken zu erw¨hnen. Dies aist ein Objekt, das Benutzer-Informationen nach einem erfolgreichen Login beinhaltet. DerBenutzer meldet sich beim Administration-Server, einem CORBA-Server, der Administrati-onsaufgaben ubernimmt, an und erh¨lt bei erfolgreicher Authorisierung ein entsprechendes ¨ a
  • 38. 4.1 Sicherheit 33AccessToken-Objekt zur¨ck. Dieses Token gilt im Folgenden als eine Art Schl¨ssel. Das Ac- u ucessToken wird jedem Funktionsaufruf des Servers mitgegeben, der anhand dieses Schl¨ssels upr¨ft, ob der Zugriff erlaubt ist. uDer Vorgang entspricht in etwa einem Hotelbesuch. Zu Begin meldet sich der Gast an derRezeption an und erh¨lt dort nach erfolgreicher Identifizierung einen Zimmerschl¨ssel. Mit a udiesem Schl¨ssel kann er sich nun im Hotel bewegen, hat aber nur Zutritt zu bestimmten uBereichen. Der Zugang zum Nachbarzimmer bleibt verwehrt.Die rollenbasierte Benutzerverwaltung stellt also bereits serverseitig die Genehmigung sicher,so dass ein neu entwickelter Web-Client keine weiteren Kontrollen durchf¨hren muss. Er umuss nur eine evtl. auftretende AccessDeniedException abfangen, die bei einem erfolglosenAnmeldungsversuch geworfen wird, und entsprechend darauf reagieren. Der Passwort-Schutz stellt jedoch nicht sicher, dass Daten nicht unerlaubt w¨hrend der a¨Ubertragung via HTTP abgeh¨rt oder sogar ver¨ndert werden k¨nnen. Weder Echtheit o a onoch Vertraulichkeit der Daten ist gew¨hrleistet. Außerdem wird lediglich ein Kommuni- akationspartner, n¨mlich der Benutzer, identifiziert. Die Frage, ob es sich auf der anderen aSeite wirklich um den richtigen Web-Server handelt, bleibt offen. Schließlich sollen ver-trauliche Daten nicht irgendwelchen unbekannten Stellen ubermittelt werden. Angreifer ¨k¨nnten DNS-Server (Domain Name Service) so manipulieren, dass Internet-Adressen auf oandere, d.h. verf¨lschte URLs geleitet w¨rden. Dem Anwender w¨rde eine vertrauliche a u uSeite somit nur vorget¨uscht. Wegen dieser als DNS-Spoofing bekannten Methode, muss af¨r eine sichere Web-Applikation folglich auch die Authentizit¨t des Servers sichergestellt sein. u a Eine L¨sung f¨r Authentizit¨t, Echtheit und Vertrautheit bieten Verschl¨sselungsverfah- o u a uren und sog. digitale Zertifikate. Sinn von Verschl¨sselung (Kryptographie) ist es, Daten vor uunberechtigtem Lesen zu sch¨tzen. Die Kryptographie besch¨ftigt sich deshalb mit der Ge- u aheimhaltung von gespeicherten und ubertragenen Daten. In der modernen Kryptographie ¨arbeiten alle Verfahren auf der Basis von Schl¨sseln. Hierbei unterscheidet man prinzipiell uzwei Arten von Algorithmen: • Symmetrische Algorithmen (secret-key) • Asymmetrische Algorithmen (public-key)Symmetrische Algorithmen basieren auf dem Prinzip, dass eine Nachricht mit ein und demselben Schl¨ssel ver- und entschl¨sselt werden kann (Abbildung 20). Das heißt, dass nur u uder Schl¨ssel, der zur Verschl¨sselung der Nachricht verwendet wurde, diese auch wieder u uentschl¨sseln kann. Dies hat zur Folge, dass sowohl der Sender als auch der Empf¨nger einer u aNachricht im Besitz dieses Schl¨ssels sein m¨ssen. Da die Nachricht nicht von Unbefugten u ugelesen werden darf, muss der Schl¨ssel selbstverst¨ndlich geheim gehalten werden. Es stellt u asich somit die Frage, wie Sender und Empf¨nger sich auf einen Schl¨ssel einigen oder, besser a ugesagt, wie sie diesen untereinander austauschen. Da der Schl¨ssel geheim gehalten werden u ¨muss, muss auch die Ubermittlung des Schl¨ssels auf einem sicheren Wege geschehen. uDer bekannteste symmetrische Algorithmus ist wohl DES (Data Encryption Standard).Diese Methode der symmetrischen Verschl¨sselung wurde 1977 vorgestellt und 1981 als uData Encryption Algorithm, ANSI-Standard X3.92-1981 ubernommen. DES verwendet eine ¨
  • 39. 4.1 Sicherheit 34 Abbildung 20: Prinzip der symmetrischen Verschl¨sselung uSchl¨ssell¨nge von 64 Bits (davon 56 signifikant) und galt lange Zeit als sicher. Im Fr¨hjahr u a u1999 gelang es jedoch einem Projekt namens Deep Crack“, einem speziellen Rechner, ”der von tausenden ubers Internet angeschlossenen Computern unterst¨tzt wurde, einen ¨ uDES-Schl¨ssel in weniger als 24 Stunden zu knacken. Seitdem gilt ein 64 Bit-Schl¨ssel nicht u umehr als sicher. Symmetrische Algorithmen sollten vielmehr eine Schl¨ssell¨nge von 128 Bits u averwenden. Dadurch ergibt sich eine Schl¨sselmenge von 2128 Schl¨sseln. Dies entspricht u uim Klartext 340.282.366.920.938.463.463.374.607.431.768.211.456 (≈ 3, 4 · 1038 ) m¨glichen oSchl¨ssel. Diese Schl¨ssell¨nge gilt nach heutigem Stand der Technik als nahezu sicher. u u aBedenkt man jedoch Moore’s Law“, das besagt, dass sich die maximale Rechenleistung eines ”Mikrochips zu einem festen Preis alle 18 Monate verdoppelt, ist es nur eine Frage der Zeit, bisauch diese Schl¨ssell¨nge geknackt werden wird. Was auf jeden Fall bleibt, ist die Notwendig- u akeit, den gemeinsamen Schl¨ssel zwichen den Kommunikationspartnern sicher auszutauschen. u Diese Problematik wird von asymmetrischen Algorithmen vermieden. Bei ihnen gibt eszwei Schl¨ssel: Einen geheimen privaten Schl¨ssel und einen offentlichen Schl¨ssel, der f¨r u u ¨ u ujedermann zug¨nglich ist. Das Prinzip von asymmetrischen Algorithmen besagt, dass eine aNachricht, die mit dem einen Schl¨ssel kodiert wurde, nur mit dem jeweils anderen dekodiert uwerden kann. Dies hat zur Folge, dass Kommunikationspartner keine geheimen Schl¨ssel aus- utauschen m¨ssen. Der Sender kodiert einfach die Nachricht mit dem ¨ffentlichen Schl¨ssel u o udes Empf¨ngers, dieser entschl¨sselt sie wieder mit seinem privaten Schl¨ssel. Abbildung 21 a u uzeigt das Prinzip der asymmetrischen Verschl¨sselung. Wird die Nachricht unterwegs abge- ufangen, kann sie nicht dekodiert werden, da hierzu der private und damit geheime Schl¨ssel unotwendig ist. Es ist also dem Besitzer des privaten Schl¨ssels vorbehalten, Nachrichten zu uentschl¨sseln. Ein Austausch von geheimen Schl¨sseln uber einen sicheren Kanal ist nicht u u ¨mehr notwendig.Das Konzept der Public-Key-Kryptographie wurde einerseits von Whitfield Diffie und Mar-tin Hellmann und andererseits davon unabh¨ngig gleichzeitig von Ralf Merkle erfunden. Alle a
  • 40. 4.1 Sicherheit 35 Abbildung 21: Prinzip der asymmetrischen Verschl¨sselung uasymmetrische Verschl¨sselungsverfahren basieren auf dem Prinzip, dass es mathematische uFunktionen gibt, deren Umkehrung nur mit einem erheblich h¨heren Aufwand m¨glich ist. o oPublic-Key-Kodierungen verwenden deshalb solche als Trapdoor-Einwegfunktion bezeichneteAlgorithmen. Solche Funktionen sind relativ leicht zu berechnen, eine Invertierung ist hinge-gen mit einem um ein Vielfaches gr¨ßeren Aufwand verbunden. Die Bezeichnung Trapdoor o(engl. Fallt¨r) deutet hingegen an, dass es eine Geheiminformation gibt, mit deren Hilfe sich udie Funktion schnell umkehren l¨ßt. F¨r einen Außenstehenden, d.h. unberechtigten Mitleser a uist es allerdings nicht m¨glich, die Nachricht in einer akzeptablen Zeitspanne zu entschl¨sseln. o uDer berechtigte Empf¨nger kann hingegen die Nachricht mit der nur ihm bekannten Gehei- aminformation schnell dekodieren.Der verbreitetste asymmetrische Algorithmus ist RSA, der nach seinen Erfindern Ron Rivest,Adi Shamir und Leonard Adleman benannt wurde. RSA wurde 1978 vorgestellt. Es ist bisheraber nicht m¨glich gewesen, die Sicherheit von RSA zu best¨tigen oder zu widerlegen. RSA o agilt deshalb bis heute als sicherer Verschl¨sselungsalgorithmus. uAls Trapdoor-Funktion verwendet RSA die Faktorisierung von Primzahlen. Diese Funktionberuht auf der Annahme, dass zwei große Primzahlen leicht miteinander multipliziert werdenk¨nnen, dass aber eine Invertierung, also die Faktorisierung eines Produktes zweier großer oPrimzahlen, ein wesentlich gr¨ßeres Problem darstellt. RSA stellt somit die Vertraulichkeit ound Echtheit der Daten¨bertragung sicher. uMit Einf¨hrung des Secure Socket Layer (SSL) hat die Verschl¨sselung Einzug ins Inter- u unet gehalten. Normale Internet-Kommunikation beruht auf dem TCP/IP-Protokol, das einevierschichtige Implementierung des OSI-Modells darstellt. Als TCP/IP vor ca. 30 Jahrenerfunden wurde, lag das Hauptaugenmerk darin, eine ausfallsichere und stabile Verbindungzwischen einer hohen Anzahl von Systemen zu schaffen. Die Authentizit¨t spielte zun¨chst a a
  • 41. 4.1 Sicherheit 36keine große Rolle, so dass Daten bei TCP/IP einfach im Klartext ubermittelt werden. Folg- ¨lich stellt eine TCP/IP-Verbindung alles andere als einen sicheren Kanal dar.Die Firma Netscape Communications war es, die 1994 das TCP/IP-Protokol um ei-ne Sicherheits-Schicht erweiterte. Genauer gesagt erg¨nzte ihr SSL-Modell das klassische aTCP/IP um gleich zwei Schichten: Das SSL Handshake Protocol“ und das dar¨ber lie- u ”gende SSL Record Protocol“. Diese beiden Protokolle werden in TCP/IP integriert und ”erweitern das Schichtenmodell um die Sicherheitsbetrachtung (Abbildung 22). Der Secure Abbildung 22: Integration von SSL in TCP/IPSocket Layer liegt zwischen Transportschicht und Verarbeitungsschicht und verh¨lt sich hier- abei v¨llig transparent, so dass weder Anwender noch die anderen Schichten im Modell von oSSL und deren Aktivit¨ten etwas mitbekommen. aSSL verwendet sog. digitale Zertifikate. Ein Zertifikat besteht aus Angaben uber die Identit¨t ¨ ades Besitzers und beinhaltet außerdem den ¨ffentlichen Schl¨ssel des Inhabers. Es garantiert o ufolglich, dass der ¨ffentliche Schl¨ssel auch tats¨chlich zu der angegebenen Person geh¨rt. o u a oDamit sichergestellt ist, dass die Angaben zur Identit¨t korrekt sind und dass sich niemand af¨r jemand anders ausgeben kann, muss ein Zertifikat zuvor zertifiziert werden. Dies geschieht uvon einem Dritten, der das Vertrauen des Empf¨ngers genießt. Dies entspricht in etwa der aSituation, dass A nicht B kennt, B aber C bekannt ist. Da A nun C vertraut, best¨tigt C adie Identit¨t von B. So entsteht ein als web of trust“ bezeichnetes Gefl¨cht. Eine Reihe von a a ”Firmen haben sich auf Zertifizierung spezialisiert. Zu nennen sind VeriSign, Thawte, beTRU-STed oder auch die Deutsche Telekom. Diese als CA (Certification Authority) bezeichnetenStellen pr¨fen auf Antrag die Identit¨t des Zertifikat-Inhabers und best¨tigen diese. Dazu be- u a asitzen solche kommerziellen Anbieter sog. Root-Zertifikate, die auch allen g¨ngigen Browsern abekannt sind. Von diesen Stellen zertifizierte Zertifikate gelten dementsprechend als sicher.Wird hingegen das Zertifikat von einer anderen, dem Browser unbekannten Stelle zertifiziert,wird ein Warnhinweis ausgegeben. Der Anwender muss diesem Zertifikat dann ausdr¨cklich uzustimmen und so das Vertrauen herstellen. Die Indentit¨tsangaben von Zertifikaten stellen aalso eine sichere Authentifizierung des Besitzers dar. ¨Der Verbindungs- und Ubertragungsvorgang im Einzelnen:
  • 42. 4.2 Internationalisierung 37 1. Bei SSL wird wird zun¨chst vom Client, also dem Browser, die Verwendung einer siche- a ren Verbindung angezeigt, indem der Seiten-Adresse ein https anstelle des gewohnten http als Protokoll vorangestellt wird. Der Client sendet daraufhin die von ihm verwen- dete SSL-Version und eine Liste von unterst¨tzten Kodierverfahren an den Web-Server. u 2. Der Server legt auf Grund der angebotenen Verschl¨sselungsroutinen den verwendeten u Algorithmus fest und informiert den Client dar¨ber. Außerdem sendet er sein digitales u Zertifikat. ¨ u ¨ 3. Nun uberpr¨ft der Client das Zertifikat des Servers. War die Uberpr¨fung nicht erfolg- u reich, wird die Verbindung abgebrochen. 4. Der Client erzeugt ein sog. premaster secret“. Dies sind zuf¨llig generierte Daten, die a ” mit dem ¨ffentlichen Schl¨ssel aus dem Zertifikat des Servers kodiert werden. Diese o u verschl¨sselten Daten werden wieder an den Server gesendet. u 5. Der Server empf¨ngt das premaster secret“ und entschl¨sselt es mit seinem privaten a u ” Schl¨ssel. Aus diesen Daten werden nun von Client und Server vier weitere Schl¨ssel ge- u u neriert. Diese Schl¨ssel heißen Client-write-key“, Client-write-MAC-secret“, Server- u ” ” ” write-key“ und Server-write-MAC-secret“. Die write-key-Schl¨ssel werden jeweils zum u ” Verschl¨sseln von Nachrichten verwendet, mit den write-MAC-secret-Schl¨sseln wer- u u den Nachrichten signiert, damit die Echtheit uberpr¨ft werden kann. Mit Hilfe dieser ¨ u u ¨ Schl¨ssel kann die weitere Ubertragung mit symmetrischen Algorithmen verschl¨sselt u werden, die um ein Vielfaches schneller laufen als asymmetrische Verfahren. 6. Client und Server senden zwei Nachrichten an das jeweilige Gegen¨ber, die anzeigen, u dass der jeweilige Teil des Handshake-Protokolls abgearbeitet wurde. 7. Mit dem Record-Protokoll und den vier erzeugten Schl¨sseln wird die weitere Verbin- u dung symmetrisch verschl¨sselt. uMan sieht, dass SSL einerseits eine verschl¨sselte Verbindung garantiert, anderseits aber auch udie Authentizit¨t des Servers gew¨hrleistet. Seit SSL 3.0 k¨nnen Zertifikate auch auf dem a a oClient-Rechner installiert werden. Diese Methode ist zwar sicherer als ein reiner Passwort-Schutz, die Flexibilit¨t der Anwendung leidet aber, da die Applikation nicht auf Anhieb avon jedem beliebigen Arbeitsplatz aus durchgef¨hrt werden kann. Außerdem k¨nnte es zu u oProblemen kommen, wenn sich mehrere Nutzer einen PC teilen.Jedenfalls ist es dank SSL m¨glich, sensible Daten auf sicherem Wege durch das Internet zu otransportieren. Die Verschl¨sselung macht das Abh¨ren und Ver¨ndern der Daten unm¨glich; u o a oEchtheit und Vertraulichkeit ist garantiert. Die Zertifizierung gew¨hrleistet dar¨ber hinaus, a udass Kommunikationspartner eindeutig identifiziert werden k¨nnen. o4.2 Internationalisierung Andere L¨nder, andere Sitten“ heißt es im Volksmund. Leider ist es im Hinblick auf die a”Entwicklung von Software oder, konkreter gesagt, von Benutzerschnittstellen damit nicht ge-tan. Internationalisierung wird zum Zauberwort auf dem Weg zu einem Einsatz uber alle ¨Landesgrenzen hinaus. Die Varial World Edition wurde, wie der Name bereits erahnen l¨ßt, a
  • 43. 4.2 Internationalisierung 38 Abbildung 23: Daten¨bertragung mit SSL uf¨r den internationalen Einsatz entwickelt. Eine durchdachte Gesch¨ftslogik erm¨glicht die u a oAnpassung an national unterschiedliche Bed¨rfnisse und Richtlinien. Gerade eine Oberl¨che u af¨rs World Wide Web muss diesen Anforderungen gerecht werden. uInternationalisierung, oft auch nur kurz als i18n3 bezeichnet, wird zu einem wichtigen Kri-terium der Anwendung. Unter i18n versteht man die Bem¨hung, ein Programm flexibel f¨r u udie Anpassung auf l¨nderspezifische Eigenheiten zu gestalten. Eine Lokalisierung (l10n), al- aso die Anpassung eines Programms an l¨nderspezifische Eigenheiten, ist notwendig, da sich adie L¨nder dieser Erde nicht nur durch ihre Sprache und die zugrunde liegenden Schrift- aund Zahlzeichen, sondern auch durch abweichende Zahlen-, Zeit- und Datumsformatierun-gen, eigene W¨hrungen, unterschiedliche Telefonnummern- und Anschriftenkonventionen und aso weiter unterscheiden. ¨4.2.1 Ubersetzung der sprachlichen InhalteDas Augenscheinlichste, das bei einem internationalen Software-Einsatz notwendig ist, ist die¨ ¨Ubersetzung von Bildschirmausgaben in die jeweilige Sprache. Uberschriften, Feldbezeich-nungen, Hilfetexte und Warnhinweise m¨ssen leicht in andere Sprachen ubersetzt werden u ¨k¨nnen. Eine Anpassung des Quellcodes sollte hierbei nicht vorgenommen werden m¨ssen. o uDie Abbildungen 24 und 25 zeigen zwei Screenshots der Web-Oberfl¨che mit jeweils englischer aund deutscher Sprache. Die Web-Oberfl¨che ubernimmt hier das Modell, das auch in der a ¨C++-Oberfl¨che von VWE Verwendung findet. Sprachbezeichnungen sind hier serverseitig ain der Datenbank gespeichert und werden von dieser entsprechend der eingestellten Spracheabgefragt. So werden Bildschirmtexte nicht hartverdrahtet“, sondern dynamisch den aktu- ”ellen Einstellung angepasst. 3 engl: internationalization; i gefolgt von 18 Buchstaben und einem n
  • 44. 4.2 Internationalisierung 39 Abbildung 24: Die Web-Oberfl¨che in Englisch a Abbildung 25: Die Web-Oberfl¨che in Deutsch aDie Umstellung bzw. Erweiterung des Web-Interfaces auf andere Sprachen kann sp¨ter pro- a ¨blemlos vorgenommen werden. Hierzu kann der Ubersetzer alle Sprachbezeichnungen miteinem von Varial speziell hierf¨r entwickelten Programm namens Sophia bearbeiten und er- uweitern.
  • 45. 4.2 Internationalisierung 404.2.2 Zeichens¨tze aGenau wie es auf der Erde eine Vielzahl von unterschiedlichen Sprachen gibt, existieren auchverschiedene Schriftzeichen. Chinesische oder kyrillische Schriftzeichen oder auch die in un-seren Breiten verwendeten lateinischen Zeichen sind nur einige wenige Beispiele. Selbst inEuropa verwenden einige Sprachen Sonderzeichen, sog. diakritische Zeichen. Beispiele sinddas d¨nische ø, das deutsche ¨ oder das im Spanischen gebr¨uchliche n. a o a ˜Zeichens¨tze sind eine Gruppe von Zeichen, die der Computer darstellen kann. In den An- afangstagen der Zeichens¨tze war Speicher ¨ußerst kostbar. Dementsprechend wurde jedes nur a am¨gliche Bit gespart, um nicht unn¨tig Platten- oder Arbeitsspeicher zu belegen und um o onicht unn¨tig viele Daten in Netzwerken zu versenden. Da die Hardware sehr teuer war, wa- oren zus¨tzliche Bits eine kostspielige Angelegenheit. Auch bei Zeichens¨tzen wurde gespart, a aso dass Schriftzeichen urspr¨nglich nur mit sieben Bits repr¨sentiert wurden. Diese Darstel- u alung gen¨gte f¨r alle Buchstaben des englischen Alphabets, den Ziffern 0 bis 9, Zeichen der u uInterpunktion sowie einigen Steuerzeichen. Da die urspr¨ngliche Aufgabe von Computern udarin bestand, mit Zahlen umzugehen, waren diese Zeichen auch durchaus ausreichend.Mit der Zeit wurden aber auch immer mehr f¨r den Menschen lesbare Texte erstellt und schon ubald zeigte sich, dass sieben Bits nicht ausreichen. Durch die Hinzunahmen eines achten Bitswurde sp¨ter auch die Darstellung aller westeurop¨ischen Sprachen m¨glich. a a oEs dauerte nicht lange, da zeigte sich, dass die 256 zur Verf¨gung stehenden Zeichen f¨r die u uinternationale Verwendung zu wenig waren. Man l¨ste das Problem damit, dass man eine oReihe von Untermengen, jeweils bestehend aus acht Bits, einf¨hrte. So wurden zehn ISO- u8859-Standards verabschiedet, die jeweils einen Zeichensatz, also die Zuordnung von achtBits zu einem Zeichen definieren.ISO-8859-1, ein Standard, der auch als Latin-1 bezeichnet wird, ist beispielsweise f¨r west- ueurop¨ische Sprachen (Englisch, Deutsch, Franz¨sisch, Schwedisch, etc) zust¨ndig. Dieses a o a ¨ist im Ubrigen der Standardzeichensatz f¨r HTTP. ISO-8859-2 deckt die zentral- und ost- ueurop¨ischen L¨nder wie Ungarn oder Polen ab, ISO-8859-5 stellt kyrillische Zeichen f¨r a a uRussisch, Bulgarisch oder Mazedonisch bereit.Mit ISO-8859 war es somit m¨glich, einen Großteil der europ¨ischen Sprachen abzudecken. o aEin Problem bestand aber nach wie vor beim japanischen oder chinesischen Alphabet, dieaus Tausenden von Zeichen bestehen, die sich jedoch nicht mit nur acht Bits darstellen lassen.Um auch diesen Alphabeten gerecht zu werden, wurden Zeichens¨tze wie Big5 f¨r Chinesch, a uEUC-KR f¨r Koreanisch oder auch Shift JIS f¨r Japanisch entwickelt, die aus mehr als acht u uBits bestanden.Auf diese Weise waren erst einmal alle Sprachen auf ihre Weise zufrieden gestellt. Ein Aus-tausch von Informationen zwischen zwei Zeichens¨tzen gestaltete sich jedoch sehr schwer, da aZeichen unterschiedlich kodiert wurden. Im Jahre 1991 gr¨ndete sich das Unicode-Konsortium uaus Firmen wie Apple, IBM, Microsoft, Novell, Sun und Xerox, um einen eindeutigen Stan- ¨dard zu definieren, der allen Sprachen gerecht werden sollte. Ergebnis der Uberlegungen warder Unicode-Standard, ein Zeichensatz aus 16 Bits. So lassen sich bis zu 65.536 verschiedeneZeichen in dem System unterbringen. Nach und nach wurden immer mehr Zeichen in Unicodeubernommen. In Version 3.0 vom September 1999 wurden bereits 49.194 Zeichen aus aller¨Welt aufgelistet. In der Version 3.1 vom M¨rz 2001 wurden dann nochmals 44.946 Zeichen aneu aufgenommen, z.B. Zeichen aus historischen Schriften. Version 3.1 beinhaltet also bereits
  • 46. 4.2 Internationalisierung 4194.140 Zeichen. Die Kapazit¨t des urspr¨nglichen Unicodes wurde somit schon uberschritten. a u ¨Das Zwei-Byte-Schema, im Unicode-System als Basic Multilingual Plane (BMP) bezeichnet,wurde deshalb von einem Vier-Byte-Schema abgel¨st. Unicode besteht seither aus nunmehr o32 Bits, wodurch sich 2 32 = 4.294.967.296 Zeichen adressieren lassen.Unicode stellt damit einen Standard dar, mit dem sich nicht nur alle erdenklichen Zeicheneinheitlich darstellen lassen, sondern der auch einen Austausch von Informationen normiert.4.2.3 L¨nderspezifische Formate aFast jedes Land hat seine eigenen Formate, beispielsweise f¨r Zahlen- oder Zeit-Angaben. Ge- urade die Darstellung von Datumsangaben k¨nnte in den einzelnen L¨ndern unterschiedlicher o anicht sein. So wird der 11. April des Jahres 1980 mal als 11.04.1980“ oder 11. Apr. 1980“, ” ”mal als 1980-11-04“ oder auch als 11/04/1980“ angegeben. Es scheint gerade so, als ob jede ” ”denkbare Formatierung in irgendeiner Region der Erde auch Verwendung finden w¨rde. uWeitere Eigenheiten findet man in der Darstellung von Uhrzeiten. In manchen Regionen isteine 24-Std-Angabe (23:12 Uhr) gebr¨uchlich, f¨r den anderen Teil der Weltbev¨lkerung ist a u odie Angabe mit einem Zusatz wie am“/ pm“ gang und g¨be (11:12 pm). Dar¨ber hinaus a u ” ”sind nat¨rlich auch weitere Darstellungsformen denkbar. uSelbst etwas so scheinbar simples wie die Darstellung von Zahlen, erweist sich doch als Stol-perstein auf dem Weg zu einem internationalen Software-Einsatz. W¨hrend man im deutsch- asprachigen Raum bei großen Zahlen Tausenderstellen durch einen Punkt trennt, verwendetder angels¨chsische Raum hier ein Komma. Bei Nachkommastellen, die, wie es das Wort be- areits zum Ausdruck bringt, im Deutschen durch ein Komma getrennt werden, verwendet manin englischensprachigen Gebieten den Punkt.Eine Anwendung, die nicht f¨r eine Region zugeschnitten sein soll, sondern in vielen (theore- utisch allen) L¨ndern zum Einsatz kommen kann, muss auf diese Besonderheiten achten. Was aeinem Schweizer als Rechnung vom 22.05.2002“ uber 12.345,67 £“ pr¨sentiert wird, muss ¨ a ” ”einem englischen Buchhalter automatisch als Rechnung vom 22/05/2002“ uber 12,345.67 ¨ ” ”£“ angezeigt werden.Bei der Entwicklung der Web-Oberfl¨che ist also sicherzustellen, dass l¨nderspezifische For- a amate ber¨cksichtigt und korrekt dargestellt werden. u4.2.4 Lokalisierung der fachlichen InhalteDie Software muss landesspezifischen Funktionalit¨ten gerecht werden. So m¨ssen unter- a uschiedliche gesetzliche und tarifliche Bestimmungen beachtet werden, so dass bereits im Vor-feld der Erstellung des Web-Interfaces darauf zu achten ist, dass fachliche Inhalte ohne großenAufwand an landes- oder unternehmenseigene Bestimmungen anpassbar sind.Gl¨cklicherweise b¨ndelt VWE die Business-Logik im Application-Layer, also im CORBA- u uServer. Folglich ist die Anpassung des Clients verh¨ltnism¨ßig einfach. Die ordnungsgem¨ße a a aBuchf¨hrung unter Ber¨cksichtigung landeseigener Bestimmungen wird bereits beim Server u udurchgef¨hrt. Der Client muss lediglich einige wenige Kleinigkeiten bei der Oberfl¨chenge- u astaltung ¨ndern. a
  • 47. 4.3 Performance 424.3 PerformanceAuch bei der Entwicklung einer Web-Applikation bestehen Anforderungen im Bereich Per-formance. Der Begriff Performance beschreibt hierbei im besonderen die Anforderung, dassdie Verarbeitung der Daten schnell erfolgt bzw. dass die Applikation im ganzen eine hoheVerarbeitungsgeschwindigkeit vorweist.4.3.1 Verteiltes RechnenCORBA unterst¨tzt die Entwicklung von Middleware. Dabei unterteilt sich die Anwendung uin drei Schichten. Auf der einen Seite befindet sich die Darstellung der Daten (Client), auf deranderen Seite die Datenhaltung. Die Middleware stellt als Server die Verbindung zwischenden beiden Enden dar. Die Performance der Anwendung l¨ßt sich u.a. dadurch steigern, adass die Verarbeitung auf verschiedene Rechner aufgeteilt wird. So ubernehmen sowohl der ¨Client als auch der Server verschiedene Programmaufgaben. Die Verarbeitung verteilt sichsomit auf mehrere Rechner, was eine h¨here Gesamtleistung zur Folge hat. Weiterhin k¨nnen o oAnfragen des Clients an mehrere Server verteilt werden. Bei VWE laufen serverseitig drei An-wendungen. Dies sind zum einen der Administration-Server und der Application-Server. DerAdministration-Server ubernimmt alle Aufgaben, die die System-Administration betreffen. So ¨werden von ihm u.a. die Verwaltung der Zugriffsrechte geregelt. Der Application-Server verar-beitet hingegen alle Anfragen, die die eigentliche Gesch¨ftslogik betreffen. Beide Server teilen asich somit die Aufgaben. Die dritte serverseitige Applikation stellt der Dispatcher dar. SeineAufgabe ist es, Client-Anfragen auf mehrere Server-Instanzen zu verteilen. VWE erm¨glicht oes n¨mlich, gleich mehrere Application-Server parallel laufen zu lassen. Der Dispatcher sorgt adann daf¨r, dass Anfragen nach einer fairen Zuteilungsstrategie auf die einzelnen Instan- uzen verteilt werden. Auf diese Weise ist es m¨glich, auch bei hohen Anfrage-Aufkommen die oServer-Last auf mehrere Server zu verteilen. Da diese Lastverteilung auf der Server-Seite gere-gelt wird, kann das Web-Interface davon profitieren, ohne selbst irgendwelche Vorkehrungenzu treffen.4.3.2 Verteilung von Server-LastNicht nur die CORBA-Anfragen k¨nnen auf mehrere Server verteilt werden. Auch die oHTTP-Anfragen k¨nnen auf mehrere Web-Server-Instanzen aufgeteilt werden. Ein sog. Load- oBalancer sorgt daf¨r, dass Anfragen des Browser auf verschiedene Web-Server gelenkt wer- uden. Abbildung 26 zeigt die Aufteilung der Anfragen. Ziel dieser Verteilung ist, dass eineReihe von gleichzeitigen Anfragen so auf die Server verteilt werden, dass die Anzahl gleich-zeitig laufender Servlet-Threads in einem Server reduziert wird. Durch diese Verringerungder Thread-Anzahl k¨nnen Servlet-Klassen u.U. sogar exklusiv und damit um ein Vielfaches oschneller laufen.Die Schwierigkeit bei der Verteilung der Server-Last besteht in der Behandlung von Sitzungs-daten. Bei statischen Web-Seiten spielt es keine Rolle, welcher Server die Seite zur Verf¨gung ustellt. Bei Erzeugung dynamischer Seiten werden jedoch sog. Sessions verwendet (auf dieNotwendigkeit von Sessions wird in Abschnitt 5.3 n¨her eingegangen werden). Da Sitzungs- adaten im Speicher des Server-Rechners verwaltet werden, muss entweder der Load-Balanceralle Anfragen einer Session immer an den selben Server leiten oder die Sitzungsdaten m¨ssen u
  • 48. 4.3 Performance 43 Abbildung 26: Verteilung der HTTP-Anfragen mit Hilfe eines Load-Balancersin einer zentralen, f¨r alle Server zugreifbaren Resource gespeichert werden. Im letzen Fall umuss bereits bei der Programmierung der Servlet-Klassen auf diese Sonderheit geachtet wer-den. Außerdem m¨ssen besondere Feinheiten im Bezug auf Synchronisation beachtet werden. uVWE-Web verzichtet deshalb auf die Anwendung der zweiten Verteilungsm¨glichkeit. Der oAufwand, den eine Verteilung der Anfragen und der Sitzungsdaten zur Folge h¨tte, steht ain keinem Verh¨ltnis zu dem daraus resultierenden Nutzen. Sehr wahrscheinlich wird die akritische Masse an Anfragen von der Applikation bei weitem nicht erreicht, so dass eine Last-verteilung hier nicht n¨tig erscheint. oSollte es hingegen denoch zu der Notwendigkeit kommen, Serverlast zu verteilen, kann immernoch ein Load-Balancer eingesetzt werden, der darauf achtet, dass Sitzungsanfragen immervom selben Server behandelt werden. Dadurch ist die Last zwar nicht unbedingt ausgewogen ¨verteilt, daf¨r bedarf es aber auch keiner Anderungen am Programmcode. In Anbetracht des uAnwendungsgebietes erscheint dieses Vorgehen als der geeignete Kompromiss.4.3.3 Komprimierte Inhalte ¨Die Ubertragung der Daten vom Web-Server zum Browser nimmt einen Großteil der Verar-beitungszeit in Anspruch. Zwar werden im Zeitalter von DSL die Internet-Verbindungen ¨schneller, aber noch immer stellt die Ubertragungszeit eine Schwachstelle von Internet-Applikationen dar. Moderne Browser bieten allerdings die M¨glichkeit, Daten komprimiert ozu versenden. Anwendung finden hierbei vor allem die Formate zip bzw. gzip. Ein Servletkann von dieser M¨glichkeit Gebrauch machen, und die erzeugten Inhalte in komprimierter oForm ubertragen. ¨Der Browser sendet bei jeder Anfrage eine Reihe von zus¨tzlichen Daten im HTTP-Header. aEin solche Header-Angabe ist beispielsweise die Information Accept-Encoding, die angibt,ob der Browser den Empfang komprimierter Daten unterst¨tzt. Das Servlet kann die Header- uAngabe auslesen und uberpr¨fen, ob und welches Komprimierungsverfahren unterst¨tzt wird. ¨ u uMit dem Packet java.util.zip des JDKs besitzt Java bereits die passende Funktionalit¨t, a
  • 49. 4.4 Anpassbarkeit 44um Daten zu komprimieren. Das Servlet muss nun einfach den OutputStream ggf. komprimie-ren und dem Browser mit Angabe des Headers Content-Encoding in der Antwort anzeigen,welches Komprimierungsverfahren verwendet wurde. Gerade bei großen Seiten ist die Zeitf¨r das Ver- und Entpacken der Nachricht geringer als die Zeit, die dadurch eingespart wird. u ¨Folglich erm¨glicht die Komprimierung, die Ubertragungsgeschwindigkeit und damit die Ge- osamtperformance zu verbessern.4.3.4 ZwischenspeicherungViele Daten der Anwendung werden oft w¨hrend der Verarbeitung abgefragt, ¨ndern sich a a ¨aber sehr selten oder gar nie. Typische Beispiele f¨r solche Daten sind die Ubersetzungstexte uoder die Men¨struktur. Beides l¨ßt sich zwar theoretisch ab¨ndern, in der Praxis sind sol- u a a ¨che Anderungen hingegen recht ungew¨hnlich. Wie bereits erw¨hnt, werden diese Daten sehr o ah¨ufig verwendet. Die Folge sind eine Reihe von Aufrufen, die den CORBA-Server betreffen. aDa diese Aufrufe nach Annahme aber sowieso immer das selbe Ergebnis liefern, k¨nnen die oErgebnisdaten auch nach dem ersten Aufruf clientseitig gespeichert werden. Sp¨ter ist es dann anicht mehr n¨tig, eine Server-Methode aufzurufen, die verh¨ltnism¨ssig lange Zeit ben¨tigt, o a a osondern es kann auf den bereits vorhandenen Datenbestand zur¨ckgegriffen werden. uBei der Zwichenspeicherung sind zwei Arten von gecachten Daten zu unterscheiden. Die erste u a ¨Art von Daten betreffen alle Benutzer. Ein Beispiel hierf¨r w¨re die Ubersetzung. Sie ist f¨r ualle Benutzer der Anwendung identisch und kann somit im application-Objekt zwischen-gepeichert werden. Die andere Art von Daten sind spezifisch f¨r einzelne Nutzer. Hierf¨r w¨re u u ader Men¨baum mi den jeweiligen Favoriten. Da sich jeder Anwender eine pers¨nliche Ansicht u oseiner h¨ufig benutzen Men¨-Punkte zusammenstellen kann, m¨ssen diese Daten auch f¨r a u u ujeden User einzelnd gespeichert werden. Sinnvoll erscheint hier die Speicherung im session-Objekt. ¨Bei der Zwichenspeicherung ist darauf zu achten, dass Anderungen der Daten nicht erkannt u ¨werden. Sollte sich also die Men¨struktur oder die Ubersetzungtexte einmal ¨ndern, muss a ¨der Web-Server neu gestartet werden, damit die Anderungen ubernommen werden. ¨4.4 AnpassbarkeitDas Web-Interface muss sich – gerade im auf Hinblick auf das Varial Vertriebsmodell mitOEM-Partnern und den Best-of-breed“-Gedanken – leicht an individuelle Bed¨rfnisse an- u ”passen lassen.4.4.1 KonfigurationDie komplette Web-Applikation kann komprimiert in Form eines Web-Archivs geliefert wer-den. Hierbei handelt es sich um eine Datei mit der Endung .war, die alle ben¨tigten Dateien obeinhaltet. Eine solche war-Datei entspricht einer jar-Datei, besitzt aber zur Unterscheidungeine unterschiedliche Endung. Tomcat und eine Reihe weiterer Web-Server unterst¨tzen mitt- ulerweile diese Technik, so dass die Applikation ohne großen Aufwand auf andere Systemeubertragbar ist.¨Die Datei varial.war muss lediglich in das Verzeichnis webapp beim Tomcat-Server oder einvergleichbares Verzeichnis eines anderen Servers kopiert werden. Klassenpfade m¨ssen nicht u
  • 50. 4.4 Anpassbarkeit 45mehr angepasst werden. So ist VWE-Web schnell nahezu uberall einsetzbar. ¨Weitere Konfigurationen und individuelle Anpassungen k¨nnen in der Datei web.xml, dem osog. Deployment-Descriptor vorgenommen werden. Wie der Name bereits verr¨t, handelt es asich um eine XML-Datei, die einem einheitlichen, von der Firma Sun festgelegten, DTD folgt.Die wichtigsten Parameter, die bei der Anpassung von VWE-Web zu beachten sind, sind imFolgenden aufgef¨hrt. u<context-param> <param-name>AdminPort</param-name> <param-value>6666</param-value></context-param><context-param> <param-name>AdminClientAuthPort</param-name> <param-value>6667</param-value></context-param><context-param> <param-name>ClientAuthPort</param-name> <param-value>6668</param-value></context-param><context-param> <param-name>AdminHost</param-name> <param-value>terra.spice.varial.de</param-value></context-param><!-- Theme --><context-param> <param-name>Theme</param-name> <param-value>varial</param-value></context-param>Man erkennt den Aufbau der Schl¨ssel-Wert-Paare, die jeweils in einem context-param- uTag gekapselt sind. Die ersten drei Angaben AdminPort, AdminClientAuthPort undClientAuthPort geben die Port-Adressen an, unter der die verschiedenen CORBA-Serveransprechbar sind. Diese Angaben finden sich außerdem in der Server-Konfiguration, in denDateien server.cfg und admin.cfg und m¨ssen mit diesen ubereinstimmen. u ¨Der vierte und letzte CORBA-Parameter AdminHost gibt den Host-Namen des CORBA-Servers an. In diesem Beispiel ist es der Rechner Terra, der bei Varial intern zum Ein-satz kommt. Laufen CORBA-Server und Servlets auf dem selben Rechner, ist die Angabelocalhost hier ausreichend.Abschließend kann mit der Angabe Theme die Oberfl¨chengestaltung des Web-Clients be- a ¨stimmt werden. Die GUI kann durch das Andern dieser Angabe an individuelle Design-Vorstellungen angepasst werden. Im folgenden Abschnitt wird diese Funktionalit¨t n¨her a a
  • 51. 4.4 Anpassbarkeit 46beschrieben.4.4.2 Corporate DesignCorporate Design bedeutet, dass zusammenh¨ngende Inhalte einer einheitlichen Darstellung afolgen. Im unternehmerischen Umfeld heißt dies im Einzelnen, dass alle mit dem Unterneh-men verbundenen Publikationen ein optisch einheitliches Bild bieten. So verbindet man z.B.mit der Deutschen Post AG intuitiv die Farbe Gelb und das Posthorn, das margentafarbeneT assoziiert man mit der Deutschen Telekom und UPS pr¨sentiert sich im einheitlichen aBraunton. Das Design ist Teil der Unternehmenskultur und so ist es selbstverst¨ndlich, dass aauch die Internetauftritte diesem optischen Leitfaden folgen.Das Varial Vertriebsmodell und die Anforderung an VWE, sich in die Software der OEM-Partner integrieren zu lassen ( Best-of-breed“), f¨hren auch bei dem Web-Interface zu der u ”Anforderung, dass das Layout an ein individuelles Corporate Design angepasst werdenkann. Das Aussehen des Web-Interfaces muss sich also komplett an unternehmensspezifischeLayout-Richtlinien anpassen lassen. Um dieser Anforderung gerecht zu werden, verwendet VWE-Web sog. Themes. EinTheme ist eine Sammlung von Darstellungsbesonderheiten und beschreibt das Aussehender grafischen Benutzeroberfl¨che. So l¨ßt sich f¨r jede Darstellung ein Theme entwerfen, a a udass detailliert Farben, Schriftarten und -gr¨ße, Grafiken, Umrandungen und vieles mehr odefiniert. Hierzu muss lediglich ein Unterverzeichnis im Ordner THEMES angelegt werden,der die n¨tigen Dateien enth¨lt. In diesen Ordner k¨nnen nun individuelle Icons abgelegt o a owerden. Weitere Einstellungen k¨nnen in der Datei styles.css vorgenommen werden. oHierbei handelt es sich um eine Datei, die sog. Cascading Stylesheets (CSS) beschreibt. Bei CSS handelt es sich um eine Formatierungssprache, die haupts¨chlich zur Erg¨nzung a avon HTML entworfen wurde. CSS wurde im Jahr 1996 vom W3C-Konsortium spezifiziertund liegt mittlerweile in Version 2.0 vor, wobei selbst Browser der neusten Generation diesenStandard noch nicht vollkommen unterst¨tzen. uSinn von CSS ist es, HTML-Elemente beliebig zu formatieren. So kann beispielsweise ¨definiert werden, das Uberschriften dritter Ordnung immer in rot und unterstrichen erschei-nen sollen. Auf diese Weise wird eine einheitliche Darstellung erm¨glicht, da nicht jedes oHTML-Tag expliziete Formatierungsangaben enthalten muss. Vielmehr ist es ausreichend,diese Information einmalig in Form von CSS zu hinterlegen.Solche zentralen Formate k¨nnen auch in externe Dateien ausgelagert werden. Nun k¨nnen o oalle Seiten eines Projekts auf diese CSS-Datei zugreifen. Folge ist, dass alle Seiten einem ¨einheitlichem Format folgen und dass Anderungen an diesem Format nur an einer Stelle ¨vorgenommen werden m¨ssen. Entschließt man sich z.B. Uberschriften nun nicht mehr in urot, sondern in gr¨n anzeigen zu lassen, muss diese Angabe lediglich einmal, n¨mlich in der u a a a ¨CSS-Datei, ge¨ndert werden. S¨mtliche Projektseiten folgen automatisch dieser Anderung. VWE-Web setzt eine solche externe CSS-Datei ein. Dazu verwendet jede Komponente, dieauf der Oberfl¨che angezeigt wird, eine Formatklasse. Die Eigenschaften dieser Formatklassen ak¨nnen beliebig an die jeweiligen Gestaltungsw¨nsche, an das Corporate Design, angepasst o u
  • 52. 4.5 Analogie zu bestehender VWE-Oberfl¨che a 47werden. ¨Das folgende Beispiel zeigt, wie die Darstellung einer Uberschrift festgelegt wird..headline { FONT-WEIGHT: bold; FONT-SIZE: 40px; COLOR: #2D4B9B; FONT-FAMILY: Arial, Tahoma, Verdana, sans-serif;} ¨Alle Uberschriften erscheinen nun in diesem Theme fett gedruckt, 40 Pixel hoch in einemBlauton. Als Schriftart wird Arial verwendet. Sollte diese Schriftart nicht verf¨gbar sein, uwird nach den Schriftarten Tahoma, Verdana und sans-serif gesucht und die erste Schriftart,die gefunden wird, wird verwendet.Diese Angaben k¨nnen von einem Web-Designer individuell angepasst und sogar erg¨nzt wer- o a o a ¨den. Beispielsweise k¨nnte zus¨tzlich definiert werden, dass Uberschriften kursiv erscheinensollen. Dies alles geschieht in einer standardisierten Sprache und ist v¨llig unabh¨ngig von o ader Implementierung. Die Abbildungen 27, 28 und 29 zeigen einige Beispiele f¨r die unter- uschiedliche Oberfl¨chengestaltung durch Themes. Ist erst einmal ein Theme-Unterverzeichnis a Abbildung 27: VWE-Web-Oberfl¨che mit dem Theme varial“ a ”entworfen, kann es in der Konfigurationsdatei web.xml als Standard-Theme angegeben wer-den. Ferner l¨ßt sich ein Theme auch uber den Query-String-Parameter theme ansteuern. a ¨4.5 Analogie zu bestehender VWE-Oberfl¨che aDas Web-Interface sollte im Aufbau dem Desktop-Client entsprechen. Durch gleiche Navi-gationsstruktur und identisch angeordnete Icons erf¨hrt der Anwender einen Wiedererken- anungwert, der die Einarbeitung in die Browser-Oberfl¨che erleichtert. Der Mitarbeiter aus adem Verkauf m¨chte auch im Außendienst die gewohnte Men¨f¨hrung und Oberfl¨chenmas- o uu ake vorfinden. Es sollte somit darauf geachtet werden, dass sich die Gestaltung der Oberfl¨che a
  • 53. 4.5 Analogie zu bestehender VWE-Oberfl¨che a 48 Abbildung 28: VWE-Web-Oberfl¨che mit dem Theme bunt“ a ” Abbildung 29: VWE-Web-Oberfl¨che mit dem Theme eurosoft“ a ”analog zur gewohnten VWE-GUI durchf¨hren l¨ßt. Dies bedeutet im Einzelnen, dass sich u aProgrammmodule in der Regel aus Listen- und Detailansicht zusammensetzen. Die Listen- ¨ansicht zeigt dem Benutzer zuerst eine Ubersicht uber alle bestehenden Objekte (z.B. eine ¨Liste mit allen Kunden). Sie enth¨lt nur wichtige Eckdaten. Nach Auswahl eines speziellen aObjektes springt die Ansicht in eine Detaildarstellung. Hier werden weitere, detaiierte Infor-mationen pr¨sentiert. Oftmals verteilen sich diese Informationen auf mehrere Register einer aTabsheet.In der Detailansicht soll es weiterhin m¨glich sein, zwischen den Objekten zu navigieren. Eine oMen¨leiste bietet daf¨r Icons, um zum ersten, vorherigen, n¨chsten oder zum letzen Objekt u u azu springen. Auch diese Funktionalit¨t soll genau wie die Icons f¨r das Anlegen eines neuen, a udas L¨schen eines vorhandenen oder das Speichern eines Business-Objektes im Web-Client o
  • 54. 4.5 Analogie zu bestehender VWE-Oberfl¨che a 49implementiert sein. Weiterhin sollen Tabelleninhalte ausgedruckt und nach Excel exportiertwerden k¨nnen. oZusammenfassend l¨ßt sich sagen, dass der Web-Client trotz Flexibilit¨t im Oberfl¨chende- a a asign eine an die bestehende VWE angelehnte Benutzerf¨hrung gew¨hrleisten muss. u a
  • 55. 5 Konzeptioneller Neuentwurf eines Web-Interfaces5.1 Multi-Tier-ArchitekturVWE-Web erweitert den dreischichtigen Aufbau von VWE um eine weitere Schicht. Diedadurch entstandene Architektur wurde bereit in Abschitt 3.3 mit Abbildung 18 skizziert.Die Kommunikation zwischen den einzelnen Schichten beruht auf offenen Standards. Durchdie Multi-Tier-Architektur wird dar¨ber hinaus ein hohes Mass an Modularit¨t und Skalier- u abarkeit erreicht. So ist es theoretisch m¨glich, dass einzelne Schichten ausgetauscht werden ok¨nnen, es kann beispielsweise eine andere Datenbank gew¨hlt werden oder es k¨nnen ver- o a oschiedene Web-Server zum Einsatz kommen.5.2 Das MVC-ModellBei der Betrachtung großer Software-Projekte fallen immer wieder Schlagworte wie Modu-larit¨t, Skalierbarkeit und Wiederverwendbarkeit. Gerade beim Entwurf komplexer Systeme amuss auch in Hinblick auf leichte Pflege und Wartung des Codes die Trennung von De-sign und Business-Logik das Ziel sein. Ein Design Pattern, das diese Teilung zur Folge hat,ist das sog. MVC-Modell. MVC steht als Abk¨rzung f¨r Model, View und Controller. Die u uMVC-Architektur kam erstmalig 1980 mit der Verbreitung von Smalltalk auf, wo sie im Zu-sammenhang mit grafischen Benutzeroberfl¨chen auch als Input-Processing-Output-Prinzip aangewandt wurde. Heute h¨lt das MVC-Modell auch Einzug in moderne objektorientierte aSprachen wie C++ oder Java. So basiert auch die Java-GUI mit Swing auf dem MVC-Gedanken.MVC teilt, wie bereits erw¨hnt, die Software-Komponenten in die Bausteine Model (zust¨ndig a af¨r die Datenhaltung), View (verantwortlich f¨r die Darstellung der Daten) und Controller u u(Verbindung zwischen beiden, bearbeitet eingehende Ereignisse). Abbildung 30 zeigt denMVC-Aufbau mit seinen drei Komponenten und den Interaktionen zwischen ihnen. Abbildung 30: Das MVC-Modell Um den Anforderungen von Web-Applikationen, bei denen die Kommunikation zwischen 50
  • 56. 5.2 Das MVC-Modell 51Web-Browser und Web-Server zustandslos vor sich geht, gerecht zu werden, wurde das MVC-Modell entsprechend abgewandelt. Ergebnis war das MVC Model 2, das oftmals auch nur alsModel 2 bezeichnet wird. Abbildung 31 zeigt den ver¨nderten Aufbau von Model 2. a Abbildung 31: Das MVC Model 25.2.1 Model – Das ModellDas Modell verwaltet die Business-Logik und ist f¨r die Datenhaltung zust¨ndig. Typischer- u aweise werden die Daten in JavaBeans gekapselt, die Ergebnisdaten mit entsprechenden Getter-Funktionen bereit stellen. Die JavaBeans sollten als Softwarekomponenten so entwickelt wer-den, dass sie auch in anderen Applikationen verwendet werden k¨nnen. Sie sind also nicht onur spezifisch f¨r diese Web-Anwendung zu entwickeln. uVWE-Web generiert dazu aus den IDL-Structs entsprechende Klassen, die auch als Business-Objekte (5.4) bezeichnet werden. Diese entsprechen den Regeln einer JavaBean und k¨nnten oauch außerhalb der Web-Anwendung verwendet werden.5.2.2 View – Die AnsichtDie View ist f¨r die grafische Darstellung der Daten verantwortlich. Sie stellt die Daten, udie das Model zur Verf¨gung stellt, f¨r den Benutzer dar. View-Komponenten werden durch u uJavaServer Pages realisiert. Zus¨tzlich zu dem normalen HTML-Code enthalten JSP-Seiten aJava-Fragmente oder auch benutzerdefinierte Elemente (Custom Tags). Solche Custom Tagsentsprechen der HTML- oder, genauer gesagt, der XML-Syntax und k¨nnen als Platzhalter of¨r Java-Code gesehen werden. Custom Tags werden in Bibliotheken, sog. Taglibs, zusam- umengefasst. VWE-Web implementiert eine Taglib namens varial.tld, die eine Reihe vonbenutzerdefinierten Tags enth¨lt. aCustom Tags lassen sich wie normale HTML-Tags verwenden. Dahinter verbergen sich Java-Klassen, welche eine Aufgabe ausf¨hren und als Resultat normalen HTML-Text ausgeben. uDurch die Verwendung von Custom Tags ist es m¨glich, dass Designer die Oberfl¨che entwer- o afen, ohne sich mit Programmieraufgaben zu besch¨ftigen. Sie verwenden einfach die Tags, wie asie es von HTML bereits gew¨hnt sind. Die Algorithmen, die dahinter stecken, bleiben ihnen o
  • 57. 5.3 HTTP und das Session-Problem 52verborgen. Wichtig ist einzig und allein die Ausgabe des Tags. Designer m¨ssen nicht Java uverstehen, w¨hrend sich Programmierer umgekehrt nicht um das Layout k¨mmern m¨ssen. a u u5.2.3 Controller – Die SteuerungDer Controller dient als Bindeglied zwischen Model und View. Er verwaltet Benutzerein-gaben und setzt die Daten im Modell mit entsprechenden Setter-Methoden. Anschließendgibt er die Verarbeitung an die View weiter, die das Ergebnis schließlich ausgibt. Dieserzentrale Teil wird von Servlets realisiert. Die VWE-Web-API bietet bereits in dem Packetcom.varial.base (6.1) einige Oberklassen, von denen Servlets abgeleitet werden k¨nnen, so odass typische Aufgaben des Controllers, wie das Dispatchen der Anfrage, mit vorgefertigtenMethoden erledigt werden k¨nnen. o5.2.4 Zusammenspiel der KomponentenDas VWE-Web-Interface folgt dem MVC Model 2, das in Abbildung 31 skizziert wurde.Anfragen vom Browser erreichen zuerst den Controller, also das Servlet. Dieses setzt ent-sprechende Daten in den Model-Komponenten, also in den GUI- und BO-Klassen. Nach derVerarbeitung wird die Anfrage an eine JSP-Seite geleitet. Dort wird der Oberfl¨chenaufbau adurch HTML- und Custom Tags beschrieben. Die Taglib-Elemente rufen die zugeh¨rigen oJava-Klassen auf, die als View f¨r die Darstellung der Daten zust¨ndig sind. Diese Klassen u abedienen sich der Daten, die das Model zur Verf¨gung stellt, generieren eine HTML-Ausgabe uund schicken diese abschließend wieder zum Browser zur¨ck. u5.2.5 Vorteile von MVCDurch die Verwendung der MVC-Architektur k¨nnen Darstellung und Gesch¨ftslogik sauber o avoneinander getrennt werden. Diese Trennung f¨hrt zu folgenden Vorteilen: u • Schaffung von Softwarebausteinen, die leicht wartbar sind. • Bausteine k¨nnen wiederverwendet werden. Andere Clients (z.B. WAP) k¨nnen das o o selbe Model verwenden. • Programmierer und Designer k¨nnen v¨llig getrennt von einander arbeiten. Kompeten- o o zen werden an den richtigen Stellen eingesetzt. • Komponenten k¨nnen unabh¨ngig voneinander ver¨ndert werden. Das Seitenlayout o a a kann komplett umgestellt werden, ohne dass Java-Code ver¨ndert werden muss (Stich- a wort Corporate Design“ 4.4.2). Umgekehrt kann bei gleichem Layout die Gesch¨ftslogik a ” uberarbeitet werden (Stichwort Lokalisierung fachlicher Inhalte“ 4.2.4). ¨ ”5.3 HTTP und das Session-ProblemDas HTTP-Protokoll ist zustandslos. Das bedeutet, dass der Web-Server eingehendeAnfragen unabh¨ngig voneinander abarbeitet. Zusammenh¨nge zwischen mehreren Anfragen a akann er hingegen nicht erkennen. Fordert ein Anwender z.B. drei Seiten nacheinander an, istes dem Server nicht m¨glich, zu erkennen, dass die drei Anfragen von dem selben Benutzer o
  • 58. 5.3 HTTP und das Session-Problem 53gekommen sind. Dieses Verhalten ist in einem rein statischen Internet durchaus akzeptabel.Zu Problemen kommt es hingegen dann, wenn mehr dynamischer Inhalt mit ins Spielkommt. Als Beispiel sei ein Online-Shop aufgef¨hrt. Der Besucher durchst¨bert das Angebot u odes H¨ndlers und legt, nachdem er das erste Mal f¨ndig geworden ist, einen Artikel in den a uWarenkorb. Nun schaut er sich weitere Artikel an und legt auch diese in den Warenkorb.Schließlich schickt er die Bestellung ab. In der heutigen Zeit ist dies zu einer trivialenSituation im Internet geworden. Wie gestaltet sich diese Szenario jedoch aus der Sichtdes Web-Servers? Er erh¨lt zun¨chst eine Reihe von Anfragen, die das Angebot des Shops a azeigen. Sp¨ter wird der Warenkorb angefordert und ein gew¨hlter Artikel wird ubergeben. a a ¨Der Server erkennt nun nicht, ob dies der erste Artikel des Kunden ist oder ob zuvor schonArtikel ausgew¨hlt wurden. Genauso steht die sp¨ter folgende zweite Warenkorb-Anfrage a aaus der Sicht des Servers v¨llig losgel¨st von der ersten Anfrage. Nimmt man weiterhin an, o odass gleichzeitig mehrere Personen das System nutzen, erh¨lt der Server eine Reihe von aAnfragen, deren Zuordnung unm¨glich ist. o HTTP braucht also Zust¨nde. Durch einen Zustand muss es m¨glich sein, Sitzungen zu a oerkennen. Zusammengeh¨rende Anfragen m¨ssen als solche identifiziert werden. Im Beispiel o udes Online-Shops heißt das, dass alle Anforderungen des Anwenders auch vom Server alszusammenh¨ngend erkannt werden, so dass dieser den Warenkorb verwalten kann. aUm solche Sitzungen oder auch Sessions zu erkennen, dient eine sog. Session-ID. Dies istein eindeutiger Schl¨ssel, den die Sitzung vom Server zugeordnet bekommt. Bei der ersten uAnfrage erzeugt der Server die Session-ID und liefert sie dem Browser. Dieser muss imFolgenden jeder Anfrage die Session-ID hinzuf¨gen. Der Server weiß so, dass gleiche Session- uIDs zur selben Sitzung geh¨ren. Auch parallele Anfragen von mehreren Nutzer lassen sich oso auseinanderhalten und richtig zuordnen. Vorraussetzung ist, dass der Algorithmus, derserverseitig die Session-ID generiert, verschiedene Schl¨ssel erzeugt. Sollten zwei Anwender udie gleiche Session-ID bekommen, w¨rden sie aus der Sicht des Servers ein und die selbe uPerson darstellen. Resultat w¨re in der Regel ein ziemliches Chaos. aDamit der Browser die Session-ID bei jeder Anfrage mitliefert, k¨nnen verschiedene oTechniken benutzt werden (Abbildung 32). Zum einen k¨nnen Session-IDs in sog. Cookies ogespeichert werden. Dies sind sehr kleine Textdateien, die von Web-Seiten auf der Festplattedes Benutzers gespeichert werden k¨nnen. Die Informationen, die in den Cookies gespeichert owerden, k¨nnen sp¨ter von der Seite wieder abgefragt werden. Bei jedem Seitenbesuch w¨rde o a udie Session-ID des Cookies mitgeliefert, so dass Sitzungen theoretisch sogar uber Wochen, ¨Monate oder gar Jahre erkannt werden k¨nnten. Cookies lassen sich jedoch vom Anwender oim Browser deaktivieren. D.h. es werden keine Informationen auf der Festplatte gespeichert.Die Folge w¨re, dass keine Session-ID ubertragen w¨rde und dass der Server keine Sitzungen a ¨ uerkennen k¨nnte. o Eine weitere M¨glichkeit besteht darin, versteckte Formfelder in eine Internetseite oeinzubauen. Dazu kann dem input-Tag als type-Attribute der Wert hidden gesetzt werden.Solche Felder werden nicht im Browser angezeigt, ihre Werte werden aber wie bei anderenFeldern mit ubertragen. Ein Formular muss somit nur um ein weiteres verstecktes Feld mit ¨der Session-ID erweitert werden. F¨r den Anwender ¨ndert sich nichts, da dieses Feld nicht u ain der Anzeige erscheint. Der Browser liefert dem Server aber die gew¨nschte Session-ID. u
  • 59. 5.3 HTTP und das Session-Problem 54 Abbildung 32: Methoden f¨r den Transport der Session-ID uDiese Technik l¨ßt sich aber nur bei Formularen anwenden. Navigiert der Benutzer uber a ¨Links, ist die Verwendung von versteckten Formularfeldern nicht m¨glich bzw. nur uber o ¨einen großen Work-a-round mit JavaScript zu realisieren.Eine weitere L¨sung bietet die als o URL-Rewritting bekannte Methode.Hier wird der angeforderten Adresse die Session-ID angehangen. Anstattdie Adresse http://www.abc.de/eineSeite.jsp?param=xy anzufordern, wirdhttp://www.abc.de/eineSeite.jsp;sessionid=0123456789?param=xy angefordert.Der Server zerlegt nun die Adresse wieder in die einzelnen Bestandteile. Die Servlet-APIbietet hierf¨r bereits vorgefertigte Methoden, so dass sich das URL-Rewritting f¨r den u uEntwickler recht einfach gestaltet. Bei VWE-Web besitzen alle von VServlet (6.1.1) abgelei-teten Klassen die Methode encodeURL(), die alle Adressen passend umwandelt. Außerdemstellen Servlets bereits ein session-Objekt bereit, in dem Sitzungsdaten gespeichert werdenk¨nnen. oZum Schluss bleibt die Frage, wie das Ende einer Sitzung erkannt wird. Angelegte Sessions
  • 60. 5.4 Business-Objekt und Enumerations 55sollten nicht ewig existieren, da dies unn¨tige Systemresourcen verbrauchen w¨rde. Deshalb o ugibt es zwei Arten, wie eine Session beendet werden kann. Zum einen kann der Anwenderexplizit das Ende einer Session bestimmen. Sobald er sich von dem Web-Client durchAnklicken des entsprechenden Symbols abmeldet, wird das Session-Objekt und die zugeh¨ri- oge ID verworfen. Nun kann es jedoch auch vorkommen, dass der Anwender die Sitzungnicht durch ein Logout beendet. Er k¨nnte genauso gut einfach den Browser schließen ooder durch die Eingabe einer anderen Adresse die Seite verlassen. Auch ein System- oderProgrammabsturz k¨nnte Ursache f¨r ein fehlendes Logout sein. Der Web-Server kann daher o uSessions nach einer gewissen Zeitspanne verwerfen. Sobald eine Sitzung f¨r das angegebene uIntervall keine neuen Anfragen mehr startet, wird sie als ung¨ltig erkl¨rt und gel¨scht. Die u a oAngabe, wie lange dieses Zeitinterval dauern soll, kann im Development Descriptor web.xmlangegeben werden. Die Voreinstellung betr¨gt 30 Minuten. aMit der Verwendung von Session-IDs wird das zustandslose HTTP um die M¨glichkeit von oSitzungsverwaltungen erweitert; komplexe Web-Applikationen werden erm¨glicht. o5.4 Business-Objekt und EnumerationsAlle CORBA-Objekte werden in der IDL als sog. Structs beschrieben. Hierbei werden inder IDL alle Attribute, die ein Objekt besitzt, beschrieben. Um auf solche Objekte zugreifenzu k¨nnen, wird f¨r jede Struct eine Java-Klasse, ein sog. Business-Objekt (BO) generiert o u(siehe auch 2.2.2 Application Objects der OMA).Zu diesem Zweck wurde ein Perl-Skript namens WebBOBuilder geschrieben. Mit seiner Hilfewerden f¨r IDL-Structs automatisch passende Java-Klassen erzeugt. uJede Klasse folgt dadurch einem einheitlichen Aufbau: • Packagebezeichnung laut IDL Die module-Angaben werden in entsprechende Java-Package-Angaben ubersetzt. Feh- ¨ lende Verzeichnisse werden hierzu bei Bedarf angelegt. • Import von n¨tigen Packeten o Alle ben¨tigten Klassen werden importiert. o • Benennung in Anlehnung an IDL-Struct Die BOs werden gem¨ß IDL benannt. Jedoch wird die Endung Struct durch BO ersetzt. a Aus CompanyStruct wird also CompanyBO. • Vererbung von BO Alle BOs werden von der Basis-Klasse BO (6.1.12) abgeleitet. • Struct als private Variable Der IDL-Struct wird private Variable jedes BOs und tr¨gt den Namen mIdlStruct. a • Zwei Konstruktoren Der erste Konstruktor erwartet als einzigen Parameter einen passenden IDL-Struct. Durch ihn k¨nnen BOs aus Structs erzeugt werden. Der zweite Konstruktor erwartet o keine Parameter. Mit ihm wird ein leeres BO erzeugt, d.h. alle Attribute werden auf Default-Werte gesetzt. Zahlen (int, short, double, etc.) erhalten den Wert 0, Zeichen- ketten einen Leerstring, boolsche Werte werden auf false gesetzt und Zeichen (char)
  • 61. 5.4 Business-Objekt und Enumerations 56 erhalten als Wert ’0’. Unions werden durch den Aufruf ihrer default-Methode ge- setzt. Besitzt ein IDL-Struct selbst andere IDL-Structs als Attribute, werden diese auf ihre Default-Werte gesetzt, indem durch ihren Konstruktor ein leeres BO erzeugt wird und anschließend durch die Funktion toIdl() in ein Struct gewandelt wird. • Getter und Setter F¨r jedes Attribute wird eine get- bzw. set-Methode erzeugt. Die Benennung folgt hier u den Regeln von JavaBeans, d.h eine Methode f¨r ein Attribut namens abc heißt immer u getAbc() bzw. setAbc(). Bei boolschen Werten tr¨gt die Getter-Funktion den Namen a isAbc(). Handelt es sich bei dem Attribut um eine Union, werden zus¨tzlich die Me- a thoden hasAbc(), die true zur¨ckliefert, wenn die Union gesetzt ist, und clearAbc(), u die die Union mit default auf den Standardwert zur¨cksetzt, erzeugt. u • Methoden zur Listenumwandlung Um eine Sequenz von Structs in ein BO-Array umzuwandeln und v.v., werden die statischen Methoden toBoArray(), die eine Liste von Structs erwartet, und toSeq(), die einen Bo-Array erwartet, generiert. • Methode um BO als Struct zu bekommen Um ein BO in eine IDL-Struct zu wandeln, wird die Methode toIdl() erzeugt. Zur Erinnerung: F¨r die andere Richtung, also BOs aus Structs, dient der Konstruktor. u • Methoden zum Speichern und L¨schen o Das Progamm WebBOBuilder erzeugt weiterhin zwei Methoden zum Speichern bzw. zum L¨schen des BOs. Sie heißen commit() und delete(). o • Funktion f¨r ObjectStruct u Fast jede IDL-Struct besitzt ein Objekt vom Typ ObjectStruct. Dieser Struct hat die Attribute objectid, welches eine eindeutige ID angibt, lastuserid, in dem die ID des Users gespeichert ist, der das Objekt als letztes ver¨ndert hat, und timestamp, das das a ¨ Datum und die Uhrzeit der letzten Anderung angibt. Um auf dieses Objekt zugreifen zu k¨nnen, wird automatisch ein Methode mit dem Namen getOidTs() erzeugt. Von o Bedeutung ist diese Methode vor allen Dingen in der Ober-Klasse BO. • Objekt-Bezeichnung Um ein Objekt eine Bezeichnung zu geben, die dem Benutzer z.B. bei L¨sch-Best¨ti- o a gungen angezeigt werden soll, wird eine Funktion getMessageDescription() generiert. Standardm¨ßig wird der Name des BOs, also z.B. Company, zur¨ckgegeben. Ein m¨gli- a u o cher Dialog w¨re also: Delete Company?. a • Methode f¨r passenden Servant u Zum Schluß wird die private Funktion getServant() geschrieben. Mit ihr kann auf den Servant, der f¨r die Behandlung des Objekts zust¨ndig ist, zugegriffen werden. u aBeispiel:IDL-Struct:
  • 62. 5.4 Business-Objekt und Enumerations 57struct TaskReminderStruct { TaskReminderShortStruct taskReminderShort; union isRecurringTaskUnion switch (boolean) { case TRUE: RecurringTaskStruct recurringTask; } recurringTask; string note;};Erzeugt wird:package com.varial.framework.domain.taskreminder;import com.varial.base.*;import com.varial.serverbase.query.*;import com.varial.framework.taskreminder.*;import com.varial.framework.servantimpl.taskreminder.*;import com.varial.framework.taskreminder.TaskReminderStructPackage.*;import java.io.*;public class TaskReminderBO extends BO implements Serializable { // --------------------------------------------------------------------- // ---- Variables ------------------------------------------------------ // --------------------------------------------------------------------- private TaskReminderStruct mIdlStruct; // --------------------------------------------------------------------- // ---- Constructors --------------------------------------------------- // --------------------------------------------------------------------- public TaskReminderBO (TaskReminderStruct struct) { super(); mIdlStruct = struct; } public TaskReminderBO() { super(); mIdlStruct = new TaskReminderStruct();
  • 63. 5.4 Business-Objekt und Enumerations 58 mIdlStruct.taskReminderShort = new TaskReminderShortBO().toIdl(); // Set default values mIdlStruct.recurringTask = new isRecurringTaskUnion(); mIdlStruct.recurringTask.__default(); mIdlStruct.note = ""; } // --------------------------------------------------------------------- // ---- Getter / Setter ------------------------------------------------ // --------------------------------------------------------------------- public TaskReminderShortBO getTaskReminderShort() { return new TaskReminderShortBO(mIdlStruct.taskReminderShort); } public void setTaskReminderShort (TaskReminderShortBO taskReminderShort) { mIdlStruct.taskReminderShort = taskReminderShort.toIdl(); } // --------------------------------------------------------------------- public void setRecurringTask (RecurringTaskBO recurringTask) { mIdlStruct.recurringTask.recurringTask(recurringTask.toIdl()); } public RecurringTaskBO getRecurringTask() { if (mIdlStruct.recurringTask.discriminator()) { return new RecurringTaskBO (mIdlStruct.recurringTask.recurringTask()); } // default return new RecurringTaskBO(); } public void clearRecurringTask() { mIdlStruct.recurringTask.__default(); } public boolean isRecurringTask() { return mIdlStruct.recurringTask.discriminator(); } // --------------------------------------------------------------------- public String getNote() {
  • 64. 5.4 Business-Objekt und Enumerations 59 return mIdlStruct.note; } public void setNote (String note) { mIdlStruct.note = note; } // --------------------------------------------------------------------- // --------------------------------------------------------------------- // ---- Generated Public Methods --------------------------------------- // --------------------------------------------------------------------- public static TaskReminderBO[] toBoArray(TaskReminderStruct[] seq) { TaskReminderBO[] result = new TaskReminderBO[seq.length]; for (int i=0; i<seq.length; i++) { result[i] = new TaskReminderBO(seq[i]); } return result; } public static TaskReminderStruct[] toSeq(TaskReminderBO[] bos) { TaskReminderStruct[] result = new TaskReminderStruct[bos.length]; for (int i=0; i<bos.length; i++) { result[i] = bos[i].toIdl(); } return result; } // --------------------------------------------------------------------- /** * Business object as IDL-Struct * * @return the business object as IDL-Struct */ public TaskReminderStruct toIdl() { return mIdlStruct; } // --------------------------------------------------------------------- public void commit (VContext ctx) { try {
  • 65. 5.4 Business-Objekt und Enumerations 60 TaskReminderStruct struct = null; if (isNew()) { struct = getServant(ctx).createTaskReminder( ctx.getAccessToken(), ctx.getOidParent(), mIdlStruct ); } else { struct = getServant(ctx).setTaskReminder(ctx.getAccessToken(), mIdlStruct); } mIdlStruct = struct; } catch (Exception e) { throw new VException(e); } } //--------------------------------------------------------------------------- public void delete (VContext ctx) { try { // delete only, if TaskReminder isn’t new if (!isNew()) { ObjectStruct[] seq = new ObjectStruct[1]; seq[0] = getOidTs(); getServant(ctx).deleteTaskReminders(ctx.getAccessToken(), seq); } } catch (Exception e) { throw new VException(e); } } // --------------------------------------------------------------------- protected ObjectStruct getOidTs() { return mIdlStruct.taskReminderShort.oidTimestamp; } // --------------------------------------------------------------------- public String getMessageDescription() { return getTaskReminderShort().getMessageDescription(); }
  • 66. 5.4 Business-Objekt und Enumerations 61 // --------------------------------------------------------------------- // ---- Generated Private Methods -------------------------------------- // --------------------------------------------------------------------- private static TaskReminderServant getServant(VContext ctx) { TaskReminderServant servant = (TaskReminderServant) getObjectFromOrb ( ctx, "com.varial.framework.servantimpl.taskreminder.TaskReminderServantImpl", "com.varial.framework.taskreminder.TaskReminderServantHelper" ); return servant; } // --------------------------------------------------------------------- // ---- User-Included Methods ------------------------------------------ // --------------------------------------------------------------------- public static TaskReminderShortBO[] getDueAndOverdueTaskReminders ( VContext ctx ) { try { TaskReminderServant servant = getServant(ctx); return TaskReminderShortBO.toBoArray( servant.getDueAndOverdueTaskReminders ( ctx.getAccessToken() ) ); } catch (Exception e) { throw new VException(e); } } public static TaskReminderBO getTaskReminder( VContext ctx, String oidTask ) { try { TaskReminderServant servant = getServant(ctx);
  • 67. 5.4 Business-Objekt und Enumerations 62 return new TaskReminderBO ( servant.getTaskReminder( ctx.getAccessToken(), oidTask ) ); } catch (Exception e) { throw new VException(e); } } public static TaskReminderBO moveTaskReminderToFolder( VContext ctx, String oidFolderTo, String oidTask ) { try { TaskReminderServant servant = getServant(ctx); return new TaskReminderBO ( servant.moveTaskReminderToFolder( ctx.getAccessToken(), oidFolderTo, oidTask ) ); } catch (Exception e) { throw new VException(e); } }}Die letzten drei Methoden wurden nicht automatisch erzeugt, sondern sp¨ter von Hand ahinzugef¨gt. Sie zeigen, wie Methoden des Servants aufgerufen und IDL-Typen in BOs uumgewandelt werden. Alle Exceptions sollten abgefangen und in VExceptions (6.1.14)umgewandelt werden. Diese werden vom aufrufenden VServlets gefangen und behandelt.Weitere Angaben, die in der IDL spezifiziert werden, sind Aufz¨hlungen (Enumeration). aUm sie in den Java-Klassen zug¨nglich zu machen, dient das Perl-Skript WebEnumBuilder. aDieses Skript erzeugt eine Java-Klasse, die es erm¨glicht, Enumerations als eine Liste von oStrings zu erhalten. N¨tzlich ist dies z.B. dann, wenn eine Combo-Box gef¨llt werden soll. u uDie erzeugte Java-Klasse hat folgenden Aufbau:
  • 68. 5.4 Business-Objekt und Enumerations 63 • Packagebezeichnung laut IDL Die module-Angaben werden in entsprechende Java-Package-Angaben ubersetzt. Feh- ¨ lende Verzeichnisse werden hierzu bei Bedarf angelegt. • Import von n¨tigen Packeten o Alle ben¨tigten Klassen werden importiert. o • Benennung in Anlehnung an IDL-Struct Die Enum-Helper werden gem¨ß IDL benannt. Jedoch wird die Endung Enum durch a Helper ersetzt. Aus MonthEnum wird also MonthHelper. • Vector und Translator als private Variablen Ein Vector, der sp¨ter die Bezeichnungen der Enum-Eintr¨ge enth¨lt, und ein a a a u ¨ Translator-Objekt (6.2.1), das f¨r die Ubersetzung zust¨ndig ist, werden als priva- a te Variablen angelegt. • Private init-Methode Eine Methode namens init() wird erzeugt. Hier wird die String-Liste aufgebaut. • Getter Zugriff auf die Enumerations hat man mit folgenden statischen Methoden, die von WebEnumBuilder automatisch erzeugt werden: Der Funktion indexOfEnum() wird der Enum-Typ ubergeben und man erh¨lt den In- ¨ a dex in der Liste zur¨ck. Mit getIdl() ist die Umwandlung in die andere Richtung u ¨ m¨glich. Ubergeben wird der Index in der Liste, die Funktion liefert den Enum-Typen. o Alternativ kann hier auch die Enum-Bezeichnung als String ubergeben werden. ¨ getString(), eine Funktion, der wahlweise der Enum-Typ oder der Listen-Index uber- ¨ geben werden kann, liefert die Bezeichnung eines Enum-Eintrags als String. Der oben angegebene Translator ubersetzt diese Bezeichnung in die aktuelle Sprache. ¨ Als letzte Methode generiert das Perl-Skript getStrings(), mit deren Hilfe die kom- plette Enumeration als String-Array abgefragt werden kann.Beispiel:IDL-Enum:enum SexEnum { SE_WOMEN, SE_MEN, SE_UNKNOW};Erzeugte Java-Helper-Klasse:package com.varial.framework.domain.basictypes;// WebBuilder:import com.varial.administration.*;import com.varial.serverbase.mapper.*;import com.varial.translation.*;
  • 69. 5.4 Business-Objekt und Enumerations 64import com.varial.base.*;import com.varial.framework.basictypes.*;import java.util.*;public class SexHelper { private static Vector mStringList = null; private final static Translator mTranslator = new Translator( "__TODO__", "__TODO__" ); private synchronized static void init() { if (mStringList == null) { mStringList = new Vector(); mStringList.addElement("monthstringlist#0"); // WOMEN mStringList.addElement("monthstringlist#1"); // MEN mStringList.addElement("monthstringlist#2"); // UNKNOWN } } public static int indexOfEnum (SexEnum enum) throws EnumException { switch (enum.value()) { case SexEnum._SE_WOMEN: return 0; case SexEnum._SE_MEN: return 1; case SexEnum._SE_UNKNOW: return 2; default: throw new EnumException("SexHelper: can’t map enum " + enum); } } public static SexEnum getIdl (int index) throws
  • 70. 5.4 Business-Objekt und Enumerations 65 EnumException { switch(index) { case 0: return SexEnum.SE_WOMEN; case 1: return SexEnum.SE_MEN; case 2: return SexEnum.SE_UNKNOW; default: throw new EnumException("SexHelper: unknown type:" + index); } } public static SexEnum getIdl (String name) throws EnumException { init(); int index = mStringList.indexOf(name); if (index < mStringList.size()) { return getIdl(index); } else { throw new EnumException("SexHelper:missing string #"+index); } } public static String getString ( VContext ctx, SexEnum enum ) throws EnumException { return getString(ctx, indexOfEnum(enum)); } private static String getString ( VContext ctx, int index )
  • 71. 5.5 Das Callback-Problem 66 throws EnumException { init(); if (index < mStringList.size()) { return mTranslator.getCaption( ctx, (String)mStringList.elementAt(index) ); } else { throw new EnumException("SexHelper:missing string #"+index); } } public static String[] getStrings (VContext ctx) { init(); String[] result = new String[mStringList.size()]; for (int i=0; i<mStringList.size(); i++) { result[i] = getString(ctx, i); } return result; }}5.5 Das Callback-ProblemTypisch f¨r ERP-Systeme sind Suchanfragen auf großen Datenmengen. Da die Zeit f¨r die u uSuche mit der Menge der Daten zunimmt, muss der Benutzer unter Umst¨nden lange War- atezeiten bis zur Ergebnis-Ausgabe hinnehmen.Sucht man z.B. alle Kunden, die ihren Sitz in Deutschland haben, so kann das bei einementsprechend großen Kundenstamm zu einer recht großen Ergebnismenge f¨hren. Es ist nicht upraktikabel, den Anwender lange auf das Suchergebnis warten zu lassen und ihm alle Datenauf einmal zu pr¨sentieren. Vielmehr ist es sinnvoller, Daten St¨ck f¨r St¨ck anzuzeigen, a u u udie Liste der Suchergebnisse also schon w¨hrend der Suche aufbauen zu lassen. So kann der aAnwender die Daten bereits lesen, w¨hrend weitere Daten noch gesucht werden. Evtl. ist der agesuchte Datenbestand bereits dabei, so dass die Suche vorzeitig vom Benutzer abgebrochenwerden kann. Eine solche Funktionalit¨t wird von VWE mit dem sog. Callback-Mechanismus aerm¨glicht. oUnter einem Callback versteht man einen Aufruf eines Servers an einen Client. Ein Call-back kehrt somit die klassischen Rollen des Clients und des Servers um. Typischerweise istein CORBA-ORB beides: Client und Server. Dem Server wird eine Objektreferenz f¨r einuClient-Callback-Objekt ubergeben, mit dem er Funktionen des Clients aufrufen kann. Auf ¨
  • 72. 5.5 Das Callback-Problem 67diese Weise kann der Server, wenn er eine gewisse Anzahl von Daten gefunden hat 4 , eineMethode des Clients aufrufen und die gefundenen Daten ubergeben. Der Client wiederum ¨kann diese Ergebnisse darstellen und auf weitere Daten warten. Um einen Callback-Aufrufzu erm¨glichen, muss der Client als Erstes das IDL-Interface AllCallback implementieren: ointerface AllCallback { void finished(); void setException(in DatabaseExceptionStruct e);};Dieses Interface beinhaltet zwei Methoden:Beim Aufruf von finished() wird der Client vom Server dar¨ber informiert, dass keine uweiteren Daten folgen. Mit setException() kann der Server Fehler an den Client melden.Es fehlt die besagte Methode, mit der die gefundenen Daten an den Client ubergeben werden ¨k¨nnen. Da die Daten typspezifisch sind, wird diese Methode hier nicht spezifiziert, sondern oes wird f¨r den jeweiligen Datentyp ein entsprechendes Interface abgeleitet: uinterface PersonalAccountShortStructCallback : serverbase::query::AllCallback{ void putData( in PersonalAccountShortSeq customers) raises (serverbase::query::PutDataException);};In diesem Bespiel wird ein Interface f¨r einen Personen-Konten-Callback definiert. Es besitzt udurch Vererbung die beiden Methoden des AllCallback-Interfaces und spezifiziert dar¨ber uhinaus die typspezifische Methode putData(). Diese Methode erwartet einen Parameter:PersonalAccountShortSeq.Dies ist eine Liste von Personen-Konten. Der Server kann also gefundene Daten mitputData() an den Client ubergeben. ¨ Beim Aufruf der Server-Methode wird dieses Callback-Objekt mit ubergeben: ¨// get personalaccounts by filtervoid getPersonalAccounts ( in serverbase::access::AccessToken token, in PersonalAccountFilterStruct queryFilter, in PersonalAccountStructCallback callback) raises ( serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException, serverbase::applicationexception::DomainException); 4 In der Regel sind dies bei VWE 50 St¨ck u
  • 73. 5.5 Das Callback-Problem 68Man erkennt als dritten Parameter den PersonalAccountStructCallback. Der Serverkann nun entsprechende Abfragen auf der Datenbank durchf¨hren, Teilergebnisse durch uden putData()-Aufruf an die Callback-Referenz weitergeben und das Ende der Suche uber ¨finished() bekannt geben. Der Client bekommt nun die Daten St¨ck f¨r St¨ck und kann sie darstellen. Im C++- u u uClient gestaltet sich die Darstellung recht einfach. An die Tabelle werden lediglich neue Spal-ten angeh¨ngt. Bei dem Web-Interface l¨sst sich dies allerdings nicht so einfach bewerkstel- a aligen.Der CORBA-Client ist in diesem Fall ein Servlet. Dieses Servlet erzeugt HTML-Code, denes uber HTTP an den Browser schickt. Im Folgenden kann das Servlet nicht mehr aktiv in ¨die Darstellung eingreifen. Eine Tabelle, die einmal generiert und an den Browser geschicktwurde, l¨sst sich nicht mehr ver¨ndern. Bei HTTP sind die Client- und Server- Rollen strikt a averteilt, so dass der Server ausschließlich auf Anfrage des Clients t¨tig werden kann. Wie akann das Servlet nun die Daten, die es in unregelm¨ßigen Abst¨nden vom CORBA-Server a abekommt, im Browser darstellen, wenn die HTTP-Verbindung keine unmittelbare Kontrolledes Servlets uber die Darstellung erm¨glicht? Im Folgenden werden m¨gliche L¨sungsans¨tze ¨ o o o aaufgezeigt:5.5.1 Daten sammeln und erst komplett an Browser ubergeben ¨Der Client k¨nnte die Daten, die er mit putData() empf¨ngt zun¨chst sammeln. Erst wenn o a adas Ende mit finished() angezeigt wird, k¨nnen alle Daten als Tabelle an den Browser ogeschickt werden.Dies hat den großen Nachteil, dass der eigentliche Zweck eines Callbacks, n¨mlich Daten a a o ¨schon w¨hrend des Suchvorgangs zu liefern, v¨llig verloren geht. Die Ubertragung an denBrowser muss also schon vor dem finished() erreicht werden.5.5.2 Server PushIm klassischen HTTP-Modell sendet der Client, also der Browser, eine Anfrage an den Web-Server, der wiederum das Ergebnis der Anfrage, z.B. eine Web-Seite, an den Client schickt.Bei der als Server Push“ bezeichneten Technologie wird der Server ohne Clientanfrage aktiv ”und dr¨ngt dem Client Daten auf“ (push = dr¨ngen). Beim Server-Push wird die Socket- a a ”Verbindung zwischen Client und Server so lange aufrecht gehalten, bis sie vom Server ge-schlossen wurde. Der Server kann so mehrere Seiten schicken und k¨nnte beispielsweise eine oAnimation oder auch das aktuelle Bild einer Webcam darstellen. Im Callback-Szenario k¨nnte odas Servlet eine Tabelle mit bereits empfangenen Daten erzeugen, dieses mittels Server-Pushan den Browser schicken, auf neue Daten warten, um dann erneut so zu verfahren. BeimAufruf von finished() k¨nnte Socket-Verbindung schließlich geschlossen werden. oAuf diese Weise sieht der Anwender im Browserfenster zuerst eine Tabelle mit wenigen Ein-tr¨gen, sp¨ter wird die Seite neu aufgebaut und die Tabelle enth¨lt nun weitere Daten. Der a a aBenutzer bekommt somit nacheinander immer wieder eine neue Seite geliefert, die jedes Malmehr Daten enth¨lt. Aber auch diese L¨sung hat vier entscheidende Nachteile: a oDadurch, dass die Seite jedes Mal neu aufgebaut wird, sieht man bei jedem Neuaufbau den
  • 74. 5.5 Das Callback-Problem 69Seitenanfang. Scrollt man nach unten, so ist es nur eine Frage der Zeit, bis die Seite neu auf-gebaut wird und man sich erneut am Seitenanfang befindet. Zweitens k¨nnte es vorkommen, odass Ergebnisse schneller gefunden werden, als der Browser zum Aufbau der Seite braucht.Bedenkt man, dass gerade die Darstellung großer Tabellen unter Umst¨nden viel Zeit ver- abraucht oder dass eine langsame Internetverbindung die Darstellung bremst, k¨nnte die Seite oerneut aufgebaut werden, bevor sie komplett dargestellt wurde. Im schlimmsten Fall k¨nnteodie Seite gar nicht angezeigt werden, da sie bereits von der n¨chsten Seite ersetzt wurde. aResultat w¨re, dass auch hier erst zum Schluss Daten angezeigt w¨rden. Der dritte Nachteil a ubeim Server-Push ist, dass die Socket-Verbindung offen gehalten werden muss. Bei vielen An-fragen an den Web-Server k¨nnte dieser stark belastet werden. Der vierte und gr¨ßte Nachteil o oist, dass sowohl der Internet Explorer als auch Opera diese Technologie nicht unterst¨tzen uund es fraglich ist, ob sie es jemals tun werden.5.5.3 Client PullWie bereits oben erw¨hnt, wird der Server auf Anfrage des Clients aktiv. Beim Client Pull al¨sst man den Browser deshalb in bestimmten Zeitintervallen neue Anfragen an den Server astarten. So k¨nnte das Servlet einen Thread starten, der im Hintergrund die bereits emp- ofangenen Daten sammelt. Der Browser k¨nnte seinerseits alle N Sekunden eine Anfrage an odas Servlet starten, dass eine Tabelle mit den bereits empfangenen Daten zur¨ckschickt. Dies uwiederholt sich solange, bis das Ende mit finshed() angezeigt wurde.Die Frage, die sich hierbei aber zun¨chst stellt, ist die, in welchen Zeitintervallen nach neuen aDaten gefragt werden soll. Der Abstand zwischen zwei pushData() ist schließlich nicht kon-stant. W¨hlt man den Abstand zwischen zwei Anfragen zu kurz, k¨nnte es sein, dass in der a oZwischenzeit keine neuen Daten beim Servlet eingegangen sind. Ein Laden der Seite w¨re so-amit uberfl¨ssig. Eine unn¨tig hohe Netz- und Server-Last w¨re die Folge. Ist das Zeitintervall ¨ u o ajedoch zu lang gew¨hlt, kann der entscheidende Callback-Vorteil, n¨mlich Daten just-in-time a azu liefern, verloren gehen.Was bleibt, sind die bereits aufgezeigten Nachteile der Server-Push-Technologie:Durch Neuaufbau der Seite befindet man sich immer am Seitenanfang und die Darstellungk¨nnte unter Umst¨nden l¨nger als das Zeitintervall sein, so dass die Seite immer wieder von o a aeiner neueren verdr¨ngt wird. a5.5.4 Client Pull + DHTMLAnstatt die Seite jedes Mal neu aufzubauen, k¨nnte eine Hilfsseite verwendet werden. Diese oSeite wird in ein verstecktes frame oder iframe geladen und l¨dt sich mittels Client Pull ain regelm¨ßigen Abst¨nden neu. Hierbei m¨ssen nicht alle gefundenen Daten vom Servlet a a ugeliefert werden, sondern lediglich die neu hinzugekommenen. So wird die Netzlast geringgehalten. Sobald die Hilfsseite neue Daten empfangen hat, werden diese mit JavaScript andie eigentliche Tabelle angeh¨ngt. Auf diese Weise w¨chst die Tabelle, ohne dass die Seite a aneu geladen werden muss. Lediglich die Hilfsseite muss neu aufgebaut werden. Da diese abernicht angezeigt wird, ist dies nicht weiter schlimm.Auch hier bleiben Nachteile:Die Frage nach dem passenden Zeitintervall zwischen zwei Ladevorg¨ngen bleibt unge- a
  • 75. 5.5 Das Callback-Problem 70kl¨rt. Gr¨ßter Nachteil ist jedoch die noch magelnde DHTML-Unterst¨tzung der Browser- a o uHersteller. Opera unterst¨tzt diese L¨sung beispielsweise nicht, da die Hilfsseite die Haupt- u oTabelle mit dem JavaScript-Befehl getElementById() ansprechen m¨sste, der von Opera unoch nicht implementiert ist.5.5.5 Daten ungepuffert schreibenAnstatt die Seite jedes Mal neu zu laden, k¨nnte sie auch einfach nach und nach aufgebaut owerden. Setzt das Servlet den Ausgabe-Puffer auf 0 Byte oder leert ihn explizit mit demflush()-Befehl, wird die Ausgabe direkt an den Browser geschickt. Wird bei jedem Aufrufvon putData() die Ausgabe erzeugt, geschrieben und mit flush() der Buffer geleert, bautsich im Browser nach und nach die Tabelle auf.Durch diesen L¨sungsansatz werden direkt mehrere oben genannte Nachteile umgangen: oDie Seite muss nicht neu geladen werden, sie baut sich auf. Dadurch springt die Scrollpositionnicht nach oben, es entsteht kein Flackern und es erscheint ein permanentes Bild. Die Datenwerden genau dann angezeigt, wenn sie vom Server geliefert werden und sind nicht an einkonstantes Zeitintervall gebunden. Die L¨sung ist frei von DHTML und schließt somit keine oBrowsertypen aus.Ausgabe, die nach der Tabelle steht, kann jedoch erst angezeigt werden, nachdem alle Da-ten geschrieben wurden. Befindet sich unterhalb der Tabelle noch ein Eingabefeld, so wirddies erst angezeigt, nachdem die Tabelle vollst¨ndig ausgegeben wurde, also erst nach dem afinished(). Dieses Problem l¨sst sich recht einfach umgehen, indem die Tabelle in ein iframe aeingebettet wird. Angenehmer Nebeneffekt hierbei ist, dass die Tabelle im Layout immer denselben Platz einnimmt und mit Scrollbalken versehen wird.Ein gr¨ßeres Problem stellt jedoch die Tatsache dar, dass viele Browser die Spaltenbreiten ooptimal an die Zelleninhalte anpassen. Um eine optimale Darstellung zu erreichen m¨ssen uaber erst alle Eintr¨ge bekannt sein. Schließlich kann der breiteste Spalteninhalt nicht ermit- atelt werden, wenn noch nicht alle Inhalte bekannt sind. Folge ist, dass Tabellen erst beimabschließenden table-Tag angezeigt werden.Werden die einzelnen Zeilen also zum Browser geschickt, zeigt dieser sie erst an, nachdemdie Tabelle komplett ubertragen wurde. Folglich sieht der Anwender keinen Unterschied zur ¨erstgenannten Sammell¨sung. oDer HTML 4.0-Standard definiert zwar ein colgroup-Tag, das dem Browser zu Beginn In-formationen uber die folgenden Daten liefert und so einen schnelleren Aufbau bewirkt, aber ¨sowohl der Internet Explorer als auch Opera zeigen sich unbeeindruckt von dieser Angabe.Setzt man die Spalten auf feste Breiten und erzwingt die Einhaltung dieser Breiten mitder CSS-Angabe table-property:fixed, baut der IE die Tabelle fl¨ssig auf. Beim Opera ubewirkt dies hingegen keine Ver¨nderung. a5.5.6 Daten ungepuffert schreiben + viele kleine TabellenWie bereits erw¨hnt, werden Tabellen oft erst angezeigt, wenn sie komplett ubertragen wur- a ¨den. Wenn man bei jedem putData()-Aufruf die Tabelle schließt und eine neue ¨ffnet, kann oder Browser die bereits ubertragenen Daten schon anzeigen. ¨Eine große Tabelle wird somit durch viele kleine ersetzt. Dadurch, dass der Browser jedoch
  • 76. 5.5 Das Callback-Problem 71die Spaltenbreiten in Tabellen vergr¨ßert, wenn Inhalte zu groß sind, f¨hrt dies zu dem un- o ugew¨nschten Nebeneffekt, dass die Spaltenbreiten in den einzelnen Tabellen unterschiedlich ubreit sein k¨nnen. Es entsteht nicht mehr der Eindruck, dass es sich um eine einzige Tabelle ohandelt.Mit der CSS-Angabe table-property:fixed, die den Browser anweist, sich bei der Dar-stellung strikt an die angegebenen Spaltenbreiten zu halten, l¨sst sich das Problem lediglich abeim IE beheben. Die CSS-Angabe overflow:hidden in den Tabellenzellen, die ubergroßen ¨Inhalt abschneidet, bleibt wirkungslos. Deshalb wurden die Zelleninhalte mit einem div-Tagumschlossen, der wiederum mit dem besagten overflow:hidden versehen wurde. Dadurchwerden auch bei Netscape und Mozilla breite Eintr¨ge abgeschnitten. Die Spalten haben aber anicht zwangsl¨ufig die selbe Breite. Ein Grund daf¨r konnte nicht gefunden werden. Ebenso a uwenig f¨r das Verhalten des Opera-Browsers: Dieser schneidet zwar die Inhalte ordnungs- ugem¨ß ab, die Spalten sind aber so breit, wie sie sein m¨ssten, wenn sie nicht abgeschnitten a uw¨ren. Hierbei handelt es sich h¨chstwahrscheinlich um einen Browser-Bug. a oMan sieht, dass sich das Bem¨hen des Browsers, Tabellen optimal darzustellen, selbst mit uCSS nicht vollst¨ndig abschalten l¨sst. Viele kleine Tabellen werden folglich schnell, aber a aunsch¨n dargestellt. o5.5.7 Daten ungepuffert schreiben + Tabelle imitierenAnstelle von table-Tabellen k¨nnen div-Elemente benutzt werden, um Tabellen zu imi- otieren. Zelleninhalte werden in div-Bl¨cke gefasst und mit CSS auf die gew¨nschte Breite o ugebracht. So werden Callback-Daten schnell und sauber formatiert dargestellt. EinzigerNachteil ist, dass H¨henangaben fest angegeben werden m¨ssen, da sonst benachbarte Zellen o u(also Zellen in der selben Zeile), nicht gleich hoch sind. Bei table-Tabellen w¨re die H¨he a ooptimal angepasst worden. Abschließend l¨sst sich sagen, dass nur dieser L¨sungsweg dem Callback-Ansatz gerecht a owird und zugleich eine browserunabh¨ngige Darstellung erm¨glicht. a o5.5.8 Asynchrones WartenDer CORBA-Server liefert die Daten, der Browser bzw. das Servlet ist f¨r die Darstellung udieser Daten zust¨ndig. Infolgedessen muss der Server darauf warten, dass die Darstellung abeendet ist, bevor neue Daten geliefert werden k¨nnen. Dieses Warten f¨hrt u.U. zu einem o uPerformanceverlust, n¨mlich genau dann, wenn die Darstellung der Daten mehr Zeit als ihre aLieferung ben¨tigt. Abhilfe schafft hier ein asynchrones Warten. oDie Situation entspricht dem klassischen Erzeuger-Verbraucher-Problem. Der CORBA-Servererzeugt die Daten, das Servlet verbraucht diese. Beide Parteien k¨nnen asynchron laufen. Das oheißt, der Erzeuger muss nicht darauf warten, dass alle Daten verbraucht wurden. Vielmehrlaufen beide Jobs in getrennten Threads. Zur Kommunikation dient eine Queue. Der Erzeugerf¨llt die Queue mit Inhalt, woraufhin der Verbraucher die Queue-Inhalte entnehmen kann. uAuf diese Weise ist es m¨glich, dass der CORBA-Server kontinuierlich Daten liefert kann. oZur Realisierung dieses Models dient die Klasse VListStateThread (6.1.17), die die Verbrau-cherseite darstellt, und die jeweilige Callback-Klasse, die als Erzeuger agiert. Beide Klassen
  • 77. 5.6 Tabsheets 72haben Zugriff auf einen Vector, der die angesprochene Queue implementiert. Die Callback-Klasse erh¨lt vom Server mittels putData()-Aufruf die Daten und schreibt sie in das Vector- aObjekt. Daraufhin informiert sie den VListStateThread, dass neue Daten vorhanden sind.Dieser ubergibt die Daten nun dem passenden VState (6.1.6), einer Klasse, die f¨r die Dar- ¨ ustellung der Daten in Tabellen zust¨ndig ist. Ist die Darstellung komplett, wird uberpr¨ft, a ¨ uob sich weitere Daten in der Warteschlange befinden. Ist dies der Fall, werden auch die-se gelesen und zur Darstellung weitergegeben. Sind keine Daten vorhanden, versetzt sich derVListStateThread in einen Wartezustand und verharrt in diesem, bis er vom CORBA-Serverresp. Callback-Klasse dar¨ber benachrichtigt wird, dass entweder neue Daten vorhanden sind uoder keine Daten mehr folgen. Durch diese asynchrone Verarbeitung beider Seiten braucht einThread keine R¨cksicht auf die Verarbeitungsgeschwindigkeit des Gegen¨bers zu nehmen. u u5.6 TabsheetsAus vielen Desktop-Applikationen sind Tabsheets, die ofmals auch als Reiter oder Register-karte bezeichnet werden, bekannt. Sie ¨hneln optisch einem Kartei-Register und erm¨glichen a oes, auf einer Seite mehrere Informationen gegliedert darzustellen. Da auch VWE regen Ge-brauch von dieser Gliederungsm¨glichkeit macht und der Web-Client nach M¨glichkeit eine o oan die, von der Desktop-Anwendung gewohnte Oberl¨che, angelehnte GUI realisieren soll, amuss nach Wegen gesucht werden, wie eine solche Tabsheet auf einer Internet-Seite darge-stellt werden kann.Als erstes ist festzuhalten, dass HTML keine passende Komponente bietet. Der erste Schrittmuss somit sein, eine grafische Nachbildung einer Karteikarte zu erstellen. Dazu wird dastable-Tag verwendet, dass eine Tabelle darstellt. Dadurch, dass mittels CSS-Angaben nurbestimmte Zellenumrahmungen dargestellt werden, entsteht der Eindruck einer Registerkarte.Abbildung 33 verdeutlicht diese Technik. Abbildung 33: Visualisierung von Tabsheets mit HTML und CSS
  • 78. 5.6 Tabsheets 73 Nachdem die Visualisierung der Tabsheet erreicht wurde, muss diese nun noch mit der o a ¨n¨tigen Funktionalit¨t versehen werden. Beim Anklicken von Register-Uberschriften mussder Inhalt der entsprechenden Karte in den Vordergrund verschoben werden und die anderenKarten verdecken. HTML bietet zwar in neueren Versionen die M¨glichkeiten, entweder sog. oLayer (layer-Tag) zu verwenden, die Schichten einer Seite definieren, oder Blockelemente(div-Tag) ein- und auszublenden, aber solche Darstellungen sind noch nicht in allen g¨ngi-agen Browsern ausgereift und selten kompatibel. Aus diesem Grunde muss jede Registerkarteals eingenst¨ndige Seite dargestellt werden. Folglich gibt es eine Seite, die die Tabsheet mit aaktivierter Karteikarte 1 darstellt, eine Seite, die die Tabsheet mit aktivierter Karteikarte 2darstellt, usw. Da der Inhalt dynamisch erzeugt wird, m¨ssen hierf¨r nicht viele unterschied- u uliche, sondern nur eine einzige Seite erstellt werden. ¨Klickt der Anwender also auf eine Register-Uberschrift, wird die Seite geladen, die den Inhaltdieses Registers anzeigt. Genauer gesagt, wird die aktuelle Seite erneut mit einem Parametergeladen, der angibt, welche Kartei-Karte dargestellt werden soll. Je nachdem, welchen Wertdieser Parameter erh¨lt, erzeugt das Servlet eine andere Ausgabe. aEs bleibt die Frage, wie dieser Parameter aussehen soll und wie er ubergeben werden muss. ¨Als Wert des Parameters bietet sich eine Zahl an, die den Index der Registerkarte angibt.Alle Karten werden einfach fortlaufend durchnummeriert und erhalten so einen eindeutigenIndex. Dieses Vorgehen stellt sicher, dass eine Register-Karte unabh¨ngig von der aktuellen aSpracheinstellung immer den selben Wert ubergibt. W¨rde die Karten¨berschrift ubergeben, ¨ u u ¨w¨re dies nicht m¨glich. Nun liegt es auf der Hand, die Spalten¨berschriften als normale a o uHTML-Verweise zu realisieren, die zus¨tzlich mit dem passenden Query-String-Parameter af¨r den Index versehen sind. Beispielsweise k¨nnte als Spalten¨berschrift der ersten Karte u o ufolgende HTML-Anweisung dienen:<a href="dasGleicheServletNochmalAufrufen?tabsheetindex=0>Erste Karte</a>Das Servlet w¨rde hierbei einfach den Query-String-Parameter tabsheetindex abfragen und unur die Ausgabe f¨r die erste Tabsheet erzeugen. uswitch(getTabsheetIndex) { case 0: // Hier die Ausgabe fuer die erste Karte einfuegen break; case 1: // Hier die Ausgabe fuer die zweite Karte einfuegen break; case 2: // Hier die Ausgabe fuer die dritte Karte einfuegen break; default: // Hier ggf. eine Fehlerseite anzeigen}
  • 79. 5.6 Tabsheets 74Mit diesen Schritten w¨re eine Tabsheet bereits visualisiert und mit der Funktion f¨r das a uUmschalten der Reiter versehen. Es offenbart sich aber ein weiteres Problem. Daten in einerTabsheet eingetragen wurden, gehen durch das Umschalten verloren. Gibt der Anwender bei-spielsweise in der ersten Kartei-Karte die Adresse eines Kunden in das daf¨r vorgesehene Feld uein und wechselt zur Karte f¨r die Bankverbindung, wird die gemachte Angabe verworfen. uDer Grund daf¨r ist, dass das bearbeitende Servlet zwar erf¨hrt, dass die Bankverbindungs- u aKarte angefordert wurde, es weiß aber nicht, welche Seite zuvor bearbeitet wurde. DiesesProblem l¨ßt sich noch leicht dadurch beheben, dass neben dem Parameter f¨r die ange- a uforderte Seite ein weiterer Parameter f¨r die verlassene Seite ubergeben wird. Das folgende u ¨Beispiel zeigt, wie der Link f¨r den ersten Reiter auszusehen hat, wenn man sich auf der udritten Kartei-Karte befindet.<a href="dasGleicheServletNochmalAufrufen?tabsheetindex=0?oldtabsheetindex=2>Erste Karte</a> a a o ¨Jetzt, wo das Servlet zus¨tzlich erf¨hrt, welcher Reiter verlassen wurde, k¨nnen Anderungennoch immer nicht gespeichert werden. Der Grund hierf¨r ist, dass die eingegebenen Daten unicht ubertragen werden. Ein Link f¨hrt einfach zur n¨chten Seite. Vielmehr m¨sste das ¨ u a uFormular, das auf der Registerkarte dargestellt wird, abgesendet werden. Zum Absendenverwendet HTML ausschließlich Buttons und in neueren Versionen zus¨tzlich Bilder. Die aVerwendung von Bildern entf¨llt, da die Spalten¨berschriften an verschiedene Sprachen an- a u a u u ¨gepasst werden m¨ssen. Es w¨re dar¨ber hinaus sehr aufwendig, f¨r jede Karten-Uberschrift ueine Grafik zu erstellen. Auch die Anzeige von Buttons erweist sich als unsch¨n. Buttons als o ¨Tabsheet-Uberschriften wirken nicht nur unpassend, sie sind auch nicht an das bestehendeDesign anpassbar. Abhilfe f¨r diese Misere verschafft ein wenig JavaScript-Code. Die Ver- u ¨weise f¨r die Uberschriften rufen nicht mehr das Servlet, sondern die JavaScript-Funktion utabClicked() auf. Diese Funktion befindet sich in der Datei varial.js, die automatisch injede JSP eingebettet wird.function tabClicked(tabsheetname, tabindex)¨Ubergibt man der Funktion den Namen der Tabsheet (da auf einer Seite mehrere Tabsheetsverwendet werden k¨nnen, m¨ssen sie benannt sein) und den Index der angeklickten o u¨Uberschrift, f¨llt sie versteckte Formularfelder mit diesen Werten und sendet das For- umular. So werden nicht nur die Benutzereingaben, sondern auch die Informationen uber ¨angeklickten und verlassenen Reiter ubergeben. Das Servlet kann sich die Daten merken und ¨entsprechende Ausgaben generieren.Eine Tabsheet wird mit allen n¨tigen versteckten Formularfeldern von der Klasse ocom.varial.gui.TabSheetBean (6.3.20) erzeugt. F¨r den Entwickler bleiben die oben uerl¨uterten Einzelheiten verborgen. Er spezifiziert lediglich mit der API einige Eigenschaften ader Tabsheet, die Ausgabe und Funktionalit¨t wird dann von der Klasse erzeugt. a Nachdem nun gekl¨rt wurde, wie Tabsheets auf der Oberfl¨che dargestellt werden und wie a a ¨das Servlet von Anderungen unterrichtet wird, soll nun darauf eingegangen werden, wie das ¨ ¨Servlet auf die Anderungen reagiert. Insbesondere stellt sich die Frage, wie die Anderungenpersistent gehalten werden. Gibt der Anwender Daten in ein Feld ein und wechselt die u ¨Kartei-Karte d¨rfen die Anderungen an dem BO noch nicht an den Server ubertragen ¨
  • 80. 5.7 Multimedia 75werden. Dieser w¨rde sie in der Datenbank speichern. Dies ist jedoch nicht erw¨nscht, da u uein BO nur dann gespeichert werden soll, wenn der Benutzer dies ausdr¨cklich durch das uentsprechende Men¨-Symbol veranlasst. Tabsheets f¨hren also zu der Notwendigkeit, BOs u utempor¨r auf der Client-Seite zu speichern. aUm diese Anforderung zu realisieren, wurde die Klasse com.varial.base.TempData(6.1.15) entworfen. Sie speichert BOs im session-Objekt. TempData verwaltet hierzu einenHashtable, der der Seite resp. der Servlet-URL das BO zuordnet. Das Servlet holt sich ¨zuerst von TempData das BO entsprechend seiner URL, f¨hrt die Anderungen mit den uSetter-Methoden des BOs durch und veranlasst die TempData-Klasse wieder, das BO inder Session zu speichern. Klickt der Anwender auf den Speicher-Button der Men¨lei- uste, muss nun einfach die commit()-Methode des BOs aus der Session ausgef¨hrt werden. uDas BO wird hierdurch an den CORBA-Server ubergeben, der es in der Datenbank speichert. ¨ Abschließend sei noch erw¨hnt, dass jede JSP-Seite ein verstecktes Formularfeld enth¨lt, a a ¨das zu Beginn den Werte false annimmt. Werden Anderungen in Formularfeldern vor-genommen, rufen diese durch einen passenden Event-Handler die JavaScript-MethodeenableSave() auf. Diese Methode setzt den Wert daraufhin auf true. Dem Servlet ist es o ¨ ¨dadurch m¨glich, abzufragen, ob uberhaupt Anderungen vorgenommen wurden. Ist dies nichtder Fall, muss das BO nicht von TempData angefordert und aktualisiert werden. Reslutat isteine Zeiteinsparung und Performance-Verbesserung des Servlets.5.7 MultimediaNeben der reinen HTML-Erzeugung k¨nnen Servlets weitere Inhalte generieren. Bei VWE obesteht zum Beispiel die Anforderung, Daten grafisch in Form von Diagrammen darzustellen.Außerdem ist ein Datenexport nach Microsoft Excel zu realisieren, damit Tabelleninhaltein Office-Dokumenten weiterverarbeitet werden k¨nnen. Als Letztes soll die Darstellung der oUnternehmensdaten f¨r portable Kleinstger¨te wie Handys und PDAs mittels WAP m¨glich u a osein.5.7.1 MIME-TypenDer Schl¨ssel f¨r die Bereitstellung multimedialer Inhalte liegt in der Verwendung von MIME- u uTypen. MIME steht f¨r Multipurpose Internet Mail Extensions. Die Bezeichnung deutet an, udass MIME-Typen ihren Ursprung im Bereich der eMail hatten. Durch die Versendung vonDateien im Anhang einer Mail ist es notwendig, die einzelnen Teile der Mail zu trennen. Somuss beispielsweise eine angeh¨ngte Bild- oder Zip-Datei von dem eigentlichen Nachrichten- atext getrennt werden. MIME ist eine Konvention dar¨ber, wie der Daten-Typ der einzelnen uTeile beschrieben wird. Mit diesem Schema kann der Software (z.B. dem Mail-Client) mitge-teilt werden, um welche Art von Inhalt es sich bei den n¨chten Bytes handelt. Ein MIME- aType besteht aus zwei Teilen: Einem Haupt- und einem Subtyp. Beide Angaben werdendurch Schr¨gstrich voneinander getrennt. Beispiele f¨r h¨ufig verwendete MIME-Typen sind a u atext/html, image/jpg oder text/plain. Der MIME-Haupttyp erm¨glicht die Einordnung oin eine der folgenden Gruppen:text Textdateien
  • 81. 5.7 Multimedia 76image Grafikdateienvideo Videodateienaudio Sounddateienapplication Dateien, die an ein bestimmtes Programm gebunden sindmultipart mehrteilige Datenmessage Nachrichtenmodel Dateien, die mehrdimensionale Strukturen repr¨sentieren a Die vom Servlet erzeugten Daten werden mit der Angabe des entsprechenden MIME-Typsversehen. So wird dem Client (i.d.R. also dem Web-Browser) mitgeteilt, welche Art von Da-ten ubermittelt werden. Ist ihm dieser Typ bekannt, kann er passend darauf reagieren. Sollte ¨ihm die MIME-Angabe unbekannt sein, f¨hrt dies zu einem Fehler. Die meisten Browser rea- ugieren in einer solchen Situation aber normalerweise damit, einen Dialog anzuzeigen, der demAnwender den Download der Datei vorschl¨gt. aEtwas problematischer ist die Verwendung eines unbekannten MIME-Typens auf der Server-seite. Unbekannte Typen werden in der Regel nicht verarbeitet. Deshalb ist es wichtig, denWeb-Server passend zu konfigurieren, wenn exotische MIME-Typen verwendet werden.5.7.2 BilderzeugungDer VWE-Web-Client soll die M¨glichkeit besitzen, Datenreihen grafisch in Form von Dia- ogrammen zu generieren. Hierzu muss wie bereits erw¨hnt, zuerst der richtige MIME-Type agesetzt werden. Dies wird ublicherweise ein Typ der Gruppe image sein. Nun kann die Packe- ¨te java.awt und javax.swing der Java-API dazu benutzt werden, Bilder zu zeichnen. F¨r udie Realisierung von VWE-Web wurde auf eine Klassenbibliothek namens jChart zur¨ck- ugegriffen, die bei der OpenSource-Sammlung sourceforge.net zu finden ist. Mit Hilfe dieserKlassen k¨nnen Graphen aus ubergebenen Daten erzeugt werden. F¨r die Verwendung im o ¨ uVWE-Umfeld wurde eine spezielle Klasse im com.varial.base-Package entworfen. Sie tr¨gt aden Namen VChartServlet (6.1.5) und dient dazu, den Inhalt von Tabellen grafisch aufzu-arbeiten.Servlets, die von dieser Klasse ableiten, generieren nicht normalen HTML-Code, sondern Bil-der im GIF-Format. Dementsprechend wird hier automatisch der MIME-Type image/gifgesetzt. Die Ausgabe des Servlets kann nun wie eine normale Bilddatei verwendet werden.<img src="servlet/com.varial.testbed.myChartServlet" alt="Ein Graph">Die VWE-Tablib (6.4) stellt einen Tag vgraph (6.4.15) zur Verf¨gung, mit dem sich das uerzeugte Diagramm in eine JSP-Seite einbetten l¨ßt. a
  • 82. 5.7 Multimedia 77 Abbildung 34: Tabellendarstellung in VWE-Web Abbildung 35: Nach Excel exportierte Tabelle5.7.3 ExcelGenau wie die Desktop-Version von VWE soll auch das Web-Interface die M¨glichkeit bie- oten, Tabelleninhalte nach Excel zu exportieren. Abbildung 34 zeigt die Tabellendarstellungin VWE-Web, Abbildung 35 stellt die exportierte Excel-Tabelle dar. Die Klasse GridBean(6.3.16) bzw. DivGridBean (6.3.17) wird deshalb um diese Funktion erweitert. Auch hiermuss zun¨chst der passende MIME-Typ gesetzt werden. In diesem Falle handelt es sich um adie Angabe application/vnd.ms-excel. Sollte Excel auf dem Client-Rechner installiert sein,werden Daten, die das Servlet nach der Angabe dieses MIME-Typs sendet, in der Anwendungangezeigt.Da Excel seit der Office2000-Version die M¨glichkeit bietet, HTML-Tabellen zu importieren, ogestaltet sich das Szenario denkbar einfach. Das Servlet muss nur den MIME-Typ setzen unddie Daten wie gewohnt senden. Nun ist es Aufgabe des Browsers, passend auf den Typ zureagieren, Excel zu ¨ffnen und die Daten in die Anwendung zu importieren. Einziger Unter- oschied auf der Serverseite ist also, dass ein anderer MIME-Type gesetzt wird. Die gesendeten
  • 83. 5.7 Multimedia 78Daten bleiben identisch. ¨Ein solcher Datenexport ließe sich im Ubrigen auch f¨r andere Office-Anwendungen realisie- uren. Auf diese Weise w¨re auch ein Export nach Word oder Outlook m¨glich. Auf Systemen, a oauf denen die passende Software nicht installiert ist (z.B. Linux), w¨rde dem Anwender ein uFenster pr¨sentiert, mit dem die Daten als xls-Datei abgespeichert werden k¨nnen. a o5.7.4 WAPWAP ist die Abk¨rzung f¨r Wireless Application Protocol und definiert ein Protokoll f¨r u u ukabellose Verbindungen. WAP wurde 1998 von den Firmen Ericsson, Nokia, Motorola andUnwired Planet (sp¨ter Phone.com) entwickelt und legt fest, wie Daten in kabellosen Netzwer- aken transportiert werden k¨nnen. Hauptaugenmerk bei WAP ist die Versendung von WML o(Wireless Markup Language). Genau wie sich Internetseiten uber HTTP mit HMTL beschrei- ¨ben lassen, werden WAP-Seiten mit WML erstellt. WML folgt strikt einem XML-Aufbau,was bedeutet, dass die Syntax im Gegensatz zu HTML den Regeln f¨r eine g¨ltige XML- u uDatei entsprechen muss. Dies heißt bespielsweise, dass jedes ge¨ffnete Element geschlossen owerden muss und dass die Verschachtelung von Elementen einer speziellen DTD entsprechenmuss. HTML ist im Vergleich dazu nicht ganz so streng. So wird beispielsweise das br-Tagnormalerweise nicht geschlossen.WAP und WML finden haupts¨chlich Verwendung in Kleinstger¨ten. Beispiele f¨r solche, a a uals Thin Clients bezeichneten, Ger¨te sind Handys, Organizer oder PDAs. Auf Grund der a o ¨kleinen Displaygr¨ße und der sehr geringen Bandbreite bei der Ubertragung k¨nnen hier kei- one normalen Internetseiten ubertragen werden. Dies d¨rfte in Verbindung mit sehr hohen ¨ uPreisen der Grund daf¨r sein, wieso sich WAP bis heute nicht so stark durchgesetzt hat, wie usich Vertreter der Mobilfunk-Industrie dies erhofften.In Analogie zu VWE-Web f¨r den Web-Browser wurde ein weiterer Client f¨r WAP ent- u uworfen. VWE-WAP benutzt hierbei die selbe Architektur wie die Web-Anwendung. Datenwerden auch hier von einem Servlet verwaltet, das die Darstellung einer JSP-Seite uberl¨ßt. ¨ aVWE-WAP kann durch diesen MVC-Ansatz (5.2) die BO-Klassen der Web-Anwendung nut-zen. Hier zeigt sich praxisnah der Vorteil des MVC-Modells.Da WAP im Vergleich zum Internet ein eher unbeachtetes Dasein fristet, soll im Rahmen derDiplomarbeit diese Technologie nur am Rande bearbeitet werden. Außerdem stellt sich dieFrage, inwieweit die eingeschr¨nkte Hardware eine sinnvolle ERP-Anwendung erm¨glicht. a oDennoch soll beispielhaft ein Anwendungsfall umgesetzt werden. Die Implementierung desTaskReminders, also einer Erinnerungsfunktion, erscheint hier vern¨nftig. Die M¨glichkeit, u oFristen und Termin mittels Handy von Unterwegs zu erfragen, erweist sich als durchaus prak-tisch.Wie bereits erw¨hnt soll auch hier die Ausgabe mit einer JSP-Seite erzeugt werden. Bei adieser JSP-Seite sind nun zwei Dinge zu beachten. Erstens muss sie den richtigen MIME-Typ setzten und zweitens muss sie nicht der HTML-, sondern der WML-Syntax entsprechen.Der MIME-Type ist leicht durch die Angabe text/vnd.wap.wml zu setzen. Wichtig hierbeiist zu wissen, dass nicht allen Web-Servern dieser Typ bekannt ist. Unter Umst¨nden muss a ¨deshalb noch eine passende Anderung in der Serverkonfiguration vorgenommen werden. DieBeachtung des zweiten Punktes, n¨mlich die Seite in WML zu schreiben, stellt ebenfalls kein agroßes Problem dar. JSP-Seiten sind, wie bereits bei der Vorstellung der Technologie erw¨hnt a
  • 84. 5.8 Darstellung mit verschiedenen Browsern 79(2.1.2), auf keine besondere Sprache beschr¨nkt. Zwar ist die Hauptanwendung das Erzeugen avon dynamischen HTML, aber es sind durchaus andere Formate wie XML, L TEXoder eben Aauch WML m¨glich. Der Adaption von VWE-Web zu VWE-WAP steht somit nichts mehr oim Wege.5.8 Darstellung mit verschiedenen BrowsernDie Tatsache, dass dem Benutzer eine Vielzahl von unterschiedlichen Browsern (mit diversenEinstellungen), auf verschiedenen Systemen zur Verf¨gung steht, f¨hrt dazu, dass bei der u uDarstellung der Daten dieser Heterogenit¨t Rechnung getragen werden muss. Die Ausgabe asollte auf allen g¨ngigen Browsern fehlerfrei dargestellt werden k¨nnen. Dabei sollte sie a ouberall m¨glichst gleich gestalltet sein, was nat¨rlich nicht ausschließt, dass Features, die¨ o unur ein gewisser Browser unterst¨tzt, nicht ausgenutzt werden sollen, wenn andere Browser uentsprechende Alternativen zur Verf¨gung stellen. u Bei der Erstellung des Web-Interfaces kommen verschiedene Techniken zum Einsatz, diebestimmte Anforderungen an den Web-Browser, der die Daten darstellen soll, stellt. ImSpezielen ist dies die Seitenbeschreibungssprache HTML, die Formatierungssprache CSS, dieProgrammiersprache JavaScript und das Document Object Model (DOM). Im Gegensatz zuanderen clientseitigen Web-Technologien wie beispielsweise Flash handelt es sich bei allenverwendeten Ans¨tzen um Standards. Immer wenn von Internet-Standards die Rede ist, af¨hrt der Weg scheinbar unweigerlich an dem Synonym w3c“ vorbei. Die Abk¨rzung steht u u ”stellvertretend f¨r das World Wide Web Consortium. Ende 1994 gr¨ndete sich das w3c aus u uf¨hrenden Vertretern der Softwareindustrie mit Ziel, die Grundlagen f¨r eine Institution u uzu schaffen, die sich um Standards der neuen Internet-Technologie k¨mmerte. Im Sommer u1995 begann das w3c dann offiziell seine Arbeit. HTML 1.0 wurde der erste Standard desneu gegr¨ndeten Konsortiums. Seither wird jede HTML-Version vom w3c verabschiedet. In uFolge dessen ist man versucht zu behaupten, dass eine standardisierte Auszeichnungsspracheproblemlos auf allen Browsern darstellbar sei. Schließlich liegt den Browser-Herstellern mitdem offiziellen HTML-Standard eine Referenz des Sprachumfangs und deren Umsetzungvor. Die Realit¨t sind jedoch anders aus. Zwischen konkurierende Browser-Hersteller wie aMicrosoft mit dem Internet Explorer auf der einen und Netscape mit ihrem Navigator auf deranderen Seite tobt bereitsseit Jahren einen als Browser-Krieg“ bezeichneter Wettbewerb. ”Im Kampf um Marktanteile scheut man sich nicht davor, den HTML-Standard nacheigenen Bed¨rfnissen zu Formen. Resultat sind browsereigene Tags, also Anweisungen, die uausschließlich im firmeneigenen Browser angezeigt werden und unterschiedliche Wiedergabeder w3c-Norm. Eine einheitliche Darstellung erweist sich in der Realit¨t schon bald als aUtopie.Bei CSS verh¨lt es sich ¨hnlich. Auch CSS steht unter der Kontrolle des w3c (erstmalig im a aJahr 1996 ver¨ffentlicht), aber genau wie bei HTML klaffen zum Teil riesige L¨cken zwischen o uden Umsetzungen in den verschiedenen Browsern. Einige Stylesheet-Angaben funktionierennur in speziellen Browsern und Opera, als die Nummer 3 hinter Microsoft und Netscape,offenbart sogar große Probleme im Umgang mit einigen CSS-Angaben.JavaScript ist im Gegensatz zu HTML und CSS kein unabh¨ngiger Standard. Vielmehr ahandelt es sich um eine 1995 von dem Unternehmen Netscape lizensierte Programmierspra-
  • 85. 5.8 Darstellung mit verschiedenen Browsern 80che. Trotzdem l¨uft JavaScript auch in den meisten anderen Browsern. Selbst der Microsoft aInternet Explorer, dem gr¨ßten Netscape-Konkurenten, unterst¨tzt JavaScript. In Wirklich- o ukeit verbirgt sich hier hinter jedoch die Sprache JScript, die in Anlehnung an JavaScript vonMicrosoft erfunden wurde. Da JScript aber mit nahezu allen JavaScript-Befehlen zurechtkommt, stellt dies in der Praxis keinen Unterschied dar. Unter der Bezeichnung ECMAScriptwurde JavaScript bereits fr¨hzeitig von der Organisation European Computer Manufacturers uAssociation (ECMA) als Industrie-Standard deklariert. Im allt¨glichen Einsatz zeigt sich ahingegen auch bei JavaScript, dass die Software-Hersteller bei der Umsetzung des Standardseigene Wege bestreiten, anstatt sich strikt an die Vorgaben des Standards zu halten.Die letzte und zugleich j¨ngste Technologie stellt DOM dar. Strenggenommen handelt es usich nicht wirklich um eine neue Technologie. DOM wurde eher als Erg¨nzung zu JavaScript aentworfen. In Hinblick auf immer mehr Dynamik in Web-Seiten bestand in den Reihen derJavaScript-Programmier schon fr¨h der Wunsch, auf Teile einer Web-Seite zugreifen und udiese sp¨ter ver¨ndern zu k¨nnen. Die beiden Protagonisten des Browser-Kriegs entwickelten a a odaraufhin zwei verschiedene L¨sungsans¨tze, die dieser Anforderung entsprechen sollten. o aDie Folge war ein doppelter Aufwand, da bei der Realisierung dynamischer Seiten beidenBrowsern Rechnung getragen werden mußte. Das w3c nahm sich dieser Problematik an undver¨ffentlichte schließlich im Oktober 1998 ein als Document Object Model bezeichnetes oModell. Dabei wurde DOM so entworfen, dass nicht nur der JavaScript-HTML-Kombinationber¨cksichtigt wurde. Ziel war es, einen einheitlichen Zugriff auf alle XML-konformen uAuszeichnungssprachen zu erm¨glichen. DOM wird in Zukunft die propriet¨ren Ans¨tze o a aabl¨sen und ein gemeinsames Modell f¨r die mit JavaScript gestallteten Web-Seiten bieten. o uDas Problem bei DOM ist weniger die Nichtbeachtung der Norm. Zwar zeigt sich auch hierdeutlich, dass die Software-Hersteller ihre eigenen Wege gehen, aber die gr¨ßte Schwierigkeit oliegt in der Tatsache, dass einige Browser das DOM-Modell noch gar nicht unterst¨tzen. u Bei der Vorstellung der vier Grundpfeiler einer Web-Applikation zeigt sich deutlich, wieschnell die Architektur ins Wanken ger¨t. Zur L¨sung dieses Problems bieten sich folgende a oM¨glichkeiten: o • Mehrfachprogrammierung F¨r jeden Browser wird eine eigene Version der Software entwickelt. Zu Beginn wird u der Browsertyp abgefragt, so dass die Anfrage sp¨ter an die richtige Seite weitergeleitet a werden kann. Der Nachteil ist ein uberm¨ßiger Programmieraufwand. ¨ a • Suche nach dem kleinsten gemeinsamen Nenner Anstatt f¨r jeden Browser seperate Seiten zu entwerfen, werden bei der Umsetzung nur u Befehle verwendet, die in allen Browsern lauff¨hig ist. Dies f¨hrt in der Regel dazu, a u dass nur wenige, sehr einfache Anweisungen benutzt werden k¨nnen. o • Festlegung auf bestimmte Browser Bei der Entwicklung der Seiten werden nur bestimm- te Browser beachtet. Die Applikation ist f¨r ausgew¨hlte Software optimiert. Andere u a Browser werden ignoriert.Bei der Umsetzung von VWE-Web wurde ein Kombination aus den drei Ans¨tzen verwendet. aZuerst werden alte Browser nicht beachtet. Als Mindestanforderung ergibt sich der Microsoft
  • 86. 5.8 Darstellung mit verschiedenen Browsern 81Internet Explorer ab Version 5.5, der Netscape Navigator ab Version 6.2, Opera ab Versi- ¨on 6.02 und Mozilla ab Version 1.0. Altere Versionen und andere Browser wurden bei derImplementierung nicht ber¨cksichtigt. Weiterhin wurde darauf geachtet, nur Techniken zu uverwenden, die in allen diesen Browsern lauff¨hig sind. Sollte es die Anwendung schließlich aerfordern, werden stellenweise browserspezifische Mehrfachl¨sungen entworfen. o
  • 87. 6 Die VWE-Web-APIDieses Kapitel stellt die neue API f¨r die Erstellung von VWE-Web-Anwendungen vor. uHierzu werden die Klassen der zentralen Packete com.varial.base, com.varial.translation,com.varial.gui und com.varial.taglib aufgezeigt und deren Funktion im einzelnen erl¨utert. aDie Erkl¨rungen beschr¨nken sich teilweise auf wichtige, d.h. h¨ufig verwendete Funktionen. a a aMethoden, die bei der Entwicklung seltener zum Einsatz kommen, werden u.U. nur am Ran-de erw¨hnt oder ganz weggelassen. Die Darstellung ist somit nicht unbedingt vollst¨ndig. a aF¨r eine komplette Auflistung wird auf die Javadoc-Dokumentation der jeweiligen Klassen uhingewiesen.6.1 Das Packet com.varial.baseDas Packet stellt Klassen f¨r die allgemeine Verwendung zur Verf¨gung. u u6.1.1 VServletDie Klasse VServlet wurde von HttpServlet abgeleitet und erweitert diese Klasse um einigen¨tzliche Funktionen. Alle Servlets sollten von dieser Klasse (oder einer ihrer Unterklassen) uabgeleitet werden!Erreicht das Servlet eine Anfrage, wird die doGet()- bzw. die doPost-Methode aufgerufen.Im folgendem werden beispielhaft nur GET-Anfragen behandelt.public void doGet ( HttpServletRequest req, HttpServletResponse res) throws IOException, ServletExceptionIn dieser Methode wird zun¨chst ein VContext-Objekt (6.1.10) erzeugt und anschließend auberpr¨ft, ob der Benutzer erfolgreich ins System eingeloggt ist. Andernfalls wird der Anwen-¨ uder auf die entsprechende Login-Seite weitergeleitet. So wird sichergestellt, dass alle Anfragennur von authorisierten Benutzer erfolgen d¨rfen. Sollte ein Callback (5.5) aktiv sein, so wird udieser gestoppt.Abschliessend wird die Methode getIt() aufgerufen, die den erzeugten VContext erh¨lt. aprotected void getItDiese Methode (oder eine entsprechende Methode einer Unterklasse) sollte uberladen ¨werden. Sicherheitsabfragen und Callback-Handling werden somit automatisch von jeder vonVServlet abgeleiteten Klasse ubernommen. ¨ Weiterhin bietet die Klasse Methoden, um auf Callback-Aufrufe zu reagieren.public synchronized void waitForCallback(VContext ctx)public synchronized void endCallback(VContext ctx) 82
  • 88. 6.1 Das Packet com.varial.base 83Die Methode waitForCallback() wird zu Beginn eines Callback-Vorgangs vom BO auf-gerufen. Das Servlet versetzt daraufhin den aktuellen Thread mit einem wait()-Aufruf ineinen wartenden Zustand. Wird der Callback beendet, wird die endCallback()-Methodeangestossen. Der wartende Thread wird mit der notify()-Anweisung wieder gestartet. Außerdem k¨nnen abgeleitete Klassen Methoden zur Weiterleitung von Anfragen nutzen. oMit sendRedirect() werden Anfragen umgeleitet, indem dem Browser ein 302-HTTP-Fehlercode ( Moved Temporarily“) zusammen mit der neuen Adresse geschickt wird. Dieser ”fordert daraufhin automatisch die neue Seite an.protected static void sendRedirect ( VContext ctx, StringBuffer url)protected static void sendRedirect ( VContext ctx, String url)Mit der forward()-Methode werden ebenfalls Anfragen umgeleitet.protected void forward ( VContext ctx, String url)Jedoch wird nicht der Browser angewiesen, die Seite neu anzufordern, sondern es wirdeinfach die Kontrolle an die angegebene URL ubergeben. ¨Da die forward()-Methode vollst¨ndig auf dem Web-Server behandelt wird, ist sie schneller aals ein Aufruf von sendRedirect(), bei dem Daten zus¨tzlich den Weg vom Web-Server azum Browser und zur¨ck nehmen m¨ssen. Jedoch andert sich bei dem forward()-Befehl die u u ¨URL nicht. Es wird die Original-URL beibehalten, obwohl die Anfrage von einer anderenURL behandelt wird.Deshalb ist darauf zu achten, dass relative Pfadangaben u.U. nicht mehr korrekt sind undggf. angepasst werden m¨ssen. u Die letzte Art, die Verarbeitung umzuleiten, besteht in der Verwendung der MethodeforwardToJsp().protected void forwardToJsp ( VContext ctx, String url)protected void forwardToJsp ( VContext ctx,
  • 89. 6.1 Das Packet com.varial.base 84 String url, MenuBarBean menu)Diese Methoden werden von Servlets benutzt, nachdem mit dem GuiHelper() (6.3.1) alleKomponenten erzeugt wurden und die Ausgabe an die JSP weitergeleitet werden soll.Erzeugt das Servlet eine Men¨-Leiste (6.3.21), die sich von dem Standard-Men¨ unterschei- u udet, so kann diese mit der zweiten Methode mit ubergeben werden. ¨ Generiert ein vom VServlet abgeleitetes Servlet einen Link, so muss die Session-ID auchin diesem Link vorhanden sein (siehe HTTP-Sessions 5.3). Andernfalls w¨rde die Anfrage unicht mehr einer Session und damit einem Benutzer zuordbar sein. Resultat w¨re ein verwei- agerter Zugriff, da der Benutzer, der die Seite anfordert, aus Sicht des Servlets nicht eingeloggtw¨re. aUm einen Link oder allgemein eine Adresse mit der Session-ID zu versehen, sollten die Me-thoden encodeURL() bzw. encodeRedirectURL() verwendet werden.protected static String encodeURL ( VContext ctx, String url)protected static String encodeRedirectURL ( VContext ctx, String url}¨Ubergeben wird neben dem VContext() die Adresse, die um die Session-ID erweitert werdensoll. Die Methoden liefern die Adresse zusammen mit der jeweiligen Session-ID zur¨ck. u6.1.2 VListServletDas VListServlet wurde vom VServlet abgeleitet und bildet wiederum eine Oberklasse f¨r ualle Servlets, die eine Listenansicht definieren.Die Methoden getIt() bzw. postIt() vom VServlet wurden hier uberladen. ¨Beim Aufruf wird zun¨chst der TempData-Speicher (6.1.15) geleert, da die Anforderung einer aListenansicht ein hinreichendes Zeichen daf¨r ist, dass die Detailansicht verlassen wurde. uWeiterhin wird uberpr¨ft, ob Benutzer-Ereignisse verarbeitet werden m¨ssen. Hierzu wird ¨ u uzun¨chst die Methode catchOwnActionEvents() aufgerufen. aprotected boolean catchOwnActionEvents(VContext ctx)Sollte ein Servlet uber die Standard-Men¨punkte hinaus noch weitere Funktionen definieren, ¨ uso kann diese Methode uberladen werden, um passend darauf zu reagieren. Soll das Servlet ¨normal fortfahren, muss false zur¨ckgegeben werden, wird die Verarbeitung dagegen nicht uwie gewohnt fortgef¨hrt (z.B. bei redirect() auf neue Seite), muss der R¨ckgabewert true u usein.
  • 90. 6.1 Das Packet com.varial.base 85Danach uberpr¨ft das VListServlet, ob ein Men¨-Ereignis vorliegt, also ob der Benutzer ¨ u ueinen Standard-Men¨punkt angeklickt hat. uDie einzige Aktion, die in der Listenansicht vorliegen kann, ist die Erzeugung eines neuen BOs.In diesem Fall w¨rde in die Detail-Ansicht gesprungen. Sind keine Ereignisse zu verarbeiten, uwird die Kontroll an die Funktion getItList() ubergeben. ¨protected void getItList (VContext ctx)Diese Methode sollte von einem Servlet, dass eine Listen-Ansicht implementiert, uberladen ¨werden.6.1.3 VDetailServletWas das VListServlet f¨r die Listen-Ansicht ist, ist das VDetailServlet f¨r die Detail- u uAnsicht. Servlets, die von VDetailServlet abgeleitet werden, reagieren bereits auf Ereig-nisse der GUI-Komponenten und besitzen eine Men¨-Leiste mit allen g¨ngigen Funktionen u awie Speichern, L¨schen, BO-Navigation etc. Es ist ebenfalls von VServlet abgeleitet und ouberl¨dt auch die Methoden doGet() bzw. doPost().¨ aAuch hier wird getestet, ob auf Benutzer-Ereignisse reagiert werden muss. Abgeleitete Servletsk¨nnen genau wie beim VListServlet die Methode catchOwnActionEvents() uberladen. o ¨Allerdings ist zu beachten, dass diese Methode im VDetailServlet() einen weiteren Para-meter besitzt:protected boolean catchOwnActionEvents( VContext ctx, boolean saveConfirmedShowed)Mit dem zweiten Parameter wird angegeben, ob zuvor ein Dialog angezeigt wurde, der denBenutzer warnt, dass die gemachten Angaben noch nicht gespeichert wurden. Ist dieser Pa- ¨rameter false und w¨rde die Verarbeitung des Ereignis die Anderungen verwerfen, ist zuvor udie Methode showSaveConfirm() aufzurufen.protected static void showSaveConfirm ( VContext ctx, String action)Dieser Methode ubergibt man die Aktion, die ausgef¨hrt werden sollte. Es wird ein ¨ uDialog gezeigt, der den Benutzer fragt, ob die Daten zuvor gespeichert werden sol-len und f¨hrt danach die Aktion erneut auf. Diesmal wird jedoch false als zweiter ucatchOwnActionEvents()-Parameter ubergeben, was anzeigt, dass der Benutzer bereits ¨gewarnt wurde. Das VDetailServlet verarbeitet außerdem selbstst¨ndig alle weiteren aEreignisse, die von den GUI-Komponenten wie z.B. der Men¨-Leiste, von Button-Feldern uoder List-Boxen ausgel¨st werden. o Damit das VDetailServlet einige Funktionen wie beispielsweise das L¨schen oder Spei- ochern von BOs ubernehmen kann, m¨ssen die abgeleiteten Klassen die Funtionen fillBO() ¨ uund getBO() implementieren.
  • 91. 6.1 Das Packet com.varial.base 86protected abstract BO getBO (VContext ctx);protected abstract BO fillBO (VContext ctx);getBO() liefert das BO, das gerade bearbeitet wird. Auch fillBO() liefert das aktuelle BO,f¨llt es aber zuvor noch mit den letzten Benutzereingaben. uBeim L¨schen eines BOs ist es ausreichend, das BO mit getBO() (ohne die neusten Ande- o ¨rungen) zu holen. Soll es jedoch gespeichert werden, muss das BO erst an die Eingaben, dievom Benutzer gemacht wurden, angepasst werden.Abschliessend gibt die getIt()-Methode die Kontrolle an getItDetail() ab.proteted void getItDetail (VContext ctx)Diese Methode sollte von einem Servlet, dass eine Detail-Ansicht implementiert, uberladen ¨werden.6.1.4 VSelectServletDie Klasse VSelectServlet ist zust¨ndig f¨r den Entwurf von Auswahl-Dialogen. Entspre- a uchende Servlets sollten von ihr abgeleitet werden. Genau wie die Klassen VListServlet undVDetailServlet ist VSelectServlet von VServlet abgeleitet und uberl¨dt die Methoden ¨ agetIt() und postIt().Die Klasse sorgt daf¨r, dass Abbr¨che durch den Cancel-Button automatisch zu einer Weiter- u uleitung an das aufrufende Servlet f¨hren. Andernfalls werden die Methoden getItSelect() ubzw. getItSelect() aufgerufen, die die Funktionalit¨t in der abgeleiteten Klasse implemen- atieren sollten.proteted void getItSelect (VContext ctx)6.1.5 VChartServletDie Klasse VChartServlet ist ebenfalls von VServlet abgeleitet und dient zur Erstellungvon Diagrammen. Beim Aufruf durch doGet() oder doPost() wird ein Diagramm erstelltund als JPG-Bild an den Browser geschickt.Um ein Diagramm zu erstellen sind einige Methoden in der abgeleiteten Klasse zu uberladen. ¨protected abstract String getXAxisTitle(VContext ctx);protected abstract String getYAxisTitle(VContext ctx);protected abstract String getTitle(VContext ctx);protected abstract String[] getXAxisLabels(VContext ctx);protected abstract String[] getLabels(VContext ctx);protected abstract double[][] getData(VContext ctx);public abstract int getWidth();public abstract int getHeight();Die Methoden getXAxisTitle() und getYAxisTitle() spezifizieren die Beschriftungen derAbzisse bzw. der Ordinate, die Methode getTitle() liefert den Titel des Diagramms.Mit getXAxisLabels() k¨nnen die Abschnitts-Bezeichnungen auf der Abzisse angegeben wer- oden. Beispielsweise k¨nnte getXAxisTitle() “Zeit“ zur¨ckgeben und getXAxisLabels() o u
  • 92. 6.1 Das Packet com.varial.base 87einen String-Array mit den Monaten Jan“, Feb“, Mrz“, etc. liefern. ” ” ”Um die Beschriftung der Datenreihen f¨r eine Legende anzugeben, muss die Funktion ugetLabels uberladen werden. Die Funktion liefert einen String-Array, bei dem der erste ¨String (also Index 0) die Bezeichnung der ersten Datenreihe ist usw. (siehe auch n¨chste aFunktion getData()).Mit der Funktion getData werden die eigentlichen Diagramm-Werte angegeben. Die Werteta-belle wird als zweidimensionale Matrix von double-Werten angegeben. Die erste Dimensionsteht hierbei f¨r die Datenreihe, die zweite f¨r die Werte. u uSollen z.B. die Sinus- und Kosinus-Funktion dargestellt werden, w¨re vereinfacht folgende aMatrix n¨tig: odouble[][] matrix = new double[2][9];// Sinus ist erste Datenreihe (Index = 0)matrix[0] = new double[] {0.0, 0.7, 1.0, 0.7, 0.0, -0.7, -1.0, -0.7, 0.0};// Kosinus ist zweite Datenreihe (Index = 1)matrix[1] = new double[] {1.0, 0.7, 0.0, -0.7, -1.0, -0.7, 0.0, 0.7, 1.0};getLabels() w¨rde in diesem Fall folgendes liefern: unew String[] {"Sinus-Werte", "Kosinus-Werte"};Mit den ubrigen Funktionen getWidth() und getHeight() kann die Gr¨ße des Bildes ¨ oangegeben werden. Die Angabe erfolgt in Pixel. Sollen bestimmte Farben f¨r die Darstellung der Balken verwendet werden, k¨nnen diese u omit der Methode getColor() angegeben werden.protected Color getColor(int index);Als Parameter wird der Index der Wertereihe (im Bespiel also 0 f¨r Sinus, 1 f¨r Kosinus) u uerwartet. Wird diese Methode nicht uberladen, w¨hlt VChartServlet selbstst¨ndig sich un- ¨ a aterscheidende Farben aus.6.1.6 VStateDie Klasse VState ist zust¨ndig f¨r die Ausgabe von Tabellen. Sie ist eine direkte Unterklasse a uvon VServlet und uberl¨dt die Methoden getIt() und postIt(). ¨ aUm eine Tabelle anzuzeigen, muss diese als erstes in einem vom VServlet abgeleiteten Servletmit dem GuiHelper (6.3.1) erzeugt worden sein. Mit der Klasse VState wird diese nun gef¨llt, uverwaltet und formatiert. Im einzelnen sind dazu folgenden Methoden wichtig:protected GridBean getGrid (VContext ctx)Dies liefert die Tabelle, die ausgegeben werden soll. Wird diese nicht uberladen, liefert die ¨Methode eine neue Instanz der Klasse GridBean (6.3.16), bzw. f¨r den Fall, dass es sich hier uum einen Callback (5.5) handelt, eine neue Instanz der Klasse DivGridBean (6.3.17). Dies ¨ist in den meisten F¨llen ausreichend. Uberladen werden muss diese Methode somit nur in aAusnahmef¨llen, z.B. wenn zuvor spezielle Methoden der Tabelle aufgerufen werden m¨ssen. a u
  • 93. 6.1 Das Packet com.varial.base 88protected boolean isCallback()Auch diese Methode muss in den seltensten F¨llen uberladen werden. Sie gibt an, ob es sich a ¨um einen Callback (5.5) handelt. Wird sie nicht uberladen, liefert sie false. Deshalb muss ¨sie nur uberladen werden, wenn die Tabelle mittels Callback aufgebaut wird. ¨protected abstract void writeData ( VContext ctx, GridBean grid);Mit dieser Methode wird die Tabelle mit Inhalt gef¨llt. Die Methode addRow() der uberge- u ¨benen GridBean kann vom angeleiteten Servlet dazu genutzt werden, Daten anzuf¨gen. uprotected void putDataRows ( VContext ctx, Object obj)Diese Methode muss ausschließlich bei der Verwendung von Callbacks uberladen werden. ¨ ¨Sie wird beim Empfang neuer Daten aufgerufen. Der Ubergabeparameter obj enth¨lt diese aDaten. Das abgeleitete Servlet muss also erst ein Casting vornehmen, um den richtigen Typezu erhalten und kann dann die Tabelle mit deren Methode addRow() um die neuen Datenerweitern. Um die Tabelle zu formatieren stehen eine ganze Reihe von Methoden zur Verf¨gung, die udie Tabelleneigenschaften festlegen.public abstract int getStyle();Gibt an, um welche Art von Tabelle es sich handelt. Tabellen finden Anwendung in Listen-Ansicht, Detail-Ansicht und Auswahl-Dialogen. Der Typ wird i.d.R. in einer der abgeleitetenKlassen VListState (6.1.7), VDetailState (6.1.8) und VSelectState (6.1.9) festgelegt, sodass der Entwickler diese Eigenschaft normalerweise nicht angeben muss, sondern die State-Klasse lediglich von der passenden Oberklasse ableiten muss.public String getID()Mit dieser Methode wird der Tabelle eine eindeutige Bezeichnung zugewiesen. Diese Bezeich-nung muss pro Seite eindeutig sein. Zwei Tabellen, die auf unterschiedlichen Seiten (alsoauch auf unterschiedlichen Tabsheets) angezeigt werden, k¨nnen deshalb durchaus die selbe oID haben. Wird die Methode nicht uberladen wird standardm¨ssig die ID grid verwendet. ¨ apublic boolean isEditable( VContext ctx, int row, int col)
  • 94. 6.1 Das Packet com.varial.base 89Gibt an, ob eine Tabellen-Zelle in der Reihe row und der Spalte col editierbar ist. PerStandard ist sie dies nicht. Wird true zur¨ckgegeben, wird der Zelleninhalt in einem Textfeld uangezeigt, ansonsten erscheint er als normaler Text.public boolean isEnable( VContext ctx, int row, int col)Gibt an, ob eine Tabellen-Zelle in der Reihe row und der Spalte col bearbeitet werden kann.Per Standard ist sie dies nicht. Sinn dieser Methode ist es, Zellen, die mit isEditable()grunds¨tzlich ver¨nderbar gemacht wurden, kurzfristig zu deaktivieren. a apublic int getEditor ( VContext ctx, int row, int col)Liefert die Art des Zelleninhaltes in Reihe row und Spalte col. M¨gliche Werte sind: o • public final static int TEXTFIELD Normales Textfeld (siehe auch 6.3.3 LabeledTextField). • public final static int COMBOBOX Combo-Box (siehe auch 6.3.11 LabeledComboBox). • public final static int EDITCOMBOBOX Combo-Box, deren Eintr¨gea jedoch editierbar sind (siehe auch 6.3.12 LabeledEditableComboBox). • public final static int CHECKBOX Check-Box (siehe auch 6.3.9 LabeledCheckBox) • public final static int PASSWORD Feld f¨r Passworteingabe. u • public final static int NUMBERFIELD Feld, in dem ausschließlich Zahlen eingegeben werden k¨nnen (siehe auch 6.3.4 o LabeledNumberField). • public final static int NUMBERFIELD_INT Zahlenfeld wie oben, jedoch nur f¨r ganze Zahlen. u • public final static int DATEFIELD Feld f¨r Datumseingabe (siehe auch 6.3.6 LabeledDateField). u
  • 95. 6.1 Das Packet com.varial.base 90 • public final static int CURRENCYFIELD Feld f¨r Eingabe eines Geldbetrages (siehe auch 6.3.5 LabeledCurrencyField). u • public final static int CURRENCYFIELD_WITHOUT_CODE Wie oben, jedoch wird hier nicht die W¨hrungsbezeichnung (z.B. das Euro-Zeichen) a angezeigt. • public final static int RADIOBUTTON Auswahllistenfeld, bei dem nur ein Eintrag selektiert sein darf (siehe auch 6.3.10 LabeledRadioButton). • public final static int BUTTONFIELD ; Text-Feld mit Drei-Punkte-Button (siehe auch 6.3.8 LabeledButtonField).public String getTextAlign ( VContext ctx, int row, int col)Gibt die Ausrichtung des Textes in der Zelle an. Standardm¨ssig liefert die Methode null, awas bedeutet, dass die Ausrichtung gem¨ß des Zellentypes erfolgt. Zahlen und W¨hrungen a awerden rechtsb¨ndig, Datumsangaben, Combo- und Radio-Boxen zentriert und alle anderen uInhalte linksb¨ndig ausgerichtet. upublic String[] getComboList ( VContext ctx, int row, int col)Gibt die Eintr¨ge an, die in der Zelle erscheinen soll, wenn es sich um eine Combo-Box ahandelt.public boolean lineBreak( VContext ctx, int row, int col)Gibt an, ob ubergroße Inhalte umgebrochen werden sollen. Per Standard geschieht dies. ¨public boolean hasSelectionCol()Gibt an, ob die Tabelle vor der ersten Spalte eine weitere Spalte mit Check-Boxen enth¨lt, mit adenen man Zeilen f¨r den L¨schvorgang ausw¨hlen kann. Standardm¨ßing wird eine solche u o a aSpalte nicht angezeigt.
  • 96. 6.1 Das Packet com.varial.base 91public String[] getHeaders( VContext ctx)Liefert die Spalten¨berschriften. upublic int[] getColWidth( VContext ctx)Liefert die Spaltenbreite in Pixel. Wird diese Methode nicht uberladen, wird null zur¨ckgege- ¨ uben. Die Spaltenbreite wird dann optimal an die L¨nge der Eintr¨ge angepasst. Die Methode a asollte nur uberladen werden, wenn eine DivGridBean (6.3.17) verwendet wird. Sonst ist die ¨Spaltenoptimierung vorzuziehen.public Object getDefaultCellValue( VContext ctx, int row, int col)Gibt den Inhalt an, den die Zelle automatisch annimmt, wenn eine neue Zeile eingef¨gt uwird. Die Methode gibt null zur¨ck, so dass folgende Werte bei neuen Zeilen eingetragen uwerden: Check- und Radio-Boxen sind deaktiviert, bei Datumsfeldern wird das aktuelleDatum eingetragen, alle anderen Felder sind leer. Sollen sich die Zellen von neu eingef¨gten uSpalten anders verhalten, kann diese Methode uberladen werden. ¨public CurrencyBO getCurrency( VContext ctx, int row, int col)Gibt die W¨hrung an, die verwendet wird, wenn es sich bei der angegebenen Zelle um ein aW¨hrungsfeld handelt. Der Zelleninhalt wird gem¨ß den W¨hrungseigenschaften (Nachkom- a a amestellen, Rundungsverfahren, W¨hrungszeichen etc.) formatiert. Standardm¨ssig liefert die a aMethode die Hausw¨hrung der aktuellen Firma. a6.1.7 VListStateDie Klasse VListState wurde von VState abgeleitet. Alle Servlets, die f¨r die Bearbeitung uvon Tabellen in der Listenansicht zust¨ndig sind, sollten wiederum von dieser Klasse abge- aleitet werden.Die Klasse besitzt als einzige Methode getStyle(), die angibt, dass es sich um eine Listen-ansicht handelt. Sie ist als final deklariert und kann somit von Unterklassen nicht ver¨ndert awerden.
  • 97. 6.1 Das Packet com.varial.base 926.1.8 VDetailStateVDetailState ist ebenfalls von VServlet abgeleitet und ist f¨r Tabellendarstellung in der uDetail-Ansicht zust¨ndig. Auch hier wird die Methode getStyle() uberladen und gibt in a ¨diesem Fall an, dass die Tabelle in einer Detail-Ansicht verwendet wurde.Weiterhin wird die Methode hasSelectionRow() uberladen, die jetzt true zur¨ckgibt, da ¨ udie meisten Tabellen in der Detail-Ansicht eine L¨schfunktion besitzen und dementsprechend oeine Auswahlspalte brauchen.Als letzte Methode enth¨lt die Klasse die zus¨tzliche Hilfs-Methode getCellName(). a aprotected String getCellName (int row, int col)Mit Hilfe dieser Methode k¨nnen abgeleitete Klassen den Namen von Formularfeldern aus oder Tabelle erfragen. Hat eine Tabelle z.B. die ID mygrid wird der Wert der Zelle in der 3Zeile und 5 Spalte als mygrid 2 4 im Query-String ubertragen. Genau diese Angabe liefert ¨die Methode.6.1.9 VSelectStateAuch die Klasse VSelectServlet wurde von VServlet abgeleitet. Genau wie VListStateund VDetailState uberl¨dt auch sie die Methode getStyle(). Diese gibt hier die Infor- ¨ amation zur¨ck, dass die Tabelle in einem Auswahl-Dialog Verwendung findet. Dementspre- uchend sollten alle Servlets, die f¨r Tabellen in solchen Auswahldialogen zust¨ndig sind, von u aVSelectState ableiten.Außerdem uberl¨dt die Klasse die Methode getGrid(). Hier wird im Gegensatz zur Super- ¨ aklasse VState nicht nur eine neue Instanz einer Tabelle zur¨ckgeliefert, sondern es werden unoch die Methoden setBackURI() und addQueryString aufgerufen. Dies ist notwendig, weileine Tabelle in der Auswahl-Ansicht Links auf das aufrufende Servlet enth¨lt. Diese Links awerden u.a. mit diesen beiden Methoden konstruiert.6.1.10 VContextDas VContext-Objekt ist zentraler Bestandteil der VWE-Web-Architektur. Es erm¨glicht es, oauf einfache Weise auf alle f¨r die Anwendung relevanten Daten zuzugreifen. So stellt der uVContext beispielsweise Methoden f¨r das Parameter-Handling zur Verf¨gung, kontrolliert u uden Zugriffsschutz auf Daten oder koordiniert den Callback-Mechanismus (5.5).Beim Aufruf eines VServlets (6.1.1) wird automatisch ein VContext erzeugt. Dieser wirddann an die entsprechende Methode zur Verarbeitung einer Anfrage weitergegeben.Erzeugen eines VContexts Die Klasse VContext stellt zwei Konstruktoren zur Verf¨gung. uIm Normalfall sollte eine Instanz mit dem dreiparametrigen Konstruktor erzeugt werden:public VContext( HttpServlet servlet, HttpServletRequest req, HttpServletResponse res)
  • 98. 6.1 Das Packet com.varial.base 93¨Ubergeben wird neben dem aufrufenden Servlet das Request- und das Response-Objekt. DerKonstruktor initialisiert darauf hin alle n¨tigen Objekte, um sp¨ter auf Cookies, Parameter, o aSession- und Request-Attribute zugreifen zu k¨nnen. oDer Konstruktor sollte nicht direkt aufgerufen werden! Dies geschieht automatisch beim Auf-ruf eines VServlets (6.1.1). Dort wird ein VContext erzeugt und an die entsprechendenMethoden f¨r das Verarbeiten der Anfragen weitergegeben. uDer zweite Konstruktor erwartet nur einen Parameter, n¨mlich ein HttpSession-Objekt: apublic VContext (HttpSession session)Dieser Konstruktor sollte ausschließlich in Ausnahmef¨llen aufgerufen werden, in denen auf akeine andere Weise ein Zugriff auf ein VContext-Objekt m¨glich ist. Ein VContext, der auf odiese Weise erzeugt wurde, kann nur f¨r den Zugriff auf Session-Attribute verwendet werden. uEine Anwendung, die den Einsatz dieses Konstruktors rechtfertigt, findet sich z.B. in der Klas-se com.varial.taglib.LanguageString. Hier wird der VContext lediglich dazu gebraucht,um das AccessToken aus der Session zu holen. Da die Erzeugung mit dem ersten Konstruk-tor an dieser Stelle nicht m¨glich ist und keine weiteren Methoden des VContext aufgerufen owerden, kann hier der Notfall-Konstruktor verwendet werden. Eine solche Verwendung solltejedoch stets die Ausnahme bleiben.Attribute-Handling Der VContext erm¨glicht es, auf einfache und einheitliche Weise, auf oAttribute zuzugreifen. So k¨nnen Informationen auf folgenden Bereichen verarbeitet werden: osession-Objekt, application-Objekt, Parameter aus Query-String, Request-Objekt, Coo-kies und Initialisierung-Parameter aus der Konfigurations-Datei web.xml.Um anzugeben, woher ein Attribute gelesen bzw. wohin es geschrieben werden soll, definiertdie Klasse folgende Konstanten:public final static int SESSION = 0;public final static int APPLICATION = 1;public final static int PARAMETER = 2;public final static int PARAMETERS = 3;public final static int REQUEST = 4;public final static int COOKIE = 5;public final static int INIT = 6;Um den Unterschied zwichen PARAMETER und PARAMETERS zu erl¨utern, sei gesagt, dass ein aParameter mehrmals im Query-String vorkommen kann. PARAMETER liefert in diesem Fallden ersten, w¨hrend PARAMETERS eine String-Array mit allen Werten zur¨ckgibt. a u Um einen Parameter zu lesen, kann die Methode getAttribute() aufgerufen werden.public Object getAttribute( int scope, String name)
  • 99. 6.1 Das Packet com.varial.base 94Sie erwartet als ersten Parameter eine Angabe dar¨ber, woher das Attribute gelesen werden usoll. Hierzu dienen die bereits beschriebenen Konstanten. Als zweiter Parameter wird derName des Attributes erwartet.Beispiel: Lesen eines Cookies mit dem Namen Last visit“: ”Object lastVisitCookie = ctx.getAttribute(VContext.Cookie, "Last visit");Die Methode liefert ein Objekt der Klasse Object zur¨ck bzw. null, wenn das Attribut unicht gefunden wurde. Wird ein unbekannter Bereich ubergeben, wirft getAttribute() eine ¨VException (6.1.14).Weiterhin kann mit der Methode hasAttribute() abgefragt werden, ob ein entsprechendesAttribute vorhanden ist:public boolean hasAttribute( int scope, String name)Der Aufruf liefert true, falls ein Attribute mit dem angebenen Namen im entsprechendenBereich existiert, andernfalls false.Außerdem kann mit hasNonEmptyAttribute() abgefragt werden, ob ein Attribute existiertund einen Wert ungleich einem Leerstring besitzt.public boolean hasNonEmptyAttribute( int scope, String name)Der Aufruf liefert true, falls ein Attribute mit dem angebenen Namen im entsprechendenBereich existiert und dieses kein Leerstring ist, andernfalls false.Um nicht jedesmal die Existenz eines Attributes zu uberpr¨fen und auf ein Fehlen entspre- ¨ uchend zu reagieren, bietet der VContext ebenfalls eine getAttribute()-Methode, die beierfolgloser Suche einen Standardwert zur¨ckgibt. Sie erwartet zus¨tzlich zur oben genannten u aMethode einen dritten Parameter, der einen Default-Wert spezifiziert:public Object getAttribute( int scope, String name, Object defaultValue)Hier wird defaultValue zur¨ckgeliedert, falls kein Attribute gefunden wird. u Durch den R¨ckgabetyp Object k¨nnen s¨mtliche Klassen gelesen werden. Im Anschluss u o amuss lediglich ein Casting in den entsprechenden Typ stattfinden.H¨ufig m¨ssen Objekte des Typs String gelesen werden. a uString lastVisitCookie = (String)ctx.getAttribute(VContext.Cookie, "Last visit");
  • 100. 6.1 Das Packet com.varial.base 95Um diesen Aufruf zu vereinfachen, stellt der VContext eine spezielle MethodegetStringAttribute() zur Verf¨gung: upublic String getStringAttribute( int scope, String name)Auch hier gibt es eine Variante mit Default-Wert:public String getStringAttribute( int scope, String name, String defaultValue)Weiterhin gibt es die Methoden getIntAttribute(), die ein int liefert,getShortAttribute(), die einen short liefert und getBooleanAttribute(), die einboolean zur¨ckgibt. Auch diese drei Methoden k¨nnen mit einem dritten Parameter u oaufgerufen werden, der den Default-Wert angibt.Die Methoden getDateAttribute() und getCurrencyAttribute() lesen ein Attribut undformatieren es anschließend in einen f¨r den CORBA-Aufruf geeignetes Textformat, liefern ualso einen String zur¨ck. uLautet der Query-String z.B. ?birthday=22.05.1978“, liefert der Aufruf ”ctx.getDateAttribute(VContext.PARAMETER, "‘birthday"’)die Angabe 1978-05-22“. ”Geschrieben werden Attribute mit der Methode setAttribute():public void setAttribute( int scope, String name, Object obj)Neben dem Bereich und den Namen des zu schreibenden Attributes wird der Wert erwartet.Dieser ist vom Typ Object. Es k¨nnen also auch hier alle Typen ubergeben werden. Zu o ¨beachten ist allerdings, dass Cookies nur Zeichenketten speichern k¨nnen. Aus diesem Grun- ode wird beim Speichern eines Cookies immer der R¨ckgabewert der Methode getString() ugespeichert.Sowohl Query-String- als auch Initialisierungs-Attribute k¨nnen nicht geschrieben werden. oHier ist nur ein lesender Zugriff m¨glich. In diesem Fall wird eine VException geworfen. o Attribute, die geschrieben werden k¨nnen, k¨nnen auch wieder entfernt werden. Hierzu o odient die Funktion removeAttribute():
  • 101. 6.1 Das Packet com.varial.base 96public void removeAttribute( int scope, String name)Der VContext bietet neben diesen Methoden noch die M¨glichkeit, auf spezielle Parameter ozuzugreifen. So kann z.B. mit hasChanged() abgefragt werden, ob der Parameter changedgesetzt wurde.Tabelle 1 zeigt, welche Methoden welche Parameter abfragen. Da diese Methoden oft zus¨tz- alich Konsistenzbedingung pr¨fen oder auf Fehler reagieren, sollten sie stets der direkten uAttribute-Abfrage vorgezogen werden. F¨r das Arbeiten mit dem Query-String einer Anfrage stellt die Klasse zwei weitere Funk- utionen zur Verf¨gung. upublic String constructQueryString()public String getExtraParameters()Die Funktion constructQueryString() erzeugt einen Query-String mit allen wichtigen Pa-rametern wie beispielsweise oiddetail, boindex oder tabsheetindex. Werden im Pro-gramm Links konstruiert, sollte der Query-String mit dieser Methode erzeugt werden.Die Funktion getExtraParameters() erzeugt einen Query-String, der alle Parameter erh¨lt, adie dem Servlet zu Beginn uber den Men¨baum mitgegeben wurden. VWE erlaubt es im ¨ uAdministrationsmodus die Men¨b¨ume zu ver¨ndern und ggf. zus¨tzliche Parameter zu uber- u a a a ¨geben.Zugriffsschutz Der VContext regelt den gesch¨tzten Zugriff auf alle Dokumen- ute. Dazu wird nach erfolgreicher Anmeldung des Benutzers von dem Servletcom.varial.administration.LoginServlet die Methode setAccessToken() aufgerufen:public void setAccessToken (AccessToken token)Das ubergebene AccessToken kann mit getAccessToken() wieder abgerufen werden: ¨public AccessToken getAccessToken ()Auf diese Weise kann den BOs beim Aufruf einer Server-Methode das VContext-Objektubergeben werden. Das BO wiederum erh¨lt mit getAccessToken() das n¨tige AccessToken¨ a of¨r den Server-Aufruf. u Um zu uberpr¨fen, ob die Seite, von einem eingeloggten Benutzer angefordert wurde, wird ¨ udie Methode checkLogin() aufgerufen.public void checkLogin()throws AccessDeniedException, IOExceptionSollte der Benutzer nicht eingeloggt sein, wird eine AccessDeniedException() geworfen undder Zugriff verweigert. Das VServlet (6.1.1) ruft diese Methode automatisch auf, so dass keinexplizieter Aufruf erforderlich ist.
  • 102. 6.1 Das Packet com.varial.base 97 Methode Parameter Bedeutung getOidParent() oidparent ObjectID des Parent- Objektes getOidCompany() oidcompany ObjectID der aktuellen Firma getTabsheetindex() tabsheetindex Index des aktuellen Tabsheet- Registers getOldTabSheetIndex() oldtabsheetindex Index des vorherigen Tabsheet-Registers getOidDetail() oiddetail ObjectID des aktuellen BOs getBoIndex() boindex Index des aktuellen BOs in der Navigations-Reihenfolge isNew() oiddetail.equals() ¨ Uberpr¨fung, ob BO gerade u erzeugt wurde getOidSelected() oidselected ObjectID des ausgew¨hlten a BOs aus Select-Dialog hasOidSelected() oidselected ¨ Uberpr¨fung, ob ein BO u im Select-Dialog ausgew¨hlt a wurde hasChanged() changed ¨ Uberpr¨fung, ob BO ge¨ndert u a wurde isEnableSave() enablesave ¨ Uberpr¨fung, ob BO ge¨ndert u a wurde, so dass gespeichert werden kann getAction() action Aktuell ausgew¨hlte Aktion a hasAction() action ¨ Uberpr¨fen, ob eine Aktion u ausgef¨hrt werden soll u isAction(String action) action ¨ Uberpr¨fen, ob die angegebe- u ne Aktion ausgef¨hrt werden u soll getMenuActionBeforeConfirm() menuaction Men¨-Aktion (ggf. mit Auf- u forderung, Best¨tigungsdialog a zu zeigen) getMenuAction() menuaction Men¨-Aktion u hasMenuAction() menuaction ¨ Uberpr¨fen, ob eine Men¨- u u Aktion ausgef¨hrt werden soll u isAction(String action) action ¨ Uberpr¨fen, ob die angege- u bene Men¨-Aktion ausgef¨hrt u u werden soll getGridAction() gridaction Tabellen-Aktion hasGridAction() gridaction ¨ Uberpr¨fen, ob eine Tabellen- u Aktion ausgef¨hrt werden soll u isExcel() gridaction ¨ Uberpr¨fen, ob eine Tabellen u in Excel dargestellt werden soll getReferer() referer und Referer-Header Aufrufende Seite getSearch() search Suchfilter f¨r Select-Dialoge u Tabelle 1: VContext-Methoden f¨r besondere Parameter u
  • 103. 6.1 Das Packet com.varial.base 98BO-Navigation Der Benutzer kann in der Detail-Ansicht mit der Men¨leiste von einem uBO zum n¨chsten springen. Der VContext beinhaltet die daf¨r n¨tigen Funktionen. Zuerst a u om¨ssen alle BOs registriert werden. Dazu dient die Methode registerBos(): upublic void registerBos ( String oidParent, BO[] bos)Der erste Parameter gibt die ObjectID des Parent-Objekts an, also das Objekt, zu dem dieBOs geh¨ren. In der Regel ist das die Firma, beim TaskReminder ist dies jedoch beispielsweise oder TaskFolder.Der zweite Parameter sind die zu registrierenden BOs.Alternativ kann auch anstelle der ObjectID das Objekt selbst ubergeben werden: ¨public void registerBos ( BO parent, BO[] bos)In den meisten F¨llen ist die Firma das Parent-Objekt. Dann kann der Funktionsaufruf weiter aminimiert werden:public void registerBos (BO[] bos)Neue BOs k¨nnen mit addBo() der BO-Liste hinzugef¨gt werden. Das neue BO reiht sich o uam Ende der List ein.public void addBo (BO bo)Mit getBoAt kann ein BO durch seinen Index geholt werden. Auch hier gibt es genau wie beiregisterBO() drei Varianten:public BO getBoAt(int index)public BO getBoAt( BO parentBo, int index)public BO getBoAt( String oidParent, int index)Die Anzahl der registrierten BOs liefert die Funktion getBoCount():public int getBoCount()public int getBoCount (BO parentBo)public int getBoCount (String oidParent)
  • 104. 6.1 Das Packet com.varial.base 99Callback Der VContext regelt weiterhin den Zugriff auf den aktuell aktiven Callback (5.5).Mit den Methoden isCallbackActive() und setCallbackActive() kann abgefragt werden,ob z.Zt. ein Callback aktiv ist bzw. kann diese Eigenschaft gesetzt werden.public boolean isCallbackActive()public void setCallbackActive (boolean active)Um auf den aktiven Callback zuzugreifen dient die Methode getCurrentCallback():public AbstractCallback getCurrentCallback()Soll der Callback gestoppt werden (z.B. durch Dr¨cken des Laden abbrechen“-Button), sollte u ”die Methode stopCurrentCallback() aufgerufen werden.public void stopCurrentCallback()Sonstige Methoden Die Klasse VContext bietet weiterhin einige n¨tzliche Getter- uFunktionen, von denen hier die wichtigsten aufgef¨hrt werden. upublic CompanyShortBO getCompany()Dies liefert die Firma, die zur Zeit ausgew¨hlt ist. Die Funktion sucht zuerst in der Session. aSollte dort keine Firma gefunden werden (dies ist der Fall, wenn der Benutzer sich neueinloggt), wird nach einem Cookie mit der ObjectID der Firma gesucht. Wird ein solcherCookie gefunden, wird die Firma mit der ObjectID vom Server angefordert. Sollte jedochkein Cookie gefunden werden, oder ist die Firma seit Erstellung des Cookies gel¨scht worden, owird einfach die erste Firma aus der Datenbank zur¨ckgegeben. upublic HttpServletRequest getRequest()public HttpServletResponse getResponse()Diese Funktionen liefern das Request- bzw. Response-Objekt des Servlets.public HttpSession getSession()Mit dieser Funktion kann die aktuelle Session abgefragt werden.public LocaleBO getLocale()Dies liefert ein LocaleBO, das alle l¨nderabh¨ngigen Daten der aktuellen Sprache beinhaltet. a apublic LanguageBO getLanguage()Mit Hilfe dieser Funktion kann die eingestellte Sprache abgefragt werden. Gesucht wird zuerstin der Session. Ist die Suche erfolglos, wird die Default-Sprache vom Server zur¨ckgegeben. upublic AdminUserBO getUser()Liefert den eingeloggten Benutzer.
  • 105. 6.1 Das Packet com.varial.base 1006.1.11 InstanceDie Klasse Instance ist lediglich dazu da, auf Initialisierung-Parameter, also Parameterder Datei web.xml zuzugreifen. Sie ist als Singleton implementiert, so dass immer nur eineInstanz der Klasse erzeugt werden kann. F¨r den Zugriff auf Initialisierungsparameter dienen udie statischen Methoden getInitParameter() und getInitParameterAsInt().public static String getInitParameter (String name)public static int getInitParameterAsInt (String name)Diese Methoden werden in aller Regel nicht direkt aufgerufen. Vielmehr benutztsie die Klasse VContext (6.1.10), die die selbe Funktionalit¨t mit dem Befehl agetAttribute(VContext.INIT, name) besitzt.6.1.12 BODie Klasse BO dient als gemeinsame Oberklasse aller Businsess-Objekte (5.4). Als Methodenstellt sie zur Verf¨gung: uprotected ObjectStruct getOidTs()Diese Methode liefert den ObjektStruct des BOs. Wird sie nicht uberladen, wird eine neue ¨Instanz einer ObjectStruct zur¨ckgegeben. upublic String getObjectID()public String getTimeStamp()public String getLastUserID() ¨Hiermit k¨nnen die ID des BOs, Datum und Uhrzeit der letzten Anderung und der Benutzer, oder das BO als letztes ver¨nderte, angefragt werden. apublic String getMessageDescription()Die Funktion getMessageDescription() liefert eine Beschreibung/Bezeichnung des Objek-tes. Wird sie nicht uberladen, liefert sie einen leeren String. ¨public boolean isNew()Diese Funktion zeigt an, ob ein Business-Object neu ist. Als neu gilt ein BO solange, bis esin der Datenbank gespeichert wurde. Alle nichtpersistenten BOs liefern also false.public boolean equals (BO other)Mit equals() k¨nnen zwei BOs miteinander verglichen werden. BOs gelten als gleich, wenn osie die selbe ObjectID besitzen. Die ObjectID wird vom CORBA-Server vergeben, sobald dasBO in der Datenbank gespeichert wurde. Folglich ist darauf zu achten, dass zwei neue BOsimmer als identisch gelten!
  • 106. 6.1 Das Packet com.varial.base 101protected static Object getObjectFromOrb ( VContext ctx, String className, String helperName)Mit dieser Methode k¨nnen abgeleitete Klassen Objekte vom ORB anfordern. Hierdurch o ¨k¨nnen sich BOs den passenden Servant besorgen. Ubergeben werden muss neben dem oVContext der Name der Klasse, die den Servant implementiert und der Name der von COR-BA erzeugten Helper-Klasse.Zum Schluss stellt die Klasse noch zwei Methoden bereit, mit denen BOs in das Log-File desWeb-Servers schreiben k¨nnen. oprotected static void log (String msg)protected static void log (String msg, Throwable throwable)6.1.13 VBeanDie Klasse dient als Oberklasse aller f¨r VWE-Web entwickelten Beans. uSie stellt als einzige Funktionalit¨t die Methode isFirstOneOfClass() zur Verf¨gung. a uprotected boolean isFirstOneOfClass()Mit Hilfe dieser Methoden kann festgestellt werden, ob es sich bei einem Objekt um die ersteerzeugte Instanz seiner Klasse handelt. Dies ist beispielsweise notwendig, bei der Verwendungvon Tabsheets. Werden Tabsheets verwendet, muss die Seite eine Reihe von verborgenen Fel-der besitzen, die Statusinformationen speichern. Diese Felder m¨ssen nat¨rlich nur eingef¨gt u u uwerden, wenn tats¨chlich Tabsheets verwendet werden. Werden nun mehrere Tabsheets auf aeiner Seite verwendet, darf trotzdem jedes Feld nur einmal vorkommen. Alle Tabsheets teilensich dann diese Felder.W¨rde jedes Tabsheets diese versteckten Felder erneut erzeugen, w¨rde dies zu JavaScript- u uFehlern f¨hren. Zur L¨sung dieses Problems schreibt ausschließlich die erste Instanz die Fel- u oder.Bei Verwendung der Methode wird also nur beim ersten Methodenaufruf true zur¨ckgegeben; ualle weiteren Aufrufe erzeugen false als R¨ckgabewert. u6.1.14 VExceptionBei der Klasse VException handelt es sich um eine Unterklasse von Exception, genauer ¨gesagt von der Klasse RuntimeException. Uberall, wo Programmfehler auftauchen, auf dienicht passend reagiert werden kann, wird eine VException erzeugt und geworfen. Das ver-arbeitende Servlet kann diese dann ggf. behandeln oder einfach als Fehlermeldung an denBenutzer weitergeben. Hierzu dient u.a. die Klasse ExceptionHelper (6.1.18).Eine VException kann auf zwei Arten erzeugt werden. Zum einen kann eine vorhandene Ex-ception in ein eine VException umgewandelt werden und zum anderen kann eine komplettneue VException erzeugt werden.
  • 107. 6.1 Das Packet com.varial.base 102Soll eine VException aus einer vorhandenen Exception erzeugt werden, muss dem Konstruk-tor lediglich die Orginal-Exception ubergeben werden. ¨public VException ( Throwable originalException)Soll hingegen eine neue VException erzeugt werden, sind drei Angaben notwendig: EineDom¨ne, eine Fehlerbezeichnung und eine Fehlernummer. Die Dom¨ne gibt an, in welchem a aProgramm-Packet der Fehler auftrat, die Bezeichnung gibt an, was f¨r ein Fehler auftrat uund die Fehlernummer dient dazu, den Fehler eindeutig in der Dom¨ne zu identifizieren. Mit adiesen drei Angaben ist es auch m¨glich, Fehlermeldungen mit dem Translator (6.2.1) in odie eingestellte Sprache zu ubersetzen. ¨Der passende Konstruktor sieht folglich so aus:public VException ( String domain, String what, int number)Um Einzelheiten des Fehlers abzufragen dient f¨r den ersten Fall die Methode ugetOriginalException().public Throwable getOriginalException()F¨r den zweiten Fall gibt es hingegen folgenden Methoden: upublic String getDomain()public String getWhat()public int getErrorNumber() Um zu unterscheiden, auf welche Art eine VException erzeugt wurde, steht der BefehlhasOriginalException() zur Verf¨gung. upublic boolean hasOriginalException()Wurde eine vorhandene Exception mit einer VException verpackt“ liefert er true, andern- ”falls wird false zur¨ckgegeben. uSehr h¨ufig vorkommende Fehler sind die von VWE verwendeten Exceptions avom Typ PersistencyException, DomainException, AccessDeniedException undApplicationLayerException. Um abzufragen, ob es sich bei der VException um einen deraufgef¨hrten Typen handelt dienen folgende Funktionen: upublic boolean isPersistencyException() {public boolean isAccessDeniedException() {
  • 108. 6.1 Das Packet com.varial.base 103public boolean isApplicationLayerException() {public boolean isDomainException() {Außerdem wurden noch die Methoden fillStackTrace() und equals() uberladen. ¨public void printStackTrace() {public void printStackTrace(PrintStream s) {public void printStackTrace(PrintWriter s) {public boolean equals(VException e) { ¨Das Uberladen von printStackTrace() sorgt daf¨r, dass ggf. nicht nur die VException, usondern auch Einzelheiten der uber die Orginal-Exception aufgef¨hrt werden. Mit der uber- ¨ u ¨ladenen Methode equals() k¨nnen zwei VExceptions auf Gleichheit uberpr¨ft werden. Zwei o ¨ uVExpeptions sind gleich, wenn Dom¨ne und Fehlernummer ubereinstimmen. a ¨6.1.15 TempDataDie Klasse TempData erm¨glicht es, BOs tempor¨r zwischenzuspeichern. Dies ist u.a. notwen- o adig, wenn Tabsheets (5.6) verwendet werden. Da jedes Register eine eigene Seite darstellt, ¨m¨ssen Anderungen, die in Feldern gemacht werden, bei Registerwechsel gespeichert werden. u ¨Solange der Benutzer jedoch nicht zum Speichern auffordert, d¨rfen solche Anderungen nicht uin der Datenbank persistent gemacht werden. Die Klasse TempData verwendet die aktuelle ¨Session, um Anderungen zu behalten. Hierzu wird eine Hashtable angelegt. Die URLs derSeite bilden die Schl¨ssel, denen das zu speichernde BO zugeordnet ist. uDie Klasse bietet drei Arten von Funktionen: BOs k¨nnen gespeichert und geladen werden. oAußerdem k¨nnen BOs aus dem Speicher entfernt werden. oUm BOs zu speichern dienen die Methoden storeBO().public static void storeBO ( VContext ctx, BO bo)public static void storeBO ( VContext ctx, String uri, BO bo)¨Ubergeben wird neben dem VContext das zu speichernde BO. So wird das ubergebene BO ¨der aktuellen Seite zugeordnet. Soll das BO hingegen einer anderen Seite zugeordnet werden,kann, wie die zweite Methode zeigt, auch die Adresse der Seite als zus¨tzlicher Parameter a
  • 109. 6.1 Das Packet com.varial.base 104ubergeben werden. Nach Aufruf dieser Funktion merkt sich die Session das BO.¨Um sp¨ter wieder auf das BO zur¨ckzugreifen, muss die Methode loadBO() aufgerufen wer- a uden.public static BO loadBO (VContext ctx)public static BO loadBO ( VContext ctx, String uri)Auch hier kann wahlweise die aktuelle oder eine angegebene Seite als Schl¨ssel verwendet uwerden.Gespeicherte BOs k¨nnen verworfen werden, indem die Methode resetBO() aufgerufen wird. opublic static void resetBO (VContext ctx)public static void resetBO ( VContext ctx, String uri)6.1.16 AbstractCallbackDie Klasse AbstractCallback ist eine abstrakte Oberklasse f¨r alle Callbacks. Bei Verwen- udung des Callback-Mechanismuses (5.5) sollte die Callback-Klasse hiervon abgeleitet werden.Die Klasse besitzt einen Konstruktor:protected AbstractCallback ( VContext ctx, VState state)throws AdministrationExceptionNeben dem VContext-Objekt muss ein passender VState (6.1.6), also eine Klasse, die f¨r die uAusgabe der Tabelle zust¨ndig ist, ubergeben werden. Der Konstruktor sorgt nach Aufruf f¨r a ¨ ueine Verbindung mit dem ORB und startet einen Thread der Klasse VListStateThread, derim folgenden auf eingehenden Daten wartet. In Analogie zum Erzeuger-Verbraucher-Problemstellt dieser Thread den Verbraucher dar.Neue Daten werden vom Server ubertragen, indem dieser die Methode putData() aufruft: ¨public void putData (Object[] data)Die Klasse AbstractCallback schreibt diese Daten in die Queue, die vom VListStateThreadabgefragt wird, benachrichtigt den Thread dar¨ber, dass neue Daten vorliegen und wartet uauf neue Daten vom Server. Die Klasse stellt somit den Erzeuger im Erzeuger-Verbraucher-Modell dar.
  • 110. 6.1 Das Packet com.varial.base 105AbstractCallback und VListStateThread laufen asynchron, so dass der CORBA-Serverbeim Liefern der Daten nicht auf die Darstellung der Tabelle warten muss.Die bereits ubertragenen Daten k¨nnen mit der Funktion getCollectedData() abgefragt ¨ owerden.public List getCollectedData()Die Anzahl der ubertragenden Daten liefert die Funktion getCollectedLines(): ¨public int getCollectedLines()Wird von Server das Ende der Daten¨bertragung angezeigt, wird die Methode finished() uaufgerufen.public void finished()Diese Methode beendet den VListStateThread, dieser ruft zuvor noch die Methodedisconnect() auf, die den Callback wieder vom ORB entfernt.public final void disconnect()throws AdministrationExceptionAls letzte Methode besitzt die Klasse setException().public void setException (DatabaseExceptionStruct e)Der Server kann mit einem solchen Funktionsaufruf Fehler anzeigen. Aus dem ubergebenen ¨DatabaseExceptionStruct wird eine VException (6.1.14) erstellt und diese anschließendgeworfen. Das aufrufende Servlet kann dann entsprechend reagieren.Wie bereits erw¨hnt, werden Callback-Klassen von AbstractCallback abgeleitet. Durch die- ase Vererbung besitzen sie schon die oben aufgef¨hrten Funktionen. Damit diese Funktionen uaber in einer solchen Oberklasse zusammengef¨hrt werden k¨nnen, m¨ssen die abgeleiteten u o uKlassen zwei Methoden implementieren:protected abstract Servant getServant();protected abstract void setCallback (Servant servant);Beide Methoden sind abh¨ngig vom jeweiligen Typ, so dass sie nicht in der Oberklasse spe- azifiziert werden k¨nnen. o6.1.17 VListStateThreadDie Klasse VListStateThread implementiert einen Thread der beim Callback-Mechanismusim Hintergrund l¨uft, auf Daten wartet und diese dann zur Darstellung an den passenden aVState (6.1.6) weitergibt. Sie sorgt also daf¨r, dass der CORBA-Server auf der einen und uder VState auf der anderen Seite asynchron zusammenarbeiten.Beide Parteien (AbstractCallback als Repr¨sentant des CORBA-Servers und VListState aals Client) werden im Konstruktor ubergeben: ¨
  • 111. 6.1 Das Packet com.varial.base 106protected VListStateThread( VContext ctx, VState state, AbstractCallback callback)Da die Klasse von der Klasse Thread abgeleitet wurde, besitzt sie auch eine Methode run().public void run()Hier wird in einer Endlosschleife abgefragt, ob Daten vorhanden sind. Ist dies der Fall wer-den diese mittels des passenden VStates ausgegeben. Sind keine Daten vorhanden, versetztsich der Thread mit dem Befehl wait() solange in einen wartenden Zustand, bis er vonAbstractCallback wieder geweckt“ wird. Dies wiederholt sich solange, bis die Methode ”finished() des Callbacks aufgerufen wird, die ihrerseits den Thread beendet.6.1.18 ExceptionHelperDer ExceptionHelper stellt als einzige Funktionalit¨t die statische Methode ahandleException() bereit. Mit ihr k¨nnen dem Anwender Exceptions als Fehlermel- odungen in einem PopUp-Fenster gezeigt werden.public static void handleException( VContext ctx, Throwable e)Die Methode erzeugt mittels GuiHelper (6.3.1) ein PopUp-Fenster. Je nach Fehlerklasse(AccessDeniedException, DomainException, InvalidDateException etc.) wird eine pas-sende Fehlermeldung erzeugt und nach M¨glichkeit in die aktuell ausgew¨hlte Sprache uber- o a ¨setzt. Sollte es sich um eine VException (6.1.14) handeln, so wird zun¨chst uberpr¨ft, ob a ¨ udiese eine eingepackte“ Exception enth¨lt. Ist dies der Fall, wird diese angezeigt. a ”6.1.19 StringMapperDie Klasse StringMapper beinhaltet statische Methoden, die bei der Verarbeitung vonStrings (insbesondere von Query-String-Parameter) hilfreich sind.public static boolean isEmpty (String txt)Die Methode isEmpty() uberpr¨ft, ob der ubergebene String leer ist. Als leer gilt er dann, ¨ u ¨wenn er aus dem Leerstring oder dem String “null“ besteht, oder selbst null ist. DieseMethode ist sinnvoll bei der Verarbeitung von Query-String-Parameter, die oftmals das Wort“null“ enthalten.Um einen String, der im Sinne dieser Methode als leer gilt, in einen wahren Leerstring zuwandeln, steht die Methode nullToEmpty() zur Verf¨gung. upublic static String nullToEmpty (String txt)
  • 112. 6.1 Das Packet com.varial.base 1076.1.20 VCurrencyDie Klasse VCurrency dient dazu, W¨hrungsangaben aus der Datenbank f¨r die Bildschir- a umausgabe zu formatieren, bzw. um solche Angaben wieder zur¨ck ins Datenbankformat zu uwandeln.Um Werte aus der Datenbank f¨r die Bildschirmdarstellung zu formatieren, kann die statische uMethode getViewCurrency() aufgerufen werden.public static String getViewCurrency( VContext ctx, String amount)public static String getViewCurrency( VContext ctx, String amount, CurrencyBO currency)Als Parameter erwarten beide Methoden den VContext, der Informationen uber Eigenheiten ¨der aktuellen Sprache, wie Tausender- oder Dezimaltrennzeichen, enth¨lt und den zu aformatierenden Betrag. Bei der ersten Methode wird der Betrag gem¨ß der Hausw¨hrung der a aaktuellen Firma formatiert, w¨hrend beim zweiten Funktionsaufruf eine W¨hrung expliziet a aangegeben werden kann. Die Ausgabe erfolgt gem¨ß Sprach- und W¨hrungseinstellung. a aDas bedeutet, der zur¨ckgegebene String besteht aus gruppierten Tausendern, wird uentsprechend der W¨hrungseinstellung gerundet und besitzt das passende W¨hrungssymbol. a aSoll kein W¨hrungssymbol angehangen werden, kann alternativ die Methode agetViewCurrencyWithoutCurrencyCode() verwendet werden, die ebenfalls in zweiAusf¨hrungen mit den oben genannten Parametern existiert. uBevor W¨hrungsangaben wieder in der Datenbank gespeichert werden k¨nnen, m¨ssen sie in a o uein entsprechendes Format umgewandelt werden. Hierzu dient der Befehl getDBCurrency().public static String getDBCurrency( VContext ctx, String amount)public static String getDBCurrency( VContext ctx, CurrencyBO currency, String amount)Die Verwendung ist ¨hnlich der oben genannten Methoden. Außer dem VContext wird der azu formatierende Betrag und optional eine W¨hrung angegeben. aAbschließend zeigt Tabelle 2 einige Beispiele f¨r korrekte Formatierungen. Es wird die uDatenbank-Angabe 123456.789“ in die folgenden W¨hrung formatiert: a ”
  • 113. 6.1 Das Packet com.varial.base 108 • US-Dollar ($), zwei Nachkommastellen, kaufm¨nnische Rundung a • Lire (Lire), zwei Stellen vor dem Komma, kaufm¨nnische Rundung a • Cocosn¨sse (CN), keine Nachkommastellen, keine Rundung u W¨hrung a Deutsch Englisch US-Dollar 123.456,79 $ 123,456.79 $ Lire 123.500 Lire 123,500 Lire Cocosn¨sse u 123.456 CN 123,456 CN Tabelle 2: Beispiele f¨r die Formatierung von W¨hrungsangaben u a6.1.21 VNumberDie Klasse VNumber dient einer ¨hnlichen Verwendung wie VCurrency (6.1.20), allerdings awerden hier lediglich Zahlen und keine W¨hrungsangaben formatiert. apublic static String getViewNumber( VContext ctx, String number)public static String getDBNumber( VContext ctx, String number) Die Methoden formatieren Werte aus der Datenbank in Angaben entsprechend der aktu-ellen Sprache und vice versa.6.1.22 VDate ¨Mit Hilfe der Klasse VDate k¨nnen Datumsangaben bearbeitet werden. Ahnlich wie bei oVCurrency (6.1.20) k¨nnen Datenbank-Angaben f¨r die Bildschirmausgabe formatiert werden o ubzw. diese wieder zur¨ckgewandelt werden. upublic static String getViewDate( VContext ctx, String date)public static String getDBDate( VContext ctx, String date)
  • 114. 6.1 Das Packet com.varial.base 109Mit der ersten Methode wird die ubergebene Datumsangabe aus der Datenbank in ein Da- ¨tum, das der aktuellen Sprache entspricht, umgewandelt. Aus 1980-04-11“ wird z.B. bei ”ausgew¨hlter deutscher Sprache 11.04.1980“. Mit der zweiten Methode kann ein solches Da- a ”tum wieder in einen String gewandelt werden, der in die Datenbank geschrieben werdenkann. o ¨Weiterhin k¨nnen sog. Timestamps, die das Anderungsdatum eines BOs angeben, f¨r die Bild- uschirmausgabe aufbereitet werden. Die Funktion getViewTimeStamp() leifert hierf¨r einen upassenden String zur¨ck. upublic static String getViewTimeStamp ( VContext ctx, String timestamp)Außerdem k¨nnen diverse Datumsberechnungen mit der Klasse VDate durchgef¨hrt werden. o uSo liefert getToday() das aktuelle Datum (im Datenbankformat) und getCurrentYear()das aktuelle Jahr.public static String getToday() {public static int getCurrentYear() {Um die Differenz zwischen zwei Datumsangaben zu bestimmen, besitzt VDate die folgendenMethoden:public static int getDaysBetween( String date1, String date2)public static int getWeeksBetween( String date1, String date2)public static int getMonthsBetween( String date1, String date2)public static int getYearsBetween( String date1, String date2)Allen vier Methoden werden zwei Datumsangaben im Datenbankformat ubergeben. Der ¨R¨ckgabewert ist jeweils die Anzahl der Tage, Wochen, Monate oder Jahre, die zwischen u
  • 115. 6.2 Das Packet com.varial.translation 110diesen beiden Datumsangaben liegen. Auch eine Vorw¨rtsrechnung ist m¨glich. Auf diese a oWeise kann ein Datum bestimmt werden, das eine gewisse Zeitspanne nach einem gegebenenDatum liegt.public static String addDays( String date, int days)public static String addWeeks( String date, int weeks)public static String addMonths( String date, int months)public static String addYears( String date, int years)Alle Methoden erwarten sowohl ein Datum als auch die Anzahl von Tagen, Wochen, Mona-te oder Jahren, die auf dieses Datum addiert werden sollen. Auch eine negative Anzahl istm¨glich. In diesem Fall werden das Zeitintervall abgezogen. Zur¨ckgegeben wird das berech- o unetete Datum im Datenbankformat.6.2 Das Packet com.varial.translation ¨Das Packet com.varial.translation beinhaltet Klassen, die f¨r die Ubersetzung aller angezeig- uten Texte zust¨ndig sind. a6.2.1 Translator ¨Die Klasse Translator stellt Methoden zur Ubersetzung von Texten zur Verf¨gung. Um ueinen Text ubersetzen zu k¨nnen, sind f¨nf Angaben notwendig: ¨ o u • Resource-Module Gibt den Bereich (Packet) in VWE an. z.B: personalaccount“ oder taskreminder“ ” ” • Parent Gibt die genau Klasse an. z.B: personalaccountdetailframe“ ” • Component Gibt den Namen des zu ubersetzenden Elements an. z.B: addresstabsheet“ ¨ ”
  • 116. 6.2 Das Packet com.varial.translation 111 • Sprache Gibt die Sprache an, in die ubersetzt werden soll ¨ • Feld Gibt an, ob die Beschriftung (Label) oder der Tooltip des Elements ubersetzt werden ¨ sollDamit man nun einen ubersetzten Text erh¨lt, gibt es zwei M¨glichkeiten. ¨ a oparagraphM¨glichkeit 1 Es wird zun¨chst eine Translator-Instanz mit dem Konstruktor, der o adie Resource-Module- und Parent-Angabe erwartet, erzeugt.public Translator( String module, String parent) ¨Jetzt k¨nnen mit den Funktionen getCaption() bzw. getHint() die Ubersetzungen abge- ofragt werden.public String getCaption( VContext ctx, String component)public String getHint( VContext ctx, String component)Die Angabe uber die Sprache wird aus dem VContext-Objekt (6.1.10) gelesen. ¨Diese Vorgehensweise bietet sich an den Stellen an, an denen oft aus dem selben Resource-Module und Parent gelesen wird.M¨glichkeit 2: Man verwendet die statischen getCaption() und getHint(). opublic static String getCaption( VContext ctx, String module, String parent, String component)public static String getHint( VContext ctx, String module,
  • 117. 6.3 Das Packet com.varial.gui 112 String parent, String component)Hier werden alle n¨tigen Angaben direkt der Funktion ubergeben, ohne den Umweg uber den o ¨ ¨Konstruktor zu nehmen.Diese Vorgehensweise bietet sich an, wenn nur vereinzelnt Texte ubersetzt werden sollen. ¨6.2.2 TranslatorCacheDiese Klasse ist nur innerhalt des Packets zugreifbar und wird lediglich vom Translator ¨(6.2.1) verwendet. Sie stellt einen Mechanismus bereit, mit dessen Hilfe Ubersetzungen ge-cachet werden k¨nnen. Darum m¨ssen Sprachbezeichnungen nicht erneut vom Server geholt o u ¨werden. Sollte sich die Ubersetzung jedoch einmal ¨ndern, so muss der Web-Server neu gest- aartet werden, um den Cache zu l¨schen. o6.3 Das Packet com.varial.guiDas Packet com.varial.gui umfasst s¨mtliche Klassen, die f¨r die Erstellung von grafischen a uBenutzeroberfl¨chen zust¨ndig sind. a a6.3.1 GuiHelperDer GuiHelper besitzt eine Reihe von statischen Methoden, mit denen auf einfache WeiseWeb-Oberfl¨chen zusammengestellt werden k¨nnen. Es handelt sich hierbei um eine Factory- a oKlasse, einem Entwurfsmuster, das f¨r die Erzeugung von Objekten zust¨ndig ist. Das heißt u aim Detail, dass GUI-Klassen nie direkt instanziiert werden, sondern dass die Factory-Klassedies durch seine statischen Methoden erledigt.Mit dem GuiHelper werden GUI-Elemente erzeugt und in dem Request-Objekt, also in derSeitenanfrage, abgelegt. Eine JSP-Seite kann die Objekte sp¨ter auslesen und entsprechend aausgeben.Eine Oberfl¨chenkomponente besteht i.d.R. aus einer sprachabh¨ngigen Beschriftung (Label), a aeinem Feld f¨r Eingabe und einem Wert, der in diesem Feld steht. Außerdem besitzen die umeisten Komponenten einen Namen, mit denen eine eindeutige Identifizierung m¨glich ist. oDie Methoden der Klasse haben somit folgenden Aufbau:addXxx ( VContext ctx, Translator translator, String name, String label, String value, ...)Die Methoden erwarten als Parameter den VContext (6.1.10), ein Translator-Objekt f¨r die u¨Ubersetzung (6.2.1), einen Namen, den die Komponente erhalten soll, die Beschriftung und
  • 118. 6.3 Das Packet com.varial.gui 113den Wert, den das Feld annehmen soll. Die Angabe f¨r label wird von dem ubergebenen u ¨Translator-Objekt automatisch in die aktuelle, im VContext-Objekt gespeicherte Spracheubersetzt.¨Unter Umst¨nden ist es notwendig, eine erzeugte Komponente nachtr¨glich zu ¨ndern. Bei- a a aspielsweise k¨nnte ein Textfeld erzeugt werden, dass unter bestimmten Bedingungen aktiviert obzw. deaktiviert ist. Ein Servlet m¨chte folglich nicht nur ein Textfeld erzeugen, sondern es im oAnschluss auch noch ver¨ndern. In diesem Beispiel also deaktivieren. Damit solche Aktionen am¨glich sind, liefern alle Methoden der GuiHelper-Klasse das erzeugte Objekt zur¨ck. o uDamit folgenden die Methoden diesem Aufbau:public static Xxx addXxx ( VContext ctx, Translator translator, String name, String label, String value, ...)Es folgen die Methoden im einzelnen. Eine genauere Beschreibung der Komponenten ist inden in Klammern angegebenen Kapitel zu finden. Erzeugen eines Textfeldes (6.3.3):public static LabeledTextField addTextField( VContext ctx, Translator translator, String name, String label, String value)public static LabeledTextField addTextField( VContext ctx, Translator translator, String name, String label, int value)Die Methode erwartet nur die oben erw¨hnten Parameter. a Erzeugen eines Zahlenfeldes (6.3.4):public static LabeledNumberField addNumberField( VContext ctx, Translator translator,
  • 119. 6.3 Das Packet com.varial.gui 114 String name, String label, int value)public static LabeledNumberField addNumberField( VContext ctx, Translator translator, String name, String label, int value, boolean allowFloat, boolean allowNegative)public static LabeledNumberField addNumberField( VContext ctx, Translator translator, String name, String label, String value)public static LabeledNumberField addNumberField( VContext ctx, Translator translator, String name, String label, String value, boolean allowFloat, boolean allowNegative)Der Methode k¨nnen zus¨tzlich zu den oben erw¨hnten, noch zwei boolsche Parameter o a aubergeben werden.¨allowFloat gibt an, ob auch Flieskommazahlen erlaubt sind, allowNegative gibt an, obnegative Eingaben m¨glich sind. Werden die Parameter nicht angegeben, ist beides, also onegative und Kommazahlen, m¨glich. o Erzeugen eines Datumfeldes (6.3.6):public static LabeledDateField addDateField( VContext ctx, Translator translator, String name, String label,
  • 120. 6.3 Das Packet com.varial.gui 115 String value)Genau wie ein normales TextFeld sind hier keine besonderen Paramter notwendig. Erzeugen eines W¨hrungsfeldes (6.3.5): apublic static LabeledCurrencyField addCurrencyField( VContext ctx, Translator translator, String name, String label, String value)public static LabeledCurrencyField addCurrencyField( VContext ctx, Translator translator, String name, String label, String value, CurrencyBO currency)Der Methode kann zus¨tzlich zu den normalen Parametern auch noch eine W¨hrung a aubergeben, die angibt, wie der Betrag formatiert werden soll (Nachkommastellen, Rundung,¨W¨hrungssymbol, etc). Fehlt diese Angabe, wird statt dessen die Hausw¨hrung der aktuellen a aFirma verwendet. Erzeugen einer Textbox (6.3.7):public static LabeledMemo addTextArea( VContext ctx, Translator translator, String name, String label, String value) ¨Hierbei besteht starke Ahnlichkeit zu der Methode addTextField(), allerding wird an-statt eines einzeiligen Textfeldes ein mehrzeiliges erzeugt. Weitere Parameter sind nicht n¨tig. o Erzeugen eines Drei-Punkte-Feldes (6.3.8):public static LabeledButtonTextField addButtonField( VContext ctx, Translator translator,
  • 121. 6.3 Das Packet com.varial.gui 116 String name, String label, String value, String href)public static LabeledButtonTextField addButtonField( VContext ctx, Translator translator, String name, String label, String value, String href, boolean directEdit)public static LabeledButtonTextField addButtonFieldForBrowser( VContext ctx, Translator translator, String name, String label, String value, String href, String target)Zus¨tzlich zu den Parametern, die auch bei der Erzeugung eines Textfeldes verwendet awerden, gibt es hier noch einen Parameter href, der angibt, was bei einem Klick auf denButton geschehen soll. Es kann sich hierbei um einen Verweis auf eine HTML-Seite, eineJavaScript-Anweisung oder alle sonstigen Angaben handeln, die im href-Attribute desHTML-a-Tags stehen d¨rfen. uBei der zweiten Methode kann zus¨tzlich angegeben werden, ob der Feldinhalt vom An- awender direkt ge¨ndert werden kann. Wird false ubergeben oder die erste Methode ohne a ¨ o ¨diesen Parameter verwendet, k¨nnen Anderungen ausschließlich uber Klick auf den Button ¨vorgenommen werden. Tastatureingaben in das Feld sind nur dann m¨glich, wenn der oParameter auf true gesetzt wird.Die dritte Methode wird verwendet, wenn der Inhalt des Feldes im Browser darstellbarist. Beispiele hierf¨r w¨ren eine Homepage-URL oder eine Mail-Adresse. Solche Felder sind u agrunds¨tzlich direkt editierbar, ein Klick auf den Button ¨ffnet die angegebene Seite bzw. a osendet eine Mail an die angegebene Adresse. Als zus¨tzlichen Parameter muss ein Zielfenster aangegeben werden, in dem die neue Seite ge¨ffnet werden soll. o Erzeugen einer Check-Box (6.3.9):public static LabeledCheckBox addCheckBox( VContext ctx,
  • 122. 6.3 Das Packet com.varial.gui 117 Translator translator, String name, String label, boolean value, StringBuffer javascript)public static LabeledCheckBox addCheckBox( VContext ctx, Translator translator, String name, String label, boolean value)Der Wert gibt in diesem Fall an, ob die Check-Box selektiert sein soll oder nicht. Außer-dem kann wahlweise JavaScript-Code ubergeben werden, der Abh¨ngigkeiten zu anderen ¨ aElementen definiert. Zum Beispiel k¨nnte der JavaScript-Code angeben, dass einige Felder onur dann editierbar sein sollen, wenn die Check-Box aktiviert ist. N¨heres hierzu findet man abei Beschreibung der Klasse LabeledCheckBox (6.3.9) und beim JavaScriptHelper (6.3.29). Erzeugen eines Radio-Buttons (6.3.10):public static LabeledRadioButton addRadioButton( VContext ctx, Translator translator, String name, String label, String group, boolean value, StringBuffer javascript)public static LabeledRadioButton addRadioButton( VContext ctx, Translator translator, String name, String label, String group, boolean value)Radio-Buttons unterscheiden sich von Check-Boxen dadurch, dass jeweils nur ein Eintragselektiert werden kann. Radio-Buttons sind immer in Gruppen zusammengefasst, wobeijeweils nur ein Eintrag der Gruppe ausgew¨hlt sein kann. Aus diesem Grunde erwarten die aMethoden im Gegensatz zu den Methoden f¨r die Erzeugung von Check-Boxen auch noch u
  • 123. 6.3 Das Packet com.varial.gui 118den Namen einer Gruppe. Alle Radio-Buttons, die den selben Gruppennamen ubergeben ¨bekommen, schließen sich in ihrer Auswahl gegenseitig aus. Erzeugen einer Combo-Box (6.3.11):public static LabeledComboBox addComboBox( VContext ctx, Translator translator, String name, String label, String[] values, int selectedIndex, StringBuffer javascript)public static LabeledComboBox addComboBox( VContext ctx, Translator translator, String name, String label, String[] values, int selectedIndex)public static LabeledComboBox addComboBox( VContext ctx, Translator translator, String name, String label, String[] values)Im Gegensatz zu den bisher vorgestellten GUI-Komponenten, besteht eine Combo-Box ausmehreren Eintr¨gen. Folglich wird hier nicht ein Wert f¨r das Feld, sondern eine Liste von a uWerten ubergeben. Optional kann der Index des selektierten Objekts angegeben werden. Die ¨Combo-Box zeigt dann den entsprechenden Wert. Andernfalls wird der erste Eintrag derListe angezeigt. Auch hier k¨nnen Abh¨ngigkeiten per JavaScript definiert werden. o a Erzeugen einer editierbaren Combo-Box (6.3.12):public static LabeledEditableComboBox addEditableComboBox( VContext ctx, Translator translator, String name, String label, String[] values,
  • 124. 6.3 Das Packet com.varial.gui 119 String value, StringBuffer javascript)public static LabeledEditableComboBox addEditableComboBox( VContext ctx, Translator translator, String name, String label, String[] values, String value)public static LabeledEditableComboBox addEditableComboBox( VContext ctx, Translator translator, String name, String label, String[] values)Die Funktionen unterscheiden sich von den eben genannten nur darin, dass eine editierbarestatt einer statischen Combo-Box erzeugt wird. Erzeugen einer List-Box (6.3.13):public static LabeledListBox addListBox( VContext ctx, Translator translator, String name, String label, String[] values, String[] keylist, int[] selectedIndexes, LabeledListBoxButtons buttons)public static LabeledListBox addListBox( VContext ctx, Translator translator, String name, String label, String[] values, String[] keylist, int selectedIndex, LabeledListBoxButtons buttons)
  • 125. 6.3 Das Packet com.varial.gui 120public static LabeledListBox addListBox( VContext ctx, Translator translator, String name, String label, String[] values, String[] keylist, LabeledListBoxButtons buttons)public static LabeledListBox addListBox( VContext ctx, Translator translator, String name, String label, String[] values, String[] keylist, int[] selectedIndexes)public static LabeledListBox addListBox( VContext ctx, Translator translator, String name, String label, String[] values, String[] keylist, int selectedIndex)public static LabeledListBox addListBox( VContext ctx, Translator translator, String name, String label, String[] values, String[] keylist)Genau wie Combo-Boxen besteht eine List-Box aus mehreren Eintr¨gen. Deshalb wird auch ahier ein Array von Werten anstelle eines einzelnen Wertes ubergeben. Unangenehm bei ¨List-Boxen ist, dass beim Absenden eines HTML-Formulars nur selektierte Werte ubertragen ¨werden. Oftmals wird jedoch eine List-Box verwendet, um lediglich Daten in einer Listeanzuzeigen. Eine Selektion ist hier gar nicht erw¨nscht. Nun w¨rde beim Senden kein Wert u u
  • 126. 6.3 Das Packet com.varial.gui 121ubertragen, die Liste w¨re also scheinbar leer. Um dies zu verhindern, muss der List-Box¨ aeine sog. Schl¨sselliste gesetzt werden. Eine solche Schl¨sselliste wird auf jeden Fall beim u uAbsenden des Formulars ubertragen. Zeigt die List-Box z.B. eine Liste von BOs, w¨ren die ¨ aIDs der BOs eine sinnvolle Schl¨sselliste. uIn einer List-Box kann ein, kein oder viele Eintr¨ge ausgew¨hlt sein. Wird ein Parameter a aselectedIndex ubergeben, wird der entsprechende Eintrag vorselektiert. Sollen mehrere ¨Eintr¨ge ausgew¨hlt sein, kann auch ein Array von Indizes ubergeben werden. Wird der a a ¨Parameter nicht angegeben, wird kein Eintrag ausgew¨hlt. aUnter Umst¨nden kann es sinnvoll sein, die List-Box mit gewissen Funktionalit¨ten auszu- a astatten. Beispiele hierf¨r ist die M¨glichkeit, einen Eintrag hinzuzuf¨gen bzw. zu l¨schen. u o u oDa HTML keine PopUp-Men¨s unterst¨tzt, m¨ssen solche Funktionen als Icons unterhalb u u uder List-Box angezeigt werden. Hierzu dient die Klasse LabeledListBoxButtons (6.3.14),die der List-Box ggf. als Parameter mitgegeben werden kann. Erzeugen einer Tabelle (6.3.15):public static LabeledGrid addGrid( VContext ctx, Translator translator, String label, VState state)public static LabeledGrid addGrid( VContext ctx, VState state)Die Funktion erwartet im Gegensatz zu den bisher beschriebenen keinen Wert, sonderneinen VState (6.1.6), der f¨r die Behandlung der Tabelle zust¨ndig ist. Sollte die Tabelle u akeine Beschriftung haben (dies ist oftmals der Fall, wenn die Tabelle das einzige Elementeiner Tabsheet ist. Dann beschreibt die Tabsheet-Bezeichnung auch die Tabelle), kann aufdie Angabe von Translator und Label verzichtet werden. Erzeugen von Auswahldialogen (6.3.25, 6.3.26, 6.3.27):public static void setSearch ( VContext ctx, String txt)public static void setCancel ( VContext ctx)public static void setOkCancel (
  • 127. 6.3 Das Packet com.varial.gui 122 VContext ctx)Die erste Methode erstellt eine Suchfeld, also ein Textfeld, in dem ein Suchbegriff eingegebenwerden kann. Ein solches Element steht in Auswahldialogen uber einer Tabelle. Durch ¨die Eingabe von Werten in dem Feld werden Inhalte aus der Tabelle gefiltert. Die zweiteMethode erstellt einen Button, mit dem der Auswahlvorgang abgebrochen werden kann. Dieletzte Methode dient dazu, sowohl einen Best¨tigungs- als auch einen Abbruch-Button zu aerstellen. Erzeugen von PopUp-Meldungen:public static void confirm ( VContext ctx, StringBuffer msg)public static void confirm ( VContext ctx, String msg)public static void popup ( VContext ctx, StringBuffer msg)public static void popup ( VContext ctx, String msg)Grunds¨tzlich gibt es zwei Arten von PopUps: Nachrichten und Best¨tigungen. W¨hrend a a ader Anwender bei Best¨tigungen die Wahl zwischen zwei Optionen (ja oder nein) hat, awerden bei Nachrichten lediglich Informationen angezeigt. Um solche PopUps zu erstellen,dienen die Methoden popup() f¨r Nachrichtenfenster und confirm() f¨r Best¨tigungen. Der u u aanzuzeigende kann wahlweise als String oder StringBuffer angegeben werden. ¨ Erzeugen von Uberschriften:public static void setHeadLine ( VContext ctx, String txt)Um Seiten¨berschriften zu erzeugen, dient der Befehl setHeadLine(). Er erwartet neben u ¨dem VContext die Uberschrift als String.
  • 128. 6.3 Das Packet com.varial.gui 123 Erzeugen einer Tabsheet (6.3.20):public static void addTabSheet ( VContext ctx, String[] captions) ¨Die Methode erzeugt eine neue Tabsheet mit den angegebenen Uberschriften. Erzeugen eines Bildes (6.3.19):public static ImageBean addImage( VContext ctx, Translator translator, String name, String description, String url)Die Methode erwartet als Parameter u.a. eine Angaben f¨r die Beschreibung des Bildes. uDiese wird analog zu der Label-Angabe der anderen GUI-Komponenten behandelt. Die URLgibt an, welchen Dateinamen das Bild tr¨gt. a Erzeugen eines Diagramms (6.1.5):public static GraphBean addGraph( VContext ctx, Translator translator, String name, String description, VChartServlet servlet)Die Methode verh¨lt sich ¨hnlich wie addImage(), jedoch wird hier das VChartServlet a a(6.1.5), das die Ausgabe erzeugt, ubergeben. ¨6.3.2 VGuiBeanAlle beschrifteten GUI-Elemente sind von der Klasse VGuiBean abgeleitet. Auf diese Wei-se besitzen alle Elemente bereits einige wichtige Attribute bzw. Methoden. Alle Attributebeschreiben bestimmte Eigenschaften einer GUI-Komponente und k¨nnen mit ¨ffentlichen o oSetter-Methoden gesetzt werden. VGuiBean stellt hiervon bereits die wichtigsten bereit.public void setTranslator (Translator translator)public void setLabel (String label)public void setName (String name)
  • 129. 6.3 Das Packet com.varial.gui 124public void setValue (String value)public void setAlign (String align)public void setEnable (boolean enable)public void setEnableLabel (boolean enableLabel)public void setShouldEnableSave (boolean enableSave)public void setColspan (int colspan)public void setRowspan (int rowspan)public void setTabIndex (int tabindex)public void setWidth (String width)public void setHeight (String height)public void setVisible (boolean visible)public void setLinebreak (boolean linebreak)public void setInterdependence (StringBuffer interdependence)Die Bedeutungen der einzelnen Eigenschaften werden in Tabelle 3 aufgef¨hrt. u Auf die letzte Eigenschaft interdependece soll noch einmal n¨her eingegangen werden. a ¨Mit dieser Eigenschaft l¨ßt sich JavaScript-Code definieren, der bei Anderungen des Feldes a ¨ausgef¨hrt werden soll. Sinn dieser Funktion ist es, bei Anderungen einzelner Komponenten udie Oberfl¨che dynamisch anzupassen. Als Beispiel wird angenommen, es existiere eine aCheck-Box, mit deren Aktivierung ein Benachrichtigung per Mail eingestellt werden kann.In einem Textfeld kann die entsprechende Mail-Adresse eingegeben werden.Da die Eingabe in dieses Feld nur Sinn macht, wenn die Check-Box aktiviert ist, kann mitder Eigenschaft interdependence eine Abh¨ngigkeit zwischen Check-Box und Textfeld abeschrieben werden. Die Klasse JavaScriptHelper (6.3.29) bietet hierf¨r n¨tzliche Metho- u u ¨den wie z.B. enableByCheckBox(). Ubergeben wird ihr der Name der Checkbox, sowie derName des Textfeldes. Man erh¨lt JavaScriptCode, der daf¨r sorgt, dass das Textfeld f¨r die a u uAdresseneingabe solange deaktiviert ist, bis die Check-Box angew¨hlt wurde. Dieser Code amuss nun nur noch der Check-Box als Eigenschaft ubergeben werden. ¨Zusammen mit dem JavaScriptHelper bietet die Eigenschaft interdependence also dieM¨glichkeit, einfache Abh¨ngigkeiten zwichen beliebig vielen Elementen zu definieren. o a
  • 130. 6.3 Das Packet com.varial.gui 125 Eigenschaft Bedeutung Default translator ¨ Translator-Objekt (6.2.1) zur Uberset- null zung label Beschriftung der Komponente name Name der Komponente. null align Horizontale Ausrichting. left“, right“, left“ ” ” ” center“ ” enable Gibt an, ob Element aktiviert/¨nderbar a true ist enableLabel Gibt an, ob die Beschriftung ausgegraut true ist shouldEnableSave ¨ Gibt an, ob Anderungen im Feld den true Speicher-Knopf aktivieren colspan Gibt an, uber wieviele Spalten sich die ¨ 1 Komponente im Tabellenraster erstreckt rowspan Wie colspan, nur f¨r Zeilen u 1 tabIndex Legt die Position in der Tabulator- gem¨ß Definitionsrei- a Reihenfolge fest henfolge5 width Breite der Komponente Browserstandard6 height H¨he der Komponente o Browserstandard visible Gibt an, ob das Element sichbar sein soll true linebreak Gibt an, ob die Beschriftung ggf. umge- false brochen werden soll interdependence ¨ Gibt JavaScript-Code an, der bei Ande- rungen ausgef¨hrt werden soll u Tabelle 3: Eigenschaften von GUI-Elementen
  • 131. 6.3 Das Packet com.varial.gui 126 Neben den Eigenschaften f¨r abgeleitete Klassen bietet die VGuiBean auch drei Hilfsme- uthoden.protected void writeLabel (Writer out) throws IOExceptionprotected StringBuffer getNameIdAndTabIndex()protected StringBuffer getWidthAndHeight()Der ersten wird eine Instanz der Klasse Writer ubergeben. Daraufhin wird HTML-Code f¨r ¨ udie Beschriftung der aktuelle Komponente erzeugt. Die zweite Methode kann von abgelei-teten Klassen aufgerufen werden, um die HTML-Attribute name, id und tabindex aus denKomponenten-Eigenschaften zu erzeugen. Die letzte Methode getWidthAndHeight() kon-struiert Style-Sheet-Angaben f¨r die Gr¨ße der Komponente. u oZur Erinnerung sei noch einmal darauf hingewiesen, dass VGuiBean-Klassen (und davon ab-geleitete Klassen) mit der Factory-Klasse GuiHelper (6.3.1) erzeugt werden.6.3.3 LabeledTextFieldDie Klasse LabeledTextField stellt ein beschriftetes Textfeld dar.Oberklasse ist VGuiBean (6.3.2). Zus¨tzlich k¨nnen der Klasse folgende Eigenschaften gesetzt a owerden:public void setValue (String value)public void setMaxlength (int maxlength) Die Eigenschaft value gibt den Wert an, der als Inhalt in dem Textfeld eingetragen werdensoll. Maxlength legt die maximale Anzahl der Zeichen fest, die in das Textfeld eingetragenwerden kann.6.3.4 LabeledNumberFieldDie Klasse LabeledNumberField definiert ein Textfeld f¨r die Eingabe von Zahlen. uDas Feld unterscheidet sich ¨ußerlich nicht von einem Textfeld, jedoch sorgen eine Reihe von a Abbildung 36: LabeledNumberFieldJavaScript-Funktionen daf¨r, dass ausschließlich Zahlen in dieses Feld eingegeben werden. Die uEingabe von Buchstaben und Sonderzeichen wird gesperrt. Große Zahlen werden automatischschon w¨hrend der Eingabe in Tausenderbl¨cken mit dem f¨r die aktuelle Sprache typischen a o u
  • 132. 6.3 Das Packet com.varial.gui 127Trennzeichen gruppiert. Eine Eingabe wie 1000000“ wird somit automatisch zu 1.000.000“ ” ”im Deutschen oder 1,000,000“ im Englischen. ”Oft werden solchen Feldern Werte aus der Datenbank ubergeben. Die Klasse sorgt in diesem ¨Fall daf¨r, dass die Ausgabe an die Sprache angepasst wird. Ein Wert wie 0.67“ wird u ”beispielsweise bei deutscher Sprache automatisch als 0,67“ dargestellt. ¨ ”Wegen der Ahnlichkeit zu normalen Textfeldern wurde die Klasse LabeledNumberField auchvon LabeledTextField abgeleitet. Sie erg¨nzt diese Klasse um zwei weitere Eigenschaften. apublic void setAllowFloat (boolean allowFloat)public void setAllowNegative (boolean allowNegative)Die Angabe allowFloat gibt an, ob auch Fließkommazahlen, also Zahlen mit Nachkomma-stelle erlaubt sind. Wird diese Eigenschaft auf false gesetzt, wird auch die Eingabe desDezimaltrennzeichens, beipielsweise ein Komma im deutschen, gesperrt.Mit allowNegative kann festgelegt werden, ob auch negative Zahlen eingegeben werdenk¨nnen. Bei false wird ebenfalls die Eingabe eines Minus-Zeichens gesperrt. o6.3.5 LabeledCurrencyFieldDie Klasse LabeledCurrencyField repr¨sentiert eine Textfeld, das die Eingabe eines Geld- abetrages erwartet.Auch ein W¨hrungsfeld unterscheidet sich auf den ersten Blick nicht von einem Text- oder aZahlenfeld, jedoch werden auch hier durch JavaScript-Funktionen konsistente Eingaben si-chergestellt. Da es sich bei Geldbetr¨gen ist erster Linie um Zahlen handelt, erweitert das aFeld die M¨glichkeiten eines Zahlenfeldes, so dass die Klasse von LabeledNumberField ab- ogeleitet wurde.Zus¨tzlich zu den Funktionen eines Zahlenfeldes, wird dem Betrag ein W¨hrunszeichen an- a agehangen. W¨hrend ein Zahlenfeld also f¨r Eintr¨ge wie “1.234,56“ gedacht ist, kann bei a u aeinem W¨hrungsfeld 1.234,56 $“ angezeigt werden. Erh¨lt das Feld den Eingabefokus, a a ”wird automatisch das W¨hrungszeichen ausgeblendet. Wird die Eingabe beendet, wird es awieder angef¨gt. uDurch die Vererbung kann auch bei der Klasse LabeledCurrencyField angegeben werden,ob negative und Fließkommazahlen erlaubt sein sollen. Durch die Angabe einer W¨hrungawird ferner festgelegt, wieviele Nachkommastellen erlaubt sind und wie Angaben gerundetwerden. LabeledCurrencyField stellt hierzu zwei zus¨tzliche Methoden zur Verf¨gung. a upublic void setCurrency (CurrencyBO currency)public void setShowCurrencyCode (boolean showCurrencyCode)Mit setCurrency() wird die W¨hrung gesetzt, setShowCurrenyCode() gibt an, ob das aW¨hrungszeichen angezeigt werden soll. Wird diese Eigenschaft auf false gesetzt, verh¨lt a asich das Feld wie ein Zahlenfeld, begrenzt jedoch Nachkommastellen gem¨ß der ubergebenen a ¨W¨hrung. a
  • 133. 6.3 Das Packet com.varial.gui 1286.3.6 LabeledTextFieldDie Klasse LabeledDateField definiert ein Textfeld f¨r die Eingabe eines Datums. uDie Eingabe muss gem¨ß des Datumsformates der aktuellen Sprache vorgenommen werden. a Abbildung 37: LabeledDateFieldErlaubt sind somit nur Ziffern und das jeweilige Datums-Trennzeichen, wie beispielsweise derPunkt. Alle anderen Eingaben, wie Buchstaben oder Sonderzeichen werden gesperrt. Das Feldverf¨gt weiterhin uber einen Mechanismus, der das Datum auf Korrektheit uberpr¨ft. Eine u ¨ ¨ uung¨ltige Eingabe (z.B. “32.12.“) wird erkannt und blockiert. Zur schnelleren Eingabe ist ues außerdem m¨glich, ein Datum ohne Trennzeichen einzugeben. Die Eingabe “160578“ wird oautomatisch in das Datum 16.05.1978“ 7 formatiert. Zweistellige Jahresangaben uber 50 ¨ ”werden mit dem Vorsatz 19, Angaben unter oder gleich 50 mit dem Pr¨fix 20 versehen. Wird akein Jahr angegeben, wird das aktuelle Jahr eingef¨gt. Ebenso wird eine fehlende Monatsan- ugabe mit dem aktuellen Monat versehen. So ist es m¨glich, mit der Eingabe “15“ auf den 15. oTag des aktuellen Monats im aktuellen Jahr zuzugreifen. Diese eingebaute Programmlogik,die mit JavaScript realistiert wird, erm¨glicht eine schnelle und unkomplizierte Datumsein- ogabe.Oberklasse ist VGuiBean (6.3.2). Zus¨tzlich k¨nnen der Klasse folgende Eigenschaften gesetzt a owerden:public void setValue (String value)Genau wie bei einem normalen Textfeld kann so der Inhalt des Feldes angegeben werden. DieEingabe kann im Datenbankformat erfolgen. Die Ausgabe wird automatisch in ein Formatgem¨ß der aktuellen Sprache formatiert. a6.3.7 LabeledMemoDie Klasse LabeledMemo stellt ein mehrzeiliges Textfeld dar.Dieses Feld erweitert die Klasse LabeledTextField, um die M¨glichkeit auch mehrzeiligen oText darzustellen. Das Feld besitzt deshalb zwei weitere Eigenschaften.public void setWrap (String wrap)public void setHeight (String height) 7 Je nach Spracheinstellung wird nat¨rlich ein anderes Format gew¨hlt u a
  • 134. 6.3 Das Packet com.varial.gui 129Die Eigenschaft height gibt die H¨he des Textfelds an, warp beschreibt, wie Texteingaben oumgebrochen werden. Hier sind alle Angaben erlaubt, die dem wrap-Attribute des textarea-Tags zugeordnet werden k¨nnen. Typische Angaben sind virtual (automatischer Umbruch oam Zeilenende) oder off (kein automatsicher Zeilenumbruch).6.3.8 LabeledButtonTextFieldDie Klasse LabeledButtonTextField stellt ein Textfeld mit einem verkn¨pften Button dar. uBei einem sog. Drei-Punkte-Button handelt es sich um ein normales Textfeld, das mit einemnebenstehenden Button um eine Funktion erweitert werden kann. Anwendung findet einesolche Komponente u.a. zur Auswahl von Konten. Das Feld zeigt die aktuelle Auswahl, miteinem Klick auf den Button wird ein Dialog ge¨ffnet, in dem eine neue Auswahl getroffen owerden kann. Ein weiteres Beispiel f¨r die Verwendung eines Drei-Punkte-Buttons ist die uDarstellung von Mail-Adressen. In das Textfeld kann eine Adresse eingegeben werden, an dieauf Knopfdruck eine Nachricht geschickt wird.Die Klasse leitet von LabeledTextField ab und f¨gt folgende Eigenschaften hinzu: upublic void setHref (String href) {public void setTarget (String target) {public void setDirectEdit (boolean directEdit) {Die Funktionalit¨t des Buttons wird durch die Eigenschaft href angegeben. Hierbei kann aes sich um eine URL handeln, die aufgerufen wird, oder auch um eine JavaScript-Funktion,die ausgef¨hrt werden soll. Die Angabe target gibt an, in welchem Fenster bzw. in welchem uFrame die Ausgabe erfolgen soll. Voreinstellung ist, dass die aufgerufenen Seiten im aktuellenFrame erscheinen. M¨glich w¨re allerdings auch, Ausgaben in einem neuen Fenster oder o ain einem anderen Frame zu offnen. Mit dem letzten Attribute directEdit kann eingestellt ¨werden, ob der Anwender Eingaben in dem Textfeld t¨tigen kann. Wird diese Eigenschaft auf a ¨false gesetzt, k¨nnen Anderungen ausschließlich mit dem Button vorgenommen werden. o6.3.9 LabeledCheckBoxDie Klasse LabeledCheckBox dient zur Ausgabe eines beschrifteten Kontrolk¨stchens. Die aKlasse definiert eine Eigenschaftpublic void setValue (boolean value)Hiermit wird angegeben, ob die Check-Box selektiert werden soll oder nicht.6.3.10 LabeledRadioButtonDie Klasse LabeledRadioButtons erzeugt genau wie LabeledCheckBox Auswahllisten, beidenen jedoch keine Mehrfachauswahl m¨glich ist. Radio-Buttons sind eine Gruppe von be- oschrifteten Kn¨pfen, von denen der Anwender immer nur einen ausw¨hlen kann. Die Klasse o awurde von LabeledCheckBox abgeleitet und erweitert diese um eine weitere Eigenschaft.
  • 135. 6.3 Das Packet com.varial.gui 130public void setGroup (String group)Die Angabe group weißt den Radio-Button einer Gruppe zu. Alle Buttons, die der selbenGruppe angeh¨ren, schließen sich in der Auswahl gegenseitig aus. o6.3.11 LabeledComboBoxDie Klasse LabeledComboBox erzeugt eine beschriftete Combo-Box. Aus einer Liste von Abbildung 38: LabeledComboBoxWerten kann jeweils einer ausgew¨hlt werden. Hierzu besitzt die Klasse zwei Eigenschaften. apublic void setValues (String[] values)public void setSelectedIndex (int selectedIndex)Die Eigenschaft values definiert die Liste mit Auswahlm¨glichkeiten. Mit selectedIndex owird angegeben, welcher Eintrag vorselektiert werden soll.6.3.12 LabeledEditableComboBoxDie Klasse LabeledEditableComboBox stellt eine editierbare Combo-Box dar. Im Gegensatzzu der Klasse LabeledComboBox (6.3.11) kann hier nicht nur ein Wert aus einer Liste gew¨hlt awerden, sondern der Benutzer kann zus¨tzlich eigene Werte eingeben. Die Klasse leitet von aLabeledComboBox ab und definiert zus¨tzlich einen weiteren Parameter. apublic void setValue (String value)Die Eigenschaft value gibt den Wert an, der ausgew¨hlt bzw. eingegeben wurde. Durch adie Vererbung besitzt die Klasse weiterhin das Attribute values. Der Unterschied zwischenvalue und values besteht darin, dass values die Auswahlliste definiert, w¨hrend value nur aden jeweils aktuellen Wert angibt.6.3.13 LabeledListBoxDie Klasse LabeledListBox erzeugt eine beschriftete Auswahlliste. Aus einer Liste mit vor-gegebenen Eintr¨gen kann der Anwender einen oder mehrere ausw¨hlen. Außerdem ist es a am¨glich, die Auswahl eines Eintrags zu verhindern. In diesem Fall dient die Komponente olediglich zur Anzeige von Elementen. Außerdem k¨nnen Auswahllisten um zus¨tzliche Funk- o ationen, wie bespielsweise das Hinzuf¨gen oder Entfernen von Elementen erweitert werden. u
  • 136. 6.3 Das Packet com.varial.gui 131Die Klasse wurde von LabeledComboBox (6.3.11) abgeleitet. Die Erweiterung besteht darin,dass im Gegensatz zu einer Combo-Box mehrere Listenelemente sichtbar sind. Die Klassebesitzt eine Reihe weiterer Eigenschaften.public void setSize (int size)public void setMultiple (boolean multiple)public void setSelectedIndexes (int[] indexes)public void setButtons (LabeledListBoxButtons buttons)public void setKeylist (String[] keylist)Mit der Eigenschaft size kann die Gr¨ße der Auswahlliste angegeben werden. Der Wert die- oser Eigenschaft gibt an, wieviele Elemente gleichzeitig sichtbar sind. Bei einem Wert von 1entspricht die Auswahlliste einer Combo-Box.Mit multiple kann angegeben werden, ob eine Mehrfachauswahl m¨glich ist. Steht diese oEigenschaft auf true, k¨nnen mehrere Eintr¨ge gleichzeitig selektiert werden. Bei false ist o alediglich die Auswahl eines Elements m¨glich. oUm anzugeben, welche Listeneintr¨ge bereits selektiert sein sollen, wird selectedIndexes agesetzt. Als Wert wird eine Array von int-Werten erwartet, die die Indizes der angew¨hlten aEintr¨gen angeben. aMit der Eigenschaft buttons k¨nnen der Auswahlliste weitere Funktionen zugewiesen wer- o ¨den. Ubergeben wird eine Instanz der Klasse LabeledListBoxButtons (6.3.14), die Buttonsmit weiteren Funktionalit¨ten implementiert. aAls letzte Eigenschaft muss der Klasse eine sog. keylist gesetzt werden. Diese Liste bein-haltet Schl¨ssel f¨r alle in der Liste erscheinenden Elemente. Der Grund hierf¨r liegt in der u u uTatsache, dass beim Absenden eines HTML-Formulars nur die Werte der selektierten Ele-mente einer Auswahlliste gesendet wird. Es kann jedoch sein, dass die Auswahlliste nur zurDarstellung von Werten benutzt wird. Eine Auswahl ist nicht erw¨nscht. Stattdessen k¨nnen u oweitere Elemente mit den entsprechenden Buttons hinzugef¨gt bzw. wieder entfernt wer- uden. Da eine Auswahl hier nicht gew¨nscht ist, w¨rden beim Absenden des Formulars keine u uWerte ubertragen. F¨r das verarbeitende Servlet entst¨nde der Eindruck, dass die Liste leer ¨ u asei. Um dies zu verhindern, wird die keylist-Eigenschaft gesetzt. Die Klasse erzeugt dannautomatisch einige versteckte Felder mit diesen Angaben. Diese Werte werden somit auf je-den Fall ubertragen und sollten die Listeneintr¨ge eindeutig beschreiben. Sinnvolle Werte f¨r ¨ a uListeneintr¨ge w¨re beispielsweise die ID des Business Objektes. a a6.3.14 LabeledListBoxButtonsMit der Klasse LabeledListBoxButtons k¨nnen einer List-Box (6.3.13) weitere Funktio- onen zugewiesen werden. Manchmal is es sinnvoll, einer Auswahlliste zus¨tzliche Funktiona- alit¨t zu verleihen. Ein Bespiel hierf¨r w¨ren Funktionen zum Hinzuf¨gen bzw. zum Ent- a u a ufernen von Elementen der Liste. Da HTML keine PopUp-Men¨s unterst¨tzt, werden sol- u uche zus¨tzlichen Funktionen bei VWE-Web in Form von Icons angezeigt. Mit der Klasse a
  • 137. 6.3 Das Packet com.varial.gui 132LabeledListBoxButtons k¨nnen solche Icons implementiert werden. Sie werden im Anschluss oder Klasse LabeledListBox uber derren Eigenschaft buttons ubergeben. Nun erscheinen die ¨ ¨Funktionen als kleine Bildchen unterhalb der Auswahlliste.Ein Button besteht immer aus zwei Eigenschaften: Caption und Action.Die Caption gibt eine Beschriftung an, also einen Text, der als Tooltip des Icons erscheint.Action gibt die eigentliche Funktion an.public void addButton (String caption, String action)H¨ufig verwendete Funktionen sind das Hinzuf¨gen eines Elements zu der Liste, das Entfernen a uaus der Liste und das Anfordern weiterer Einzelheiten zu einem ausgew¨hlten Element. F¨r a udiese drei Funktionen bietet die Klasse bereits vorgefertigte Methoden.public static LabeledListBoxButtons getAddRemoveDetail( VContext ctx, String listBoxName)public static LabeledListBoxButtons getAddRemoveDetail( VContext ctx, String listBoxName, String[] tooltips)// ---------------------------------------------------------------------public static LabeledListBoxButtons getAddRemove( VContext ctx, String listBoxName)public static LabeledListBoxButtons getAddRemove( VContext ctx, String listBoxName, String[] tooltips)// ---------------------------------------------------------------------public static LabeledListBoxButtons getDetail( VContext ctx, String listBoxName)public static LabeledListBoxButtons getDetail(
  • 138. 6.3 Das Packet com.varial.gui 133 VContext ctx, String listBoxName, String[] tooltips)Mit Hilfe dieser statischen Methoden k¨nnen leicht Button-Kombinationen erstellt werden. oTabelle 4 zeigt, welche Ausgaben die Funktionen erzeugen. Alle Funktionen k¨nnen wahlweise o Methode Hinzuf¨gen u Entfernen Details getAddRemoveDetail() ja ja ja getAddRemove() ja ja nein getDetail() nein nein ja Tabelle 4: Erzeugte Ausgaben der Klasse LabeledListBoxButtonsmit oder ohne den Parameter tooltip aufgerufen werden. Wird dieser Parameter ubergeben, ¨werden die ubergebenen Texte als Hinweistext bei den Icons angezeigt. ¨6.3.15 LabeledGridDie Klasse LabeledGrid stellt eine beschriftete Tabelle dar. Tabellen sind eine zentrale GUI-Komponente in VWE. Mit ihr werden Daten strukturiert dargestellt. Außerdem kann derBenutzer Zelleninhalte ver¨ndern. In HTML sind zwar Tabellendarstellungen m¨glich, eine a oKomponente mit editierbaren Zellen gibt es hingegen nicht. Deshalb wurde selbst eine solcheKomponente entworfen. Sie befindet sich in der Klasse GridBean (6.3.16). Die Handhabungvon Benutzereingaben und die Formatierung der Tabelle ubernimmt die Klasse VState (6.1.6) ¨bzw. eine ihrer Unterklassen. Die Klasse LabeledGrid stellt eine Instanz des VGrids mit einerBeschriftung dar. Als Eigenschaften besitzt sie:public void setState (VState state)public void setHeight (String height)public void setWidth (String width)public void setShowMenu (boolean showMenu)public void setHeaderAlign (String headerAlign)Zuerst sollte state gesetzt werden. Der ubergebene VState formatiert die Tabelle und behan- ¨delt Benutzereingaben. Die Gr¨ße der Tabelle wird mit den Attributen height und width ogeregelt, die die H¨he und Breite der Tabelle angeben. Mit showMenu kann definiert wer- oden, ob die Tabelle eine Men¨zeile mit zus¨tzlichen Funktionen erhalten soll. Als weitere u aEigenschaft kann mit headerAlign die Ausrichtung der Beschriftung ge¨ndert werden. Stan- adardm¨ssig wird die Beschriftung der Tabelle links neben ihr angezeigt. Alternativ kann die aEingschaft auf auch top“ gesetzt werden, so dass die Beschriftung oberhalb erscheint. ”
  • 139. 6.3 Das Packet com.varial.gui 134Genau wie bei der Klasse LabeledListBox (6.3.13) werden Funktionalit¨ten in Form von aIcons unterhalb der Tabelle angezeigt. Um Icons einzuf¨gen, dient die Methode addEntry(). upublic int addEntry ( String img, String description, String action)So wird ein Symbol f¨r eine neue Aktion eingef¨gt. Der Parameter img gibt den Namen des u uBildes an, description liefert die Beschreibung der Aktion, die als Tooltip erscheinen soll undmit action wird der Aktion ein Name gegeben. Dieser Namen wird bei Klick auf den Buttonubertragen. Das Servlet kann mit catchActionEvent() darauf reagieren. R¨ckgabewert ist¨ uder Index des neuen Symbols in der Men¨leiste. uTrennsymbole zwischen den Icons lassen sich mit addSeparator() einf¨gen: upublic int addSeparator()Das Tabellen-Men¨ ist so voreingestellt, dass bereits Icons f¨r die Aktionen Reihe hin- u u ”zuf¨gen“, Reihe entfernen“, Export nach Excel“ und Drucken“ erscheinen. Es m¨ssen u u ” ” ”also nur noch benutzerdefinierte Funktionen hinzugef¨gt werden. Um Icons ein- bzw. auszu- ublenden dienen die Methoden showIcon() und hideIcon().public void showIcon (int iconindex)public void hideIcon (int iconindex)¨Ubergibt man einer dieser Methoden den Index eines Men¨icons wird dieses angezeigt ubzw. versteckt. Um Icons ein- bzw. auszublenden dienen die Methoden turnIconOn() undturnIconOff().public void turnIconOn (int iconindex)public void turnIconOff (int iconindex)Die Klasse bietet weiterhin die M¨glichkeit, fest definierte Zust¨nde anzunehmen. o apublic void toInfoView()public void toListView()Bei dem Aufruf von toListView() nimmt das Tabellen-Men¨ das f¨r Listenansicht typi- u usche Aussehen an. Das Hinzuf¨gen und Entfernen von Zeilen wird ausgeblendet, alle anderen uSymbbole bleiben stehen. Bei der zweiten Methode wird das Men¨ in eine Info-Ansicht ver- usetzt. Auch hier werden die Aktionen f¨r das Hinz¨gen und Entfernen deaktiviert. u u
  • 140. 6.3 Das Packet com.varial.gui 1356.3.16 GridBeanDie Klasse GridBean ist f¨r die Darstellung einer editierbaren Tabelle zust¨ndig. Die Be- u ahandlung von Aktionen sowie die Formatierung der Tabelle wird wie bereits beschrieben vonder Klasse VState (6.1.6) oder einer abgeleiteten Klasse ubernommen. Die Erzeugung einer ¨Tabelle ubernimmt in der Regel die Klasse LabeledGrid (6.3.15). Aus diesen Gr¨nden bleibt ¨ uals einzige Aufgabe der GridBean, neue Datens¨tze zu den bestehenden Daten hinzuzuf¨gen a ubzw. diese zu l¨schen. Um die Tabelle mit Inhalt zu f¨llen dient die Methode addRow(). o upublic void addRow ( VContext ctx, Object[] rowData)public void addRow ( VContext ctx, BO bo, Object[] rowData)public void addRow ( VContext ctx, BO bo, Object[] rowData, String[] linkData)Der Methode muss zum einen ein VContext-Objekt ubergeben werden. Zum anderen wird ¨immer ein Object-Array erwartet, der die anzuzeigenden Werte beinhaltet. An der erstenPosition des Arrays befindet sich der Wert f¨r die linkeste Spalte, die ¨ußerste rechte Spal- u ate wird mit dem letzten Wert gef¨llt. Da als Typ ein Object m¨glich ist, k¨nnen beliebige u o oTypen ubergeben werden. So ist es m¨glich, Strings, Integer, Vectoren f¨r Combo-Boxen ¨ o uoder auch Boolean f¨r Check- oder Radio-Boxen zu ubergeben. u ¨ ¨Damit beim Uberfahren der Eintr¨ge die Statusmeldung mit Datum und Benutzerkennung a ¨der letzten Anderung erscheint, kann dem neuen Tabelleneintrag weiterhin ein BO ubergeben ¨werden. Hierzu dient die zweite Methode. Bei der dritten Methode kann ein weiteres Arraymit Strings als Parameter mit angegeben werden. Dieser kann Verweise aufnehmen, zu denengesprungen wird, wenn der Benutzer einen Tabelleneintrag anklickt. So k¨nnen beispielsweise oDetailansichten zu Eintr¨gen definiert werden. Die Verweise, mit denen der Anwender von ei- aner normalen Listendarstellung zur Detaildarstellung navigieren kann, m¨ssen ubrigens nicht u ¨expliziet angegeben werden. Wird der Tabelle ein VListState (6.1.7) zugewiesen und wirdder addRow()-Methode ein BO bekannt gemacht, werden die Tabellenzeilen automatisch mitLinks zu Detailansicht versehen.Weitere Aktionen, wie das Hinzuf¨gen einer neuen, d.h. leeren Zeile und das entfernen von uvorhandenen Werten behandelt die Klasse bzw. der entsprechende State selbstst¨ndig, so adass die addRow()-Methode in der Regel die einzige Methode sein wird, die aufgerufen wird.
  • 141. 6.3 Das Packet com.varial.gui 1366.3.17 DivGridBeanDie Klasse DivGridBean stellt ebenfalls eine Tabelle dar. Sie ¨hneld nicht nur der GridBean a(6.3.16), sondern wurde auch von ihr abgeleitet. Der Unterschied zwischen beiden Tabellen be-steht darin, dass DivGridBean nicht als HTML-Tabelle mit dem table-Tag dargestellt wird,sondern mit Blockelementen mit dem div-Tag nachgebildet werden. Hierdurch ist ein Einsatzals Callback (5.5) m¨glich. Dem Vorteil einer schnellen Darstellung von großen Tabellen steht oder Nachteil gegeb¨ber, dass bei der Verwendung einer DivGridBean im zugeh¨rigen VState u o(6.1.6 Werte f¨r Spaltenbreite angegeben werden m¨ssen, w¨hrend die Spaltenbreite bei ei- u u aner GridBean optimal an die jeweiligen Eintr¨ge angepasst werden. Die Klasse DivGridBean akommt deshalb ausschließlich in Verbindung mit Callbacks zum Einsatz.Sowohl f¨r den Anwender als auch f¨r den Entwickler gestalltet sich die Handhabung v¨llig u u otransparent. Unterschiede in der Benutzung gibt es keine. Der Entwickler muss lediglich imin der passenden VState-Klasse (6.1.6) die Methode isCallback() so uberladen, dass diese ¨true liefert.Die Klasse DivGridBean uberl¨dt ausschließlich Methoden der Oberklasse und definiert keine ¨ aeigenen Funktionen.6.3.18 GraphBeanDie Klasse GraphBean stellt ein Diagramm dar. Dem Benutzer wird zuerst eine Miniatur-ansicht pr¨sentiert, die sich durch Anklicken vergr¨ßern l¨ßt. Das Diagramm wird mit Hilfe a o ader Klasse VChartServlet erzeugt. Der GraphBean muss lediglich eine Instanz dieser Klasseubergeben werden.¨public void setServlet (VChartServlet servlet)6.3.19 ImageBeanMit Hilfe dieser Klasse k¨nnen Bilder dargestellt werden. Der ImageBean muss mit der Me- othode setUrl() die Adresse der Bilddatei gesetzt werden.public void setUrl (String url)6.3.20 TabSheetBeanDie Klasse TabSheetBean stellt eine Tabsheet dar. Bei einer Tabsheet handelt es sich umeine Komponente, die oft auch als Reiter oder Register bezeichnet wird. Die Darstellung istangelehnt an eine Karteikartenregister. Durch Anklicken der Karteikarten¨berschriften wird uder entsprechende Inhalt angezeigt. Eine solche grafische Komponente findet sich in einerVielzahl von Desktop-Anwendungen, aud Web-Seiten ist sie hingegen seltener zu finden, daHTML keine entsprechende Komponente zur Verf¨gung stellt. Eine Tabsheet musste somit uselbst entwickelt werden (siehe auch 6.4.20). ¨Der Tabsheet muss als einzige Eigenschaft eine Liste von Uberschriften ubergeben werden. ¨public void setTabSheets (String[] tabsheets)
  • 142. 6.3 Das Packet com.varial.gui 137 ¨Die Strings werden als Uberschriften der Register verwendet. Dabei steht der erste Eintrag ¨ganz links, weitere werden rechts daneben aufgereiht. Werden mehr Uberschriften uberge-¨ben als auf der Bildschirmbreite Platz finden, werden die Bezeichnungen in mehrere Reihenaufgeteilt. Die Reihe mit der jeweils ausgew¨hlten Registerkarte befindet sich hierbei immer aunten.Wird f¨r eine Registerkarte null als Bezeichnung ubergeben, wird diese nicht angezeigt. Die- u ¨se Vorgehensweise hat in der Praxis durchaus Sinn, da sich so einzelne Karten ausblendenlassen. Ein praktisches Beispiel findet sich in der Finanzbuchf¨hrung bei den Debitoren- und uKreditoren-Stammdaten. Da sich beide Anwendungen sehr stark ahneln, kann ein Servlet ¨die Verarbeitung von beiden Use-Cases ubernehmen. Debitoren weißen aber einige Merkmale ¨auf, die bei Kreditoren nicht vorgesehen sind. Die Oberfl¨che besitzt folglich einige Regi- asterkarten mehr. Bei der Kreditorenverwaltung wird dort, wo die Debitorenverwaltung dieentsprechenen Tabsheet-Beschriftung ubergibt, einfach null angegeben. Folge ist, dass diese ¨Karteikarte nicht angezeigt wird, aber in der Vergabe von Index-Nummern f¨r die Tabsheet uber¨cksichtigt wird. Ein kleines Beispiel in Tabelle 5 soll dies verdeutlichen: Kreditoren be- u Use-Case Index 1 Index 2 Index 3 Debitoren Adresse Mahnwesen Bankverbindung Kreditoren Adresse null Bankverbindung Tabelle 5: Beispiel f¨r die Vergabe von Index-Nummern bei Tabsheets u ¨sitzen keine Registerkarte f¨r das Mahnwesen; hier wird mit der Uberschrift null die Karte ueinfach ausgeblendet. Die Registerkarte f¨r Bankverbindung erh¨lt genau wie in der Debi- u atorenverwaltung den Index 3. Da nun bei Wechsel der Karte nicht die Bezeichnung (dieseist ja abh¨ngig von der aktuellen Sprache), sondern der Index an das Servlet geliefert wird, akann das Servlet den Index 3 eindeutig der Bankverbindung zuordnen. W¨rde bei Kreditoren uanstelle von null nichts ubergeben, w¨re die Ausgabe der TabSheetBean zwar identisch, das ¨ aServlet m¨sste aber die Bankverbindungsdaten einmal bei dem Index 2 und das andere mal ubeim Index 3 liefern. Ein gemeinsame Bearbeitung von mehreren Use-Cases durch ein Servletw¨re nicht m¨glich. a o6.3.21 MenuBarBeanDie MenuBarBean erzeugt eine Men¨leiste und stellt diese dar. Die Men¨leiste setzt sich aus u udrei Teilen zusammen: Icons vor der Combo-Box, die Combo-Box selbst und Icons hinterder Combo-Box. Symbole links neben der Combobox sind in der Regel fest vorgegeben. Hierk¨nnen keine neuen Symbole hinzugef¨gt oder bestehende entfernt werden. Die Combobox o uselbst beinhaltet standardm¨ssig eine Firmenauswahl, kann aber auch ge¨ndert werden. Icons, a adie rechts neben der Combobox stehen, sind spezifisch f¨r den jeweiligen Use-Case, sie werden ualso expliziet hinzugef¨gt. Dazu bietet die Klasse die Methode addEntry. upublic int addEntry ( String img, String description
  • 143. 6.3 Das Packet com.varial.gui 138)public int addEntry ( String img, String description, String action)Der Methode wird zum einen der Name des Bildes ubergeben, zum anderen erwartet sie als ¨Parameter zus¨tzlich die Beschreibung der Funktion, die als Tooltip angezeigt wird. Das op- ationale action-Attribute wird beim Anklicken als Parameter ubergeben, so dass das Servlet ¨erkennen kann, welche Aktion ausgel¨st wurde. Die Klasse VContext (6.1.10) bietet in diesem oZusammenhang einige n¨tzliche Methoden wie getMenuAction() etc. Wird keine Aktion an- ugegeben, wird er Name des Bildes als Aktionsname verwendet.Nat¨rlich k¨nnen auch Trennsymbole eingef¨gt werden. Hierf¨r muss die Methode u o u uaddSeparator() aufgerufen werden.public int addSeparartor()Alle diese Methoden liefern eine Zahl zur¨ck. Sie zeigt an, welchen Index das eingef¨gte u uIcon in der Men¨leiste einnimmt. Mit diesem Index k¨nnen die Symbole sp¨ter angesprochen u o awerden. Sie k¨nnen ein- und ausgeblendet werden und aktiviert bzw. deaktiviert werden. opublic void turnIconOff (int iconindex)public void turnIconOn (int iconindex)public void hideIcon (int iconindex)public void showIcon (int iconindex)Mit turnIconOn() und turnIconOff() werden Men¨punkte aktiviert bzw. deaktiviert, uhideIcon() blendet Symbole aus, showIcon() sorgt daf¨r, dass sie wieder angezeigt wer- uden. Als Parameter wird der erw¨hnte Index angegeben. Wird eine negative Zahl ubergeben, a ¨ ¨betreffen die Anderungen die Combo-Box.Die Klasse bietet bereits vorgefertigte Schemata, die oft vorkommende Ansichten definieren.public void toListView()public void toListView (boolean isCallback)public void toInfoView()public void toInfoView (boolean isCallback)public void showCallback()
  • 144. 6.3 Das Packet com.varial.gui 139In der Listenansicht sollte die Men¨leiste mit Aufruf von toListView() in die passende uAnsicht versetzt werden. Lediglich das Symbol zum Anlegen neuer Objekte und der Reload-Button sind hier aktiviert. Alle anderen Aktionen machen keinen Sinn und werden dement-sprechend deaktiviert. Die Methode toInfoView() deaktiviert die Symbole f¨r das Anlegen, uL¨schen und Speichern von Objekten. Diese Ansicht sollte gew¨hlt werden, wenn die Detail- o aAnsicht keine schreibende Zugriffe erm¨glicht, sondern nur Informationen zur Verf¨gung o ustellt. Die Kontenliste im Use-Case NominalLedgerAccountInformation“, die vorhande- ”ne Kontenst¨nde zeigt w¨re ein Beispiel f¨r eine solche Ansicht. a a uEs f¨llt auf, dass allen Methoden ein Wahrheitswert mit der Bezeichnung isCallback uber- a ¨geben werden kann. Wird hier true ubergeben, wird zus¨tzlich das Symbol f¨r das Abrechen ¨ a udes Ladevorgangs angezeigt. Alternativ kann man auch mit der showCallback()-Methodedaf¨r sorgen. uAls letztes kann auch noch die Combo-Box in der Men¨leiste ver¨ndert werden. In einem u a ¨Großteil aller Anwendungen wird hier die aktuelle Firma ausgew¨hlt. Anderungen sind dann anicht notwendig. Soll hingegen etwas anderes ausgew¨hlt werden (der Use-Case TaskRemin- a ”der“ definiert z.B. eine Ordnerauswahl), kann die Combo-Box mit setComboBox ge¨ndert awerden.public void setComboBox(MenuBarComponentInterface combobox) ¨Das Ubergebene Objekt muss das MenuBarComponentInterface (6.3.24) implementieren.6.3.22 MenuEntryTreeBeanMit der Klasse MenuEntryTreeBean wird der Men¨baum erstellt. Die Daten f¨r die u uMen¨punkte liefert der Server aus der Datenbank. Diese Daten k¨nnen im VWE- u oAdministrationsmodus gepflegt werden, d.h. es k¨nnen vorhandene Programmmodule aus- ogeblendet oder gel¨scht werden oder es k¨nnen neue Use-Cases aufgenommen werden. Da o odies allerdings sehr selten passiert, werden die Daten f¨r den Men¨baum nicht jedesmal vom u u ¨Server geholt, sondern im Client gecachet. Dies hat zur Folge, dass nach Anderungen der u ¨Men¨struktur der Web-Server neugestartet werden muss, um die Anderungen zu uberneh-¨men.Als einzige ¨ffentliche Methode besitzt die Klasse getOutput(). opublic String getOutput()6.3.23 MenuEntryDie Klasse MenuEntry wird ausschließlich von MenuEntryTreeBean (6.3.22) verwendet undist deshalb außerhalb des Packets nicht zug¨nglich. Sie repr¨sentiert einen einzelnen Men¨- a a uEintrag mit dessen Eigenschaften.6.3.24 MenuBarComponentInterfaceDas Interface MenuBarComponentInterface legt fest, dass alle Objekte, die als Combo-Boxin der Men¨leiste erscheinen sollen, die Methode getOutput() implementieren. u
  • 145. 6.3 Das Packet com.varial.gui 140public String getOutput( VContext ctx, boolean enable)6.3.25 SelectCompanyBeanDie Klasse SelectCompanyBean implementiert das Interface MenuBarComponentInterface(6.3.24) und erstellt die Combo-Box zur Firmenauswahl, die in der Men¨leiste erscheint. u6.3.26 SelectOkCancelButtonBeanMit der Klasse SelectOkCancelButtonBean k¨nnen Buttons f¨r Auswahldialogen erzeugt o uwerden. Als Buttom k¨nnen Best¨tigungs- und Abruch-Buttons erstellt werden. Ein Abbruch- o aButton wird immer erzeugt, die Anzeige des OK-Buttons ist hingegen optional. Um festzule-gen ob er angezeigt werden soll, muss die Methode setShowOkButton() aufgerufen werden.public void setShowOkButton (boolean show)Wird die Methode mit true aufgerufen, wird zus¨tzlich ein OK-Button f¨r die Best¨ti- a u agung erzeugt, andernfalls nicht. Oft wird die Klasse in Verbindung mit Tabellen und derSelectSearchBean-Klasse (6.3.27) verwendet. Der Auswahldialog zeigt dann eine Tabellemit einer Reihe von Eintr¨gen. Ein Eintrag wird durch einfaches Anklicken ausgew¨hlt, so a adass ein OK-Button in diesem Fall nicht notwendig ist.6.3.27 SelectSearchBeanAuch die Klasse SelectSearchBean findet in Auswahldialogen Verwendung. Sie erzeugt einTextfeld, dessen Eingabe zum Filtern von Tabellen-Inhalten verwendet wird. Der Inhalt derTabelle passt sich den Eingaben in diesem Feld an. D.h. dass die Tabelle nur Daten zeigt,die den eingegebenen Filter-Kriterien entsprechen. Zeigt die Tabelle beispielsweise eine Auf-listung von Konten, kann der Anwender durch Eingabe des Konto-Codes die Auswahl ein-schr¨nken. Dies kann entweder automatisch oder nur auf Anfrage geschehen. Hierzu befindet asich rechts neben dem Textfeld ein Icon, mit dem die Tabellenausgabe aktualisiert wird. DerAnwender gibt also zun¨chst das Suchkriterium ein und klickt dann auf das Icon. Die Tabel- alenansicht wird entsprechend aktuallisiert. Um diesen Vorgang zu automatisieren, befindetsich neben dem Icon ein Check-Box. Ist diese angew¨hlt, f¨hren alle Angaben sofort zur Aus- a ugaben¨nderung. Die Tabelle wird unmittelbar an den Filter angepasst. Da dies bei langsamen aVerbindungen einige Zeit in Anspruch nehmen kann, k¨nnte der Bedienungskonfort der An- owendung deutlich darunter leiden. Aus diesem Grunde, wurde dem Anwender die M¨glichkeit ogegeben, die automatische Aktuallisierung auszuschalten.6.3.28 JavaScriptBeanDie Klasse JavaScriptBean ist daf¨r zust¨ndig, JavaScript-Code f¨r die HTML-Ausgabe u a uvorzubereiten. Erzeugt ein Servlet, eine GuiBean oder sonstige Klassen JavaScript-Code, sokann dieser Code durch die JavaScriptBean in die JSP-Seite eingebettet werden. Alle auf
  • 146. 6.3 Das Packet com.varial.gui 141diese Weise erzeugten JavaScript-Befehle befinden sich dann automatisch im head-Bereichder Seite. Der JavaScript-Code wird einfach einem der Konstruktoren ubergeben. ¨public JavaScriptBean( VContext ctx, String code)public JavaScriptBean( VContext ctx, StringBuffer code)public JavaScriptBean( VContext ctx, String version, String code)public JavaScriptBean ( VContext ctx, String version, StringBuffer code)Die ersten beiden Konstruktoren erwarten keine Versionsangabe, die beiden anderen hinge-gen schon. Da es auch bei JavaScript verschiedene Sprachversionen gibt, werden nicht alleBefehle von allen Browsern unterst¨tzt. Um anzugeben, dass die Ausf¨hrung nur ab einer u ubestimmten Version erfolgen soll, kann eine solche Versionsnummer ubergeben werden. Der ¨JavaScript-Code kann sowohl als String als auch als StringBuffer angegeben werden. Da-durch entstehen insgesammt vier Konstruktoren.Eine besondere Bedeutung kommt der Versionsangabe INIT“ zu. Wird eine solche Version ”angegeben, wird der Code unmittelbar nach dem Ladevorgang der Seite ausgef¨hrt. Bei allen uJavaCode-Befehle, die mit der Version INIT“ erzeugt werden, sorgt die JavaScriptBean ”daf¨r, dass sie zu Beginn ausgef¨hrt werden. u uDer ubergebene Code wird von der Klasse (unter Ber¨cksichtigung evtl. spezifizierten Versi- ¨ uonsnummern) in ein passendes script-Element eingebettet und in die JSP-Ausgabe einge-baut.6.3.29 JavaScriptHelperMit der Klasse JavaScriptHelper k¨nnen oft wiederkehrende JavaScript-Fragmente erstellt owerden. Die Klasse beitet dazu eine Reihe statischer Funktionen. Ein Bespiel f¨r solche Me- uthoden sind die mailto- und http-Anweisung.public final static String mailto (String fieldname)
  • 147. 6.3 Das Packet com.varial.gui 142public final static String http (String fieldname)Diese Funktionen werden im Zusammenhang mit Drei-Punkte-Buttons (6.3.8) verwendet.Bei diesen Button-Feldern ist es m¨glich, eine eMail- oder Homepage-Adresse einzugeben. oEin Klick auf den Button ¨ffnet in diesem Fall die Adresse. Um eine solche Funktionalit¨t zu o aerreichen, ist die Verwendung von JavaScript erforderlich. Die beiden Methoden implemen-tieren diesen JavaScriptCode f¨r http- bzw. mailto-Adressen. Sie erwarten als Parameter uden Namen des Feldes, dass die Adresse enth¨lt. Die erzeugte Ausgabe kann dann dem Drei- aPunkte-Button als Adresse ubergeben werden. ¨Beispiel:GuiHelper.addButtonFieldForBrowser( ctx, translator, "contacts__mail", "emaillabel", "moeller@varial.de", JavaScriptHelper.mailto("contacts__mail"), "_self")Das Beispiel erzeugt ein Drei-Punkte-Button mit dem Namen contacts mail“. Dieser ”wird mit der Adresse moeller@varial.de“ gef¨llt. Man erkennt, dass die Ausgabe der u ”mailto()-Funktion als URL-Angabe ubergeben wurde. Dadurch werden die Eingaben, die in ¨diesem Feld get¨tigt werden, auf Knopfdruck im Mail-Client ge¨ffnet. Analog hierzu w¨rde a o udie http()-Funktion verwendet, um eine Internet-Seite zu ¨ffnen. o Der zweite Anwendung des JavaScriptHelpers liegt darin, Abh¨ngigkeiten zwischen zwei aoder mehreren GUI-Komponenten zu definieren. Beispielsweise k¨nnte eine Check-Box ein oEingabefeld aktivieren bzw. deaktivieren. Der JavaScriptHelper bietet die M¨glichkeit der oAbh¨ngigkeitsdefinition f¨r Check-Boxen, Radio-Buttons und Combo-Boxen. a uAbh¨ngigkeiten von Check-Boxen werden wie folgt definiert: apublic final static StringBuffer enableByCheckBox( String checkbox, String field)public final static StringBuffer enableByCheckBox( String checkbox, String[] fields)public final static StringBuffer disableByCheckBox( String checkbox, String field
  • 148. 6.3 Das Packet com.varial.gui 143)public final static StringBuffer disableByCheckBox( String checkbox, String[] fields)Da Komponenten durch die Anw¨hlen Check-Box entweder aktiviert oder deaktiviert awerden k¨nnen, gibt es sowohl eine Methode namens enableByCheckBox() als auch odisableByCheckBox(). Weil weiterhin eine einzelne Komponente oder eine Reihe von Kom-ponenten gesteuert werden k¨nne, gibt es jede Methode in zweifacher Ausfertigung. oAls Parameter wird zum einen der Name der Check-Box angegeben, die f¨r die Aktivie- urung/Deaktivierung verantwortlich ist, zum anderen wird das Feld oder die Felder ubergeben, ¨die aktiviert/deaktiviert werden. Die Ausgabe dieser Funktionen k¨nnen den entsprechenden oMethoden des GuiHelpers (6.3.1) als interdependence-Angabe ubergeben werden. ¨Beispiel:GuiHelper.addCheckBox( ctx, translator, "address__stop", "stoplabel", mBo.isStop(), JavaScriptHelper.enableByCheckBox( "address__stop", "address__comment" ));In diesem Beispiel wird das Feld mit dem Namen addresss comment“ nur dann aktiviert, ”wenn die Combo-Box namens address stop“ angeklickt wurde. Hintergrund ist der, dass ”im Feld addresss comment“ ein Kommentar angegeben werden kann, weshalb eine Adresse ”nicht mehr verwendet werden sollte. Dieser Kommentar macht nat¨rlich nur dann Sinn, wenn umit der Check-Box addess stop“ angegeben wurde, dass die Adresse keine Verwendung ”mehr findet.Die Methoden f¨r Radio-Buttons verhalten sich analog zu den obigen. upublic final static StringBuffer enableByRadioButton( String group, int index, String field)public final static StringBuffer enableByRadioButton( String group, int index, String[] fields
  • 149. 6.3 Das Packet com.varial.gui 144) Ein wenig anders verh¨lt es sich bei Combo-Boxen. Diese haben im Gegensatz zu Check- aBoxen oder Radio-Buttons keinen boolschen Wert, der angibt, ob die Komponente ausgew¨hlt aist oder nicht. Vielmehr kann eine Combo-Box eine Reihe von m¨glichen Werten annehmen. oEs muss also zus¨tzlich angegeben werden, wann die Aktivierung/Deaktivierung erfolgen soll. aHierzu dient ein weiterer Parameter mit Namen condition.public final static StringBuffer enableByComboBox( String combobox, String condition, String field)public final static StringBuffer enableByComboBox( String combobox, String condition, String[] fields)Die Funktionsweise l¨ßt sich auch hier am einfachsten mit einem Beispiel erkl¨ren. Der a afolgende Befehl erstellt eine Combo-Box namens address ECVATRegNrCountry“. Diese ”Combo-Box enth¨lt eine Liste von L¨ndercodes. Im Zusammenhang mit dem Textfeld a a address ECVATRegNr“ bildet sie eine Angabe f¨r einen Steuerschl¨ssel. Ein solcher Steuer- u u”schl¨ssel besitzt immer den Aufbau L¨nderkennung + Zahlen-/Buchstabenfolge. Eine Einga- u abe der Zahlen-/Buchstabenfolge soll nur dann m¨glich sein, wenn ein L¨ndercode ausgew¨hlt o a awurde. Da der erste Eintrag der Combo-Box leer ist, muss gepr¨ft werden, ob ein Eintrag uungleich dem ersten ausgew¨hlt ist. Erst dann darf das Textfeld aktiviert werden. aGuiHelper.addComboBox( ctx, translator, "address__ECVATRegNrCountry", "ectaxnumberlabel", eccsl.getStrings(), ecIndex, JavaScriptHelper.enableByComboBox( "address__ECVATRegNrCountry", "!=0", "address__ECVATRegNr" )); ¨Man erkennt, dass als Bedingung !=0“ angegeben wurde. Es wird also eine Uberpr¨fung u ”durchgef¨hrt, ob ein Element ungleich dem ersten selektiert ist. Ist dies der Fall, wird das uFeld address ECVATRegNr“ f¨r die Eingabe freigegeben. u ”
  • 150. 6.3 Das Packet com.varial.gui 1456.3.30 ThemeMit der Klasse Theme wird es erm¨glicht, die Oberfl¨che an verschiedene Corporate Designs o a(4.4.2) anzupassen. Sie sorgt daf¨r, dass Stylesheets und Bilddateien (Symbole, etc) gem¨ß u adem momentan eingestellten Theme geladen werden. Dazu bietet sie zwei Arten von statischenMethoden. Zum einen kann die CSS-Datei und zum anderen ein Bild angefordert werden.public static String getCss ( HttpServlet servlet, HttpServletRequest req, int move)public static String getCss ( VContext ctx, String url, int move)public static String getCss ( VContext ctx, int move)public static String getImg ( HttpServlet servlet, HttpServletRequest req, String url, int move)public static String getImg ( VContext ctx, String url, int move)Die Funktion getCss() liefert die Adresse der Stylesheet-Datei, der R¨ckgabewert von ugetImg() bezeichnet die URL eines angeforderten Bildes. Je nach Situation, aus der die ¨Methoden aufgerufen werden, ist entweder die Ubergabe eines VContexts (6.1.10), oderdie Angabe eines Servlets und dem passenden Request-Objekts leichter. Die Methodender Klasse Theme unterst¨tzen beide Vorgehensweisen. Es f¨llt auf, dass ein weiterer u aParameter namens move angegeben werden muss. In der Regel ist dies der Wert 0, derbesagt, dass Theme die richtige Adresse liefert. Durch Umleitung einer Anfrage mittels dessendRedirect()-Befehls der Klasse VServlet (6.1.1) kann es vorkommen, dass der Aufrufder Theme-Funktion von einer anderen Seite, als der angeforderten durchgef¨hrt wird. Wenn u
  • 151. 6.4 Das Packet com.varial.taglib 146sich beide Seiten in verschiedenen Verzeichnistiefen befinden, liefert die Klasse Theme einfalsches Ergebnis, das aber mit dem move-Parameter korrigiert werden kann. Positive Zahlenbedeuten, dass die aufgerufene Datei um die entsprechende Anzahl von Verzeichnissen tieferliegt. W¨rde Theme also ../../THEME/varial/style.css“ liefern, w¨rde der Wert 1 f¨r u u u ”den move-Paramter die Ausgabe in ../../../THEME/varial/style.css“ ¨ndern. Analog a ”dazu leifert -1 dann ../THEME/varial/style.css“. ”Um ein Bild anzufordern muss außerdem der Name des Bildes angegeben wer-den. Dies kann beispielsweise icon SaveBo on“ sein. Dieses Bild stellt das akti- ”vierte Symbol f¨r das Speichern eines Business-Objektes dar. Je nach eingestell- uten Theme w¨rde die Methode dann ../../THEME/varial/pic/icon SaveBo on“, u ” ../../THEME/einAnderesTheme/pic/icon SaveBo on“ oder” ../../THEME/eineAusgefalleneOberflaeche/pic/icon SaveBo on“ zur¨ckgeben. Der u”Entwickler muss also nur alle themespezifischen Angaben von der Klasse Theme anfordern.Diese sorgt dann daf¨r, dass die richtigen Dateien geladen werden. u6.4 Das Packet com.varial.taglibDas Packet enth¨lt benutzerdefinierte Tags, die sich genau wie HTML-Tags in JSP-Seiten aeinbetten lassen und dort f¨r die Ausf¨hrung von Java-Code zust¨ndig sind. Eine solche u u aSammlung von selbsterstellten Tags wird auch als Taglib bezeichnet.6.4.1 varial.tldBei der Datei varial.tld handelt es sich um eine sog. Taglib Descriptor, also umdie Beschreibung von benutzerdefinierten Tags. Es ist eine XMl-Datei, die dem in derDTD http://java.sun.com/j2ee/dtds/web-jsptaglibrary 1 1.dtd beschriebenen Auf-bau folgt. In dieser Datei werden die Tags bestimmten Java-Klassen zugeordnet. Weiterhinwird definiert, welche Attribute die Tags haben, ob diese optional oder obligatorisch sind undob bzw. welche Art von Inhalt die Tags haben d¨rfen. uJedesmal, wenn ein Tag der Taglib in der Seite erscheint, wird die angegebene Klasse aufge-rufen und die Attribut-Werte an die entsprechenden Setter-Methoden ubergeben. Optionale ¨Werte werden bei Nicht-Setzen auf Default-Werte gesetzt. Da einige Eigenschaften auch vom ¨verarbeitenden Servlet gesetzt werden k¨nnen, kann es zu Uberschneidungen kommen. In die- osen F¨llen haben die Angaben des Servlets Vorrang, Wertzuweisungen durch tag-Attribute a ¨sind bei Uberschneidungen also wirkungslos.Die Varial Taglib beinhaltet folgende Elemente:textfield Behandelt durch die Klasse VTextField (6.4.3).numberfield Behandelt durch die Klasse VNumberField (6.4.4).currencyfield Behandelt durch die Klasse VCurrencyField (6.4.5).datefield Behandelt durch die Klasse VDateField (6.4.6).
  • 152. 6.4 Das Packet com.varial.taglib 147 Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 maxlength Maximale Anzahl von Zeichen unbegrenzt enable Aktivierung des Elements true width Breite des Feldes Browserabh¨ngig a linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 6: Attribute des Tags textfield Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 maxlength Maximale Anzahl von Zeichen unbegrenzt enable Aktivierung des Elements true width Breite des Feldes Browserabh¨ngig a linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 7: Attribute des Tags numberfield Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 maxlength Maximale Anzahl von Zeichen unbegrenzt enable Aktivierung des Elements true width Breite des Feldes Browserabh¨ngig a linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 8: Attribute des Tags currencyfieldmemo Behandelt durch die Klasse VMemo (6.4.7).buttontextfield Behandelt durch die Klasse VButtonTextField (6.4.8).checkbox Behandelt durch die Klasse VCheckBox (6.4.9).radiobutton Behandelt durch die Klasse VRadioButton (6.4.10).
  • 153. 6.4 Das Packet com.varial.taglib 148 Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 maxlength Maximale Anzahl von Zeichen unbegrenzt enable Aktivierung des Elements true width Breite des Feldes Browserabh¨ngig a linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 9: Attribute des Tags datefield Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 maxlength Maximale Anzahl von Zeichen unbegrenzt enable Aktivierung des Elements true width Breite des Felder Browserabh¨ngig a height h¨he des Feldes o Browserabh¨ngig a wrap Umbruch im Feld virtual linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 10: Attribute des Tags memo Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true width Breite des Feldes Browserabh¨ngig a linebreak Umbruch bei langer Beschriftung false target Zielfenster des Button-Links self tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 11: Attribute des Tags buttontextfieldcombobox Behandelt durch die Klasse VComboBox (6.4.11).editablecombobox Behandelt durch die Klasse VEditableComboBox (6.4.12).listbox Behandelt durch die Klasse VListBox (6.4.13).
  • 154. 6.4 Das Packet com.varial.taglib 149 Attribute Bedeutung Default-Wert id ID des Elements obligatorisch colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 12: Attribute des Tags checkbox Attribute Bedeutung Default-Wert id ID des Elements obligatorisch colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 13: Attribute des Tags radiobutton Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true width Breite der Combo-Box Breite des l¨ngsten Eintrags a linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 14: Attribute des Tags combobox Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true width Breite der Combo-Box Breite des l¨ngsten Eintrags a linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 15: Attribute des Tags editablecomboboxgrid Behandelt durch die Klasse VGrid (6.4.14).graph Behandelt durch die Klasse VGraph (6.4.15).
  • 155. 6.4 Das Packet com.varial.taglib 150 Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true width Breite der List-Box Breite des l¨ngsten Eintrags a size Anzahl von sichtbaren Eintr¨gen a 3 linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 16: Attribute des Tags listbox Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 enable Aktivierung des Elements true headeralign Ausrichtung der Beschriftung top width Breite der Tabelle 100% height h¨he der Tabelle o Browserabh¨ngig a tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 17: Attribute des Tags grid Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 rowspan Ausbreitung uber mehrere Zeilen ¨ 1 width Breite des Graphen Bildgr¨ße aus VChartServlet o height h¨he des Graphen o Bildgr¨ße aus VChartServlet o linebreak Umbruch bei langer Beschriftung false tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 18: Attribute des Tags graphimage Behandelt durch die Klasse VImage (6.4.16).empty Behandelt durch die Klasse Empty (6.4.17).Keine Parameter.vspacer Behandelt durch die Klasse Vspacer (6.4.18).
  • 156. 6.4 Das Packet com.varial.taglib 151 Attribute Bedeutung Default-Wert id ID des Elements obligatorisch align horizontale Ausrichtung left colspan Ausbreitung uber mehrere Spalten ¨ 1 rowspan Ausbreitung uber mehrere Zeilen ¨ 1 width Breite des Bildes Bildgr¨ße o height h¨he des Bildes o Bildgr¨ße o tabindex Reihenfolge bei der Tabulator-Navigation Gem¨ß Erstellungs-Reihenfolge a Tabelle 19: Attribute des Tags image Attribute Bedeutung Default-Wert height h¨he o obligatorisch colspan Ausbreitung uber mehrere Spalten ¨ 1 Tabelle 20: Attribute des Tags vspacertabsheetcontrol Behandelt durch die Klasse TabSheetControl (6.4.19).Keine Parameter.tabsheet Behandelt durch die Klasse TabSheet (6.4.20). Attribute Bedeutung Default-Wert index Index der Registerkarte obligatorisch Tabelle 21: Attribute des Tags tabsheetmenubar Behandelt durch die Klasse MenuBar (6.4.21).Keine Parameter.selectokcancel Behandelt durch die Klasse SelectOkCancel (6.4.22).Keine Parameter.selectsearch Behandelt durch die Klasse SelectSearch (6.4.23).Keine Parameter.headline Behandelt durch die Klasse HeadLine (6.4.24).Keine Parameter.lastchange Behandelt durch die Klasse LastChange (6.4.25).javascript Behandelt durch die Klasse JavaScript (6.4.26).
  • 157. 6.4 Das Packet com.varial.taglib 152 Attribute Bedeutung Default-Wert align horizontale Ausrichtung left Tabelle 22: Attribute des Tags lastchange Attribute Bedeutung Default-Wert id ID des Elementes javascript Tabelle 23: Attribute des Tags javascriptcsslink Behandelt durch die Klasse CssLink (6.4.27).Keine Attribute.hiddenfield Behandelt durch die Klasse HiddenField (6.4.28). Attribute Bedeutung Default-Wert name Name des Feldes/Parameters obligatorisch Tabelle 24: Attribute des Tags hiddenfieldhiddenextrafield Behandelt durch die Klasse HiddenExtraField (6.4.29). Attribute Bedeutung Default-Wert name Name des Feldes/Parameters obligatorisch Tabelle 25: Attribute des Tags hiddenextrafieldtranslator Behandelt durch die Klasse Translator (6.4.30). Attribute Bedeutung Default-Wert id ID des Elements obligatorisch module ¨ Module der Ubersetzung obligatorisch owner ¨ Parent der Ubersetzung obligatorisch Tabelle 26: Attribute des Tags translatorlanguagestring Behandelt durch die Klasse LanguageString (6.4.31).
  • 158. 6.4 Das Packet com.varial.taglib 153 Attribute Bedeutung Default-Wert id ID des translator-Tags obligatorisch component ¨ Komponte der Ubersetzung obligatorisch Tabelle 27: Attribute des Tags languagestring6.4.2 VComponentDie Klasse VComponent ist keinem Tag der Taglib direkt zugeordnet. Vielmehr stellt sie eineabstrakte Oberklasse f¨r eine Vielzahl von anderen Klassen dar. Bei der Betrachtung der uTaglib Descriptor (6.4.1) f¨llt auf, dass viele Elemente die gleichen Attribute besitzen. Weil adiese Attribute entsprechende Setter-Methoden in den verantwortlichen Klassen ben¨tigen, obietet es sich an, diese in einer gemeinsamen Oberklasse zu implementierung und durchVererbung weiterzugeben. So besitzt VComponent folgende Methoden:public void setId (String name)public void setAlign (String align)public void setWidth (String width)public void setHeight (String height)public void setTabindex (int tabindex)public void setColspan (int colspan)public void setRowspan (int rowspan)public void setEnable (boolean enable)public void setVisible (boolean visible)public void setLinebreak (String linebreak)Außerdem bietet die Klasse eine Methode namens fillBean() um diese Eigenschaften einemObjekt zuzuweisen.protected void fillBean (VGuiBean bean)Die Funktionsweise der abgeleiteten Taglib-Klasse soll nun am Beispiel der Klasse VTextFieldetwas genauer erl¨utert werden. a6.4.3 VTextFieldDie Klasse VTextField wird verwendet, wenn das textfield-Tag der Varial Taglib in eineJSP-Seite eingebettet ist. Zun¨chst werden f¨r alle Attribute, die in der JSP-Seite gesetzt a u
  • 159. 6.4 Das Packet com.varial.taglib 154werden, die entsprechenden Setter-Methoden aufgerufen. Die Namensgebung der Methodenmuss daf¨r den Regeln einer JavaBean folgen, d.h. eine Methode tr¨gt immer den Namen, u ader sich aus set“ und dem großgeschriebenen Attributenamen zusammensetzt. Dementspre- ”chend implementiert die Klasse f¨r das Attribute maxlength die Methode setMaxlength. upublic void setMaxlength (int maxlength)Dadurch, dass die Klasse VTextField wie viele alle anderen Klassen der Taglib von VCom-ponent abgeleitet wurde, besitzt sie bereits Setter-Methoden f¨r allgemeine Attribute wie uzum Beispiel id, align oder enable. Klassen der Taglib m¨ssen deshalb nur noch f¨r sie u uspezifische Attribut-Setter implementieren.Nachdem die Attribute gesetzt wurden, wird vom Server die Methode doEndTag() aufgerufen.public int doEndTag() throws JspExceptionIn dieser Methode wird die Instanz der Klasse LabeledTextField (6.3.3), die zuvorvom verarbeitenden Servlet mit dem GuiHelper (6.3.1) erzeugt wurde, wieder aus demRequest-Objekt geholt und die restlichen Attribute werden gesetzt. Schließlich wird diegetOutput()-Methode des LabeledTextField aufgerufen, die daf¨r sorgt, dass die entspre- uchende HTML-Ausgabe geschrieben wird.Viele Klassen der Taglib verhalten sich genau so wie die Klasse VTextField. Sie sindvon VComponent abgeleitet, implementieren spezifische Setter-Methoden und holen in derdoEndtag()-Methode die erzeugten GUI-Elemente aus dem Request-Objekt um nachWertzuweisung die Ausgabe der getOutput()-Funktion an den Browser zu senden. Uberall ¨dort, wo ein Tag der Taglib stand, befindet sich anschließend die Ausgabe der entsprechendenKlasse des Packets com.varial.gui. Die Klassen des Packets com.varial.taglib sorgennur daf¨r, dass die HTML-Tags mit den richtigen GUI-Klassen verkn¨pft werden. Hierdurch u ul¨ßt sich eine Programmierung nach dem bereits beschriebenen MVC-Modell (5.2) erreichen. a6.4.4 VNumberFieldDie Klasse VNumberField wird verwendet, wenn das numberfield-Tag der Varial Taglibin eine JSP-Seite eingebettet ist. Die Klasse wurde von VTextField (6.4.3) abgeleitet unddefiniert keine weiteren Setter-Methoden. Das numberfield-Tag wird durch die Ausgabeder entsprechenden Instanz der Klasse LabeledNumberField (6.3.4) ersetzt.Oberklasse: VTextField (6.4.3)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledNumberField (6.3.4)6.4.5 VCurrencyFieldOberklasse: VNumberField (6.4.4)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledCurrencyField (6.3.5)
  • 160. 6.4 Das Packet com.varial.taglib 1556.4.6 VDateFieldOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledDateField (6.3.6)6.4.7 VMemoOberklasse: VTextField (6.4.3)Zus¨tzliche Setter-Methoden: a • public void setWrap (String wrap) • public void setHeight (String height)Ausgabe der Klasse: LabeledMemo (6.3.7)6.4.8 VButtonTextFieldOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: a • public void setTarget (String target)Ausgabe der Klasse: LabeledButtonTextField (6.3.8)6.4.9 VCheckBoxOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledCheckBox (6.3.9)6.4.10 VRadioButtonOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledRadioButton (6.3.10)6.4.11 VComboBoxOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledComboBox (6.3.11)
  • 161. 6.4 Das Packet com.varial.taglib 1566.4.12 VEditableComboBoxOberklasse: VComboBox (6.4.11)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: LabeledEditableComboBox (6.3.12)6.4.13 VListBoxOberklasse: VComboBox (6.4.11)Zus¨tzliche Setter-Methoden: a • public void setSize (int size)Ausgabe der Klasse: LabeledListBox (6.3.13)6.4.14 VGridOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: a • public void setHeaderalign (String align) • public void setHeight (String height)Ausgabe der Klasse: LabeledGrid (6.3.15)6.4.15 VGraphOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: GraphBean (6.3.18)6.4.16 VImageOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: ImageBean (6.3.19)6.4.17 EmptyDie Klasse Empty behandelt das Tag empty und gibt leeren Inhalt aus. Die mag auf denersten Blick verwunderlich erscheinen, eine solche leere Ausgabe hat aber durchaus Sinn. Umdie Oberfl¨che gleichm¨ssig strukturiert darzustellen, wird mit Hilfe unsichtbarer Tabellen a a(auch als blinde Tabellen bezeichnet) eine Art Raster erzeugt. Wird ein Feld des Rastersnicht belegt, sollte in diese Tabellenzelle ein empty-Tag gelegt werden. Dieser erzeugt nichtwirklich leeren, sondern lediglich unsichtbaren Inhalt. Die Ausgabe des Tags bzw. der Klassesorgt daf¨r, dass die Tabellenstruktur gem¨ß HTML-Standard gef¨llt ist. W¨rde hier einfach u a u unichts stehen, w¨re das Dokument nicht mehr valide. a
  • 162. 6.4 Das Packet com.varial.taglib 157Oberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: -6.4.18 VspacerDie Klasse Vspacer, die das Tag vspacer behandelt, erzeugt genau die die Klasse Empty(6.4.17) keine sichtbare Ausgabe. Sie wird verwendet um vertikale Abt¨nde zwischen Kom- aponenten zu erzeugen. Dazu kann eine H¨he in Pixel angegeben werden. Zus¨tzlich zu dem o anormalen Abstand wird dann ein weiterer Leerraum erzeugt. So k¨nnen Komponenten auf oder Oberfl¨che optisch von einander getrennt werden. aOberklasse: VComponent (6.4.2)Zus¨tzliche Setter-Methoden: a • public void setHeight (int height)Ausgabe der Klasse: -6.4.19 TabSheetControlOberklasse: BodyTagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: TabSheetBean (6.3.20)6.4.20 TabSheetDie Klasse TabSheet wird aufgerufen, wenn ein tabsheet-Tag in der JSP-Datei steht. Wieder Taglib Descriptor (6.4.1) zu entnehmen ist, besitzt dieses Tag nur ein Attribute, n¨mlich adas Attribute index. Mit Hilfe des Tags lassen sich Inhalte zusammenfassen, die nur dannangezeigt werden, wenn die Registerkarte mit dem angegebenen Index aktiv ist. So kanndie JSP-Seite eine Reihe von Ausgaben definieren, wovon jeweils eine angezeigt wird. DieKlasse Tabsheet sorgt daf¨r, dass die anderen Teile nicht dargestellt werden. Hierzu wird die uMethode doStartTag() so uberladen, dass der Inhalt des Tags nur dann ausgef¨hrt wird, ¨ uwenn der angegeben Index dem aktuellen Tabsheetindex entspricht.Beispiel:<varial:tabsheetcontrol> <varial:tabsheet index="0"> Dieser Text wird nur dann angezeigt, wenn das <b>ERSTE</b> Register ausgew"ahlt ist. </varial:tabsheet> <varial:tabsheet index="1"> Dieser Text wird nur dann angezeigt, wenn das <b>ZWEITE</b> Register ausgew"ahlt ist.
  • 163. 6.4 Das Packet com.varial.taglib 158 </varial:tabsheet> <varial:tabsheet index="2"> Dieser Text wird nur dann angezeigt, wenn das <b>DRITTE</b> Register ausgew"ahlt ist. </varial:tabsheet><varial:tabsheetcontrol>6.4.21 MenuBarOberklasse: TagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: MenuBarBean (6.3.21)6.4.22 SelectOkCancelOberklasse: TagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: SelectOkCancelButtonBean (6.3.26)6.4.23 SelectSearchOberklasse: TagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: SelectSearchBean (6.3.27)6.4.24 HeadLine ¨Die Klasse HeadLine geh¨rt zu dem Tag headline und stellt die Uberschrift, die das Servlet ozuvor mit Hilfe der setHeadLine()-Methode des GuiHelpers (6.3.1) dar.Oberklasse: TagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: -
  • 164. 6.4 Das Packet com.varial.taglib 1596.4.25 LastChangeDie Klasse LastChange behandelt das lastchange-Tag und gibt ein kurze Statusmeldungaus, wann das aktuelle Objekte von wem das letzte Mal ge¨ndert wurde. aOberklasse: TagSupportZus¨tzliche Setter-Methoden: a • public void setAlign (String align)Ausgabe der Klasse: -6.4.26 JavaScriptOberklasse: TagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: JavaScriptBean (6.3.28)6.4.27 CssLinkDie Klasse CssLink ist zust¨ndig f¨r das csslink-Tag. Dieses Tag erzeugt als Ausgabe eine a uZeile mit HTML-Code, der eine CSS-Datei einbettet. Die Klasse sorgt daf¨r, dass die Datei ugem¨ß des aktuell eingestellten Corporate Designs (4.4.2) eingebunden wird. Dazu wird die agetCss()-Methode der Klasse Theme (6.3.30) verwendet.Oberklasse: TagSupportZus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: -6.4.28 HiddenFieldMit dem hiddenfield-Tag und der zugeh¨rigen Klasse HiddenField k¨nnen Parameter in o oversteckten Feldern zwischengespeichert werden. Damit Query-String-Parameter und Attri-bute im Request-Objekt auch bei Absenden eines Formulars ubergeben werden, m¨ssen sie ¨ uselbst Teil des Formulars sein. Das hiddenfield-Tag sorgt daf¨r, dass die Parameter mit udem als Tag-Attribute angegebenen Namen als versteckte Felder in das Formular integriertwerden.Oberklasse: TagSupportZus¨tzliche Setter-Methoden: a • public void setName (String name)Ausgabe der Klasse: -
  • 165. 6.4 Das Packet com.varial.taglib 1606.4.29 HiddenExtraFieldDie Klasse HiddenExtraField verh¨lt sich ¨hnlich zu der Klasse HiddenField. Allerdings a awerden hier speziell die Werte in versteckten Formularfelder verwaltet, die dem Servlet vomMen¨baum mitgegeben wurden. VWE erlaubt es im Administrations-Modus die Men¨bau- u ume der Programms zu editieren. Hier k¨nnen u.a. auch Parameter f¨r die aufgerufenen o uProgramm-Module angegeben werden. Diese Parameter werden dem Servlet bei Start uber- ¨geben und k¨nnen mit dem hiddenextrafield-Tag gespeichert werden. Eine Anwendung of¨r einen Men¨-Parameter findet sich beispielsweise in der Verwaltung von Debitoren und u uKreditoren. Dies sind zwei getrennte Use-Cases werden aber von einem Servlet verarbeitet.Damit das Servlet weiß, von welchem Men¨punkt es aufgerufen wird, wird vom Men¨baum u uder Parameter TYPE=SUPPLIER bzw. TYPE=CUSTOMER ubergeben. ¨Oberklasse: HiddenField (6.4.28)Zus¨tzliche Setter-Methoden: keine aAusgabe der Klasse: -6.4.30 TranslatorSollen Bezeichnungen, die von der JSP-Seite erzeugt werden, ubersetzt werden, muss zuvor ¨ein translator-Tag in die Seite integriert werden. Die Klasse Translator behandelt dieses ¨Tag. Eine Ubersetzung besteht immer aus den Angaben Module, Parent und Component. Dieletzte Angabe wird vom zu ubersetzenden Text angegeben. Die anderen Angaben m¨ssen als ¨ uTag-Attribute spezifiziert werden. Da die Klasse TagSupport, von der die Klasse ableitet,bereits eine setParent()-Methode besitzt, musste der Parent-Parameter umbenannt werdenund heißt nun Owner. Werden mehrere Translator in die Seite integriert, muss diesen dasid-Attribute gesetzt werden, damit sie sp¨ter zu unterscheiden sind. aNach Initialisierung des Translators k¨nnen Texte mit demlanguagestring-Tag (6.4.31) oubersetzt werden.¨Oberklasse: TagSupportZus¨tzliche Setter-Methoden: a • public void setId (String id) • public void setModule (String module) • public void setOwner (String owner)Ausgabe der Klasse: -6.4.31 LanguageString ¨Das Tag languagestring und die zugeh¨rige Klasse LanguageString dient zu Ubersetzung o ¨von Texten in einer JSP-Seite. Nachdem die Ubersetzung mit dem translator-Tag initiali- ¨siert wurde, kann die letzte fehldende Komponente der Ubersetzung, die Angabe der Compo-nent, mit dem languagestring-Tag angegeben werden. Gibt es mehr als ein translator-Tag,muss dem languagestring mit dem id-Attribute angegeben werden, auf welchen Translatorman sich bezieht.
  • 166. 6.4 Das Packet com.varial.taglib 161Oberklasse: TagSupportZus¨tzliche Setter-Methoden: a • public void setId (String id) • public void setComponent (String component)Ausgabe der Klasse: -Beispiel (entnommen aus accounting/personalaccount/CustInfoAgingListDetail.jsp“): ”<varial:translator module="personalaccountinfo" owner="vpersaccinfoagingentrylistframe1"/><varial:languagestring component="persaccinfoagingfromaginglistlabel"/>Zuerst wird mit dem translator die Angabe zu Module und Owner/Parent angegeben.Sp¨ter wird die letzte Angabe, n¨mlich Component, durch den languagestring spezifi- a a ¨ziert. Die Klasse Translator (6.2.1) kann nun die Ubersetzung f¨r die aktuelle Sprache uvom CORBA-Server erfragen und ausgeben.
  • 167. 6.4 Das Packet com.varial.taglib 162 Abbildung 39: LabeledComboBox (ausgeklappt)
  • 168. 7 Beispiel fur die Verwenung der VWE-Web-API ¨Nachdem im letzen Kapitel die neu entwickelte Klassenbibliothek f¨r die Umsetzung einer uWeb-Oberfl¨che f¨r die Varial World Edition vorgestellt wurde, soll nun deren Verwendung a uan einem Anwendungsfall praktisch erkl¨rt werden. Als Programm-Modul soll die W¨hrungs- a averwaltung implementiert werden. In VWE findet man diese unter dem Men¨punkt Allg. u ”Einstellungen/General Setup”⇒ W¨hrung/Currency“. a ”Mit diesem Modul lassen sich alle im System verwendeten W¨hrungen pflegen. Einer der aVorteile von VWE gegen¨ber anderen ERP-Systemen ist die Mehrw¨hrungsf¨higkeit. D.h. u a aBuchungen und andere Transaktionen lassen sich flexibel in verschiedenen, frei definierbarenW¨hrungen durchf¨hren und umrechnen. Hierdurch wird die M¨glichkeit eines internationa- a u olen Einsatzes m¨glich. Die Umsetzung der W¨hrungen-Pflege dient in diesem Kapitel lediglich o aals Beispiel, da sie zum einen im Vergleich zu anderen Programmpunkten nicht besondersumfangreich ist, zum anderen aber f¨r ihren Umfang viele verschiedene GUI-Komponenten uenth¨lt. Der Frage, inwieweit eine solche Funktionalit¨t im Internet-Umfeld uberhaupt Sinn a a ¨macht, soll deshalb hier nicht nachgegangen werden.7.1 Vorbereitung7.1.1 Die IDL-BeschreibungAm Anfang jedes Use-Cases steht die IDL. Sie beschreibt zum einen die Business-Objekte,in diesem Fall die W¨hrungen, mit deren Attributen und zum Anderen ein Interface, das aentsprechende Methoden f¨r die Bearbeitung der BOs zur Verf¨gung stellt. Die Beschreibung u uder Anwendung definiert folgende Attribute einer W¨hrung: a • Eine Bezeichnung (Code) der W¨hrung a • Den ISO-Code der W¨hrung a • Eine Beschreibung der W¨hrung a • Die Anzahl der Nachkommastellen • Die Art der Rundung • Name der Haupteinheit • Name der Untereinheit • Evtl. Datum, bis wann die W¨hrung g¨ltig ist a u • Angabe, ob die W¨hrung f¨r Triangulation in der Europ¨ischen W¨hrungsunion (EWU) a u a a verwendet werden soll • Evtl. weitere Angaben, wenn es sich um eine EWU-W¨hrung handelt a – Datum, ab wann die W¨hrung g¨ltig ist a u – Umrechnugskurs zum Euro 163
  • 169. 7.1 Vorbereitung 164 • Eine Notiz • Den Importcode • Angabe, ob es sich bei der W¨hrung um den Euro handelt aDiese Angaben werden in einer entsprechenden IDL-Datei festgehalten. Da VWE denUse-Case bereits f¨r die Desktop-Version definiert, existiert bereits eine IDL-Beschreibung uf¨r W¨hrungen. Sie befindet sich im Verzeichnis source/corba/framework/Currency.idl. u aDort wird auch ein Interface f¨r die Serverfunktionen definiert. Im einzelnen sind das u a u ¨createCurrency() zum Anlegen einer neuen W¨hrung, setCurrency() f¨r das Andern ei-ner W¨hrung, deleteCurrencies() f¨r das L¨schen von W¨hrungen, getCurrencies() f¨r a u o a udas Abfragen aller Einheiten und getCurrencyByOid() um eine W¨hrung durch die Angabe ader ObjectID zu finden. Außerdem wird eine Methode ben¨tigt, mit der eine Liste aller ISO- oCodes abgefragt werden kann. Diese Funktionalit¨t bietet findSwiftcodes. Das folgende aListing zeigt die Ausschnitte der IDL, die f¨r den Use-Case von Bedeutung sind. u#ifndef CURRENCY_IDL#define CURRENCY_IDL#include "Exception.idl"#include "BasicTypes.idl"#include "Access.idl"#include "Query.idl"module com { module varial { module framework { module currency { enum RoundingEnum {RE_NO_ROUNDING, RE_COMMERCIAL_ROUNDING}; union optConversionRate switch (boolean) { case TRUE: basictypes::ConversionRate rate; }; const short MIN_DECIMAL_PLACES = -3; const short MAX_DECIMAL_PLACES = 3; struct SwiftcodeStruct { string code; string currencyName; long tag; };
  • 170. 7.1 Vorbereitung 165 typedef sequence<SwiftcodeStruct> SwiftcodeSeq; struct EmuDataStruct { string dateEmuCurrency; basictypes::ConversionRate emuRate; }; struct CurrencyStruct { serverbase::query::ObjectStruct oidTimestamp; string code; string swift; string description; short decimalplaces; RoundingEnum roundingmode; string unitname; string subunitname; string stopDate; boolean triangleCalculation; union isEmuCurrencyUnion switch (boolean) { case TRUE: EmuDataStruct emudata; } emuData; string note; string importcode; boolean isTheEuro; // only the Euro can have this true !! }; typedef sequence<CurrencyStruct> CurrencySeq; interface CurrencyServant { // swift codes SwiftcodeSeq findSwiftcodes( in serverbase::access::AccessToken token, in string code ) raises ( serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException ); CurrencyStruct getCurrencyByOid( in serverbase::access::AccessToken token,
  • 171. 7.1 Vorbereitung 166 in string oidCurrency ) raises ( serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException, serverbase::applicationexception::DomainException ); // get all currencies CurrencySeq getCurrencies( in serverbase::access::AccessToken token ) raises ( serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException, serverbase::applicationexception::DomainException ); // create a new currency CurrencyStruct createCurrency( in serverbase::access::AccessToken token, in CurrencyStruct currency ) raises ( serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException, serverbase::applicationexception::DomainException ); // update currency CurrencyStruct setCurrency( in serverbase::access::AccessToken token, in CurrencyStruct currency ) raises ( serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException, serverbase::applicationexception::DomainException ); // delete currencies void deleteCurrencies( in serverbase::access::AccessToken token, in serverbase::query::ObjectSeq oidTs ) raises (
  • 172. 7.1 Vorbereitung 167 serverbase::applicationexception::AccessDeniedException, serverbase::applicationexception::ApplicationLayerException, serverbase::applicationexception::PersistencyException, serverbase::applicationexception::DomainException ); }; }; }; };};#endif // CURRENCY_IDL7.1.2 Die Server-FunktionDer n¨chste Schritt zur Umsetzung der Anwendung ist die Implementierung des IDL- aInterfaces als Server-Funktion. Dadurch, dass VWE bereits die W¨hrungsverwaltung an- abietet, kann auf die vorhanden Server-Methoden zugegriffen werden. Der CORBA-Server isthier also schon vorhanden.7.1.3 Die Client-BOsAls n¨chstes m¨ssen die IDL-Strukturen in Java-Klassen abgebildet werden, damit die Serv- a ulets auf die Daten zugreifen k¨nnen. Diese Klassen werden auch als Business-Objekte (5.4) obezeichnet. Es handelt sich hierbei um JavaBeans, die den Namen der Struct, allerdings mitder Endung BO“ tragen. Sie sind von der abstrakten Klasse BO (6.1.12) abgeleitet, kapseln ”die Daten und bieten entsprechende Getter- und Setter-Methoden.BOs m¨ssen nicht manuell erstellt werden. Um den Programmieraufwand erheblich zu min- udern, wurde ein Perl-Skript namens WebBOBuilder geschrieben. Es befindet sich im Verzeich-nis source/web/templates und erwartet als Kommandozeilen-Parameter den Namen derIDL und die Bezeichnung der Struktur, aus der die Klasse generiert werden soll. Der Aufruflautet demzufolge:perl WebBoBuilder.pl framework/Currency.idl CurrencyStructperl WebBoBuilder.pl framework/Currency.idl EmuDataStructperl WebBoBuilder.pl framework/Currency.idl SwiftcodeStructDas Perl-Skript erzeugt automatisch eine Java-Datei im Verzeichnissource/web/com/varial/framework/domain/currency mit dem Namen CurrencyBO,EmuDataBO und SwiftcodeBO. Die Pfad- bzw. Package-Angabe entspricht der module-Definition in der IDL. Lediglich der Zusatz domain ist hinzugekommen. In domain-Verzeichnissen werden BOs geschrieben, w¨hrend in servlet-Verzeichnisse die Servlets auntergebracht werden. Mehr dazu folgt sp¨ter. aDie erzeugte Java-Datei l¨ßt sich nun schon fast vollst¨ndig und l¨ßt sich fehlerfrei kom- a a apilieren. Bei komplexeren Strukturen ist unter Umst¨nden eine kleine manuelle Korrektur a
  • 173. 7.1 Vorbereitung 168notwendig. Jedenfalls hat das Perl-Skript dem Entwickler bereits eine Menge Arbeitabgenommen.Zum Schluß m¨ssen nun noch die Interface-Methoden implementiert werden. Die Methoden u ¨entsprechen immer dem selben Aufbau. Die Funktionen zum Anlegen, Andern und L¨schen oeines BOs werden von den commit() bzw. delete() Methoden der Klasse ubernommen. ¨Sie werden bereits vom Perl-Skript generiert. Weitere Methoden werden meist als statischeMethoden wie folgt hinzugef¨gt. upublic static CurrencyBO[] getCurrencies( VContext ctx) { try { CurrencyServant servant = getServant(ctx); CurrencyStruct[] seq = servant.getCurrencies( ctx.getAccessToken() ); return toBoArray(seq); } catch (Exception e) { throw new VException(e); }}Parameter ist immer der VContext. Er enth¨lt das AccessToken, das der Server-Aufruf amitgegeben bekommt, damit die Zugriffsberechtigung uberpr¨ft werden kann. Mit der au- ¨ utomatisch generierten Funktion getServant() wird zun¨cht ein Servant geholt. Nun kann adie passende Methode aus der IDL (hier getCurrencies()) mit diesem Servant aufgerufenwerden. Die vom Perl-Skript geschriebenen Hilfsfunktion toBoArray() sorgt daf¨r, dass die uIDL-Sequenz in eine Array mit CurrencyBOs umgewandelt wird. Alle Ausnahmen werdenpauschal mit einer catch-Anweisung gefangen und in eine VException (6.1.14) umgewan-delt. Diese Exceptions werden von der Klasse VServlet (6.1.1), von der das Servlet sp¨ter aableitet, gefangen und behandelt.Sollte anstelle mehrere BOs nur ein BO zur¨ckgegeben werden, kann der Konstrukter der uKlasse zur Umwandlung der IDL-Struct in eine Java-Klasse benutzt werden.public static CurrencyBO getCurrency( VContext ctx, String oidcurrency) { try { CurrencyServant servant = getServant(ctx); return new CurrencyBO ( servant.getCurrencyByOid( ctx.getAccessToken(),
  • 174. 7.2 Listen-Ansicht 169 oidcurrency ) ); } catch (Exception e) { throw new VException(e); }}Nun kann mit Hilfe dieser BO-Klasse auf die IDL-Struktur bzw. auf den CORBA-Serverzugegriffen werden. F¨r das Servlet und alle Klassen, die das BO verwenden, erscheint das uObjekt lokal. Die Verteilung der Anwendung gestalltet sich folglich v¨llig transparent. o7.1.4 Die EnumerationsDie IDL beschreibt weiterhin eine Aufz¨hlung (Enumeration). Diese kann ebenfalls mit einem aPerl-Skript in eine Java-Klasse exportiert werden. Hierzu muss das Skript WebEnumBuilderaufgerufen werden.perl WebEnumBuilder.pl framework/Currency.idl RoundingEnumErgebnis ist eine Java-Datei mit dem Namen RoundingHelper.java im selben Verzeichniswie das zuvor erzeugte BO. Auch diese Klasse ist fast vollst¨ndig, nur die Angaben f¨r die a u¨Ubersetzung m¨ssen angepasst werden. Zum einen muss die Module- und Parent-Angabe des uTranslator-Objektes (6.2.1) angepasst werden, zum anderen muss in der init()-Methodedie Component-Bezeichnung der Eintr¨ge ge¨ndert werden. Die n¨tigen Angaben k¨nnen aus a a o o ¨dem Programm Sophia, das eigens f¨r die VWE-Ubersetzung entwickelt wurde, oder direkt uaus der Datenbank-Relation resouretranslat t entnommen werden. In diesem Fall ist es currency“ f¨r Module, vcurrencylistframe1“ f¨r Parent und roundingmodes#0“ bzw. u u” ” ” roundingmodes#1“ f¨r die Component-Angabe. u”Alle n¨tigen Klassen des domain-Verzeichnisses sind nun erstellt. Jetzt k¨nnen die passenden o oServlets umgesetzt werden.7.2 Listen-Ansicht7.2.1 Das ListServletDie W¨hrungen-Verwaltung unterteilt sich wie die meisten Anwendung der VWE in eine aListen- und eine Detail-Ansicht. Der Anwender bekommt zu Beginn als erstes eine Listen¨ber- usicht geboten, die die BOs mit den wichtigsten Attributen auff¨hrt. Die Frage, welche Daten udie Listen-Ansicht zur Verf¨gung stellen soll, wird bereits vom vorhandenen C++-Client be- uantwortet. Es sind Code, Name, ISO-Code, W¨hrungseinheit, Untereinheit, Dezimalstellen, aRundung und Import-Code.Servlets, die eine Listenansicht definieren, sollten von der Klasse VListServlet (6.1.2) ab-geleitet werden. Der Einfachheit halber kann ein vorhandes Servlet, wie beispielsweise dieKlasse PersonalAccountListServlet aus dem Packet com.varial.accounting.servlet,genommen und angepasst werden. Die Datei sollte in das beresits angesproche-ne Packet com.varial.framework.servlet.currency gelegt werden und den Namen
  • 175. 7.2 Listen-Ansicht 170 ¨CurrencyListServlet tragen. Die Klasse definiert zuerst den Translator, der f¨r die Uber- usetzung zust¨ndig ist, als konstante Klassenvariabel. Die Angabe f¨r die Parameter lassen a usich auch hier dem Programm Sophia bzw. der Datenbank entnehmen. Es sind currency“ ”und vcurrencyform“ f¨r Module und Parent. u ”package com.varial.framework.servlet.currency;import com.varial.base.*;import com.varial.gui.*;import com.varial.translation.*;public class CurrencyListServlet extends VListServlet { private final static Translator translator = new Translator("currency", "vcurrencyform");Der n¨chste Schritt besteht darin, die Methode getItList() zu uberladen. Sie bekommt von a ¨der Oberklasse VServlet (6.1.1) ein VContext ubergeben und ist f¨r die Behandlung von ¨ uGET-Anfragen zust¨ndig. Sollte die Methode postItDetail() nicht uberladen sein, werden a ¨hier auch POST-Anfragen behandelt.protected void getItList (VContext ctx)In dieser Methode sollte zun¨cht die Tabelle erzeugt werden. Hierzu stellt die Klasse aGuiHelper (6.3.1) eine statische Methode addGrid() bereit. Sie erwartet als Parameter denVContext und eine sog. State-Klasse. Eine State-Klasse, oder kurz State genannt, formatiertdie Tabelle und behandelt Benutzereingaben in Tabellenzellen. Oberklasse aller States istVState (6.1.6). Ein solcher State wird im n¨chsten Schritt entworfen. F¨r das ListServlet ist a ues zun¨chst nur wichtig zu wissen, dass ein solcher State existiert. Er wird der GuiHelper- aMethode ubergeben. ¨GuiHelper.addGrid( ctx, new CurrencyListGridState());Als n¨chstes sollte mit der Methode setHeadLine, die ebenfalls vom GuiHelper angeboten a ¨ ¨wird, die Uberschrift gesetzt werden. Damit auch die Uberschrift in der jeweiligen Spracheerscheint, wird sie mit dem Translator-Objekt erstellt.GuiHelper.setHeadLine( ctx, translator.getCaption( ctx, "vcurrencyform" ));
  • 176. 7.2 Listen-Ansicht 171Als n¨chstes muss noch die Men¨leiste angepasst werden. Listenansichten erlauben als a uMen¨-Aktion lediglich das Anlegen eines neuen Objektes. Alle anderen Icons sind akti- uviert. Die Klasse MenuBarBean (6.3.21 besitzt zur Herstellung dieses Layouts die MethodetoListView().MenuBarBean menu = new MenuBarBean(ctx);menu.toListView();Die Verarbeitung ist nun abgeschlossen. Zum Schluß muss nun nur noch die Kontrolle aneine JSP-Seite abgegeben werden, die die Angaben darstellt. Diese Vorgehensweise entsprichtdem unter 5.2 angesprochenen MVC-Modell.7.2.2 Der ListStateWie breits oben angesprochen, wird jede Tabelle von einem sog. State verwaltet. Dieser for-matiert zum einen die Tabelle, zum anderen ist er daf¨r zust¨ndig, dass Benutzereingaben in u a ¨Tabellenzellen entsprechend verarbeitet werden. Da bei VWE-Web Anderungen und Einga-ben nur in der Detail-Ansicht vorgenommen werden k¨nnen, muss in der Listen-Ansicht nur odie Formatierung ubernommen werden. ¨States f¨r Listenansicht sollten von der Klasse VListServlet (6.1.2) ableiten. upublic class CurrencyListGridState extends VListState a u ¨Auch hier sollte zun¨chst ein Translator-Objekt angelegt werden, das f¨r die Ubersetzungzust¨ndig ist. Außerdem ist es ratsam, alle Spaltennamen als int-Konstanten zu definieren. aHierdurch wird es m¨glich, die Spalten durch deren Namen anzusprechen. Dies ist nicht nur o ¨intuitiver als die Verwendung ihrer Indizes, sondern es wird so m¨glich, dass Anderungen in o ¨der Spaltenreihenfolge nur zu einer Anderungung an einer zentralen Stelle f¨hren. Folglich usehen die Konstanten so aus:private static final int TABLE_CODE = 0;private static final int TABLE_NAME = 1;private static final int TABLE_SWIFT_CODE = 2;private static final int TABLE_UNIT = 3;private static final int TABLE_SUBUNIT = 4;private static final int TABLE_DECIMAL_PLACES = 5;private static final int TABLE_ROUNDING = 6;private static final int TABLE_IMPORT_CODE = 7;Die Aufgabe des State ist es nun, die Tabelle mit Inhalt zu f¨llen. Dazu muss die Methode uwriteData(), die von der Oberklasse eine GridBean (6.3.16) ubergeben bekommt, zu im- ¨plementieren. Der Aufbau der Methode ist bei fast jeder Anwendung identisch. Zun¨chst awerd mit der statischen Methode des BOs alle Objekte vom CORBA-Server erfragt. In einerSchleife werden die Objekte durchlaufen und f¨r jedes Objekt eine neue Zeile an die Tabelle uangehangen. Hierzu dient die Methode addRow() der GridBean, die als Parameter die Listeder Spaltenwerte besitzt. Diese Spaltenwerte, also der Code, Name, Rundung etc, wird mitden Getter-Methoden des BOs abgefragt. Dementsprechend sieht die Funktion wie folgt aus.
  • 177. 7.2 Listen-Ansicht 172public void writeData(VContext ctx, GridBean grid) { CurrencyBO[] currencies = CurrencyBO.getCurrencies(ctx); ctx.registerBos("", currencies); // Fill grid for (int i=0; i<currencies.length; i++) { CurrencyBO currency = currencies[i]; grid.addRow ( ctx, currency, new Object[] { currency.getCode(), currency.getDescription(), currency.getSwift(), currency.getUnitname(), currency.getSubunitname(), new Short(currency.getDecimalplaces()), RoundingHelper.getString( ctx, currency.getRoundingmode() ), currency.getImportcode() } ); }}Zu erw¨hnen w¨ren hier noch drei Dinge. Erstens werden hier die BOs, nachdem sie vom Ser- a aver angefordert wurden, mit der Methode registerBos() beim VContext angemeldet. Dies ¨erm¨glicht es, eine Statusmeldung mit den Daten der letzen Anderungen anzuzeigen, wenn oder Cursor sich uber einer Tabellenzeile befindet. Der erste Parameter gibt an, zu welchen ¨Parent-Objekt die BO-Liste geh¨rt. Dies ist sehr h¨ufig die aktuelle Firma, kann aber auch et- o awas anderes, wie beispielsweise ein Ordner im TaskReminder-Use-Case sein. W¨hrungen sind aunabh¨ngig von einem Parent-Objekt. Deshalb wird hier einfach der Leerstring angegeben. aAls zweites f¨llt auf, dass das Ergebnis der getDecimalplaces()-Funktion in einen Short- aKonstruktor gepackt wurde. Der Grund daf¨r ist der, dass die addRow()-Methode einen Array uvon Objects erwartet. Da der R¨ckgabewert der Getter-Funktion vom Typ short ist, der uals primitiver Datentyp keine Unterklasse von Object darstellt, muss zu diesem Trick ge-griffen werden. Dementsprechend verh¨lt es sich nat¨rlich auch bei int, long oder boolean. a uAls drittes und letztes soll noch auf den Wert f¨r den Rundungsmodus eingegangen werden. uHier zeigt sich die Verwendung der in der Vorbereitungsphase erzeugten Helper-Klasse. DieFunktion getString() des RoundingHelpers sorgt daf¨r, dass ein RoundingEnum-Objekt als uString in der aktuellen Sprache angezeigt wird. Bevor die Bearbeitung der State-Klasse entg¨ltig abgeschlossen werden kann, m¨ssen u unoch die Formatierungsangaben gemacht werden. Weil die Listenansicht keine M¨glichkeit o
  • 178. 7.2 Listen-Ansicht 173bietet, Daten einzugeben bzw. diese zu ver¨ndern, m¨ssen in VListState-Klassen in der Regel a unur wenig Formatierungsangaben gemacht werden. Hier m¨ssen nur Spalten¨berschriften u ugesetzt werden und evtl. die Art der Zelleninhalte angegeben werden. Letzteres geschiehtmit der Methode getEditor(). Wird diese Methode nicht uberladen, die Eigenschaft also ¨nicht expliziet gesetzt, werden alle Inhalte als normaler Text linksb¨ndig angezeigt. Bei der uW¨hrungsliste soll jedoch die Angabe f¨r die Dezimalstellen als Zahl und somit rechtsb¨ndig a u uangezeigt werden. Die Methode getEditor() muss folglich angeben, dass es sich bei Wertedieser Spalte um Zahlen handelt.public int getEditor ( VContext ctx, int row, int col) { switch (col) { case TABLE_DECIMAL_PLACES: return NUMBERFIELD; default: return TEXTFIELD; }}Als letztes m¨ssen nun nur noch die Spalten¨berschriften mit getHeaders() angegeben wer- u uden.public String[] getHeaders( VContext ctx) { return new String[] { translator.getCaption(ctx, "grid#column#0"), // Code translator.getCaption(ctx, "grid#column#1"), // Name translator.getCaption(ctx, "grid#column#2"), // SWIFT Code translator.getCaption(ctx, "grid#column#3"), // Unit translator.getCaption(ctx, "grid#column#4"), // Subunit translator.getCaption(ctx, "grid#column#5"), // Decimal Places translator.getCaption(ctx, "grid#column#6"), // Rounding translator.getCaption(ctx, "grid#column#7") // Import Code };}Wie man sieht, liefert die Funktion nicht hartverdrahtete“ Strings, sondern nutzt den ¨ ”Translator, um eine Ubersetzung in die aktuelle Sprache zu gew¨hrleisten. aNun sind alle Java-Klassen f¨r die Listen-Ansicht implementiert worden. Was fehlt ist die uDarstellung. Diese wird mit einer JSP-Seite realisiert, an die das ListServlet wie oben gezeigtdie Kontrolle ubergibt. ¨7.2.3 Die JSP-Listen-SeiteDie JSP-Seite verwendet HTML-Tags und die Varial-Taglib mit Custom-Tags um die Ergeb-nisse der Servlet-Verarbeitung darzustellen. W¨hrend die Servlet-Programmierer die Java- a
  • 179. 7.2 Listen-Ansicht 174Klassen implementiert, kann ein Designer sich mit dem Design der Ausgabe besch¨ftigen. aDie Bearbeitung geschiet hier parallel und vollkommen unabh¨ngig voneinander. Dabei ha- aben JSP-Seiten unter normalen Umst¨nden immer einen sehr ¨hnlichen Aufbau. Es bietet a asich also auch hier an, vorhandene Seiten zu kopieren und entsprechend anzupassen.Die JSP-Seiten befinden sich im Verzeichnis source/web/resource/html. Hier gibt es f¨rudie Programm-Teile entsprechende Unterverzeichnisse. So sollte die W¨hrungs-Seite unter aframework/currency gespeichert werden.Die JSP-Seite muss folgende Dinge tun: • Die Varial-Taglib einbinden • Mit der page-Direktive ben¨tigte Packete importieren o • Einen VContext erzeugen und mit dessen checkLogin()-Methode pr¨fen, ob die Seite u angezeigt werden darf • Das csslink-Tag dazu benutzen, Stylesheets gem¨ß des aktuellen Themes zu laden a • Mit den javascript-Tag die vom Servlet erzeugten JavaScript-Funktionen laden • Das bearbeitende Servlet als Formular-Ziel angeben • Die GUI-Elemente, die das Servlet erzeugt hat, zu positionierenDies alles f¨hrt zu folgender JSP-Seite: u<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.0 Transitional//EN"><%@ page errorPage="../../errorpage.jsp" %><%@ taglib uri="/WEB-INF/tlds/varial.tld" prefix="varial" %><%@ page import=" com.varial.framework.servlet.currency.*, com.varial.base.*, com.varial.gui.* "%><% VContext ctx = new VContext(this, request, response); ctx.checkLogin(); ctx.setAttribute(VContext.REQUEST, "__ctx", ctx);%><html><head> <title>Currency</title> <varial:csslink/>
  • 180. 7.2 Listen-Ansicht 175 <varial:javascript/></head><body class="base" leftmargin="0" topmargin="0" onLoad="init()"> <form name="vform" action="<%= response.encodeRedirectURL("com.varial.framework.servlet.cu <table width="645" cellspacing="10"> <tr> <td width="10"></td> <td width="100%"> <!-- - - - - - - - HEADLINE - - - - - - - - - ---> <varial:headline/><br> <!-- - - - - - - - MENU - - - - - - - - - - - - --> <varial:menubar/> <!-- - - - - - - - GRID - - - - - - - - - - - - --> <varial:grid width="100%" height="415px"/> </td> </tr> </table> </form></body></html>Benutzerdefinierte Tags, die an dem vorangestellten varial: zu erkennen sind, werden vonJava-Klassen der Taglib (6.4) behandelt. Deren Ausgabe erscheint dann anstelle der Tags. Sok¨nnen die Daten, die von dem Servlet erzeugt werden, in eine JSP-Seite eingebettet werden. o7.2.4 ZusammenfassungNach den oben beschriebenen Schritten ist die Listenansicht komplett. Der Ablauf istdabei immer identisch. Man erzeugt zuerst aus der Use-Case-Beschreibung die IDL undimplementiert den Server. Sehr oft sind diese Schritte bereits vollzogen. Die Perl-SkripteWebBoBuilder und WebEnumBuilder bilden Structs und Enumerations in Java-Klassen,die Servlets verwenden k¨nnen. Das Servlet leitet von VListServlet ab, erzeugt mit odem GuiHelper eine Tabelle, der eine VListState-Klasse ubergeben wird. Diese f¨llt und ¨ uformatiert die Tabelle. Anschließend wird die Verarbeitung an eine JSP-Seite ubetragen, die ¨mittels der Varial-Taglib die Elemente in einer HTML-Seite positioniert. Wird f¨r die Daten¨bertragung ein Callback (5.5) verwendet, sind die Schritte fast u uidentisch. Die VListServlet-Klasse muss nach Erzeugen der MenuBarBean nur noch der-ren Eigenschaft showCallback auf true setzen. Dadurch erh¨lt die Men¨leiste eine Icon, a uum das Laden abzubrechen. Der State muss die Methode isCallback() so uberladen, ¨
  • 181. 7.3 Detail-Ansicht 176dass sie true zur¨ckgibt und das F¨llen der Tabelle in die Methode putDataRows() ver- u uschieben. F¨r ein Beispiel sei auf die Klasse PersonalAccountListGridState im Packet ucom.varial.accounting.servlet verwiesen.7.3 Detail-Ansicht7.3.1 Das DetailServletNachdem der Anwender ein BO aus der Listenansicht ausgew¨hlt hat, werden ihm in der aDetail-Ansicht weitere Informationen zur Verf¨gung gestellt. Hier befinden sich dann auch udie Objekt-Attribute, die in der Listen-Ansicht nicht angezeigt wurden. Da die W¨hrungen- aVerwaltung im Verh¨ltnis zu anderen Programm-Modulen nur wenige Daten anzeigt, verwen- adet VWE hier keine Tabsheet um die Daten zu strukturieren. Dies macht zwar durchaus Sinn,im Rahmen der Beispielumsetzung sollen aber Registerkarten verwendet werden, um einenm¨glichst breiten Funktionsumfang der VWE-Web-API zu demonstrieren. Deshalb werden odie Daten auf die drei Karteikarten Details/Details“, EWU/EMU“ und Notiz/Note“ auf- ” ” ”geteilt.Das Servlet, das die Detail-Ansicht implementiert sollte von der Klasse VDetailServlet(6.1.3) abgeleitet werden und passenderweise den Namen CurrencyDetailServlet tragen.public class CurrencyDetailServlet extends VDetailServletAls n¨chster Schritt ist auch beim DetailServlet die Angabe eines Translators notwendig, aum Bildschirmtexte zu ubersetzen. Ein Blick in Sophia oder die Datenbank verr¨t die Anga- ¨ aben currency“ und vcurrencydetailframe1“ als Parameter. Weiterhin ist auch in dieser ” ”Klasse die Einf¨hrung von int-Konstanten hilfreich. Die drei Tabsheet-Register werden als uKonstanten definiert, so dass ein benannter Zugriff anstelle des nichtssagenden Index m¨glich osein wird.private final static int TAB_DETAILS = 0;private final static int TAB_EMU = 1;private final static int TAB_NOTE = 2;Nachdem diese Vorbereitungen getroffen wurden, kann nun die eigentliche Funktion in An-griff genommen werden. Hierzu sollte die Methode getItDetail() uberladen werden, die als ¨Parameter den VContext ubergeben bekommt. ¨protected void getItDetail (VContext ctx) a u ¨In dieser Methode sollte zun¨chst die Men¨leiste und die Uberschrift der Seite bearbeitetwerden. Hierzu erzeugt man eine neue MenuBarBean und ruft deren Methode hideIcon()mit dem Parameter MenuBarBean.COMBOBOX auf. Dadurch wird die Men¨leiste erstellt und udie Combo-Box, die in diesem Fall nicht verwendet wird, weil kein Bezug zu einem Parent-Objekt besteht, ausgeblendet.MenuBarBean menu = new MenuBarBean(ctx);menu.hideIcon(MenuBarBean.COMBOBOX);
  • 182. 7.3 Detail-Ansicht 177 ¨Die Uberschrift wird wie im ListServlet mit dem GuiHelper im Zusammenspiel mit einem ¨Translator erzeugt. Da die Uberschrift eines Moduls aber in der Form als Parent-Angabezu finden ist, der Translator der Seite aber vcurrencydetailframe1“ als Parent definiert, ”muss hier ein anderer Translator verwendet werden. Weil dieser nur einmal verwendet wird,soll hier die statische Methode der Translator-Klasse verwendet werden.GuiHelper.setHeadLine ( ctx, Translator.getCaption( ctx, "currency", "vcurrencyform", "vcurrencyform" ));Bevor die W¨hrung nun endlich dargestellt werden kann, muss das passende BO geholt wer- aden. Hierzu bietet jede VDetailServlet-Klasse die Funktion fillBO(), auf die sp¨ter genauer aeingegangen wird. An dieser Stelle ist es ausreichend zu wissen, dass diese Funktion immerden aktuellen Stand des BOs liefert. Der R¨ckgabewert ist jedoch immer vom Typ Object. uEin explizietes Casting ist notwendig.CurrencyBO mBo = (CurrencyBO) fillBO(ctx);Nun kann auf die ausgew¨hlte W¨hrung mit dem Objekt mBo zugegriffen werden. Im folgen- a aden m¨ssen nur noch die GUI-Elemente mit dem GuiHelper erstellt werden. Den Anfang umacht die Tabsheet. Der GuiHelper besitzt daf¨r eine statische Methode mit dem Namen u ¨addTabSheet(), die neben dem VContext die Bezeichnungen der Register-Uberschriften er- ¨wartet. Deshalb werden zuerst die Uberschriften mit dem Translator erzeugt und dann derMethode ubergeben. ¨String[] tabs = { translator.getCaption(ctx, "detaildetailtabsheet"), translator.getCaption(ctx, "detailemutabsheet"), translator.getCaption(ctx, "detailnotetabsheet")};GuiHelper.addTabSheet(ctx, tabs);Die Anwendung besitzt nun eine Tabsheet mit drei Registern. Man sieht, dass sich die Er-stellung der Komponente dank der VWE-Web-API denkbar einfach gestaltet. Die Register-Karten k¨nnen nun mit Inhalt gef¨llt werden. Da nur die Komponenten angezeigt werden, die o usich auf der aktiven Karte befinden, ist es uberfl¨ssig, alle Komponenten zu erzeugen. Eine ¨ ubessere Performance wird dadurch erreicht, dass lediglich die Felder im Servlet erzeugt undgef¨llt werden, die sp¨ter auch angezeigt werden. Aus diesem Grunde wird die Erzeugung u ader Felder in drei Bl¨cke einer switch-Anweisung unterteilt, die jeweils nur dann ausgef¨hrt o uwerden, wenn die jeweilige Karte ausgew¨hlt wurde. a
  • 183. 7.3 Detail-Ansicht 178switch (ctx.getTabSheetIndex()) { case TAB_DETAILS: // Hier Komponenten des ersten Registers erzeugen break; case TAB_EMU: // Hier Komponenten des zweiten Registers erzeugen break; case TAB_NOTE: // Hier Komponenten des dritten Registers erzeugen break;} // switchDadurch, dass zu Beginn Konstanten f¨r die Tabsheet-Register definiert wurden, k¨nnen u ohier die Namen der Karten verwendet werden, was die Lesbarkeit und die Wartung desCodes deutlich verbessert. Im ersten Register wird zun¨chste ein Textfeld f¨r die Eingabe a uder Code-Bezeichnung erstellt. Hierf¨r wird die Methode addTextField() des GuiHelpers uaufgerufen. Als Parameter erwartet diese den VContext, den Translator, den Namen, dendas Feld bekommen soll, die Beschriftungsbezeichnung, mit derren Hilfe der Translator dieFeldbeschriftung ubersetzt und nat¨rlich den Wert, den das Feld anzeigen soll. In diesem Fall ¨ uist es der Code der W¨hrung, der mit der Funktion getCode() abgefragt wird. Folglich lautet ader Aufruf:// CodeGuiHelper.addTextField( ctx, translator, "details__codelabel", "codelabellabel", mBo.getCode());Die Felder f¨r den Namen, die Haupt- und Untereinheit, sowie den Import-Code der W¨hrung u ak¨nnen analog dazu erstellt werden. o// NameGuiHelper.addTextField( ctx, translator, "details__namelabel", "namelabellabel", mBo.getDescription());// UnitGuiHelper.addTextField( ctx, translator,
  • 184. 7.3 Detail-Ansicht 179 "details__unitlabel", "unitlabellabel", mBo.getUnitname());// SubunitGuiHelper.addTextField( ctx, translator, "details__subunitlabel", "subunitlabellabel", mBo.getSubunitname());// Import CodeGuiHelper.addTextField( ctx, translator, "details__importcodelabel", "importlabel", mBo.getImportcode());Das n¨chste Feld dient zur Angabe des ISO-Codes, der zu der W¨hrung geh¨rt. Dieser Code a a okann entweder frei eingegeben werden oder der Benutzer w¨hlt die passende Bezeichnung aus aeiner Liste vorgefertigter ISO-Codes aus. Eine solche Funktionalit¨t stellt der Drei-Punkte- aButton repr¨sentiert durch die Klasse LabeledButtonTextField (6.3.8) zur Verf¨gung. Die a uGuiHelper-Funktion addButtonField() erzeugt die Komponente. Als zus¨tzlichen Parame- ater erwartet die Methode die URL einer Seite bzw. eines Servlets, das den Auswahldialogdarstellt. Der Befehl lautet zusammengefasst:GuiHelper.addButtonField( ctx, translator, "details__swiftlabel", "swiftlabel", mBo.getSwift(), new StringBuffer() .append("com.varial.framework.servlet.currency.SelectIsoCodeServlet?__search=") .append(mBo.getSwift()) .toString()).setDirectEdit(true);Der erste Teil der Anweisung ist bekannt. Auff¨llig ist hingegen die Verwendung des aStringBuffers und der Methodenaufruf setDirectEdit(true). Der StringBuffer spezi-fiziert die Adresse des Servlets, das sp¨ter die Auswahlseite darstellt. Dieser Seite wird als a
  • 185. 7.3 Detail-Ansicht 180Query-String-Parameter der aktuelle ISO-Code ubergeben. Da das Zusammenf¨gen zwei- ¨ uer String-Objekte intern relativ viel Speicher und dadurch auch viel Rechenzeit ben¨tigt, owird ein StringBuffer verwendet, der diese Aufgabe schneller erledigt. Die FunktionsetDirectEdit() sorgt daf¨r, dass auch freie Eingaben in das Feld m¨glich sind. Ohne u odiesen Aufruf k¨nnten Werte f¨r das Feld ausschließlich durch die Auswahl vordefinierter o uAngaben ge¨ndert werden. Da die addButtonField()-Methode wie jede add()-Methode des aGuiHelpers das erzeugte Objekt zur¨ckliefert, kann die Methode direkt mit der dem Funk- utionsaufruf verbunden werden.Bei den Feldern f¨r die Angabe der Dezimalstellen und des Rundungsverfahrens handelt es usich um Combo-Boxen. Sie werden durch den GuiHelper und dessen addComboBox()-Methodeerzeugt. Diese Methode erwartet neben einer Liste von Eintr¨gen f¨r die Combo-Box den In- a udex des aktuell ausgew¨hlten Eintrags. Die Erstellung der Combo-Box f¨r die Rundungsart a uist recht einfach. Gl¨cklicherweise stellt der RoundingHelper, der zuvor von dem Perl-Skript uerzeugt wurde, alle n¨tigen Methoden zur Verf¨gung. Die getStrings()-Methode liefert alle o uEintr¨ge f¨r die Combo-Box, mit indexOfEnum() kann der Index eines Eintrags abgefragt a uwerden. Als Befehl zum Erzeugen der Combo-Box ergibt sich damit:// Rounding ModeGuiHelper.addComboBox( ctx, translator, "details__roundinglabel", "roundingmodelabel", RoundingHelper.getStrings(ctx), RoundingHelper.indexOfEnum( mBo.getRoundingmode() ));F¨r die Angabe der Dezimalstellen existiert keine Helper-Klasse, da die IDL hierf¨r keine u uEnumeration definiert. Vielmehr beschreibt sie zwei Konstanten MIN DECIMAL PLACES undMAX DECIMAL PLACES. F¨r das Servlet ist dadurch noch ein wenig Java-Code erforderlich. uint MIN = MIN_DECIMAL_PLACES.value;int MAX = MAX_DECIMAL_PLACES.value;String[] decimalPlaces = new String[MAX-MIN+1];for (int i=0; i<=MAX-MIN; i++) { int tmp = MIN+i; String dp = ""; if (tmp < 0) { dp = (""+(Math.pow(10, tmp))).substring(0,-tmp+2); } else { dp = ""+((int)Math.pow(10, tmp)); } decimalPlaces[i] = VNumber.getViewNumber(ctx, dp);}
  • 186. 7.3 Detail-Ansicht 181Diese Zeilen erzeugen einen String-Array, der die Eintr¨ge f¨r die Dezimalstellen-Auswahl a ubeinhaltet. Dabei werden die Werte als 0.01“, 0.1“, 1“, 10“, 100“ usw. enth¨lt. Durch a ” ” ” ” ”die Verwendung der VNumber-Klasse (6.1.21) ist gew¨hrleistet, dass die Zahlen gem¨ß der a aaktuellen Sprache formatiert werden. Die erzeugte String-Liste kann der addComboBox-Methode nun als Parameter ubergeben werden. ¨GuiHelper.addComboBox( ctx, translator, "details__decimalplaceslabel", "decimalplaceslabel", decimalPlaces, mBo.getDecimalplaces()-MIN);Das letzte Feld, das f¨r das erste Tabsheet-Register fehlt ist das Feld f¨r die Angabe eines u uG¨ltigkeitsdatums. Hierf¨r wird die addDateField()-Methode des GuiHelpers verwendet, u udie ein Feld f¨r eine Datumseingabe, ein sog. DateField (6.3.6) erstellt. Die Verwendung uentspricht der eines normalen Textfeldes.// Use UntilGuiHelper.addDateField( ctx, translator, "details__useuntillabel", "useuntillabel", mBo.getStopDate());Nun ist erste Kartei-Karte der Tabsheet erstellt. Es folgt der Code f¨r die zweite Karte, udie Angaben zur Verwendung im Rahmen der Europ¨ischen W¨hrungsunion enth¨lt. Dort a a abefindet sich zuerst eine Check-Box, die angibt, ob es sich bei der W¨hrung um den Euro han- adelt oder nicht. Zur Erstellung einer solchen Check-Box kann die addCheckBox()-Methodedes GuiHelpers verwendet werden. Wie jede add()-Methode der Klasse liefert sie als R¨ck- ugabewert die erzeugte Komponente. In den meisten F¨llen wird diese R¨ckgabe ignoriert, a uin diesem Fall kann sie aber dazu genutzt werden, weitere Eigenschaften der Check-Box zusetzen. Da die Eigenschaft nicht vom Benutzer gesetzt werden kann, ist dieses Feld nichteditierbar. Deshalb wird die Eigenschaft enable auf false gesetzt. Es entsteht folgenderAufruf.// Is EuroGuiHelper.addCheckBox( ctx, translator, "emu__iseurolabel", "iseurolabel", mBo.isTheEuro()).setEnable(false);
  • 187. 7.3 Detail-Ansicht 182Die zweite Check-Box f¨r die Angabe, ob es sich um eine W¨hrung der EWU handelt, kann u agenauso implementiert werden. Allerdings werden hier Abh¨ngigkeiten von Feldern definiert. aEine Eingabe in die Felder f¨r das Startdatum der G¨ltigkeit und den Umrechnungskurs zum u uEuro ist nur dann sinnvoll, wenn diese Check-Box aktiviert ist. Folglich muss beim Erzeugender Check-Box angegeben werden, dass die anderen Felder nur im Falle einer Aktivierung zurVerf¨gung stehen. Hierzu dient die Klasse JavaScriptHelper (6.3.29), die f¨r ein solches Sze- u unario die Methode enableByCheckBox() anbietet. Dieser Mehode ubergibt man den Namen ¨der Check-Box und eine Liste von Elementen, die von ihr abh¨ngig sind. Den R¨ckgabewert a uder enableByCheckBox()-Funktion kann wiederum der GuiHelper-Methode als zus¨tzlicheraParameter ubergeben werden. Zusammen ergibt sich der folgende Funktionsaufruf. ¨// EMU CurrencyGuiHelper.addCheckBox( ctx, translator, "emu__emucurrencylabel", "emucurrencylabel", mBo.hasEmuData(), JavaScriptHelper.enableByCheckBox( "emu__emucurrencylabel", new String[] { "emu__dateemucurrencylabel", "emu__triangulationlabel", "emu__emuratelabel" } ));Die weiteren Felder werden wie gewohnt hinzugef¨gt. u// Date EMU CurrencyGuiHelper.addDateField( ctx, translator, "emu__dateemucurrencylabel", "dateemucurrencylabel", mBo.getisEmuCurrencyUnion().getDateEmuCurrency());// EMU RateGuiHelper.addNumberField( ctx, translator, "emu__emuratelabel", "emuratelabel", mBo.getisEmuCurrencyUnion().getEmuRate());
  • 188. 7.3 Detail-Ansicht 183Somit w¨re auch der zweite Tabsheet-Reiter vollst¨ndig. Der letzte Reiter besteht nur aus a aeinem Feld. Es handelt sich hierbei um ein mehrzeiliges Textfeld, das zur Angabe von diversenNotizen gedacht ist. Um ein mehrzeiliges Textfeld zu erzeugen, sollte die addTextArea()-Funktion der GuiHelper-Klasse verwendet werden. Die Handhabung entspricht exakt dereines einzeiligen Textfeldes.GuiHelper.addTextArea( ctx, translator, "notes__notes", null, mBo.getNote());Es f¨llt auf, dass keine Beschriftung, sondern null ubergeben wurde. Hierdurch l¨ßt sich die a ¨ aBeschriftung ausschalten. Eine Feldbezeichnung ist hier nicht notwendig, weil das Tabsheet- ¨Register keine weitern Felder enth¨lt. Somit bildet bereits die Register-Uberschrift eine Be- azeichnung f¨r das Eingabefeld. uNachdem nun alle GUI-Elemente erzeugt wurden, kann auch hier die Verarbeitung an eineJSP-Seite weitergegeben werden. Genau wir bei der VListServlet-Klasse dient hierzu derAufruf von forwardToJsp().forwardToJsp( ctx, "/framework/currency/CurrencyDetail.jsp", menu);Nachdem die Oberfl¨che erzeugt wurde, sollen nun noch die Methoden getBO() und fillBO() ader Klasse angesprochen werden. Beide Methoden sind in der Oberklasse VDetailServletals abstrakt gekennzeichnet. Das bedeutet, dass alle abgeleiteten Klassen diese Methodenimplementieren m¨ssen. Die Methoden dienen dazu, das jeweils aktuelle BO zu erfragen. ufillBO() wurde bereits oben angwendet. Die Methode liefert das BO im aktuellen Zusand, ¨d.h. alle Anderungen des Benutzers sind an diesem BO vorgenommen, obwohl es noch nichtin der Datenbank gespeichert wurde. Damit BOs auf eine solche Weise tempor¨r zwischen- agespeichert werden k¨nnen, ohne dass ein Speichern in der Datenbank notwendig ist, wurde odie Klasse TempData (6.1.15) entworfen. Mit ihr k¨nnen BOs in der Session gespeichert und oaus dieser geladen werden. Genau diesen Mechanismus stellt getBO() bereit.In dieser Methode wird das BO aus dem TempData-Speicher geladen. Wird dort ein BOgefunden, wird es zur¨ckgegeben. Sollte kein BO gefunden werden, gibt es zwei weitere uM¨glichkeiten. Erstens kann es sein, dass das BO gerade vom Benutzer neu angelegt wurde. oIn diesem Fall wird eine neue Instanz des BOs zur¨ckgegeben. Zweitens k¨nnte die Anfra- u oge die erste sein. Folglich wurde noch kein BO in den TempData-Speicher geschrieben. DiegetBO()-Methode muss dann mit der Server-Funktion das BO mit der ObjectID erfragen. ¨Diese Uberlegungen f¨hren zu folgender Implementierung: uprotected BO getBO (VContext ctx) {
  • 189. 7.3 Detail-Ansicht 184 CurrencyBO mBo = (CurrencyBO) TempData.loadBO(ctx); if ((ctx.isNew()) && (mBo == null)) { mBo = new CurrencyBO(); } if (mBo == null) { mBo = CurrencyBO.getCurrency(ctx, ctx.getOidDetail()); } return mBo;}Man sieht, dass getBO() immer das aktuelle BO liefert. Es bleibt jedoch die Frage offen,wann und wie Benutzereingaben den BO-Zustand ¨ndern und wo dass BO in den TempData- aSpeicher geschrieben wird. Genau diese Funktionalit¨ten bietet die Methode fillBO(). Sie a ¨liefert im Gegensatz zu getBO() das BO inklusive der letzten Anderungen. Dazu erfragt es ¨zun¨chst das BO von der getBO()-Methode. Wurden keine Anderungen vorgenommen, muss adas BO nicht angepasst werden.protected BO fillBO (VContext ctx) { CurrencyBO mBo = (CurrencyBO) getBO(ctx); if (!ctx.hasChanged()) { TempData.storeBO(ctx, mBo); return mBo; }Anschließend erfolgt die Verarbeitung der Benutzereingaben entspr¨chend des aktuellen aTabsheet-Registers.switch (ctx.getTabSheetIndex()) { case TAB_DETAILS: // Hier Komponenten des ersten Registers updaten break; case TAB_EMU: // Hier Komponenten des zweiten Registers updaten break; case TAB_NOTE: // Hier Komponenten des dritten Registers updaten break;} // switchDas BO wird auf den neusten Stand gebracht, indem zuerst die Formularwerte mit einer dergetAttribute()-Methoden des VContexts abgefragt werden und diese dann an die Setter-Methoden des BOs ubergeben werden. ¨// CodemBo.setCode( ctx.getStringAttribute(PARAMETER, "details__codelabel"));
  • 190. 7.3 Detail-Ansicht 185Hier wird der Wert des Element details codelabel abgefragt. Die entspricht dem Namen,der dem Feld bei seiner Erstellung zugewiesen wurde. Genauso werden die Werte f¨r Name, uHaupt-, Untereinheit und Importcode gesetzt. Auch der Wert des LabeledButtonTextFieldswird so gesetzt.// Code// SWIFTmBo.setSwift( ctx.getStringAttribute(PARAMETER, "details__swiftlabel"));Bei der Eingabe der G¨ltigkeitsdauer wurde ein Datumsfeld verwendet. Solche Parameter usollten mit getDateAttribute() abgefragt werdebm da dieser Methode den R¨ckgabewert ubereits in ein passendes Format f¨r den Serveraufruf formatiert. u// Use UntilmBo.setStopDate( ctx.getDateAttribute(PARAMETER, "details__useuntillabel"));Als letztes fehlen die beiden Combo-Boxen. Ihr Wert kann mit getIntAttribute() abgefragtwerden. Man erh¨lt den Index des selektierten Eintrags. Auch f¨r die Umwandlung des Index a uin ein Enum-Objekt bietet der automatisch erzeugte RoundingHelper eine passende FunktiongetIdl().// RoundingmBo.setRoundingmode( RoundingHelper.getIdl( ctx.getIntAttribute(PARAMETER, "details__roundinglabel") ));Die Angabe der Dezimalstelle kann fast unver¨ndert ubernommen worden. Jedoch ist zu a ¨beachten, dass noch eine Umrechnung des Combo-Box-Index in die Angabe der Nachkom-mastellen durchzuf¨hren ist. Im Detail bedeutet dies, dass zu dem Index der Wert f¨r u uMIN DECIMAL PLACES addiert werden muss.// DecimalPlacesmBo.setDecimalplaces( (short)( ctx.getShortAttribute(PARAMETER, "details__decimalplaceslabel") + MIN_DECIMAL_PLACES.value ));Beim zweiten Tabsheet-Register ist zu beachten, dass die IDL-Struktur hier eine Unionenth¨lt. Unions erm¨glichen es, in verschiedenen Situationen unterschiedliche Datentypen zu a overwenden. In diesem Fall bedeutet das konkret, dass die Klasse CurrencyBO eine Instanz der
  • 191. 7.3 Detail-Ansicht 186Klasse EmuDataBO enthalten kann oder nicht. Ist die Check-Box f¨r die EWU aktiviert, enth¨lt u adas W¨hrungs-BO auch ein EmuDataBO, andernfalls nicht. Die Attribute des EmuDataBOs wer- aden durch die jeweiligen Setter-Methoden an die Benutzereingaben angepasst.// EMU Currencyif (!ctx.getBooleanAttribute(PARAMETER, "emu__emucurrencylabel")) { mBo.clearEmuData();} else { EmuDataBO emu = new EmuDataBO(); // Date EMU Currency emu.setDateEmuCurrency( ctx.getDateAttribute(PARAMETER, "emu__dateemucurrencylabel") ); // EMU Rate if (ctx.hasNonEmptyAttribute(PARAMETER, "emu__emuratelabel")) { emu.setEmuRate( ""+ctx.getIntAttribute(PARAMETER, "emu__emuratelabel") ); } else { emu.setEmuRate(""); } mBo.setisEmuCurrencyUnion(emu); // Triangulation mBo.setTriangleCalculation( ctx.getBooleanAttribute(PARAMETER, "emu__triangulationlabel") );}Zu letzt, werden die Angaben des letzten Registers geschrieben. Dies geschiet genau wie beiden Textfeldern des ersten Registers.// NotesmBo.setNote( ctx.getStringAttribute( PARAMETER, "notes__notes" ));Nachdem nun das BO durch die Setter-Methoden auf den aktuellen Stand gebracht wurden,kann das BO in den TempData-Speicher geschrieben werden und anschließend als Wert derfillBO()-Funktion zur¨ckgeliefert werden. u// NotesTempData.storeBO(ctx, mBo);return mBo;
  • 192. 7.3 Detail-Ansicht 1877.3.2 Die JSP-Detail-SeiteGenau wie bei der Listen-Ansicht ubernimmt eine JSP-Seite die Darstellung der Detail- ¨ ¨Angaben. Diese Seite hat große Ahnlichkeit mit der Listen-Seite. Auch hier wird die Varial-Taglib eingebunden, ben¨tigte Klassen importiert und ein VContext erzeugt, der den Seiten- ozugriff regelt. Ziel des Formulars ist hier das DetailServlet.Als erstes m¨ssen eine Reihe von Parametern eingebunden werden. Im einzelnen sind dies u oiddetail (ObjectID des aktuell in der Dateiansicht angezeigten BOs), boindex (Indexin der Navigationsreihenfolge), oidparent (ObjectID des Parent-Objekts) und enablesave(Angabe, ob der Speicher-Button aktiviert ist). Durch die Verwendung des hiddenfield-Tagsder Varial-Taglib wird garantiert, dass die Parameterwerte w¨hrend der Verarbeitung nicht averloren gehen, sondern von Anfrage zu Anfrage ubergeben werden. Also letztes verstecktes ¨Feld muss die Seite folgende Zeile enthalten:<input type="hidden" name="__changed" value="false"> ¨Dieses Feld gibt an, dass keine Anderungen vorgenommen wurden. Werden Elemente derOberfl¨che ver¨ndert, wird von ihnen die JavaScript-Methode enableSave() aufgerufen, die a aden Wert des Feldes auf true setzt. Auf diese Weise ist es dem Servlet m¨glich zu erkennen, o ¨ob der Anwender Anderungen an dem BO vergenommen hat. o u ¨Als n¨chstes k¨nnen Men¨leiste und Uberschrift genau wie bei der Listenansicht eingef¨gt a uwerden. Es folgen die vom Servlet erzeugten GUI-Komponenten. Diese werden mit benutzer-definierten Tags eingebunden. Alle Tag erwarten als Attribute den Namen der Componente.Ein Aufruf entspricht immer dem Aufbau dieses Beispiels:<varial:textfield id="details__codelabel" width="150px"/>Damit eine saubere Darstellung garantiert wird, werden die Komponenten in einer Tabelleangeordnet. Das folgende Listing zeigt die komplette JSP-Seite.<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.0 Transitional//EN"><%@ page errorPage="errorpage.jsp" %><%@ taglib uri="/WEB-INF/tlds/varial.tld" prefix="varial" %><%@ page import=" com.varial.translation.*, com.varial.base.*, com.varial.gui.* "%><% VContext ctx = new VContext(this, request, response); ctx.checkLogin(); Translator translator = new Translator ("personalaccountinfo", "vcustomerinfoform");%>
  • 193. 7.3 Detail-Ansicht 188<html><head> <title>Currency (Detail)</title> <varial:csslink/> <varial:javascript/></head><body class="base" leftmargin="0" topmargin="0" onLoad="init()"> <form name="vform" action="<%= response.encodeRedirectURL("com.varial.framework.servlet.cu <table width="660" cellspacing="10"> <tr> <td width="100%"> <%-- - - - - - - - HIDDEN-FIELDS - - - - - - - --%> <varial:hiddenfield name="__oiddetail"/> <varial:hiddenfield name="__boindex"/> <varial:hiddenfield name="__oidparent"/> <varial:hiddenfield name="__enablesave"/> <input type="hidden" name="__changed" value="false"> <%-- - - - - - - - HEADLINE - - - - - - - - - - --%> <varial:headline/><br> <%-- - - - - - - - MENU - - - - - - - - - - - - --%> <varial:menubar/> <%-- - - - - - - - TABSHEETS - - - - - - - - - - --%> <varial:tabsheetcontrol> <%-- - - - - - - - TAB 0 - - - - - - - - - - - - --%> <varial:tabsheet index="0"> <div align="center"> <table border="0"> <tr> <varial:textfield id="details__codelabel" width="150px"/> <varial:textfield id="details__namelabel" width="150px"/> </tr> <tr> <varial:textfield id="details__unitlabel" width="150px"/> <varial:textfield id="details__subunitlabel" width="150px"/> </tr> <tr> <varial:vspacer height="12" colspan="4"/>
  • 194. 7.3 Detail-Ansicht 189 </tr> <tr> <varial:buttontextfield id="details__swiftlabel" width="140px"/> <varial:empty/> </tr> <tr> <varial:vspacer height="12" colspan="4"/> </tr> <tr> <varial:combobox id="details__decimalplaceslabel" width="150px"/> <varial:combobox id="details__roundinglabel" width="150px"/> </tr> <tr> <varial:datefield id="details__useuntillabel" width="150px"/> <varial:textfield id="details__importcodelabel" width="150px"/> </tr> </table> </div> </varial:tabsheet> <%-- - - - - - - - TAB 1 - - - - - - - - - - - - --%> <varial:tabsheet index="1"> <div align="center"> <table border="0"> <tr> <varial:checkbox id="emu__iseurolabel"/> <varial:empty/> </tr> <tr> <varial:checkbox id="emu__emucurrencylabel"/> <varial:datefield id="emu__dateemucurrencylabel" width="150px"/> </tr> <tr> <varial:checkbox id="emu__triangulationlabel"/> <varial:numberfield id="emu__emuratelabel" width="150px"/> </tr> </table> </div> </varial:tabsheet> <%-- - - - - - - - TAB 2 - - - - - - - - - - - - --%> <varial:tabsheet index="2"> <table border="0" width="100%"> <tr valign="top"> <varial:memo id="notes__notes" width="100%" maxlength="254" wrap="virtual"/>
  • 195. 7.4 Auswahl-Dialog 190 </tr> </table> </varial:tabsheet> </varial:tabsheetcontrol> <hr> <varial:lastchange align="right"/> </td> </tr> </table> </form></body></html>Interessant ist hier die Verwendung der Tabsheets. Alle Register sind mit demtabsheetcontrol-Tag umrandet. Jedes einzelne Register befindet sich wiederum in einemtabsheet-Tag, das daf¨r sorgt, dass der Inhalt nur dann angezeigt wird, wenn die jeweilige uRegister-Karte ausgew¨hlt ist. Ebenfalls neu ist das lastchange-Tag. Es ist daf¨r zust¨ndig, a u a ¨dass eine Statusmeldung mit Datum und Benutzer der letzen Anderung angezeigt wird.7.3.3 ZusammenfassungNach den oben beschriebenen Schritten ist nun auch die Detailansicht komplett. Der Ab-lauf ist dabei immer identisch. Das Servlet leitet von VDetailServlet ab, erzeugt mit demGuiHelper passende Elemente, die als Wert die Ergebnisse der Getter-Methoden erhalten.Anschließend wird die Bearbeitung an eine JSP-Seite zwecks Visualisierung abgegeben. EinDetailServlet definiert ferner die Methoden getBO() und fillBO(). W¨hrend getBO() nur adas BO aus dem TempData-Speicher l¨dt bzw. es neu erzeugt oder vom CORBA-Server an- a ¨fordert, f¨llt die Methode fillBO() das BO mit den neusten Anderungen. Dazu wird den uSetter-Methoden des BOs die Query-String-Parameter ubergeben. ¨7.4 Auswahl-DialogEinige Use-Cases beinhalten diverse Auswahl-Dialoge. Im Beispiel ist dies die Auswahl desISO-Codes aus einer Liste vordefinierter Angaben.7.4.1 Das SelectServletServlets, die Auswahl-Dialoge implementieren, werden von der Klasse VSelectServlet ¨(6.1.4) abgeleitet und definieren als erstes eine Translator, der die Ubersetzung der Sei-te regelt.public class SelectIsoCodeServlet extends VSelectServlet { private final static Translator translator = new Translator("currency", "vsearchswiftform");
  • 196. 7.4 Auswahl-Dialog 191Um die HTTP-Anfragen zu verarbeiten, wird die Methode getItDetail() uberladen. ¨protected void getItSelect (VContext ctx)Im Folgendem unterscheidet sich das SelectServlet kaum vom ListServlet der Listen-Ansicht. ¨Es werden die Uberschrift und die Tabelle (mit State-Klasse) angegeben und die Verarbei-tung an eine JSP-Seite ubergeben. Neu ist hier nur, dass mit der Methode setSearch() des ¨GuiHelpers eine weitere Komponente definiert wird. Hierbei handelt es sich um ein Textfeld,mit dessen Hilfe der Anwender den Tabelleninhalt filtern kann. Tippt man beispielsweiseein A“ ein, erscheinen in der Tabelle nur Eintr¨ge, die mit diesem Buchstaben beginnen. a ”Entsprechend kann man die Suchvorgabe weiter verfeinern. Die Aktuallisierung des Tabellen-inhalts kann dabei immer direkt mit der Eingabe oder erst nach ausdr¨cklicher Anweisung uerfolgen. Ein Klick auf das Reload-Icon aktuallisiert die Tabelle. Durch Aktivierung der ne-benstehenden Check-Box erfolgt die Aktuallisierung automatisch nach jedem eingegebenenZeichen.// HeadlineGuiHelper.setHeadLine(ctx, translator.getCaption(ctx, "vsearchswiftform"));// SearchGuiHelper.setSearch(ctx, translator.getCaption(ctx, "vsearchswiftform"));// GridGuiHelper.addGrid ( ctx, new SelectIsoCodeGridState());// Forward to JSPforwardToJsp( ctx, "/framework/currency/SelectIsoCode.jsp");7.4.2 Der SelectStateDurch die Verwendung einer Tabelle auf der Auswahlseite muss eine passende State-Klasse entworfen werden. Sie tr¨gt den Namen SelectIsoCodeGridState und wird von aVSelectState (6.1.9) abgeleitet. Sie beinhaltet einige bekannte Elemente. So wird auch hierein Translator angelegt und die Methode writeData uberladen. ¨public class SelectIsoCodeGridState extends VSelectState { private final static Translator translator = new Translator("currency", "vsearchswiftform"); public void writeData(VContext ctx, GridBean grid)
  • 197. 7.4 Auswahl-Dialog 192In der Methode wird zun¨chst der Query-String-Parameter search gelesen, der angibt, awelche Eingabe bereits vom Benutzer get¨tigt wurde. Der Tabelleninhalt soll ja entsprechend aangepasst werden. Dazu wird diese Angabe der Methode findSwiftcodes() ubergeben, die ¨daraufhin eine Liste aller passenden ISO-Codes liefert.String code = "";if (ctx.hasAttribute(PARAMETER, "__search")) { code = ctx.getSearch();}// Get AccountsSwiftcodeBO[] swifts = SwiftcodeBO.findSwiftcodes( ctx, code );Nun wird die Tabelle durch Aufruf der addRow()-Methode in einer Schleife genau wie bei derListen-Ansicht gef¨llt. u// Fill gridgrid.setQueryStringForRowSize(swifts.length);for (int i=0; i<swifts.length; i++) { SwiftcodeBO swift = swifts[i]; grid.addQueryStringForRow( i, new StringBuffer() .append("__selectedCode=") .append(swift.getCode()) .toString() ); grid.addRow ( ctx, swift, new Object[] { swift.getCode(), swift.getCurrencyName() } );}Es f¨llt auf, dass zus¨tzlich mit setQueryStringForRowSize() jeder Reihe ein weiterer a aQuery-String-Parameter gesetzt wird. Es ist der jeweilige ISO-Code, der als selectedCodeubergeben wird. Diese Angabe dient dazu, dass das SelectServlet erf¨hrt, welcher Eintrag der¨ aListe ausgew¨hlt wurde. Normalerweise liefert jede Zeile in einem VSelectGrid die ObjectID ades jeweiligen Eintrags. Das SelectServlet kann dar¨ber das passende Objekt finden. Da der uCORBA-Server aber in der IDL aber keine Methode bereit stellt, mit der ein SwiftcodeBO
  • 198. 7.4 Auswahl-Dialog 193bzw. ein SwiftcodeStruct¨ber die ObjectID erfragt werden kann, muss statdessen die Code- uAngabe verwendet werden.Wie gewohnt definiert auch diese State-Klasse die Tabellen¨berschriften. upublic String[] getHeaders( VContext ctx) { return new String[] { translator.getCaption(ctx, "grid#column#0"), // Code translator.getCaption(ctx, "grid#column#1"), // Name };}Neu dagegen ist die Methode getAction(), die eine eindeutige Bezeichnung f¨r den Aufruf udes Auswahldialogs liefert.public String getAction (VContext ctx) { return "selectSwiftCode";}Hierdurch wird die Aktion selectSwiftCode“ mit der Auswahl eines ISO-Codes in Verbin- ”dung gebracht. Beim Anklicken einer Tabellenzeile wird diese Angabe als Aktionsbezeichnungan das Select-Servlet ubertragen. Das Servlet weiß dann, welche Aktion ausgef¨hrt wurde. ¨ uBei Abbruch der Auswahl durch den entsprechenden Cancel-Button wird keine Aktionsbe-zeichnung ubertragen. Aus Sicht des Servlet ist dadurch einfach nichts passiert. ¨7.4.3 Die JSP-Auswahl-SeiteDie JSP-Seite unterscheidet sich nicht viel von der Listen-Ansicht. Jedoch wird zus¨tzlich adas Suchfeld durch das selectsearch-Tag eingebunden. Außerdem m¨ssen genau wie bei uder JSP-Seite f¨r die Detaildarstellung einige Parameter mit versteckten Formularfeldern uzwischengespeichert werden, damit die entsprechenden Werte nicht w¨hrend der Verarbeitung averloren gehen.<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.0 Transitional//EN"><%@ page errorPage="../../errorpage.jsp" %><%@ taglib uri="/WEB-INF/tlds/varial.tld" prefix="varial" %><%@ page import=" com.varial.base.*, com.varial.gui.* "%><% VContext ctx = new VContext(this, request, response);
  • 199. 7.4 Auswahl-Dialog 194 ctx.checkLogin(); ctx.setAttribute(VContext.REQUEST, "__ctx", ctx);%><html><head> <title>SWIFT</title> <varial:csslink/> <varial:javascript/></head><body class="base" leftmargin="0" topmargin="0" onLoad="init()"> <form name="vform" action="<%= response.encodeRedirectURL("com.varial.framework.servlet.cu <table width="640" cellspacing="10"> <tr> <td width="15"></td> <td width="100%"> <varial:hiddenfield name="__oiddetail"/> <varial:hiddenfield name="__oidparent"/> <varial:hiddenfield name="__boindex"/> <varial:hiddenfield name="__tabsheetindex"/> <varial:hiddenfield name="__referer"/> <varial:hiddenfield name="__action"/> <!-- - - - - - - - HEADLINE - - - - - - - - - ---> <varial:headline/><br> <br> <hr> <!-- - - - - - - - SEARCH - - - - - - - - - - ---> <varial:selectsearch/><br> <hr> <!-- - - - - - - - GRID - - - - - - - - - - - - --> <varial:grid height="350px"/> </td> </tr> </table> </form></body></html>
  • 200. 7.5 Abschluss 1957.4.4 ZusammenfassungAuswahldialoge bestehen zumeist aus einem Servlet, das von der Klasse VSelectServletabgeleitet wird, und einer State-Klasse, einer Unterklasse von 6.1.9. Der Aufbau ist fastidentisch mit der Listenansicht, jedoch kann zus¨tzlich ein Suchfeld erstellt werden, das den aInhalt der Tabelle filtert. Jede Auswahl hat eine eindeutige Aktionsbezeichnung, durch diedie Auswahl vom DetailServlet erkannt wird.7.5 AbschlussDie VWE-Web-GUI erm¨glicht den Entwurf grafischer Benutzeroberfl¨chen f¨r die Browser- o a uDarstellung. Der Aufbau der Seiten ist hierbei bei jedem Use-Case nahezu identisch.Nach kurzer Einarbeitungszeit k¨nnen so weitere Programm-Module relativ schnell f¨rs o uWeb implementiert werden. Die Umsetzung der W¨hrungsverwaltung war beispielsweise ain knapp zwei Stunden m¨glich. Dadurch, dass die API die Feinheiten von CORBA und odas typische Request-/Response-Modell mit all seinen T¨cken vor dem Entwickler ver- ubergen, ist eine Entwicklung auf einer recht hohen Abstraktionsebene m¨glich. Bevor der oUse-Case endg¨ltig abgschlossen ist, muss er jetzt nur noch in der Men¨struktur ver- u ulinkt werden. Dazu ist VWE im Administrationsmodus zu starten. Dort k¨nnen berech- otigte User die Men¨darstellung von VWE ver¨ndern. Nach Auswahl des Web-Men¨s kann u a udie W¨hrungen-Pflege als neuer Men¨punkt aufgenommen werden. Neben einer Bezeich- a unung wird das Packet (com.varial.framework.servlet.currency) und der Servlet-Name ¨(CurrencyListServlet) angegeben. Nachdem die Anderungen gespeichert wurden, befindetsich die W¨hrungen-Pflege im Web-Men¨. Um eine h¨here Performance zu erreichen, werden a u oMen¨daten jedoch im Server gecacht. In der Regel ¨ndert sich die Men¨struktur nur sehr u a uselten oder uberhaupt nicht. Infolgedessen ist die Zwischenspeicherung nicht weiter schlimm. ¨Sollten neue Punkte ins Web-Men¨ aufgenommen werden. Muss der Web-Server neu gestar- utet werden, bevor die neuen Programmmodule angezeigt werden.Der komplette Source-Code kann im Anhang noch einmal zusammengefasst betrachtet wer-den.
  • 201. 8 Aufbau und Bedienung der Web-Oberflache ¨ 196
  • 202. 9 Zusammenfassung und AusblickeIm Rahmen der Diplomarbeit wurde eine Klassenbibliothek entwickelt, mit der das ERP-System Varial World Edition um ein Web-Interface erweitert werden kann. Es wurdenTechniken und Konzepte diskutiert und an Hand ausgew¨hlter Beispiele eine Realisierung ademonstriert.Die Diplomarbeit zeigt zum einen, dass eine Web-Anbindung nicht nur sinnvoll ist, sonderndass sie auch mit dem hier entworfenen System umsetzbar ist. Zum anderen zeigte sichjedoch auch deutlich, dass der momentane Stand der Technik f¨r solche Anwendungen noch unicht als ausgereift bezeichnet werden kann. Zwar bietet CORBA eine optimale Infrastrukturf¨r verteilte Anwendungen, in der problemlos ein Servlet den Platz eines Client einnehmen ukann, jedoch liegen die Schwachstellen f¨r die Entwicklung von webbasierten Anwendungen udeutlich im Bereicht HTTP und HTML.Da das Servlet lediglich eine HTML-Seite erzeugen kann, die dann vom Web-Server ander Browser geschickt wird, ist es ihm nicht m¨glich, unmittelbar auf die Verarbeitung der oEingaben zu reagieren. Mit HTTP werden Aktionen des Web-Servers ausschließlich aufClient-Anfrage hin ber¨cksichtigt. Somit fehlt der erzeugten HTML-Seite teilweise die n¨tige u oProgrammlogik, um auf Oberfl¨chenereignisse und Benutzeraktionen passend zu reagieren. aJavaScript stellt auf Grund seines eher rudiment¨ren Charakters keine wirkliche Alternative azur m¨chtigen Java-API dar. aWeiterhin hat sich gezeigt, dass sich die Browser unterschiedlicher Hersteller zum Teilso stark unterscheiden, dass eine allgemein g¨ltige und auf allen Systemen lauff¨hige u aInternet-Applikation sehr schwer und nur mit vielen Umwegen zu realisieren sind. Vor allemin der Handhabung von DOM (Document Object Modell) unterscheiden sich die einzelnenBrowser sehr stark. Einige Varianten unterst¨tzten das Modell erst gar nicht. uEine weitere H¨rde, die auf dem Weg zur Realisierung eines Web-Interfaces genommen uwerden musste, war die Tatsache, dass einige allgemein gebr¨uchliche grafische Ober- afl¨chenelemement von HTML nicht angeboten werden. So gibt es beispielsweise keine aeditierbare Combo-Box, so dass eine entsprechende Komponente selbst aus den vorhandenenM¨glichkeiten entwickelt werden musste. oZusammenfassend l¨ßt sich sagen, dass eine Realisierung eines webbasierten ERP-Systems atrotz der noch nicht ausgereiften Technik, erm¨glicht wurde. In Zukunft werden die entspre- ochenden Web-Technologien sicherlich entsprechend erweitert, so dass Internet-Applikationden gewohnten Desktop-Anwendungen in nichts nachstehen. Eventuell werden die Grenzenzwischen diesen beiden Arten von Software bald sogar ganz verwischen, so dass zuk¨nftig ukein Unterschied zwischen Online- und Offline-Applikation mehr bestehen wird. Leider konnten nicht alle Ideen, die zu Beginn im Vorfeld entworfen wurden, umgesetztwerden, da sie den Umfang der Arbeit gespregt h¨tten. Einige Vision werden vorraussichtlich aim Anschluss an die Arbeit bei Varial in Angriff genommen werden. 197
  • 203. 198Erklarung ¨Hiermit versichere ich, daß ich die vorliegende schriftliche Arbeit als auch die Programmie-rung selbstst¨ndig und unter Verwendung der angegebenen Literatur und Hilfsmittel erstellt ahabe. Gleichzeitig versichere ich, daß diese Arbeit in keiner Weise, gleich oder ¨hnlich, weder aver¨ffentlicht noch einer anderen Pr¨fungsbeh¨rde vorgelegt habe. o u oSiegen, den 28. August 2002.
  • 204. 199A AnhangTabellenverzeichnis 1 VContext-Methoden f¨r besondere Parameter . . . . . . . . u . . . . . . . . . . 97 2 Beispiele f¨r die Formatierung von W¨hrungsangaben . . . u a . . . . . . . . . . 108 3 Eigenschaften von GUI-Elementen . . . . . . . . . . . . . . . . . . . . . . . . 125 4 Erzeugte Ausgaben der Klasse LabeledListBoxButtons . . . . . . . . . . . . . 133 5 Beispiel f¨r die Vergabe von Index-Nummern bei Tabsheets u . . . . . . . . . . 137 6 Attribute des Tags textfield . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 7 Attribute des Tags numberfield . . . . . . . . . . . . . . . . . . . . . . . . . . 147 8 Attribute des Tags currencyfield . . . . . . . . . . . . . . . . . . . . . . . . . 147 9 Attribute des Tags datefield . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 10 Attribute des Tags memo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 11 Attribute des Tags buttontextfield . . . . . . . . . . . . . . . . . . . . . . . . 148 12 Attribute des Tags checkbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 13 Attribute des Tags radiobutton . . . . . . . . . . . . . . . . . . . . . . . . . . 149 14 Attribute des Tags combobox . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 15 Attribute des Tags editablecombobox . . . . . . . . . . . . . . . . . . . . . . . 149 16 Attribute des Tags listbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 17 Attribute des Tags grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 18 Attribute des Tags graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 19 Attribute des Tags image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 20 Attribute des Tags vspacer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 21 Attribute des Tags tabsheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 22 Attribute des Tags lastchange . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 23 Attribute des Tags javascript . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 24 Attribute des Tags hiddenfield . . . . . . . . . . . . . . . . . . . . . . . . . . 152 25 Attribute des Tags hiddenextrafield . . . . . . . . . . . . . . . . . . . . . . . . 152 26 Attribute des Tags translator . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 27 Attribute des Tags languagestring . . . . . . . . . . . . . . . . . . . . . . . . 153
  • 205. A.1 Abbildungsverzeichnis 200A.1 AbbildungsverzeichnisAbbildungsverzeichnis 1 Web-Server mit CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2 Web-Server mit FastCGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3 Web-Server mit Server-Extension-API . . . . . . . . . . . . . . . . . . . . . . 8 4 Web-Server mit Servlet-Unterst¨tzung . . . . . . . . . . . . . . u . . . . . . . . 9 5 Aufbau der Object Management Architecture . . . . . . . . . . . . . . . . . . 13 6 Aufruf verteilter Objekte uber den ORB . . . . . . . . . . . . . ¨ . . . . . . . . 15 7 ORB-Verbindung mit IIOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 8 Sprachunanh¨ngigkeit durch IDL . . . . . . . . . . . . . . . . . a . . . . . . . . 16 9 Verteilte Anwendung mit RMI . . . . . . . . . . . . . . . . . . . . . . . . . . 18 10 Entwicklung von DCOM aus COM und RPC . . . . . . . . . . . . . . . . . . 19 11 Software-Komponente nach COM: Aufbau und Zugriff . . . . . . . . . . . . . 20 12 Verteilte Anwendung mit DCOM . . . . . . . . . . . . . . . . . . . . . . . . . 21 13 Aufbau des DCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 14 Kommunikation von COM-Objekten ohne MTS . . . . . . . . . . . . . . . . . 22 15 Kommunikation von COM-Objekten mit MTS . . . . . . . . . . . . . . . . . 22 16 Aufbau der SOAP Envelope . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 17 Der dreischichtige Aufbau von WVE . . . . . . . . . . . . . . . . . . . . . . . 27 18 Der vierschichtige Aufbau von WVE-Web . . . . . . . . . . . . . . . . . . . . 30 19 Anlegen eines Benutzers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 20 Prinzip der symmetrischen Verschl¨sselung . . . . . . . . . . . u . . . . . . . . 34 21 Prinzip der asymmetrischen Verschl¨sselung . . . . . . . . . . . u . . . . . . . . 35 22 Integration von SSL in TCP/IP . . . . . . . . . . . . . . . . . . . . . . . . . . 36 23 Daten¨bertragung mit SSL . . . . . . . . . . . . . . . . . . . . u . . . . . . . . 38 24 Die Web-Oberfl¨che in Englisch . . . . . . . . . . . . . . . . . . a . . . . . . . . 39 25 Die Web-Oberfl¨che in Deutsch . . . . . . . . . . . . . . . . . . a . . . . . . . . 39 26 Verteilung der HTTP-Anfragen mit Hilfe eines Load-Balancers . . . . . . . . 43 27 VWE-Web-Oberfl¨che mit dem Theme varial“ . . . . . . . . . a . . . . . . . . 47 ” 28 VWE-Web-Oberfl¨che mit dem Theme bunt“ . . . . . . . . . a . . . . . . . . 48 ” 29 VWE-Web-Oberfl¨che mit dem Theme eurosoft“ . . . . . . . . a . . . . . . . . 48 ” 30 Das MVC-Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 31 Das MVC Model 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 32 Methoden f¨r den Transport der Session-ID . . . . . . . . . . . u . . . . . . . . 54 33 Visualisierung von Tabsheets mit HTML und CSS . . . . . . . . . . . . . . . 72 34 Tabellendarstellung in VWE-Web . . . . . . . . . . . . . . . . . . . . . . . . . 77 35 Nach Excel exportierte Tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . 77 36 LabeledNumberField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 37 LabeledDateField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 38 LabeledComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 39 LabeledComboBox (ausgeklappt) . . . . . . . . . . . . . . . . . . . . . . . . . 162
  • 206. A.2 Glossar 201A.2 GlossarApplets Ein in Java geschriebenes Programm, das uber das Internet ubertragen und im ¨ ¨ Browser ausgef¨hrt wird. uBO Business-ObjektBOA Basic Object Adapter. Kernst¨ck eines ORBs. Sorgt daf¨r, dass verteilte Objekte u u aktiviert werden.Browser Programm, das HTML-Seiten darstellt und mit dem man durch diese navigieren kann.Business-Objekt Objekt im Sinne der objektorientieren Programmierung, das Eigenschaften und Methoden in einer Klasse b¨ndelt. uByte-Code Java-Programme werden in sog. Byte-Code kompiliert. Dieser Byte-Code ist plattformunabh¨ngig und kann mit einer JVM ausgef¨hrt werden, a uC++ Objektorientierte Programmiersprache.CGI Common Gateway Interface. Schnittstelle, die es dem Web-Server erlaubt, externe Pro- gramme zu starten und derren Inhalt an den Browser zu leiten.Cookie Kleine Textdatei, mit derren Hilfe Informationen auf dem Client-Rechner gespeichert werden k¨nnen. oCORBA Common Object Request Broker Architecture. CORBA erm¨glicht die Entwick- o lung verteilter Anwendungen, unabh¨ngig davon, welches Betriebssystem oder welche a Programmiersprache verwendet wird.CSS Cascading Stylesheets. Formatierungssprache, die vorwiegend f¨r HTML entwickelt wur- u de.Custom Tag JavaServer Pages erlaubt die Definition eigener Tags. Alle Vorkommnisse sol- cher benutzerdefinierten Tags werden von einer zugeh¨rigen Java-Klasse behandelt. oDesign Pattern Entwurfsmuster. Designvorschl¨ge f¨r den Entwurf objektorientierter Softwa- a u resysteme, die vordefinierte L¨sungen f¨r konkrete Programmierprobleme darstellen. o uDigital Economy Digitale Wirtschaft. Vision, die die Vernetzung von Wirtschaftspartnern uber moderne Kommunikationswege beschreibt. ¨ ¨DNS Domain Name Service. Ubersetzung symbolischer Adressen (www.varial.de) in die zu- geh¨rige IP-Adresse. oDTD Document Type Definition. Schemadefinitionssprache, die den Aufbau einer XML- Datei festlegt.Embedded-Systeme
  • 207. A.2 Glossar 202ERP Enterprise Resource Planning. Software, die ein Unternehmen bei der Abwicklung von Gesch¨ftsprozessen unterst¨tzt. a uGUI Graphical User Interface. Grafische Benutzeroberfl¨che. aHTML Hypertext Text Markup Language. Sprache, die Hypertext-Dokumente beschriebt. ¨HTTP Hypertext Transfer Protocol. Ubertragungsprotokoll f¨r HTML-Seiten. uIDL Interface Definition Language. Unabh¨ngige Sprache, mit der CORBA-Objekte be- a schrieben werden.IIOP Internet Inter-ORB Protocol. Protokol f¨r CORBA, das die Zusammenarbeit ver- u schiedener ORBs erm¨glicht. oIIS Internet Information Server. Web-Server von Microsoft.Java Moderne objektorientierte Programmiersprache von der Firma Sun MicrosystemsJDBC Java Database Connectivity. Schnittstelle zwischen einem Java-Programm und einer SQL-Datenbank.JScript Eine von Microsoft entwickelte Skript-Sprache, die an JavaScript angelehnt ist. We- gen lizenzrechtlichen Gr¨nden darf Microsoft JavaScript nicht weiterentwickeln und u implementiert deshalb JScript.JVM Java Virtual Machine. Erm¨glicht die Ausf¨hrung von Java-Byte-Code. o uLoad Balancer Software die Anfragen auf mehrere Server-Instanzen verteilt.MIME-Typ Multipurpose Internet Mail Extensions. Beschreibung von Multimedia-Typen.ObjectID Eindeutige Bezeichnung (Schl¨ssel) eines Business-Objekts. uOMG Object Managment Group. Konsortium aus uber 800 Firmen, das u.a. den CORBA- ¨ Standard definiert.ORB Object Request Broker. Software, die die CORBA-Spezifikation implementiert.Perl Practical Extraction and Report Language. Skript-Sprache mit m¨chtiger Syntax f¨r a u das Bearbeiten von Texten und Dateien (Regular Expressions). Meist eingesetzte Sprache f¨r CGI. uPOA Portable Object Adapter. Neuere Version des BOA. Weiter Vorschriften der OMG haben daf¨r gesorgt, dass die BOAs verschiedener Hersteller kompatibel zu einander u sind. Resultat ist POA.Query-String Zeichenkette mit Schl¨ssel-Werte-Paaren, die an eine URL angeh¨ngt werden u a und serverseitig ausgelesen werden kann.
  • 208. A.2 Glossar 203Regular Expresions Reg¨l¨re Ausdr¨cke. Syntax, mit der Suchmuster definiert werden ua u k¨nnen, Regul¨re Ausdr¨cke stellen ein m¨chtiges Mittel zur Bearbeitung von Texten o a u a dar.Session Sitzung. Zustand, bei dem Benutzer-Aktionen als zusammenh¨ngend erkannt werden. aSession-ID Eindeutiger Schl¨ssel f¨r eine Session. Der Web-Server verwaltet Sitzungen an- u u hand der Session-ID.Socket Einfache Peer-to-Peer-Verbindung. Dient als Schnittstelle f¨r den Zugriff auf u Netzwerk-Protokolle.SSL Secure Socket Layer. Eine von Netscape entwickelte Technologie, die Authentifizierung erm¨glicht. Der Datenverkehr erfolgt verschl¨sselt. o uTag Auszeihnungsbefehl, der ein Element in HTML bzw. XML markiert.Taglib Sammlung von zusammenh¨ngenden Tags zu einer Bibliothek. aTCP/IP Transmission Control Protocol / Internet Protokol. Verbindungsorientiertes Transport-Protokoll des Internets bei HTTP-Verbindungen. ¨UDP User Datagram Protocol. Verbindungsloses Ubertragungsprotokoll. Es besteht keine ¨ keine Ubertragungsgarantie.Union CORBA erlaubt in der IDL den Entwurf sog. Unions. Dies sind Objekt-Attribute, die in verschiedenen Situationen unterschiedliche Datentypen annehmen k¨nnen. oURL Uniform Resource Locator. Bezeichnet eine eindeutige Adresse, unter der ein Dokument im Internet gefunden werden kann.Use-Case Beschreibung eines typischen Anwendungsfall.Varial World Edition Neuentwickeltes ERP System der Firma Varial Software AGVBScript Eine von Microsoft entwicklete Skriptsprachem, die sich sehr stark an Visual Basic anlehnt. H¨ufig verwendet f¨r die Programmierung von ASP-Seietn. a uW3C World Wide Web Consortium. Gruppe verschiedener Softwarehersteller, deren Ziel die Weiterentwicklung und standadisierung von Internet-Technlogien ist. ¨WAP Wireless Application Protocol. Ubertragungsprotokoll f¨r Seiten f¨r Kleinstger¨te wie u u a Handys, Organizer oder PDAs.WAP Wireless Markup Language. Eine Beschreibungssprache f¨r WAP. uWeb-Browser BrowserWorld-Wide-Web InternetXML Extensible Markup Language. Metasprache, die eine strukturierte Darstellung von Da- ten in Textform erlaubt. XML-Dateien besitzen eine DTD, die den Aufbau des Do- kuments beschreibt. Inhalte werden wie bei HTML in Tags gekappselt.