Diplomarbeit


Entwicklung 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
INHALTSVERZEICHNIS                                                                                                                      i


Inhaltsverzeichnis
1   Einleitung                                                                                                                         3

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

3   Varial World Edition                                                                                                               26
    3.1 Leistungsumfang VWE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                              26
    3.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                          26
    3.3 Das Web-Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                            28

4   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-Ober߬che .  a         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47

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

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

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

8   Aufbau und Bedienung der Web-Ober߬che
                                      a                                                                                                                    196
INHALTSVERZEICHNIS                                                                             1


9   Zusammenfassung und Ausblicke                                                            197

A Anhang                                                                                      199
  Tabellenverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
  A.1 Abbildungsverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
  A.2 Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Vorwort
Die vorliegende Diplomarbeit beschreibt die Entwicklung einer Internet-Schnittstelle f¨r
                                                                                      u
das 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
                                                                                   a
war. Aus meinem Interesse sowohl an modernen Internet-Technologien als auch an der Java-
                                        ¨
Programmierung und den strategischen Uberlegungen des Unternehmens Varial entstand
die Idee, eine Anbindung der World Edition f¨r das World Wide Web zu konstruieren. Der
                                            u
Grundstein f¨r VWE-Web war gelegt.
             u

    Die Arbeit ist schließlich recht umfangreich ausgefallen, da sie neben den verwendeten
Technologien sowohl die Bedienung des Web-Interfaces als auch dessen Entwicklung be-
schreibt. Durch die Dokumentation aller wichtigen Klassen und die beispielhafte Umsetzung
einer Anwendung, soll es dem Leser erm¨glicht werden, die entwickelte API selbstst¨ndig zu
                                         o                                         a
verwenden 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                                 u
besonderer 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 ein
sehr 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                                     u
Korrekturlesen der Arbeit opferte. Auch bei meinen Kommilitonen Maik, der neben der
Korrektur f¨r viele interessante fachliche Diskussionen zur Stelle war, und Tobi f¨r seine
           u                                                                       u
Erkl¨rungen zu DCOM, SOAP & Co m¨chte ich mich an dieser Stelle herzlich bedanken.
    a                                    o
Ihr wart mir eine große Hilfe.

   Ebenfalls haben die vielen unz¨hligen User diverser Internet-Foren, wie vorzugweiße dem
                                 a
SELFHTML-Forum, zum Gelingen dieser Arbeit beigetragen. Danke f¨r die vielen guten
                                                                        u
Ratschl¨ge, Meinungen und Kritiken.
       a

    Außerdem sei meinen Mitmenschen gedankt, die mich in den letzen Monaten unterst¨tzt, u
gelobt, ertragen und getr¨stet haben und mit ihrem Verst¨ndnis den n¨tigen Freiraum f¨r
                          o                                 a             o                 u
die Erstellung der Arbeit gegeben haben und damit deren Realisierung erst erm¨glichten. Zu
                                                                                 o
guter Letzt gilt mein besonderer Dank nat¨rlich Julia, die mir nicht nur in Zeiten technischer
                                          u
Schwierigkeiten 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 mancher
Tiefphase und f¨r die Fertigstellung der Arbeit lieferte. Danke!
                 u
1 Einleitung
Die Industrie befindet sich zur Zeit im Wandel. Die traditionelle Wirtschaft bewegt sich
hin 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
                          u
Informations- und Kommunikationsmedium schlechthin.

    W¨hrend vor Jahren das Internet lediglich statische Inhalte zur Verf¨gung stellte, nimmt
      a                                                                 u
mittlerweile mehr und mehr dynamischer Content das Netz ein. Das Potential reicht jedoch
weit uber die M¨glichkeiten eines einfachen eShops oder eines G¨stebuchs hinaus. So bieten
     ¨         o                                                 a
sich auch einem modernen ERP-System interessante M¨glichkeiten, das Internet f¨r eine
                                                          o                           u
unternehmens- und weltweite Abwicklung von Gesch¨ftsf¨llen zu nutzen.
                                                     a a

    Diese Diplomarbeit beschreibt hierzu die Entwicklung eines Systems, mit dessen Hilfe
webbasierte 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. Der
Server wird in Java implementiert, w¨hrend clientseitig C++ zum Einsatz kommt.
                                    a
Im Rahmen der Diplomarbeit wird die Software um die M¨glichkeit erweitert, auf aus-
                                                            o
gew¨hlte Datenbest¨nde mittels Web-Browser zugreifen zu k¨nnen. Auf diese Weise wird
    a               a                                       o
es dem Benutzer erm¨glicht, VWE via Intra-, Extra- oder Internet von jedem beliebigen
                      o
Arbeitsplatz zu nutzen. Hierbei kommen Java Servlets zum Einsatz.

    Die Arbeit gliedert sich in neun Abschnitte. Nach dieser Einf¨hrung werden im zweiten
                                                                 u
Kapitel zun¨chst die beiden Techniken CORBA und Java Servlets vorgestellt. Hierbei werden
           a
insbesondere Alternativen zu diesen Technologien aufgezeigt und diskutiert. Die Vorteile des
verwendeten L¨sungsansatzes werden herausgestellt und die Entscheidung f¨r CORBA und
               o                                                            u
Java Servlets begr¨ndet.
                   u

   Kapitel 3 beschreibt das ERP-System VWE. Es wird ein Einblick in den Leistungsumfang
und den Aufbau von VWE gegeben. Außerdem wird gezeigt, wie ein Web-Interface die
bestehenden Funktionalit¨ten sinnvoll erweitern bzw. erg¨nzen kann.
                         a                              a

    Das vierte Kapitel fasst anschließend alle Anforderungen, die an eine Browser-Oberfl¨che
                                                                                       a
gestellt werden, zusammen. Kapitel 5 zeigt, wie diese Anforderungen umgesetzt wurden und
welche Fragestellungen und Probleme sich bei der Entwicklung ergaben.

   Kapitel 6 erl¨utert die Komponenten, die zur Realisierung entwickelt wurden. Zentrale
                a
Packete werden aufgef¨hrt und die Funktionen der Klassen im Einzelnen erl¨utert.
                      u                                                  a

    Im siebten Kapitel wird aufgezeigt, wie die entwickelten Komponenten zur Realisierung
eines Use-Cases eingesetzt werden k¨nnen. Hier wird eine kleine Anwendung beispielhaft
                                     o
4


umgesetzt.

   Kapitel 8 widmet sich der Bedienung der Web-Ober߬che. Der Aufbau sowie die
                                                    a
Handhabung des Web-Interfaces werden erl¨utert.
                                        a

   Das abschließende neunte Kapitel fasst noch einmal alle gewonnenen Erkenntnisse
zusammen und bietet einen Ausblick auf zuk¨nftige Entwicklungen.
                                          u
2 Technologie
2.1 Java Servlets
Servlets 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       u
sp¨ter das Interesse an Java durch den Einsatz als Applets. Bei Applets handelt es sich um
   a
Java-Code, der in einem Web-Umfeld clientseitig, also im Browser, ausgef¨hrt wird. Dank
                                                                          u
Javas Plattformunabh¨ngigkeit ist der Byte-Code auf jedem Betriebssytem ausf¨hrbar. Dies
                       a                                                      u
f¨hrte zusammen mit der Tatsache, dass eine solche Funktionalit¨t im Browser bislang
 u                                                                 a
unbekannt 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                                 u
keinesfalls auf die Behandlung von HTTP-Anfragen beschr¨nkt. Denkbar w¨re auch, ein
                                                             a                 a
Servlet in einen Mail- oder FTP-Server einzubetten, um dessen Funktionalit¨t zu erweitern.
                                                                            a
In der Praxis bilden solche Einsatzm¨glichkeiten jedoch eher die Ausnahme, so dass Servlets
                                    o
uberwiegend f¨r HTTP-Anfragen verwendet werden.
¨              u

2.1.1   Entstehungsgeschichte
Urspr¨nglich bestand die Aufgabe des Internets darin, Informationen in Form von statischen
      u
Seiten zur Verf¨gung zu stellen. Der Web-Server konnte die Anfrage eines Clients durch
                u
             ¨
die einfache Ubermittlung vorgefertigter Dokumente befriedigen. Mittlerweile hat sich das
Internet jedoch stark gewandelt, so dass die Bereitstellung statischer Seiten u.U. nicht mehr
ausreichend ist, sondern dass f¨r jede Anfrage eine andere Seite generiert werden muss. Es
                               u
gibt 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        a
nach dynamischen Web-Seiten entsprachen, gesucht.

2.1.2   Alternative Ans¨tze
                       a
Common Gateway Interface Das Common Gateway Interface (CGI) war die erste Techno-
logie, die das Erzeugen von dynamischen Web-Seiten erm¨glichte.
                                                      o

                                             5
2.1   Java Servlets                                                                       6


Bei CGI nimmt der Web-Server wie gewohnt eine Client-Anfrage entgegen, startet dann aber
ein externes Programm und leitet die Bearbeitung an dieses Programm weiter. Das Programm
generiert daraufhin die Antwortseite. Diese Seite kann nun vom Web-Server an den Client
gesendet werden.
Mit CGI k¨nnen dynamsiche Seiten in fast jeder Programmiersprache erzeugt werden. CGI
            o
ruft lediglich ein Programm auf und erwartet eine R¨ckgabe, die an den Browser geschickt
                                                     u
wird. In welcher Sprache das Programm geschrieben ist spielt hierbei keine Rolle. Allerdings
hat sich Perl als Programmiersprache durchgestetzt, da Perl m¨chtige Befehle zur Verar-
                                                                  a
beitung von Texten bereitstellt (u.a. Regular Expressions), die sich im Umfeld von CGI als
große Hilfe herausstellen. Auf diese Weise war es erstmals m¨glich, dynamsiche Seiten zu
                                                               o
erzeugen. Schnell verbreitete sich CGI und immer mehr Web-Server stellten dieses Interface
zur Verf¨gung.
         u
Der Nachteil von CGI ist jedoch, dass nicht gerade sparsam mit Serverresourcen umgegangen
wird. F¨r jede Anfrage wird das verarbeitende Programm als eigener Prozess gestartet. Bei
        u
hochfrequentierten 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                                         u
bei CGI jedesmal der Perl-Interpreter gestartet werden. Abbildung 1 zeigt die Funktionsweise
von 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
         o
beispielsweise nicht in das Logfile des Servers schreiben. Außerdem k¨nnen CGI-Skripte nur
                                                                    o
recht 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       a
Die Firma Open Market entwickelte eine Alternative namens FastCGI, die im Gegensatz zu
CGI ein Programm immer im selben Prozess laufen l¨sst. So wird nur noch ein Prozess pro
                                                      a
Programm, und nicht mehr pro Anfrage gestartet. Dies f¨hrt zwar zu einer Performance-
                                                           u
Verbesserung, 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
2.1   Java Servlets                                                                            7


Speziell f¨r Perl-Skripte auf dem Apache-Server wurde mod perl entwickelt. Bei mod perl
          u




                            Abbildung 2: Web-Server mit FastCGI


handelt es sich um ein Modul f¨r den Apache-Server, das den Perl-Interpreter direkt in den
                                 u
Server einbettet. Perl-Skripte laufen so wesentlich schneller als zuvor. Dieser Ansatz ist jedoch
ausschließlich f¨r Perl-Skripte, die auf dem Apache-Server laufen, geeignet.
                u

Server-Extension-API Einige Serverhersteller entwickelten sog. Extension-APIs f¨r ihre
                                                                                    u
Web-Server. Auf diese Weise k¨nnen Server um weitere Funktionalit¨ten erweitert werden.
                                 o                                    a
Beispiele hierf¨r sind ISAPI f¨r Microsofts Internet Information Server (IIS) oder WAI (ur-
               u               u
spr¨nglich ver¨ffentlicht unter der Bezeichnung NSAPI) von iPlanet/Netscape f¨r deren Ser-
   u           o                                                               u
ver. Abbildung 3 stellt die Funktionsweise der Server-Extensions dar.
 Diese Erweiterungen sind i.d.R. in C++ geschrieben, was eine hohe Performance zur Folge
hat. Jedoch hat auch diese L¨sung einige Nachteile: Durch die enge Verbindung mit dem Web-
                             o
Server kann eine abgest¨rzte Server-Erweiterung den kompletten Server lahm legen. Außer-
                         u
                                                                                ¨
dem sind Erweiterungen immer auf einen bestimmten Servertyp festgelegt. Eine Ubertragung
auf andere Server ist somit nicht m¨glich.
                                    o

Server Side Includes Mit Hilfe von Server Side Includes (SSI) k¨nnen dynamische Infor-
                                                                  o
mation direkt innerhalb von HTML-Dateien eingebunden werden. Server Side Includes sind
generell 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
                                            u
ubertragbar. Jedoch ist der Funktionsumfang recht beschr¨nkt, so dass SSI nicht f¨r gr¨ßere
¨                                                         a                      u    o
Projekte geeignet ist.

ASP, PHP, SSJS Eine weitere M¨glichkeit zum Erstellen dynamischer Web-Seiten bieten
                                o
die Technologien ASP (Active Server Pages), PHP (benannt nach einem Vor¨ngerprodukt
                                                                       a
namens Personal Homepage) oder auch SSJS (Server Side JavaScript).
Bei dieser Technik werden Code-Fragmente in HTML-Seiten eingebettet. Wird eine Seite
2.1   Java Servlets                                                                           8




                      Abbildung 3: Web-Server mit Server-Extension-API



angefordert, wird der eingebettete Code zuerst vom Web-Server ausgef¨hrt, bevor er zum
                                                                          u
Client geschickt wird.
Diese Technik ist vor allem hilfreich bei Seiten, die nur sehr wenig dynamischen Inhalt bieten
und uberwiegend aus statischen Teilen bestehen, da hier lediglich ein paar zus¨tzliche Zeilen
     ¨                                                                           a
in den bestehenden HTML-Code eingef¨gt werden m¨ssen. Ein Beispiel ist ein Seite, die den
                                         u              u
Besucher namentlich begr¨ßt, sonst aber keine benutzerabh¨ngigen Informationen enth¨lt.
                           u                                    a                            a
Ein anderes Beispiel ist ein Besucherz¨hler auf einer sonst statischen Seite.
                                       a
Besteht die Seite jedoch aus sehr vielen dymanischen Teilen, zeigen sich die Schw¨chen dieser
                                                                                    a
Technologie. 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.
       ¨            o
Außerdem sind ASP und SSJS serverabh¨ngig. So verwendet ASP in der Regel VBScript
                                            a
oder JScript und l¨uft nur auf Microsofts IIS. Zwar gibt es bereits kommerzielle Software wie
                   a
z.B. InstantASP von Halcyon Software oder OpenASP von ActiveScripting.org, die ASP auch
auf anderen Servern m¨glich macht, jedoch ist dies mit großem Aufwand verbunden und bis
                       o
heute nicht vollkommen ausgereift. SSJS wurde von iPlanet/Netscape entwickelt und bettet
JavaScript-Fraktmente in HTML ein. SSJS l¨uft jedoch ausschließlich auf iPlanet/Netscape-
                                               a
Servern.
Lediglich PHP, das sich stark an dem vielen CGI-Programmiern bekannte Perl anlehnt, l¨uft   a
auf nahezu allen Servern. So verwundert es auch nicht, dass PHP die verbreitetste dieser
drei Sprachen ist. Der Nachteil, dass große Projekte schnell un¨bersichtlich werden, bleibt
                                                                   u
allerdings 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
2.1   Java Servlets                                                                       9


nannt 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
                                                            a
mittlerweile viele n¨tzliche Features, die jedoch in ihrer M¨chtigkeit der Java-API deutlich
                    u                                        a
unterlegen sind.
Die neuste Version von ColdFusion er¨ffnet jedoch die M¨glichkeit, benutzerdefinierte Ele-
                                       o                   o
mente zu entwickeln, die mit JavaServlets kommunizieren k¨nnen. ColdFusion bietet sich
                                                               o
somit als Erg¨nzung von Servlets an, wobei allerdings zu abzuw¨gen ist, ob die Verwendung
              a                                                  a
von JavaServer Pages, die sp¨ter beschrieben werden, nicht die bessere Alternative ist.
                              a

Servlets Ein Java Servlet l¨uft ¨hnlich wie Server-Extensions im Web-Server und erweitert
                            a    a
dessen Funktionalit¨t. Jedoch laufen Servlets als Java-Programme in einer Java Virtual Ma-
                   a
chine (JVM), so dass sie erstens sicher sind und zweitens, dank Byte-Code, leicht auf andere
Plattformen ubertragen werden k¨nnen. Servlet-Unterst¨tzungen sind bereits f¨r viele Web-
             ¨                    o                      u                     u
Server erh¨ltlich.
           a
Der große Vorteil von Servlets besteht darin, dass Client-Anfragen nicht zu einer Unmenge
von Prozessen f¨hren. Vielmehr ist es mit Servlets m¨glich, separate Threads zu erzeugen,
                 u                                     o
die in ein und dem selben Prozess laufen. Abbildung 4 zeigt diese Vorgehensweise. Denkbar




                      Abbildung 4: Web-Server mit Servlet-Unterst¨tzung
                                                                 u


w¨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.
                    o
Gleichzeitig ist es Servlets m¨glich, eng mit dem Web-Server zusammen zu arbeiten, da sie
                              o
direkt in diesen eingebettet werden. Eine solche Art der Kommunikation w¨re beispielsweise
                                                                         a
mit CGI nicht m¨glich.
                  o
Dies alles f¨hrt zu den folgenden entscheidenden Vorteilen:
            u
2.1   Java Servlets                                                                           10


    Effizienz Servlets laufen im Gegensatz zu CGI-Skripts nicht als schwergewichtiger
Betriebssystem-Prozess, sondern als resourcenschonender Thread. CGI-Progamme m¨ssten  u
bei N parallelen Anfragen N mal in den Arbeitsspeicher geladen werden. Bei Servlets g¨be a
es 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-
                                                                                 u
frage der (Perl-)Interpreter erneut geladen werden muss, kann ein Servlet somit, wenn es erst
einmal geladen wurde, jede weiter Anfrage quasi unmittelbar ausf¨hren. Weiterhin ist es Serv-
                                                                u
lets m¨glich, einen Zustand uber mehrere Anfragen hinweg bei zu behalten. Daten k¨nnen
       o                      ¨                                                        o
als Klassenvariablen zwischengespeichert werden, vorangegangene Berechnungen k¨nnen ge-
                                                                                   o
cachet werden oder externe Resourcen, wie z.B. eine Datenbank-Verbindung, k¨nnen gehalten
                                                                             o
werden, 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                           o
Datenbank-Verbindungen mit JDBC, Multithreading, Datenkomprimierung, Internationali-
sierung, Grafikerzeugung oder Serialisierung sind nur einige Beispiele f¨r die M¨glichkeiten,
                                                                       u        o
die sich Servlets bieten. Kommuniziert ein Servlet mit einem Applet, k¨nnte auf die M¨glich-
                                                                      o              o
keit von Remote Method Invokation (RMI) zur¨ckgegriffen werden. Zus¨tzlich zu den auf-
                                                 u                       a
gef¨hrten Gebieten decken Klassen von Drittanbietern fast jedes andere Einsatzgebiet ab.
   u
Das Parsen von XML, die Verwendung von regul¨ren Ausdr¨cken oder das Erzeugen von
                                                   a          u
Diagrammen seien als Beispiel genannt.
Alles in allem bietet die Java-API eine M¨chtigkeit, die kaum oder nur schwer von CGI-
                                            a
Programmen oder Skriptsprachen erreicht werden kann.

    Portierbarkeit Da Servlets in Java geschrieben sind, k¨nnen sie problemlos zwischen
                                                           o
verschiedenen 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                    a
einen 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                            u
erst entstehen.
Javas Garbage Collector und das Fehlen von Zeigern stellt sicher, dass Speicherprobleme wie
beispielsweise Memory Leaks, ung¨ltige oder gar b¨swillig ver¨nderte Pointer, nicht m¨glich
                                    u               o            a                         o
sind. In C++ k¨nnte beispielsweise auf die 1000-te Position eines Arrays mit nur 200 Ein-
                 o
tr¨gen zugegriffen werden. Dies w¨rde dazu f¨hren, dass so in Bereiche des Arbeitsspeichers
  a                                 u          u
geschrieben w¨rde, auf die sonst kein Zugriff best¨nde. Tats¨chlich ist dies eine oft benutzte
               u                                   u           a
Hintert¨r f¨r Angriffe. Servlets bieten diese M¨glichkeit nicht, da automatsich Array-Grenzen
        u u                                    o
uberpr¨ft werden.
¨       u
Fehler 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     u
eine Exception, die entweder vom Servlet selbst oder aber vom Server abgefangen werden.
Ein Absturz des Servers ist nicht mehr m¨glich.
                                            o
Zu guter Letzt werden bei Servlets keine externen Programme ausgef¨hrt, wie es bei CGI
                                                                          u
2.1   Java Servlets                                                                                 11


der 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
     u
verschickt, indem das Unix-Programm sendmail verwendet wird. Auf den ersten Blick ist
es ausreichend, die Adresse, die der Benutzer in ein Formular eingegeben hat, an sendmail
weiter zu reichen. Da jedoch auch mehrere Befehle in einer Unix-Shell mit einem Semikolon
getrennt 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                                    a
mmo@varial.de;rm -rf /. Resultat w¨re neben dem Senden einer Mail auch die Ausf¨hrung
                                        a                                            u
des rm-Befehls, der die Festplatte des Servers l¨schen w¨rde.
                                                o        u
Dies ist nur eines von vielen Beispielen, das zeigt, dass die Ausf¨hrung von externen Pro-
                                                                   u
grammen ein erhebliches Sicherheitsrisiko darstellt. Servlets hingegen verwenden keine Shell,
selbst dann nicht, wenn ein Remote-Systemaufruf ausgef¨hrt wird.
                                                          u
Man 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                                            o
URLs in absolute Pfadangaben ubersetzen oder auch Benutzerberechtigungen uberpr¨fen.
                              ¨                                              ¨      u
CGI-Programme laufen hingegen getrennt vom eigentlichen Server, so dass eine solche Art
der Zusammenarbeit dort unm¨glich ist.
                            o

JavaServerPages JavaServer Pages oder kurz JSP verbinden die Vorteile von Servlets, Cold-
Fusion und eingebetteten Skript-Sprachen. JavaServer Pages ¨hneln vom Aufbau recht stark
                                                              a
dem ASP- oder PHP-Ansatz. In statischen HTML-Code        1 werden Elemente f¨ r dynamischen
                                                                            u
Inhalt eingef¨gt. Seiten, die nur wenig dynamische Teile beinhalten, k¨nnen so ohne großen
              u                                                       o
Aufwand erstellt werden.
Sollte der dynamische Inhalt einen gr¨ßeren Teil der Seite ausmachen, k¨nnen JSP-Seiten
                                       o                                  o
leicht mit Servlets zusammen arbeiten. Hierzu k¨nnen sog. Taglibs entwickelt werden. Dies
                                                 o
sind Bibliotheken mit benutzerdefinierten Elementen. Dem Entwickler wird es auf diese Weise
erm¨glicht, eigene Tags zu entwerfen. Die Funktion der Tags wird von einer Java-Klasse im-
    o
plementiert. Der Vorteil dieser Vorgehensweise ist, dass Ausgabe (JSP) und Funktion (Java-
Klasse) klar voneinander getrennt sind. Die JSP-Seite unterscheidet sich vom Aufbau her
kaum von herk¨mmlichen HTML-Seiten, da alle Elemente der XML-Syntax folgen. So k¨nnen
                o                                                                      o
Web-Designer, die mit dem Umgang mit HTML-Seiten vertraut sind, fast ohne Einarbei-
tungszeit komplexe Seiten gestallten. Die Funktionalit¨t wird hingegen von Programmierern
                                                       a
ubernommen, die sich ihrerseits nicht mit dem Seitenlayout belasten m¨ssen. Beide Parteien
¨                                                                     u
erstellen so gemeinsam ein Projekt, arbeiten aber unabh¨ngig von einander.
                                                         a
Mit JSP und Taglibs kann so spielend einfach das Seitenlayout ge¨ndert werden, ohne dass
                                                                   a
die Programmlogik angepasst werden muss und umgekehrt. Dies macht auch die Pflege eines
Projekts denkbar einfach.
Der JSP-Ansatz beinhaltet dar¨ber hinaus auch alle Vorteile von Servlets, da es sich bei JSP-
                                u
Seiten nur um eine andere Darstellung von Servlets handelt. JSP-Code wird bei erstmaliger
Ausf¨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
                                        a
werden. Denkbar w¨ren ebenso XML- oder L TEX-Dokumente.
                    a                     A
   2
     JSP-Code kann auch vorkompiliert werden.
2.2     CORBA                                                                             12


vom Server somit als Servlet betrachtet, sie sind also genauso effizient, m¨chtig, portierbar
                                                                         a
und sicher wie Servlets.

2.1.3    Die Zukunft
Mit Java Servlets setzt die Programmiersprache Java ihren Siegeszug der letzen Jahre weiter
fort. Java besticht durch die M¨chtigkeit und Eleganz der Sprache, die eine saubere, objek-
                                a
torientierte, modulare und einfache Programmierung erm¨glicht. Mit Java Servlets k¨nnen
                                                           o                           o
diese 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       u
lets auf lange Sicht auf Grund ihrer Performance-Vorteile und Portierbarkeit den weitverbrei-
teten CGI-Ansatz abl¨sen werden.
                       o

2.2 CORBA
Die Common Object Request Broker Architecture oder kurz CORBA ist eine Spezifikation,
die von der Object Managment Group (OMG) entwickelt wurde. CORBA unterst¨tzt die u
Realisierung verteilter Objekte. So k¨nnen Objekte zusammen agieren ohne voneinander zu
                                     o
wissen, wo sich das Gegen¨ber befindet, oder in welcher Sprache es implementiert wurde.
                          u
CORBA ist in der letzten Zeit immer mehr zu dem Standard f¨r die Entwicklung von Middle-
                                                           u
ware geworden. Die OMG umfasst mittlerweile mehr als 800 Firmen, die das ganze Spektrum
der Computerindustrie repr¨sentieren. Die einzige bemerkenswerte Ausnahme bildet Micro-
                            a
soft mit einem eigenen konkurierenden Objektbus namens Distributed Component Object
Model (DCOM).

2.2.1    Die OMG
OMG ist die Abk¨rzung f¨r Object Managment Group. Sie wurde im April 1989 gegr¨ndet
                  u        u                                                           u
und bestand urspr¨nglich aus 11 Firmen, darunter u.a. 3Com Corporation, American Air-
                   u
lines, Canon Inc., Data General, Hewlett-Packard, Philips Telecommunications N.V., Sun
Microsystems und Unisys Corporation. Mittlerweile umfasst die OMG uber 800 Mitglieder.
                                                                         ¨
Auf der Basis eines Vorschlags, Request for Comment (RFC) genannt, wird zun¨chst disku-
                                                                                 a
tiert, was standardisiert werden soll. Dann k¨nnen zu einem festgelegten Anforderungsprofil,
                                             o
als Request for Proposal (RFP) bezeichnet, Technologien zur Standardisierung vorgeschlagen
werden. Ziel der OMG ist es, herstellerunabh¨ngige, technisch ausgereifte und kommerziell
                                               a
erfolgreiche Spezifikationen zu erarbeiten und zu standardisieren. Diese Spezifikationen sollen
es erm¨glichen, objektorientierte Modelle unter Abstraktion von der verwendeten Hardware
        o
und des Betriebsystems zu gestalten.

2.2.2    Object Management Architecture
Die OMG ver¨ffentlichte im Herbst 1990 die Object Management Architecture (OMA) im
              o
Rahmen 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
         a
Einzelheiten der sog. Common Facilities hinzugef¨gt. Der endg¨ltige Stand der Spezifikation
                                                  u            u
ist in Abbildung 5 dargestellt. Das Bild zeigt den Aufbau der OMA. Die Architektur gliedert
2.2   CORBA                                                                            13




                  Abbildung 5: Aufbau der Object Management Architecture



sich 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            a
Dinge des realen Lebens. Wichtige Einzelheiten werden mit entsprechenden Attributen mo-
deliert, unwichtige Details wegabstrahiert. Im Folgendem werden diese Objekte, bzw. die
Java-Klassen, die diese implementieren, als Business-Objekte (BO) bezeichnet.
Die Business-Objekte werden speziell f¨r die jeweilige Anwendung programmiert. Folglich
                                        u
werden diese von der OMG nicht n¨her spezifiziert. Die Business Object Task Force der
                                     a
OMG definiert lediglich, dass ein BO eine Komponente der Applikationsebene ist, die sich
entsprechend des Prinzips der Wiederverwendbarkeit, vielseitig einsetzen l¨ßt.
                                                                          a

Common 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                u
zur Verf¨gung. Dazu z¨hlen beispielsweise grafische Benutzeroberfl¨chen, Drucker- und Da-
         u             a                                          a
tenbankdienste, mobile Agenten oder auch Frameworks f¨r Internationalisierung. Das Reper-
                                                       u
toire an CORBAfacilities wird laufend weiterentwickelt und wird in Zukunft praktisch jeden
verteilten 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
                                                  u
sind Sammlungen von elementare Diensten auf Systemebene, die f¨r die Entwicklung von
                                                                u
2.2    CORBA                                                                               14


verteilten 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.
2.2   CORBA                                                                              15


Object Request Broker Die OMG definiert mit CORBA einen offenen Standard, liefert
selbst jedoch keine Implementierung. Software, die die CORBA-Spezifikation implementiert,
heißt Object Request Broker (ORB). Als Beispiele seien hier VisiBroker von Visigenic, Orbix
von Iona oder Suns Java IDL genannt.
Der ORB trennt die Anfrage eines Services (Client) von dessen Bereitstellung (Server). Der
ORB ist das Herzst¨ck der CORBA-Technologie. Alle Aufrufe von Objekten (ob lokal oder
                     u
entfernt) 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
                                     u
wird und leitet Auftr¨ge an diese Objekte weiter. Dies geschieht automatisch, ohne dass sich
                      a
der Entwickler Gedanken dar¨ber machen muss, wo und ob ein Serverobjekt zur Zeit aktiv
                                u
ist. Der Objektadapter sorgt daf¨r, dass aus Sicht des Clients alle Serverobjekte aktiv und
                                   u
lokal 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
                u
war, entwickelten sich viele herstellerabh¨ngige BOAs, die zwar alle den CORBA-Standard
                                          a
erf¨llten, jedoch u.U. nicht richtig zusammen arbeiteten. Aus diesem Grunde wurde CORBA
   u
2.0 um den Portable Object Adapter (POA) erweitert. Durch zus¨tzliche Spezifikationen der
                                                                  a
OMG ist nun sichergestellt, dass POAs zueinander kompatibel sind, w¨hrend das bei BOAs
                                                                       a
nicht unbedingt der Fall sein muss.
Da die ORB-Implementierungen an die Spezifikation der OMG gebunden sind, k¨nnen ORBs
                                                                               o
verschiedener 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,
                                                            u
dass 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,
                                             a
die als gemeinsames Backbone-Protokoll dienen.

2.2.3 Interface Definition Language
CORBA ist ein selbstbeschreibendes System. Damit Objekte sprachenunabh¨ngig mitein-
                                                                           a
ander agieren k¨nnen, wird klar zwischen Schnittstellenbeschreibung und Implementierung
               o
unterschieden. Hierzu dient die Interface Definition Language (IDL). Mit dieser neutralen
Sprache, deren Syntax an C++ angelehnt ist, werden CORBA-Objekte mit ihren Attributen
2.2     CORBA                                                                              16




                          Abbildung 7: ORB-Verbindung mit IIOP


                      ¨
und Funktionen (inkl. Uber- und R¨ckgabe-Parameter und Fehlerbehandlungen) beschrieben.
                                 u
Komponenten, die in IDL geschrieben sind, sollten zu anderen Sprachen, Betriebssystemen
und Netzwerken hin kompatibel sein (Abbildung 8). Hierzu generiert der Compiler aus der




                       Abbildung 8: Sprachunanh¨ngigkeit durch IDL
                                               a


IDL-Beschreibung f¨r die jeweilige Programmiersprache passende Interfaces. Diese Interfa-
                     u
ces heißen serverseitig Skeletons, w¨hrend sie clientseitig als Stubs bezeichnet werden. Diese
                                     a
Interfaces 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
                                   o
und Java-Server implementiert und auf verschiedenen Rechnern platziert wird. Die IDL stellt
hierf¨r die programmiersprachenunabh¨ngige Verbindung her, der ORB sorgt f¨r die Loka-
      u                                 a                                         u
lisierung der verteilten Objekte. F¨r den Programmierer gestaltet sich das Szenario dank
                                     u
CORBA v¨llig transparent.
           o

2.2.4    Alternative Ans¨tze
                        a
Sockets Sockets stellen die wohl primitivste Art der Netzwerkkommunikation dar. Ein
Socket ist ein Peer-to-Peer-Kommunikationsendpunkt uber TCP/IP. 1981 wurden Sockets
                                                   ¨
2.2    CORBA                                                                                 17


im 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.
                                u
Ein Socket besteht aus einem Namen und einer Netzwerkadresse und l¨ßt sich in eine von
                                                                       a
drei 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 auch
einige Nachteile. So bieten Sockets weder Parameter Marshaling noch dynamische Service-
Bindung. Der Entwickler muss eigene Protokolle entwickeln, die die Methodenaufrufe des
Clients den Methoden des Servers zuordnen. Bedenkt man, dass große Systeme leicht einige
hundert Funktionen umfassen, k¨nnte dies zu einem gewaltigen Aufwand f¨hren. Die Pflege
                                o                                       u
und Wartung der Software w¨rde schnell eine un¨berschaubare Aufgabe. Folglich stellen
                              u                  u
Sockets f¨r die Anforderung moderner Systeme keine ausreichende L¨sung dar.
         u                                                        o

RMI Remote Method Invocation oder kurz RMI ist eine von der Firma Sun Microsystems
entwickelte 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
                                                          o
Entwicklung von RMI war es, ein verteiltes Objektmodel in Java zu integrieren, ohne dabei
das 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
                                                        o
Client-Server-Architektur, die sich f¨r den Entwickler fast vollkommen transparent gestaltet.
                                     u
RMI 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.
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.
                        u

Genau 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-
              a
munikation transparent erscheinen lassen. Der Client hat Zugriff auf eine Stub-Klasse, die
das Server-Interface implementiert. Methodenaufrufe des Stubs werden uber das Netzwerk
                                                                      ¨
ubertragen und von dem Gegenst¨ck auf der Serverseite, dem Skeleton, an das jeweilige
¨                                 u
Server-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
                                             a
den Anforderungen besser gerecht wird. RMI stellt eine wesentlich einfachere Architektur als
CORBA zur Verf¨gung, was dazu f¨hrt, dass RMI besonders f¨r kleinere Projekte geeignet ist.
                u                  u                          u
Dar¨ber hinaus ist es einfacher zu erlernen und direkt in neueren JDK-Versionen eingebettet.
   u
2.2   CORBA                                                                              19


Der Nachteil gegen¨ber CORBA ist allerdings, dass gerade große Projekte durch verschie-
                  u
dene CORBA-Features (CORBAservices und CORBAfacilities) besser mit die Technologie
der OMG umsetzbar sind. Außerdem k¨nnen mit RMI nur reine Java-Projekte implementiert
                                     o
werden. Eine Kommunikation zwischen Objekte, die in unterscheidlichen Programmierspra-
chen geschrieben wurden, ist im Gegensatz zu CORBA nicht m¨glich. RMI stellt folglich bei
                                                           o
heterogenen Projekten keine Alternative dar.

DCOM Das Distributed Component Object Model (DCOM) ist Microsofts Antwort auf den
OMG-Standard. Mit DCOM stellt Microsoft eine weitere M¨glichkeit zur Realisierung verteil-
                                                       o
ter Anwendungen zur Verf¨gung. Dabei gehen die Wurzeln von DCOM weit in die Vergangen-
                        u
heit zur¨ck. Strenggenommen wurde 1987 mit Einf¨hrung der Zwischenablage in Windows
        u                                       u
der Grundstein f¨r DCOM gelegt (Abbildung 10). Mit der Zwischenablage war es erstmals
                 u




               Abbildung 10: Entwicklung von DCOM aus COM und RPC


m¨glich, Texte aus einem Programm zu kopieren und in anderen Applikationen einzusetzen.
   o
1992 wurde diese Technik erweitert und als OLE (Object Linking & Embedding) ver¨ffent-o
licht. Nun war es nicht nur m¨glich, Texte zwischen zwei Applikationen auszutauschen, son-
                                  o
dern es wurde gar erm¨glicht, komplexere Objekte durch die Zwischenablage zu kopieren.
                         o
Ein oft zitiertes Beispiel ist das Einbinden einer Excel-Tabelle in einem Word-Dokument. Bei
Doppelklick 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
                                ¨                        ¨                     a
Anwendungen jedoch unabh¨ngig von einander entwickelt werden, bedarf es einem standar-
                                a
disierten Verfahrens, das die Kommunikation zwischen den Windows-Applikationen regelt.
OLE bot mit DDE (Dynamic Data Exchange) die grundlegende Kommunikationsschicht f¨r        u
den Datenaustausch. Da sich DDE jedoch schon schnell als zu langsam und unflexibel her-
ausstellte, konnte sich die Technologie nicht wie gew¨nscht durchsetzen.
                                                       u
Microsoft entwickelte daraufhin OLE 2. Die Fragestellung, wie zwei Windows-Programme
miteinander Daten austauschen k¨nnen, wurde jetzt ein wenig ausgeweitet. Als zentrales Ziel
                                    o
wurde definiert, dass eine Applikation die Funktionalit¨t beliebiger bin¨rer Komponenten in
                                                          a               a
einer objektorientierten Art und Weise nutzen solle. Dies unabh¨ngig von den verwendeten
                                                                    a
2.2   CORBA                                                                              20


Implementierungssprachen 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 u
COM bilden sollte.
COM ist die Kurzbezeichnung f¨r Component Object Model und definiert einen Standard f¨r
                               u                                                         u
die 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
                                                        a
Schnittstellen zur Verf¨gung stellt. Bei der Verwendung der Komponente ist es hierbei v¨llig
                       u                                                               o
egal, wie und in welcher Programmiersprache sie geschrieben ist. Mit Hilfe der Interfaces
kann die Komponente von anderen Anwendungen genutzt werden ohne den inneren Aufbau
zu kennen (Abbildung 11).
 Schnell fand ein neues Zauberwort Einzug in die Windows-Welt: ActiveX. ActiveX beinhaltet




           Abbildung 11: Software-Komponente nach COM: Aufbau und Zugriff


dabei lediglich COM. Der Grund f¨r die babylonische Sprachverwirrung, in der auch VBX,
                                  u
das Software-Komponenten f¨r Visual-Basic-Steuerelemente beschreibt, und das allgemeinere
                             u
OCX, 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
                                                            u
alte Technologie. Mit Windows NT und einer Version f¨r Windows 95 fand ActiveX schnell
                                                      u
erste Einsatzgebiete in der Windows-Welt. Fortan sollte das Component Object Model bzw.
ActiveX eine entscheidende S¨ule in der Entwicklung von Windows-Applikationen spielen.
                              a
W¨hrend COM lediglich das Zusammenspiel von Software-Komponenten auf dem selben
   a
Rechner erlaubt, hebt DCOM als verteiltes COM diese Grenzen auf. DCOM erm¨glicht nun
                                                                                o
auch 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 auf
RPC. 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 von
deren 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
    o
Microsoft 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
                                                                          a
verkauft. COM+ bezeichnet somit keine wirkliche Neuentwicklung des Standards, sondern
nur ein neu zusammengestelltes Microsoft Produkt.
2.2   CORBA                                                                             21




                     Abbildung 12: Verteilte Anwendung mit DCOM



Der propriet¨re DCOM-Standard stellt eine f¨r Windows-Produkte optimierte Technik f¨r
             a                              u                                          u
die Umsetzung verteilter Systeme dar. Dementsprechend einfach gestaltet sich die Entwick-
lung auf der Microsoft-Plattform. Auf der anderen Seite bietet DCOM keine oder kaum
Unterst¨tzung f¨r andere Betriebssysteme. Die Firma Software AG portierte ActiveX un-
        u       u
ter dem Namen EntireX zwar auf verschiedene Plattformen wie Linux, Sun Solaris, Digital
Unix, HP-UX oder OS/390, eine komplette Kompatibilit¨t wurde hingegen noch nicht er-
                                                       a
reicht. Außerdem ist DCOM ein Bin¨rstandard. Die Folge ist eine enge Bindung an die
                                      a
x86-Prozessorarchitektur.
           ¨
Alle diese Uberlegungen zeigen, dass DCOM in einem reinen Windows-System sicherlich eine
gute L¨sung darstellt. F¨r die Verwendung in heterogenen Systemen stellt CORBA jedoch
       o                u
die bessere Wahl dar.

SOAP Das Simple Open Access Protocol oder kurz SOAP ist die neuste Entwicklung aus
dem Hause Mircrosoft und definiert ein Transportprotokoll, das die wesentlichen Merkmale
von 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 direkte
Bindung 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                       a
in heterogenen Systemen.
SOAP beruht im Prinzip auf der Verwendung von sog. Remote Procedure Calls (RPC). Wie
der Name bereits andeutet, werden mit dieser Technik entfernte Funktionsaufrufe erm¨glicht.
                                                                                   o
Durch gestiegene Sicherheitsbed¨rfnisse in Netzwerken bzw. dem Internet werden aber immer
                               u
mehr Netzwerke durch Firewalls gesichert. Diese Firewalls sch¨tzen an das WWW angeschlos-
                                                             u
sene Netzwerke, indem sie Ports blockieren und Anfragen filtern. In der Regel werden nur
Anfragen auf den Ports der Standard-Protokolle wie HTTP (Port 80), FTP (Port 21) oder
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
2.2    CORBA                                                                          23


SMTP (Port 25) zugelassen. Die Folge ist, dass RPC-Aufrufe des Clients von der Firewall
blockiert werden. Zur L¨sung dieses Problems verwendet SOAP den offenen Port 80, indem
                       o
RPC-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 Envelope


terteilt sich wiederum in einen SOAP Header und einen SOAP Body. Der Header enth¨lt   a
Informationen dar¨ber, was f¨r eine Art von Nachricht vorliegt, den Empf¨nger der Nach-
                   u          u                                           a
richt und welche Bestandteile der Nachricht optional bzw. obligatorisch sein m¨ssen, um
                                                                               u
eine g¨ltige SOAP-Nachricht darzustellen. Der SOAP-Body enth¨lt den eigentlichen Inhalt
       u                                                         a
der Nachricht. Außerdem kann eine SOAP-Nachricht noch einen Block mit der Bezeichnung
Fault 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-Informationen

Mit 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
                                                                o
auf prinzipiell jeder Plattform auszuf¨hren. Andererseits entstehen gerade bei komplexen
                                      u
Anwendungen u.U. schnell sehr große Datenmengen, da XML-Dateien neben den reinen In-
formationen große Mengen von Formatierungs- bzw. Gliederungsanweisungen in Form von
Tags besitzen. Beachtet man weiterhin den Aufwand f¨r das Parsen des Dokuments, erfolgt
                                                     u
die Verarbeitung dementsprechend langsamer als bei CORBA oder DCOM. SOAP bietet
2.2     CORBA                                                                             24


daf¨r jedoch eine einfachere Zusammenarbeit mit Firewalls. Zusammenfassend l¨ßt sich sa-
   u                                                                            a
gen, dass Microsoft bei der Entwicklung von SOAP eher die Verwendung im Internet im Auge
hatte, w¨hrend DCOM in kleineren, homogenen LANs St¨rken offenbart.
         a                                               a
Als Erg¨nzung sei an dieser Stelle ein ¨hnliches Verfahren genannt, dass unter der Bezeich-
        a                              a
nung 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 ausgereift
und findet deshalb nur in kleineren Projekten Anwendung.

2.2.5    Vorteile von CORBA
Stellt man CORBA und andere Techniken f¨r die Entwicklung verteilter Anwendungen ge-
                                             u
gen¨ber, zeigen sich schnell die St¨rken des OMG-Standards. Die reine Socket-Verbindung
    u                              a
bietet 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 Abstraktion
bieten.
RMI bietet bereits eine sehr hohe Abstraktionsebene. Die Kommunikation erfolgt in einem
standardisieren Protokoll und Verbindsdetails werden f¨r den Entwickler verborgen, so dass
                                                        u
dieser 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-
                                   a
formen. Bei der Verteilung von Java-Applikationen stellt RMI sicherlich die beste L¨sung dar.
                                                                                   o
Allerdings erm¨glicht RMI nicht das Zusammenspiel zwischen verschiedenen Programmier-
                o
sprachen.
Microsofts DCOM-Architekur erm¨glicht im Gegensatz zu RMI zwar eine Kommunikati-
                                    o
on zwischen Software-Komponenten, die in verschiedenen Sprachen implementiert werden
k¨nnen. Zugleich wurde auch hier eine hohe Abstraktionsebene erreicht. Der Nachteil von
  o
DCOM ist hingegen die enge Bindung an das Microsoft-Betriebssystem und die Prozessor-
Architektur. In einer reinen Windows-Applikation bietet DCOM somit eine gute Alternative
zu CORBA. In heterogenen Systemen offenbart DCOM aber seine Schw¨chen.    a
SOAP 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
          ¨                                      a
uber Port 80 und somit die Zusammenarbeit mit Firewalls. Die Unabh¨ngigkeit von XML
¨                                                                        a
wird jedoch mit einem hohen Mass an Overhead f¨r Strukturierungsbefehle bezahlt. Dadurch,
                                                 u
dass die XML-Beschreibungen gerade in großen Projekten sehr groß werden, und dass diese
Dokumente vor der Verarbeitung entsprechend geparst werden m¨ssen, zeigen sich deutliche
                                                                 u
Performance-Schw¨chen bei SOAP. Mit dem selben Problem ist auch XML-RPC behaftet.
                   a
Außerdem bietet sich hier ein geringerer Funktionsumfang.
Mit CORBA l¨ßt sich Middleware auf einer sehr hohen Abstraktionsebene realisieren.
                 a
Dar¨ber hinaus bietet CORBA ein Optimum an Unabh¨ngigkeit. Der Standard ist weder
    u                                                     a
an Betriebssysteme, noch an Programmiersprachen gebunden. Außerdem stellt CORBA mit
den CORBAfacilities und den CORBAservices viele sehr n¨tzliche Dienste zur Verf¨gung.
                                                             u                        u
Die OMG vereinigt das Know-How vieler Experten und definiert einen offenen Standard.
Resultat ist ein st¨ndig weiterentwickelter und verbesserter CORBA-Standard.
                   a
2.3   Verbindung von Java Servlets und CORBA                                              25


2.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
                                                                             o
vierschichtige webbasierte Anwendungen zu bauen.
Mit Java Servlets steht eine effiziente und m¨chtige M¨glichkeit zur Verf¨gung, mit der die
                                              a        o                 u
Vorteile von Java nun auch auf Web-Servern genutzt werden k¨nnen. CORBA erm¨glicht
                                                                 o                    o
wiederum die Entwicklung leistungsf¨higer Middleware.
                                     a
Die Verbindung beider Technologien ist geradezu optimal. Java Servlets sind von Natur aus
plattformunabh¨ngig. CORBA ist dar¨ber hinaus nicht nur unabh¨ngig vom Betriebssystem,
                a                      u                          a
sondern auch von der Programmiersprache. So l¨ßt sich ein Servlet-CORBA-System nicht nur
                                                a
beliebig auf andere Betriebssysteme ubertragen, sondern es ist auch m¨glich, Servlets mit je-
                                     ¨                                 o
dem beliebigen CORBA-Server zusammen arbeiten zu lassen, gleichg¨ltig in welcher Sprache
                                                                     u
dieser geschrieben ist oder auf welchem Betriebssystem er l¨uft.
                                                            a
Zusammen stellen CORBA und Servlets ein Optimum an Leistungsf¨higkeit und Unabh¨ngig-
                                                                   a                  a
keit dar.
3 Varial World Edition
3.1 Leistungsumfang VWE
Die Varial World Edition ist ein neu entwickeltes ERP-System der Firma Varial Software
AG. Neben der Personalwirtschaft bietet VWE u.a. auch L¨sungen f¨r das Finanzwesen und
                                                           o         u
Controlling. VWE wurde erstmalig auf der CeBIT 2000 vorgestellt und liegt momentan in
einer deutschen und einer englischen Version vor. Seit September 2001 befindet sich VWE
bei einem Pilotkunden, der britischen Firma Espera Scales Ltd. aus Dorking, s¨dlich von
                                                                                  u
London, im Testbetrieb.
VWE wurde speziell f¨r den Einsatz in international operierenden Unternehmen entwickelt.
                      u
Dabei k¨nnen Firmengruppen (Holdings) problemlos mehrere Firmen getrennt in einem Pro-
        o
gramm verwalten. VWE ist nicht nur mehrsprachen-, sondern auch mehrw¨hrungsf¨hig. D.h.
                                                                           a       a
im System k¨nnen Buchungen in mehreren W¨hrungen vorgenommen werden. Umrechnungen
             o                                a
finden zu fixen oder auf Basis tagesgenauer Umrechungskurse aus dem Internet statt. Auch die
Anpassung an landesspezifische Formate ist gew¨hrleistet. Selbst fachliche Besonderheiten,
                                                 a
wie beispielsweise unterschiedliche gesetzliche Bestimmungen, k¨nnen mit VWE verwaltet
                                                                  o
werden. Hierzu wurde eine spezielle Berechnungslogik entwickelt, die einfache Anpassung, oft-
mals sogar vom Anwender selbst, ohne Programmieraufwand, erm¨glicht. L¨nder-, branchen-
                                                                  o         a
oder unternehmensspezifische Versionen lassen sich somit schnell und effektiv umsetzen.
Auf Grund des Vertriebsmodels mit OEM-Partnern wurde bereits bei dem Entwurf von VWE
darauf geachtet, dass ein hohes Maß an Integration erreicht wird. VWE l¨ßt sich leicht an ein
                                                                         a
bestehendes Design anpassen und in vorhandene Systeme integrieren. Durch einen modularen
Aufbau, bei dem Funktionalit¨ten bzw. Use-Cases in Programmbausteinen gekapselt sind, ist
                              a
es m¨glich, nur einzelne Funktionen zur Verf¨gung zu stellen. Auf diese Weise k¨nnen indi-
     o                                        u                                  o
viduelle ERP-Systeme zusammengestellt werden, die den Anforderungen des Endanwenders
gerecht 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.
                                         u

3.2 Architektur
Neben 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.
                  a
Der Presentation Layer ist die Oberfl¨che der VWE und ist f¨r die Darstellung der fachlichen
                                    a                      u
Inhalte verantwortlich. Neben der ergonomischen Gestaltung zeichnet sich die Ober߬che a
durch die Integration von Office Standards und der M¨glichkeit der flexiblen Anpassung
                                                        o
an bestehendes Corporate Design aus. OEM-Partnern wird mit dem Varial Client SDK
(Software Development Kit) eine vollst¨ndige und nahtlose Integration mit anderen Produk-
                                       a
ten erm¨glicht. Ein einheitliches Look and Feel“ mit gleichen Symbolen, Oberfl¨chen und
        o                                                                        a
                                 ”
ergonomischen Prinzipien ist sichergestellt. Beim Anwender treten Wiedererkennungseffekte
auf, der Schulungsaufwand reduziert sich.
Auch durch die Nutzung von Resource Bundles und die getrennte Haltung von l¨nderspezi-
                                                                                a

                                             26
3.2    Architektur                                                                       27




                     Abbildung 17: Der dreischichtige Aufbau von WVE



fischen Formaten vereinfacht sich die Anpassung an andere Sprachen und L¨nder.a
Zusammenfassend l¨ßt sich sagen, dass der Presentation Layer eine sehr flexible Oberfl¨chen-
                    a                                                                 a
gestaltung zul¨ßt. Diese Entwicklungsweise bewahrt vor monolithischen Strukturen, deren
               a
Adaption an andere Sprachen und reginale Sonderheiten massive Ver¨nderungen erfordern
                                                                        a
w¨rde.
  u
Beim Application Layer handelt es sich um das Kernst¨ck der VWE. In ihm ist die
                                                            u
Funktionalit¨t aller Anwendungen realisiert. Er stellt eine fachliche Korrektheit, also eine
             a
ordnungsgem¨ße kaufm¨nnische Buchf¨hrung, sicher und deckt auch technische Erfordernisse
              a         a             u
wie Transaktionsicherheit und Performance ab.
Der Application Layer folgt einem modularen Aufbau, bei dem alle verwendeten Entit¨ten in
                                                                                     a
sog. Business Objekten gekapselt sind, die den Regeln der objektoriertierten Programmierung
entsprechen. Diese modulare Bauweise vereinfacht sowohl die Wartung und Erweiterungen
als auch die Anpassung der Software.
Ferner sorgt der Application Layer f¨r Transaktionssicherheit und optimalen Datendurchsatz
                                    u
in Richtung Persistency und Presentation Layer. Dabei wird die Verarbeitung durch den
Einsatz von Callbacks, einem Mechanismus, bei dem Daten asynchron geliefert werden, auch
großen Datenmengen gerecht.
Der Persitency Layer sorgt f¨r die Datenhaltung in VWE. Obgleich er den kleinsten Anteil
                             u
am Gesamtcode des Systems ausmacht, entscheidet er uber Stabilit¨t und Anwendungsbreite
                                                       ¨           a
der 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 mit
allen Datenbanken auf SQL-92-Basis kommunizieren kann. Datenbankunterschiede werden
vom Persistency Layer ausgeglichen, damit die Datenhaltung in den verschiedensten RDBS
m¨glich ist. Derzeit l¨uft VWE mit Oracle, Interbase, Informix, Sybase und dem SQL-Server
  o                   a
von Microsoft.

      Durch die Verwendung von CORBA und die klare Trennung der Schichten, insbesondere
3.3   Das Web-Interface                                                                   28


des Presentation und Application Layers, wurde es nicht nur m¨glich, die Gesch¨ftslogik von
                                                             o                a
der Darstellung zu trennen, sondern es konnte bei der Realisierung auch auf unterschied-
liche Programmiersprachen zur¨ckgegriffen werden. Der Presentation Layer (Client) wurde
                              u
in C++ geschrieben, w¨hrend auf der Serverseite im Application Layer Java zum Einsatz
                       a
kommt. Im Rahmen der Diplomarbeit wird nun zus¨tzlich zum bestehenden Client eine wei-
                                                   a
tere Anwendung entwickelt, mit der es m¨glich ist, VWE uber das Internet zu nutzen.
                                        o                ¨

3.3 Das Web-Interface
Ein Web-Interface erm¨glicht es dem Anwender, VWE mit einem Browser von nahezu
                         o
jedem beliebigen Arbeitsplatz aus zu nutzen. Hierdurch ergeben sich ein Reihe von neuen
Anwendungsm¨glichkeiten der Varial World Edition. Zu Beginn muss erst einmal gekl¨rt
               o                                                                           a
werden, welche Funktionalit¨ten die zu entwickelnde Anwendung zur Verf¨gung stellen soll.
                             a                                             u
Es soll also der Frage nachgegangen werden, welche Daten welchem Benutzer zug¨nglich   a
gemacht werden sollen, welche Gesch¨ftsprozesse im Umfeld einer Internet-Anwendung
                                        a
sinnvoll sind und welche eher nicht.
Prinzipiell lassen sich alle Benutzer in zwei Gruppen unterteilen: Betriebsinterne und
betriebsexterne Anwender. Als betriebsintern gilt beispielsweise der Vorstand, der Buchhal-
ter oder Mitarbeiter im Außendienst. Zur Gruppe der betriebsexternen Anwender z¨hlen     a
z.B. die Kunden, der Steuerberater oder der Wirtschaftspr¨fer. Um nun die verschiedenen
                                                            u
M¨glichkeiten eines Web-Interfaces zu demonstrieren, seien hier beispielhaft einige Use-Cases
  o
aufgef¨hrt:
       u
Ein Vorstandsmitglied geh¨rt, wie bereits oben erw¨hnt, zu den betriebsinternen Anwendern,
                           o                        a
hat somit tendenziell mehr Zugriffsrechte als externe Anwender. Es hat Zugriff auf s¨mtliche
                                                                                     a
Daten. Jedoch ist man eher daran interessiert, schnell Daten in aggregierter Form, wie
z.B. Bilanzen, Jahresstatistiken etc, geliefert zu bekommen. Einzelheiten sind hier nicht
von Interesse, behindern zuweilen sogar bei der Auswertung der Daten. Eine denkbare
Anwendung des Web-Interfaces w¨re, dass der Vorstandschef auf Dienstreise im Hotelzimmer
                                  a
die 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
                    a
zugegriffen werden kann, deutlich eingeschr¨nkter, beinhalten daf¨r aber mehr Einzelheiten.
                                            a                     u
Der Außendienst kann uber das Web-Interface s¨mtliche Kundendaten auswerten und auf
                         ¨                        a
einzelne schreibend zugreifen. Beispielsweise kann hier im Außendienst direkt der Name des
Ansprechpartners 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                   a
ein 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-
                           u
on sinnvoll erg¨nzen kann, findet sich im Bereich Personalwirtschaft. Den Mitarbeitern
                a
des Unternehmens k¨nnen pers¨nliche Daten zur Verf¨gung gestellt werden. Auf diese
                      o           o                       u
Weise 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
3.3   Das Web-Interface                                                                    29


    Rechte von externen Usern sind im Gegensatz hierzu deutlich eingeschr¨nkter. So sollten
                                                                         a
Daten nur gelesen, diese aber nicht ver¨ndert werden d¨rfen. Einem externen User wird des-
                                       a                u
halb in der Regel nur ein sog. Pr¨ferarbeitsplatz eingerichtet.
                                 u
So 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
                                                                           o
Betriebspr¨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.
             u

Einem Wirtschaftspr¨fer kann ubers Internet Zugang zu Informationen gew¨hrt werden,
                    u          ¨                                             a
die f¨r Pr¨fungen notwendig sind. Weitere Daten sollten aber selbstverst¨ndlich verborgen
     u    u                                                             a
bleiben. Ein Web-Interface w¨rde diesen neuen Anforderungen gerecht werden.
                            u
Weiterhin k¨nnen Kunden die Software dazu nutzen, um offene Rechnungsbetr¨ge einzu-
            o                                                                  a
sehen. Kunden des Unternehmens k¨nnen sich so von jedem Browser aus ansehen, welche
                                   o
Rechnungen noch bezahlt werden m¨ssen. Eine Bonit¨tseinsch¨tzung hingegen sollte dem
                                    u                a       a
Kunden nicht gezeigt werden.

   Man sieht, dass es eine Reihe von Einsatzm¨glichkeiten und Anwendungsf¨llen f¨r ein
                                               o                              a u
Web-Interface im Rahmen eines modernen ERP-Systems gibt, bei dem jedem Benutzer eine
an die entsprechende Rolle angepasste Datensicht zur Verf¨gung gestellt wird.
                                                         u

    Dadurch, dass bei VWE klar zwischen der Darstellung und Verarbeitung von fachlichen
Inhalten 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.
                                                                                a
Abbildung 18 zeigt den neuen vierschichtigen Aufbau der Software mit Webanbindung. Die
Aufgabe, die den normalen Desktop-Client zukommt, wird von einem Java Servlet ubernom-
                                                                                    ¨
men, das auf einem Web-Server (beispielsweise Apache Tomcat, JRun von Macromedia oder
BEA WebLogic Server) l¨uft. Da das Servlet selbst jedoch nur die Ausgabe erzeugen bzw.
                           a
vorbereiten kann, diese aber selbst nicht dargestellen kann, wird ein Browser ben¨tigt. Dieser
                                                                                 o
stellt die vierte Schicht im Modell dar. Die vom Servlet erzeugten Daten werden mit HTTP
bzw. HTTPS an den Browser geschickt. Dieser stellt sie dann f¨r den Anwender dar und
                                                                   u
dient zur Bedienung der Anwendung.
3.3   Das Web-Interface                                                30




                 Abbildung 18: Der vierschichtige Aufbau von WVE-Web
4 Anforderungen an das Web-Interface
4.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 Daten
haben. 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
                                                          a
der Benutzung muss sich der Anwender mit einem Login und dem dazugeh¨rigen Passwort
                                                                               o
anmelden. Ein Zugriff auf die Applikation wird nur dann gew¨hrt, wenn der Benutzerna-
                                                                 a
me g¨ltig ist und das Passwort korrekt eingegeben wurde. Unter der Annahme, dass das
      u
Passwort geheim gehalten wird, ist gew¨hrleistet, dass ausschließlich authorisierte Benutzer
                                          a
Zugang zum System erhalten. Da das Passwort f¨r jeden Anwender unterschiedlich ist, ist es
                                                   u
weiterhin nicht m¨glich, sich f¨r jemand anderes auszugeben. Ein erfolgreicher Login ist des-
                   o            u
halb ein relativ sicheres Zeichen daf¨r, dass es sich bei dem Anwender um die Person mit der
                                     u
angegebenen Benutzerkennung handelt. Die Authentizit¨t des Benutzers ist sichergestellt.
                                                            a
Diese Art der Benutzerverwaltung ist weiterhin hilfreich, um Genehmigungen zu definieren.
Da der Benutzer eindeutig identifiziert wurde, k¨nnen ihm Zugriffsrechte gegeben bzw. die-
                                                    o
se eingeschr¨nkt werden. So ist es m¨glich, dass verschiedene Benutzer auf unterschiedliche
             a                         o
Programmteile zugreifen d¨rfen. Der VWE-Administrations-Modus bietet hier eine rollen-
                             u
basierte 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          o
Name, Adresse, Funktion, Abteilung, Durchwahl etc. angegeben werden. Weiterhin kann ein
Benutzer 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
                                                             a
noch nicht gel¨scht, aber zwischenzeitlich aus dem System genommen) oder die G¨ltigkeit
                o                                                                     u
des Passworts kann festgelegt werden. So kann beispielsweise angegeben werden, dass das
Passwort alle 14 Tage ge¨ndert werden muss.
                          a
    Ist ein solcher Benutzer angelegt, k¨nnen ihm Rechte zugewiesen werden. Dies geschieht
                                         o
jedoch 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
4.1   Sicherheit                                                                        32




                          Abbildung 19: Anlegen eines Benutzers



der 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
                                                                     o
angelegt und verwaltet werden. Nach Erzeugung der Verkauf-Rolle k¨nnen ihr die n¨tigen
                                                                     o               o
Rechte zugewiesen werden. VWE stellt hierzu eine detaillierte Liste mit Rechten, die in der
Applikation vergeben werden k¨nnen, zur Verf¨gung. Der erzeugten Rolle wird beispielsweise
                              o              u
das 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 bei
der Verwaltung mehrere Firmen beispielsweise nur die Mitarbeiter einer speziellen Firma
bearbeiten. 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
                                   a
Einschr¨nkung code LIKE ’A%’ AND code LIKE ’M%’“ angegeben werden. Der Benutzer
         a
                 ”
hat somit nur Zugriff auf die von ihm ben¨tigten Daten.
                                         o
Im Zusammenhang mit der Zugriffskontrolle ist das sog. AccessToken zu erw¨hnen. Dies
                                                                              a
ist ein Objekt, das Benutzer-Informationen nach einem erfolgreichen Login beinhaltet. Der
Benutzer meldet sich beim Administration-Server, einem CORBA-Server, der Administrati-
onsaufgaben ubernimmt, an und erh¨lt bei erfolgreicher Authorisierung ein entsprechendes
              ¨                      a
4.1    Sicherheit                                                                             33


AccessToken-Objekt zur¨ck. Dieses Token gilt im Folgenden als eine Art Schl¨ssel. Das Ac-
                          u                                                      u
cessToken wird jedem Funktionsaufruf des Servers mitgegeben, der anhand dieses Schl¨ssels
                                                                                        u
pr¨ft, ob der Zugriff erlaubt ist.
  u
Der Vorgang entspricht in etwa einem Hotelbesuch. Zu Begin meldet sich der Gast an der
Rezeption an und erh¨lt dort nach erfolgreicher Identifizierung einen Zimmerschl¨ssel. Mit
                      a                                                             u
diesem Schl¨ssel kann er sich nun im Hotel bewegen, hat aber nur Zutritt zu bestimmten
            u
Bereichen. 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
                                                                               u
muss nur eine evtl. auftretende AccessDeniedException abfangen, die bei einem erfolglosen
Anmeldungsversuch 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                 o
noch Vertraulichkeit der Daten ist gew¨hrleistet. Außerdem wird lediglich ein Kommuni-
                                          a
kationspartner, n¨mlich der Benutzer, identifiziert. Die Frage, ob es sich auf der anderen
                  a
Seite 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
 o
andere, d.h. verf¨lschte URLs geleitet w¨rden. Dem Anwender w¨rde eine vertrauliche
                  a                         u                          u
Seite somit nur vorget¨uscht. Wegen dieser als DNS-Spoofing bekannten Methode, muss
                       a
f¨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                                          u
ren und sog. digitale Zertifikate. Sinn von Verschl¨sselung (Kryptographie) ist es, Daten vor
                                                  u
unberechtigtem Lesen zu sch¨tzen. Die Kryptographie besch¨ftigt sich deshalb mit der Ge-
                              u                              a
heimhaltung von gespeicherten und ubertragenen Daten. In der modernen Kryptographie
                                      ¨
arbeiten alle Verfahren auf der Basis von Schl¨sseln. Hierbei unterscheidet man prinzipiell
                                               u
zwei Arten von Algorithmen:

      • Symmetrische Algorithmen (secret-key)

      • Asymmetrische Algorithmen (public-key)

Symmetrische Algorithmen basieren auf dem Prinzip, dass eine Nachricht mit ein und dem
selben Schl¨ssel ver- und entschl¨sselt werden kann (Abbildung 20). Das heißt, dass nur
            u                      u
der Schl¨ssel, der zur Verschl¨sselung der Nachricht verwendet wurde, diese auch wieder
         u                     u
entschl¨sseln kann. Dies hat zur Folge, dass sowohl der Sender als auch der Empf¨nger einer
       u                                                                         a
Nachricht im Besitz dieses Schl¨ssels sein m¨ssen. Da die Nachricht nicht von Unbefugten
                                 u            u
gelesen werden darf, muss der Schl¨ssel selbstverst¨ndlich geheim gehalten werden. Es stellt
                                    u              a
sich somit die Frage, wie Sender und Empf¨nger sich auf einen Schl¨ssel einigen oder, besser
                                           a                        u
gesagt, 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.
                                            u
Der bekannteste symmetrische Algorithmus ist wohl DES (Data Encryption Standard).
Diese Methode der symmetrischen Verschl¨sselung wurde 1977 vorgestellt und 1981 als
                                             u
Data Encryption Algorithm, ANSI-Standard X3.92-1981 ubernommen. DES verwendet eine
                                                          ¨
4.1   Sicherheit                                                                            34




                   Abbildung 20: Prinzip der symmetrischen Verschl¨sselung
                                                                  u



Schl¨ssell¨nge von 64 Bits (davon 56 signifikant) und galt lange Zeit als sicher. Im Fr¨hjahr
     u    a                                                                             u
1999 gelang es jedoch einem Projekt namens Deep Crack“, einem speziellen Rechner,
                                                 ”
der von tausenden ubers Internet angeschlossenen Computern unterst¨tzt wurde, einen
                     ¨                                                     u
DES-Schl¨ssel in weniger als 24 Stunden zu knacken. Seitdem gilt ein 64 Bit-Schl¨ssel nicht
          u                                                                         u
mehr als sicher. Symmetrische Algorithmen sollten vielmehr eine Schl¨ssell¨nge von 128 Bits
                                                                      u     a
verwenden. Dadurch ergibt sich eine Schl¨sselmenge von 2128 Schl¨sseln. Dies entspricht
                                           u                          u
im Klartext 340.282.366.920.938.463.463.374.607.431.768.211.456 (≈ 3, 4 · 1038 ) m¨glichen
                                                                                      o
Schl¨ssel. Diese Schl¨ssell¨nge gilt nach heutigem Stand der Technik als nahezu sicher.
     u                u    a
Bedenkt 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, bis
auch diese Schl¨ssell¨nge geknackt werden wird. Was auf jeden Fall bleibt, ist die Notwendig-
               u     a
keit, den gemeinsamen Schl¨ssel zwichen den Kommunikationspartnern sicher auszutauschen.
                           u

    Diese Problematik wird von asymmetrischen Algorithmen vermieden. Bei ihnen gibt es
zwei Schl¨ssel: Einen geheimen privaten Schl¨ssel und einen offentlichen Schl¨ssel, der f¨r
          u                                   u               ¨                u         u
jedermann zug¨nglich ist. Das Prinzip von asymmetrischen Algorithmen besagt, dass eine
               a
Nachricht, die mit dem einen Schl¨ssel kodiert wurde, nur mit dem jeweils anderen dekodiert
                                 u
werden kann. Dies hat zur Folge, dass Kommunikationspartner keine geheimen Schl¨ssel aus-
                                                                                  u
tauschen m¨ssen. Der Sender kodiert einfach die Nachricht mit dem ¨ffentlichen Schl¨ssel
            u                                                         o                u
des Empf¨ngers, dieser entschl¨sselt sie wieder mit seinem privaten Schl¨ssel. Abbildung 21
          a                   u                                         u
zeigt das Prinzip der asymmetrischen Verschl¨sselung. Wird die Nachricht unterwegs abge-
                                              u
fangen, kann sie nicht dekodiert werden, da hierzu der private und damit geheime Schl¨ssel
                                                                                       u
notwendig ist. Es ist also dem Besitzer des privaten Schl¨ssels vorbehalten, Nachrichten zu
                                                          u
entschl¨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
4.1   Sicherheit                                                                             35




                   Abbildung 21: Prinzip der asymmetrischen Verschl¨sselung
                                                                   u



asymmetrische Verschl¨sselungsverfahren basieren auf dem Prinzip, dass es mathematische
                         u
Funktionen gibt, deren Umkehrung nur mit einem erheblich h¨heren Aufwand m¨glich ist.
                                                                  o                   o
Public-Key-Kodierungen verwenden deshalb solche als Trapdoor-Einwegfunktion bezeichnete
Algorithmen. 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
             u
die Funktion schnell umkehren l¨ßt. F¨r einen Außenstehenden, d.h. unberechtigten Mitleser
                                   a     u
ist es allerdings nicht m¨glich, die Nachricht in einer akzeptablen Zeitspanne zu entschl¨sseln.
                          o                                                              u
Der berechtigte Empf¨nger kann hingegen die Nachricht mit der nur ihm bekannten Gehei-
                        a
minformation 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 bisher
aber nicht m¨glich gewesen, die Sicherheit von RSA zu best¨tigen oder zu widerlegen. RSA
               o                                                a
gilt deshalb bis heute als sicherer Verschl¨sselungsalgorithmus.
                                            u
Als Trapdoor-Funktion verwendet RSA die Faktorisierung von Primzahlen. Diese Funktion
beruht auf der Annahme, dass zwei große Primzahlen leicht miteinander multipliziert werden
k¨nnen, dass aber eine Invertierung, also die Faktorisierung eines Produktes zweier großer
  o
Primzahlen, ein wesentlich gr¨ßeres Problem darstellt. RSA stellt somit die Vertraulichkeit
                                o
und Echtheit der Daten¨bertragung sicher.
                           u
Mit Einf¨hrung des Secure Socket Layer (SSL) hat die Verschl¨sselung Einzug ins Inter-
           u                                                         u
net gehalten. Normale Internet-Kommunikation beruht auf dem TCP/IP-Protokol, das eine
vierschichtige Implementierung des OSI-Modells darstellt. Als TCP/IP vor ca. 30 Jahren
erfunden wurde, lag das Hauptaugenmerk darin, eine ausfallsichere und stabile Verbindung
zwischen einer hohen Anzahl von Systemen zu schaffen. Die Authentizit¨t spielte zun¨chst
                                                                            a              a
4.1   Sicherheit                                                                          36


keine 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
                                                       a
TCP/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/IP


Socket Layer liegt zwischen Transportschicht und Verarbeitungsschicht und verh¨lt sich hier-
                                                                                 a
bei v¨llig transparent, so dass weder Anwender noch die anderen Schichten im Modell von
      o
SSL und deren Aktivit¨ten etwas mitbekommen.
                        a
SSL verwendet sog. digitale Zertifikate. Ein Zertifikat besteht aus Angaben uber die Identit¨t
                                                                            ¨              a
des Besitzers und beinhaltet außerdem den ¨ffentlichen Schl¨ssel des Inhabers. Es garantiert
                                             o              u
folglich, dass der ¨ffentliche Schl¨ssel auch tats¨chlich zu der angegebenen Person geh¨rt.
                   o               u              a                                      o
Damit sichergestellt ist, dass die Angaben zur Identit¨t korrekt sind und dass sich niemand
                                                       a
f¨r jemand anders ausgeben kann, muss ein Zertifikat zuvor zertifiziert werden. Dies geschieht
 u
von einem Dritten, der das Vertrauen des Empf¨ngers genießt. Dies entspricht in etwa der
                                                  a
Situation, dass A nicht B kennt, B aber C bekannt ist. Da A nun C vertraut, best¨tigt C
                                                                                      a
die 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) bezeichneten
Stellen pr¨fen auf Antrag die Identit¨t des Zertifikat-Inhabers und best¨tigen diese. Dazu be-
           u                         a                                 a
sitzen solche kommerziellen Anbieter sog. Root-Zertifikate, die auch allen g¨ngigen Browsern
                                                                           a
bekannt 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 u
zustimmen und so das Vertrauen herstellen. Die Indentit¨tsangaben von Zertifikaten stellen
                                                          a
also eine sichere Authentifizierung des Besitzers dar.
                        ¨
Der Verbindungs- und Ubertragungsvorgang im Einzelnen:
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.
                             u

Man sieht, dass SSL einerseits eine verschl¨sselte Verbindung garantiert, anderseits aber auch
                                           u
die Authentizit¨t des Servers gew¨hrleistet. Seit SSL 3.0 k¨nnen Zertifikate auch auf dem
                 a                  a                        o
Client-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
                      a
von jedem beliebigen Arbeitsplatz aus durchgef¨hrt werden kann. Außerdem k¨nnte es zu
                                                  u                               o
Problemen kommen, wenn sich mehrere Nutzer einen PC teilen.
Jedenfalls ist es dank SSL m¨glich, sensible Daten auf sicherem Wege durch das Internet zu
                             o
transportieren. Die Verschl¨sselung macht das Abh¨ren und Ver¨ndern der Daten unm¨glich;
                           u                        o           a                       o
Echtheit und Vertraulichkeit ist garantiert. Die Zertifizierung gew¨hrleistet dar¨ber hinaus,
                                                                   a             u
dass Kommunikationspartner eindeutig identifiziert werden k¨nnen.
                                                              o

4.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
4.2     Internationalisierung                                                             38




                               Abbildung 23: Daten¨bertragung mit SSL
                                                  u



f¨r den internationalen Einsatz entwickelt. Eine durchdachte Gesch¨ftslogik erm¨glicht die
 u                                                                   a           o
Anpassung an national unterschiedliche Bed¨rfnisse und Richtlinien. Gerade eine Oberl¨che
                                             u                                         a
f¨rs World Wide Web muss diesen Anforderungen gerecht werden.
 u
Internationalisierung, 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                             u
die Anpassung auf l¨nderspezifische Eigenheiten zu gestalten. Eine Lokalisierung (l10n), al-
                    a
so die Anpassung eines Programms an l¨nderspezifische Eigenheiten, ist notwendig, da sich
                                        a
die L¨nder dieser Erde nicht nur durch ihre Sprache und die zugrunde liegenden Schrift-
      a
und Zahlzeichen, sondern auch durch abweichende Zahlen-, Zeit- und Datumsformatierun-
gen, eigene W¨hrungen, unterschiedliche Telefonnummern- und Anschriftenkonventionen und
              a
so weiter unterscheiden.

      ¨
4.2.1 Ubersetzung der sprachlichen Inhalte
Das 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                                                                                    u
Die Abbildungen 24 und 25 zeigen zwei Screenshots der Web-Ober߬che mit jeweils englischer
                                                                  a
und deutscher Sprache. Die Web-Ober߬che ubernimmt hier das Modell, das auch in der
                                         a     ¨
C++-Oberfl¨che von VWE Verwendung findet. Sprachbezeichnungen sind hier serverseitig
             a
in der Datenbank gespeichert und werden von dieser entsprechend der eingestellten Sprache
abgefragt. So werden Bildschirmtexte nicht hartverdrahtet“, sondern dynamisch den aktu-
                                            ”
ellen Einstellung angepasst.
  3
      engl: internationalization; i gefolgt von 18 Buchstaben und einem n
4.2   Internationalisierung                                                          39




                       Abbildung 24: Die Web-Ober߬che in Englisch
                                                  a




                       Abbildung 25: Die Web-Ober߬che in Deutsch
                                                  a



Die Umstellung bzw. Erweiterung des Web-Interfaces auf andere Sprachen kann sp¨ter pro-
                                                                               a
                                                  ¨
blemlos vorgenommen werden. Hierzu kann der Ubersetzer alle Sprachbezeichnungen mit
einem von Varial speziell hierf¨r entwickelten Programm namens Sophia bearbeiten und er-
                               u
weitern.
4.2     Internationalisierung                                                              40


4.2.2    Zeichens¨tze
                 a
Genau wie es auf der Erde eine Vielzahl von unterschiedlichen Sprachen gibt, existieren auch
verschiedene Schriftzeichen. Chinesische oder kyrillische Schriftzeichen oder auch die in un-
seren Breiten verwendeten lateinischen Zeichen sind nur einige wenige Beispiele. Selbst in
Europa verwenden einige Sprachen Sonderzeichen, sog. diakritische Zeichen. Beispiele sind
das 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-
          a
fangstagen der Zeichens¨tze war Speicher ¨ußerst kostbar. Dementsprechend wurde jedes nur
                          a                 a
m¨gliche Bit gespart, um nicht unn¨tig Platten- oder Arbeitsspeicher zu belegen und um
  o                                    o
nicht unn¨tig viele Daten in Netzwerken zu versenden. Da die Hardware sehr teuer war, wa-
           o
ren zus¨tzliche Bits eine kostspielige Angelegenheit. Auch bei Zeichens¨tzen wurde gespart,
        a                                                                a
so dass Schriftzeichen urspr¨nglich nur mit sieben Bits repr¨sentiert wurden. Diese Darstel-
                             u                                a
lung gen¨gte f¨r alle Buchstaben des englischen Alphabets, den Ziffern 0 bis 9, Zeichen der
          u    u
Interpunktion sowie einigen Steuerzeichen. Da die urspr¨ngliche Aufgabe von Computern
                                                            u
darin 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
                                              u
bald zeigte sich, dass sieben Bits nicht ausreichen. Durch die Hinzunahmen eines achten Bits
wurde sp¨ter auch die Darstellung aller westeurop¨ischen Sprachen m¨glich.
           a                                         a                 o
Es dauerte nicht lange, da zeigte sich, dass die 256 zur Verf¨gung stehenden Zeichen f¨r die
                                                              u                         u
internationale Verwendung zu wenig waren. Man l¨ste das Problem damit, dass man eine
                                                       o
Reihe von Untermengen, jeweils bestehend aus acht Bits, einf¨hrte. So wurden zehn ISO-
                                                                  u
8859-Standards verabschiedet, die jeweils einen Zeichensatz, also die Zuordnung von acht
Bits zu einem Zeichen definieren.
ISO-8859-1, ein Standard, der auch als Latin-1 bezeichnet wird, ist beispielsweise f¨r west-
                                                                                     u
europ¨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-
                                            u
europ¨ischen L¨nder wie Ungarn oder Polen ab, ISO-8859-5 stellt kyrillische Zeichen f¨r
      a         a                                                                           u
Russisch, Bulgarisch oder Mazedonisch bereit.
Mit ISO-8859 war es somit m¨glich, einen Großteil der europ¨ischen Sprachen abzudecken.
                                o                               a
Ein Problem bestand aber nach wie vor beim japanischen oder chinesischen Alphabet, die
aus 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            u
EUC-KR f¨r Koreanisch oder auch Shift JIS f¨r Japanisch entwickelt, die aus mehr als acht
             u                                  u
Bits 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
                                                   a
Zeichen unterschiedlich kodiert wurden. Im Jahre 1991 gr¨ndete sich das Unicode-Konsortium
                                                          u
aus 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 war
der Unicode-Standard, ein Zeichensatz aus 16 Bits. So lassen sich bis zu 65.536 verschiedene
Zeichen in dem System unterbringen. Nach und nach wurden immer mehr Zeichen in Unicode
ubernommen. 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
                                              a
neu aufgenommen, z.B. Zeichen aus historischen Schriften. Version 3.1 beinhaltet also bereits
4.2     Internationalisierung                                                               41


94.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
                                                    o
32 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 Zeichen
einheitlich darstellen lassen, sondern der auch einen Austausch von Informationen normiert.

4.2.3    L¨nderspezifische Formate
          a
Fast jedes Land hat seine eigenen Formate, beispielsweise f¨r Zahlen- oder Zeit-Angaben. Ge-
                                                           u
rade die Darstellung von Datumsangaben k¨nnte in den einzelnen L¨ndern unterschiedlicher
                                            o                        a
nicht 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.   u
Weitere Eigenheiten findet man in der Darstellung von Uhrzeiten. In manchen Regionen ist
eine 24-Std-Angabe (23:12 Uhr) gebr¨uchlich, f¨r den anderen Teil der Weltbev¨lkerung ist
                                       a        u                                o
die 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.
         u
Selbst 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-
                                                                     a
sprachigen Raum bei großen Zahlen Tausenderstellen durch einen Punkt trennt, verwendet
der angels¨chsische Raum hier ein Komma. Bei Nachkommastellen, die, wie es das Wort be-
            a
reits zum Ausdruck bringt, im Deutschen durch ein Komma getrennt werden, verwendet man
in englischensprachigen Gebieten den Punkt.
Eine Anwendung, die nicht f¨r eine Region zugeschnitten sein soll, sondern in vielen (theore-
                             u
tisch allen) L¨ndern zum Einsatz kommen kann, muss auf diese Besonderheiten achten. Was
              a
einem 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                                 a
mate ber¨cksichtigt und korrekt dargestellt werden.
           u

4.2.4    Lokalisierung der fachlichen Inhalte
Die Software muss landesspezifischen Funktionalit¨ten gerecht werden. So m¨ssen unter-
                                                     a                             u
schiedliche 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ßen
Aufwand an landes- oder unternehmenseigene Bestimmungen anpassbar sind.
Gl¨cklicherweise b¨ndelt VWE die Business-Logik im Application-Layer, also im CORBA-
   u                u
Server. Folglich ist die Anpassung des Clients verh¨ltnism¨ßig einfach. Die ordnungsgem¨ße
                                                    a       a                               a
Buchf¨hrung unter Ber¨cksichtigung landeseigener Bestimmungen wird bereits beim Server
      u                  u
durchgef¨hrt. Der Client muss lediglich einige wenige Kleinigkeiten bei der Oberfl¨chenge-
         u                                                                             a
staltung ¨ndern.
          a
4.3     Performance                                                                         42


4.3 Performance
Auch bei der Entwicklung einer Web-Applikation bestehen Anforderungen im Bereich Per-
formance. Der Begriff Performance beschreibt hierbei im besonderen die Anforderung, dass
die Verarbeitung der Daten schnell erfolgt bzw. dass die Applikation im ganzen eine hohe
Verarbeitungsgeschwindigkeit vorweist.

4.3.1    Verteiltes Rechnen
CORBA unterst¨tzt die Entwicklung von Middleware. Dabei unterteilt sich die Anwendung
                 u
in drei Schichten. Auf der einen Seite befindet sich die Darstellung der Daten (Client), auf der
anderen Seite die Datenhaltung. Die Middleware stellt als Server die Verbindung zwischen
den beiden Enden dar. Die Performance der Anwendung l¨ßt sich u.a. dadurch steigern,
                                                               a
dass die Verarbeitung auf verschiedene Rechner aufgeteilt wird. So ubernehmen sowohl der
                                                                       ¨
Client als auch der Server verschiedene Programmaufgaben. Die Verarbeitung verteilt sich
somit auf mehrere Rechner, was eine h¨here Gesamtleistung zur Folge hat. Weiterhin k¨nnen
                                        o                                                o
Anfragen 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. Der
Administration-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
                                                         a
sich somit die Aufgaben. Die dritte serverseitige Applikation stellt der Dispatcher dar. Seine
Aufgabe ist es, Client-Anfragen auf mehrere Server-Instanzen zu verteilen. VWE erm¨glicht
                                                                                        o
es n¨mlich, gleich mehrere Application-Server parallel laufen zu lassen. Der Dispatcher sorgt
    a
dann daf¨r, dass Anfragen nach einer fairen Zuteilungsstrategie auf die einzelnen Instan-
          u
zen verteilt werden. Auf diese Weise ist es m¨glich, auch bei hohen Anfrage-Aufkommen die
                                               o
Server-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 Vorkehrungen
zu treffen.

4.3.2    Verteilung von Server-Last
Nicht nur die CORBA-Anfragen k¨nnen auf mehrere Server verteilt werden. Auch die
                                     o
HTTP-Anfragen k¨nnen auf mehrere Web-Server-Instanzen aufgeteilt werden. Ein sog. Load-
                   o
Balancer sorgt daf¨r, dass Anfragen des Browser auf verschiedene Web-Server gelenkt wer-
                   u
den. Abbildung 26 zeigt die Aufteilung der Anfragen. Ziel dieser Verteilung ist, dass eine
Reihe von gleichzeitigen Anfragen so auf die Server verteilt werden, dass die Anzahl gleich-
zeitig laufender Servlet-Threads in einem Server reduziert wird. Durch diese Verringerung
der Thread-Anzahl k¨nnen Servlet-Klassen u.U. sogar exklusiv und damit um ein Vielfaches
                     o
schneller 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
                                                                                         u
stellt. Bei Erzeugung dynamischer Seiten werden jedoch sog. Sessions verwendet (auf die
Notwendigkeit von Sessions wird in Abschnitt 5.3 n¨her eingegangen werden). Da Sitzungs-
                                                     a
daten im Speicher des Server-Rechners verwaltet werden, muss entweder der Load-Balancer
alle Anfragen einer Session immer an den selben Server leiten oder die Sitzungsdaten m¨ssen
                                                                                          u
4.3     Performance                                                                       43




         Abbildung 26: Verteilung der HTTP-Anfragen mit Hilfe eines Load-Balancers



in einer zentralen, f¨r alle Server zugreifbaren Resource gespeichert werden. Im letzen Fall
                     u
muss 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.
                   u
VWE-Web verzichtet deshalb auf die Anwendung der zweiten Verteilungsm¨glichkeit. Der
                                                                              o
Aufwand, den eine Verteilung der Anfragen und der Sitzungsdaten zur Folge h¨tte, steht
                                                                                  a
in keinem Verh¨ltnis zu dem daraus resultierenden Nutzen. Sehr wahrscheinlich wird die
                 a
kritische Masse an Anfragen von der Applikation bei weitem nicht erreicht, so dass eine Last-
verteilung hier nicht n¨tig erscheint.
                        o
Sollte es hingegen denoch zu der Notwendigkeit kommen, Serverlast zu verteilen, kann immer
noch ein Load-Balancer eingesetzt werden, der darauf achtet, dass Sitzungsanfragen immer
vom 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
             u
Anwendungsgebietes 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
                                                            o
zu versenden. Anwendung finden hierbei vor allem die Formate zip bzw. gzip. Ein Servlet
kann von dieser M¨glichkeit Gebrauch machen, und die erzeugten Inhalte in komprimierter
                  o
Form ubertragen.
      ¨
Der Browser sendet bei jeder Anfrage eine Reihe von zus¨tzlichen Daten im HTTP-Header.
                                                       a
Ein 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-
                                                        u
Angabe auslesen und uberpr¨fen, ob und welches Komprimierungsverfahren unterst¨tzt wird.
                    ¨      u                                                   u
Mit dem Packet java.util.zip des JDKs besitzt Java bereits die passende Funktionalit¨t,
                                                                                     a
4.4     Anpassbarkeit                                                                     44


um 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 Zeit
f¨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-
             o
samtperformance zu verbessern.

4.3.4    Zwischenspeicherung
Viele 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
                                                   u
oder 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                         a
h¨ufig verwendet. Die Folge sind eine Reihe von Aufrufen, die den CORBA-Server betreffen.
  a
Da diese Aufrufe nach Annahme aber sowieso immer das selbe Ergebnis liefern, k¨nnen die
                                                                                    o
Ergebnisdaten auch nach dem ersten Aufruf clientseitig gespeichert werden. Sp¨ter ist es dann
                                                                              a
nicht mehr n¨tig, eine Server-Methode aufzurufen, die verh¨ltnism¨ssig lange Zeit ben¨tigt,
              o                                               a       a                 o
sondern es kann auf den bereits vorhandenen Datenbestand zur¨ckgegriffen werden.
                                                                   u
Bei 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
                                                                                           u
alle 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 a
der Men¨baum mi den jeweiligen Favoriten. Da sich jeder Anwender eine pers¨nliche Ansicht
        u                                                                     o
seiner h¨ufig benutzen Men¨-Punkte zusammenstellen kann, m¨ssen diese Daten auch f¨r
        a                    u                                      u                      u
jeden 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 Anpassbarkeit
Das Web-Interface muss sich – gerade im auf Hinblick auf das Varial Vertriebsmodell mit
OEM-Partnern und den Best-of-breed“-Gedanken – leicht an individuelle Bed¨rfnisse an-
                                                                            u
                       ”
passen lassen.

4.4.1    Konfiguration
Die 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
                                                                               o
beinhaltet. Eine solche war-Datei entspricht einer jar-Datei, besitzt aber zur Unterscheidung
eine unterschiedliche Endung. Tomcat und eine Reihe weiterer Web-Server unterst¨tzen mitt-
                                                                                  u
lerweile diese Technik, so dass die Applikation ohne großen Aufwand auf andere Systeme
ubertragbar ist.
¨
Die Datei varial.war muss lediglich in das Verzeichnis webapp beim Tomcat-Server oder ein
vergleichbares Verzeichnis eines anderen Servers kopiert werden. Klassenpfade m¨ssen nicht
                                                                                   u
4.4   Anpassbarkeit                                                                     45


mehr angepasst werden. So ist VWE-Web schnell nahezu uberall einsetzbar.
                                                          ¨
Weitere Konfigurationen und individuelle Anpassungen k¨nnen in der Datei web.xml, dem
                                                         o
sog. Deployment-Descriptor vorgenommen werden. Wie der Name bereits verr¨t, handelt es
                                                                              a
sich 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 im
Folgenden 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-
                                   u
Tag gekapselt sind. Die ersten drei Angaben AdminPort, AdminClientAuthPort und
ClientAuthPort geben die Port-Adressen an, unter der die verschiedenen CORBA-Server
ansprechbar sind. Diese Angaben finden sich außerdem in der Server-Konfiguration, in den
Dateien 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 Angabe
localhost 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
4.4     Anpassbarkeit                                                                     46


beschrieben.

4.4.2    Corporate Design
Corporate Design bedeutet, dass zusammenh¨ngende Inhalte einer einheitlichen Darstellung
                                             a
folgen. 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 margentafarbene
T assoziiert man mit der Deutschen Telekom und UPS pr¨sentiert sich im einheitlichen
                                                              a
Braunton. Das Design ist Teil der Unternehmenskultur und so ist es selbstverst¨ndlich, dass
                                                                              a
auch 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 werden
kann. Das Aussehen des Web-Interfaces muss sich also komplett an unternehmensspezifische
Layout-Richtlinien anpassen lassen.

   Um dieser Anforderung gerecht zu werden, verwendet VWE-Web sog. Themes. Ein
Theme ist eine Sammlung von Darstellungsbesonderheiten und beschreibt das Aussehen
der grafischen Benutzeroberfl¨che. So l¨ßt sich f¨r jede Darstellung ein Theme entwerfen,
                              a         a        u
dass detailliert Farben, Schriftarten und -gr¨ße, Grafiken, Umrandungen und vieles mehr
                                             o
definiert. 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                      o
werden. Weitere Einstellungen k¨nnen in der Datei styles.css vorgenommen werden.
                                   o
Hierbei 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             a
von HTML entworfen wurde. CSS wurde im Jahr 1996 vom W3C-Konsortium spezifiziert
und liegt mittlerweile in Version 2.0 vor, wobei selbst Browser der neusten Generation diesen
Standard noch nicht vollkommen unterst¨tzen.
                                           u
Sinn 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
                                                                       o
HTML-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                                                          o
alle 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
                          u
rot, 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, die
auf der Ober߬che angezeigt wird, eine Formatklasse. Die Eigenschaften dieser Formatklassen
             a
k¨nnen beliebig an die jeweiligen Gestaltungsw¨nsche, an das Corporate Design, angepasst
 o                                             u
4.5   Analogie zu bestehender VWE-Ober߬che
                                       a                                                 47


werden.
                                                       ¨
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 einem
Blauton. Als Schriftart wird Arial verwendet. Sollte diese Schriftart nicht verf¨gbar sein,
                                                                                   u
wird 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 erscheinen
sollen. Dies alles geschieht in einer standardisierten Sprache und ist v¨llig unabh¨ngig von
                                                                        o            a
der Implementierung. Die Abbildungen 27, 28 und 29 zeigen einige Beispiele f¨r die unter-
                                                                                 u
schiedliche Ober߬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-Ober߬che
                                     a
Das Web-Interface sollte im Aufbau dem Desktop-Client entsprechen. Durch gleiche Navi-
gationsstruktur und identisch angeordnete Icons erf¨hrt der Anwender einen Wiedererken-
                                                    a
nungwert, der die Einarbeitung in die Browser-Ober߬che erleichtert. Der Mitarbeiter aus
                                                      a
dem Verkauf m¨chte auch im Außendienst die gewohnte Men¨f¨hrung und Oberfl¨chenmas-
               o                                              uu                  a
ke vorfinden. Es sollte somit darauf geachtet werden, dass sich die Gestaltung der Oberfl¨che
                                                                                       a
4.5   Analogie zu bestehender VWE-Ober߬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      a
Programmmodule 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
                                    a
Objektes springt die Ansicht in eine Detaildarstellung. Hier werden weitere, detaiierte Infor-
mationen pr¨sentiert. Oftmals verteilen sich diese Informationen auf mehrere Register einer
             a
Tabsheet.
In der Detailansicht soll es weiterhin m¨glich sein, zwischen den Objekten zu navigieren. Eine
                                         o
Men¨leiste bietet daf¨r Icons, um zum ersten, vorherigen, n¨chsten oder zum letzen Objekt
     u                u                                        a
zu springen. Auch diese Funktionalit¨t soll genau wie die Icons f¨r das Anlegen eines neuen,
                                       a                           u
das L¨schen eines vorhandenen oder das Speichern eines Business-Objektes im Web-Client
      o
4.5   Analogie zu bestehender VWE-Ober߬che
                                       a                                               49


implementiert sein. Weiterhin sollen Tabelleninhalte ausgedruckt und nach Excel exportiert
werden k¨nnen.
         o
Zusammenfassend l¨ßt sich sagen, dass der Web-Client trotz Flexibilit¨t im Oberfl¨chende-
                    a                                                a           a
sign eine an die bestehende VWE angelehnte Benutzerf¨hrung gew¨hrleisten muss.
                                                       u          a
5 Konzeptioneller Neuentwurf eines Web-Interfaces
5.1 Multi-Tier-Architektur
VWE-Web erweitert den dreischichtigen Aufbau von VWE um eine weitere Schicht. Die
dadurch entstandene Architektur wurde bereit in Abschitt 3.3 mit Abbildung 18 skizziert.
Die Kommunikation zwischen den einzelnen Schichten beruht auf offenen Standards. Durch
die Multi-Tier-Architektur wird dar¨ber hinaus ein hohes Mass an Modularit¨t und Skalier-
                                      u                                       a
barkeit erreicht. So ist es theoretisch m¨glich, dass einzelne Schichten ausgetauscht werden
                                         o
k¨nnen, es kann beispielsweise eine andere Datenbank gew¨hlt werden oder es k¨nnen ver-
 o                                                           a                    o
schiedene Web-Server zum Einsatz kommen.

5.2 Das MVC-Modell
Bei der Betrachtung großer Software-Projekte fallen immer wieder Schlagworte wie Modu-
larit¨t, Skalierbarkeit und Wiederverwendbarkeit. Gerade beim Entwurf komplexer Systeme
     a
muss 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      u
MVC-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
                                            a
angewandt wurde. Heute h¨lt das MVC-Modell auch Einzug in moderne objektorientierte
                             a
Sprachen 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                                                         a
f¨r die Datenhaltung), View (verantwortlich f¨r die Darstellung der Daten) und Controller
 u                                            u
(Verbindung zwischen beiden, bearbeitet eingehende Ereignisse). Abbildung 30 zeigt den
MVC-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
5.2     Das MVC-Modell                                                                  51


Web-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 als
Model 2 bezeichnet wird. Abbildung 31 zeigt den ver¨nderten Aufbau von Model 2.
                                                   a




                              Abbildung 31: Das MVC Model 2



5.2.1    Model – Das Modell
Das Modell verwaltet die Business-Logik und ist f¨r die Datenhaltung zust¨ndig. Typischer-
                                                  u                       a
weise 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
                                                                 o
nur spezifisch f¨r diese Web-Anwendung zu entwickeln.
               u
VWE-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
                                                                                    o
auch außerhalb der Web-Anwendung verwendet werden.

5.2.2    View – Die Ansicht
Die View ist f¨r die grafische Darstellung der Daten verantwortlich. Sie stellt die Daten,
               u
die das Model zur Verf¨gung stellt, f¨r den Benutzer dar. View-Komponenten werden durch
                       u              u
JavaServer Pages realisiert. Zus¨tzlich zu dem normalen HTML-Code enthalten JSP-Seiten
                                 a
Java-Fragmente oder auch benutzerdefinierte Elemente (Custom Tags). Solche Custom Tags
entsprechen der HTML- oder, genauer gesagt, der XML-Syntax und k¨nnen als Platzhalter
                                                                     o
f¨r Java-Code gesehen werden. Custom Tags werden in Bibliotheken, sog. Taglibs, zusam-
 u
mengefasst. VWE-Web implementiert eine Taglib namens varial.tld, die eine Reihe von
benutzerdefinierten Tags enth¨lt.
                               a
Custom 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.
                                   u
Durch die Verwendung von Custom Tags ist es m¨glich, dass Designer die Oberfl¨che entwer-
                                                o                             a
fen, ohne sich mit Programmieraufgaben zu besch¨ftigen. Sie verwenden einfach die Tags, wie
                                                a
sie es von HTML bereits gew¨hnt sind. Die Algorithmen, die dahinter stecken, bleiben ihnen
                              o
5.3     HTTP und das Session-Problem                                                     52


verborgen. Wichtig ist einzig und allein die Ausgabe des Tags. Designer m¨ssen nicht Java
                                                                         u
verstehen, w¨hrend sich Programmierer umgekehrt nicht um das Layout k¨mmern m¨ssen.
            a                                                           u          u

5.2.3    Controller – Die Steuerung
Der Controller dient als Bindeglied zwischen Model und View. Er verwaltet Benutzerein-
gaben und setzt die Daten im Modell mit entsprechenden Setter-Methoden. Anschließend
gibt er die Verarbeitung an die View weiter, die das Ergebnis schließlich ausgibt. Dieser
zentrale Teil wird von Servlets realisiert. Die VWE-Web-API bietet bereits in dem Packet
com.varial.base (6.1) einige Oberklassen, von denen Servlets abgeleitet werden k¨nnen, so
                                                                                o
dass typische Aufgaben des Controllers, wie das Dispatchen der Anfrage, mit vorgefertigten
Methoden erledigt werden k¨nnen.
                            o

5.2.4    Zusammenspiel der Komponenten
Das 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 der
Verarbeitung wird die Anfrage an eine JSP-Seite geleitet. Dort wird der Ober߬chenaufbau
                                                                               a
durch HTML- und Custom Tags beschrieben. Die Taglib-Elemente rufen die zugeh¨rigen  o
Java-Klassen auf, die als View f¨r die Darstellung der Daten zust¨ndig sind. Diese Klassen
                                u                                  a
bedienen sich der Daten, die das Model zur Verf¨gung stellt, generieren eine HTML-Ausgabe
                                                u
und schicken diese abschließend wieder zum Browser zur¨ck.
                                                        u

5.2.5    Vorteile von MVC
Durch die Verwendung der MVC-Architektur k¨nnen Darstellung und Gesch¨ftslogik sauber
                                            o                             a
voneinander 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-Problem
Das HTTP-Protokoll ist zustandslos. Das bedeutet, dass der Web-Server eingehende
Anfragen unabh¨ngig voneinander abarbeitet. Zusammenh¨nge zwischen mehreren Anfragen
               a                                         a
kann er hingegen nicht erkennen. Fordert ein Anwender z.B. drei Seiten nacheinander an, ist
es dem Server nicht m¨glich, zu erkennen, dass die drei Anfragen von dem selben Benutzer
                      o
5.3   HTTP und das Session-Problem                                                       53


gekommen sind. Dieses Verhalten ist in einem rein statischen Internet durchaus akzeptabel.
Zu Problemen kommt es hingegen dann, wenn mehr dynamischer Inhalt mit ins Spiel
kommt. Als Beispiel sei ein Online-Shop aufgef¨hrt. Der Besucher durchst¨bert das Angebot
                                                u                        o
des H¨ndlers und legt, nachdem er das erste Mal f¨ndig geworden ist, einen Artikel in den
      a                                              u
Warenkorb. 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 trivialen
Situation im Internet geworden. Wie gestaltet sich diese Szenario jedoch aus der Sicht
des Web-Servers? Er erh¨lt zun¨chst eine Reihe von Anfragen, die das Angebot des Shops
                         a       a
zeigen. 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 schon
Artikel ausgew¨hlt wurden. Genauso steht die sp¨ter folgende zweite Warenkorb-Anfrage
                a                                   a
aus der Sicht des Servers v¨llig losgel¨st von der ersten Anfrage. Nimmt man weiterhin an,
                            o          o
dass gleichzeitig mehrere Personen das System nutzen, erh¨lt der Server eine Reihe von
                                                              a
Anfragen, deren Zuordnung unm¨glich ist.
                                  o

    HTTP braucht also Zust¨nde. Durch einen Zustand muss es m¨glich sein, Sitzungen zu
                             a                                      o
erkennen. Zusammengeh¨rende Anfragen m¨ssen als solche identifiziert werden. Im Beispiel
                          o                  u
des Online-Shops heißt das, dass alle Anforderungen des Anwenders auch vom Server als
zusammenh¨ngend erkannt werden, so dass dieser den Warenkorb verwalten kann.
             a
Um solche Sitzungen oder auch Sessions zu erkennen, dient eine sog. Session-ID. Dies ist
ein eindeutiger Schl¨ssel, den die Sitzung vom Server zugeordnet bekommt. Bei der ersten
                     u
Anfrage erzeugt der Server die Session-ID und liefert sie dem Browser. Dieser muss im
Folgenden jeder Anfrage die Session-ID hinzuf¨gen. Der Server weiß so, dass gleiche Session-
                                                u
IDs zur selben Sitzung geh¨ren. Auch parallele Anfragen von mehreren Nutzer lassen sich
                            o
so auseinanderhalten und richtig zuordnen. Vorraussetzung ist, dass der Algorithmus, der
serverseitig die Session-ID generiert, verschiedene Schl¨ssel erzeugt. Sollten zwei Anwender
                                                        u
die gleiche Session-ID bekommen, w¨rden sie aus der Sicht des Servers ein und die selbe
                                       u
Person darstellen. Resultat w¨re in der Regel ein ziemliches Chaos.
                              a
Damit der Browser die Session-ID bei jeder Anfrage mitliefert, k¨nnen verschiedene
                                                                          o
Techniken benutzt werden (Abbildung 32). Zum einen k¨nnen Session-IDs in sog. Cookies
                                                           o
gespeichert werden. Dies sind sehr kleine Textdateien, die von Web-Seiten auf der Festplatte
des Benutzers gespeichert werden k¨nnen. Die Informationen, die in den Cookies gespeichert
                                    o
werden, k¨nnen sp¨ter von der Seite wieder abgefragt werden. Bei jedem Seitenbesuch w¨rde
          o        a                                                                    u
die 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
                                           o
im 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                          ¨           u
erkennen k¨nnte.
            o

    Eine weitere M¨glichkeit besteht darin, versteckte Formfelder in eine Internetseite
                    o
einzubauen. 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 anderen
Feldern 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                a
in der Anzeige erscheint. Der Browser liefert dem Server aber die gew¨nschte Session-ID.
                                                                      u
5.3   HTTP und das Session-Problem                                                       54




                Abbildung 32: Methoden f¨r den Transport der Session-ID
                                        u



Diese 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. Anstatt
die     Adresse     http://www.abc.de/eineSeite.jsp?param=xy           anzufordern,    wird
http://www.abc.de/eineSeite.jsp;sessionid=0123456789?param=xy                   angefordert.
Der Server zerlegt nun die Adresse wieder in die einzelnen Bestandteile. Die Servlet-API
bietet hierf¨r bereits vorgefertigte Methoden, so dass sich das URL-Rewritting f¨r den
            u                                                                        u
Entwickler 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ßerdem
stellen Servlets bereits ein session-Objekt bereit, in dem Sitzungsdaten gespeichert werden
k¨nnen.
 o
Zum Schluss bleibt die Frage, wie das Ende einer Sitzung erkannt wird. Angelegte Sessions
5.4    Business-Objekt und Enumerations                                                    55


sollten nicht ewig existieren, da dies unn¨tige Systemresourcen verbrauchen w¨rde. Deshalb
                                          o                                   u
gibt es zwei Arten, wie eine Session beendet werden kann. Zum einen kann der Anwender
explizit das Ende einer Session bestimmen. Sobald er sich von dem Web-Client durch
Anklicken des entsprechenden Symbols abmeldet, wird das Session-Objekt und die zugeh¨ri- o
ge ID verworfen. Nun kann es jedoch auch vorkommen, dass der Anwender die Sitzung
nicht durch ein Logout beendet. Er k¨nnte genauso gut einfach den Browser schließen
                                          o
oder durch die Eingabe einer anderen Adresse die Seite verlassen. Auch ein System- oder
Programmabsturz k¨nnte Ursache f¨r ein fehlendes Logout sein. Der Web-Server kann daher
                     o               u
Sessions nach einer gewissen Zeitspanne verwerfen. Sobald eine Sitzung f¨r das angegebene
                                                                          u
Intervall keine neuen Anfragen mehr startet, wird sie als ung¨ltig erkl¨rt und gel¨scht. Die
                                                              u        a          o
Angabe, wie lange dieses Zeitinterval dauern soll, kann im Development Descriptor web.xml
angegeben werden. Die Voreinstellung betr¨gt 30 Minuten.
                                            a
Mit der Verwendung von Session-IDs wird das zustandslose HTTP um die M¨glichkeit von
                                                                              o
Sitzungsverwaltungen erweitert; komplexe Web-Applikationen werden erm¨glicht.
                                                                           o

5.4 Business-Objekt und Enumerations
Alle CORBA-Objekte werden in der IDL als sog. Structs beschrieben. Hierbei werden in
der IDL alle Attribute, die ein Objekt besitzt, beschrieben. Um auf solche Objekte zugreifen
zu 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 Hilfe
werden f¨r IDL-Structs automatisch passende Java-Klassen erzeugt.
         u
Jede 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)
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                                 a

Beispiel:
IDL-Struct:
5.4   Business-Objekt und Enumerations                                      57


struct 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();
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() {
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 {
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();
      }
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);
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
                                                                      a
hinzugef¨gt. Sie zeigen, wie Methoden des Servants aufgerufen und IDL-Typen in BOs
        u
umgewandelt 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).
                                                                a
Um sie in den Java-Klassen zug¨nglich zu machen, dient das Perl-Skript WebEnumBuilder.
                                a
Dieses Skript erzeugt eine Java-Klasse, die es erm¨glicht, Enumerations als eine Liste von
                                                   o
Strings zu erhalten. N¨tzlich ist dies z.B. dann, wenn eine Combo-Box gef¨llt werden soll.
                       u                                                  u
Die erzeugte Java-Klasse hat folgenden Aufbau:
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.*;
5.4   Business-Objekt und Enumerations                                      64


import 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
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
      )
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-Problem
Typisch f¨r ERP-Systeme sind Suchanfragen auf großen Datenmengen. Da die Zeit f¨r die
          u                                                                         u
Suche mit der Menge der Daten zunimmt, muss der Benutzer unter Umst¨nden lange War-
                                                                        a
tezeiten bis zur Ergebnis-Ausgabe hinnehmen.
Sucht man z.B. alle Kunden, die ihren Sitz in Deutschland haben, so kann das bei einem
entsprechend großen Kundenstamm zu einer recht großen Ergebnismenge f¨hren. Es ist nicht
                                                                        u
praktikabel, den Anwender lange auf das Suchergebnis warten zu lassen und ihm alle Daten
auf einmal zu pr¨sentieren. Vielmehr ist es sinnvoller, Daten St¨ck f¨r St¨ck anzuzeigen,
                  a                                               u   u   u
die Liste der Suchergebnisse also schon w¨hrend der Suche aufbauen zu lassen. So kann der
                                         a
Anwender die Daten bereits lesen, w¨hrend weitere Daten noch gesucht werden. Evtl. ist der
                                     a
gesuchte Datenbestand bereits dabei, so dass die Suche vorzeitig vom Benutzer abgebrochen
werden kann. Eine solche Funktionalit¨t wird von VWE mit dem sog. Callback-Mechanismus
                                       a
erm¨glicht.
    o
Unter 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 ist
ein CORBA-ORB beides: Client und Server. Dem Server wird eine Objektreferenz f¨r einu
Client-Callback-Objekt ubergeben, mit dem er Funktionen des Clients aufrufen kann. Auf
                        ¨
5.5    Das Callback-Problem                                                              67


diese Weise kann der Server, wenn er eine gewisse Anzahl von Daten gefunden hat 4 , eine
Methode des Clients aufrufen und die gefundenen Daten ubergeben. Der Client wiederum
                                                          ¨
kann diese Ergebnisse darstellen und auf weitere Daten warten. Um einen Callback-Aufruf
zu erm¨glichen, muss der Client als Erstes das IDL-Interface AllCallback implementieren:
       o

interface 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
                                                                u
weiteren 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
 o
es wird f¨r den jeweiligen Datentyp ein entsprechendes Interface abgeleitet:
         u

interface 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
                                      u
durch Vererbung die beiden Methoden des AllCallback-Interfaces und spezifiziert dar¨ber u
hinaus die typspezifische Methode putData(). Diese Methode erwartet einen Parameter:
PersonalAccountShortSeq.
Dies ist eine Liste von Personen-Konten. Der Server kann also gefundene Daten mit
putData() an den Client ubergeben.
                          ¨

      Beim Aufruf der Server-Methode wird dieses Callback-Objekt mit ubergeben:
                                                                     ¨

// get personalaccounts by filter
void 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
5.5     Das Callback-Problem                                                                68


Man erkennt als dritten Parameter den PersonalAccountStructCallback. Der Server
kann nun entsprechende Abfragen auf der Datenbank durchf¨hren, Teilergebnisse durch
                                                           u
den 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    u
Client 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                              a
ligen.
Der CORBA-Client ist in diesem Fall ein Servlet. Dieses Servlet erzeugt HTML-Code, den
es 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 geschickt
wurde, l¨sst sich nicht mehr ver¨ndern. Bei HTTP sind die Client- und Server- Rollen strikt
         a                        a
verteilt, so dass der Server ausschließlich auf Anfrage des Clients t¨tig werden kann. Wie
                                                                       a
kann das Servlet nun die Daten, die es in unregelm¨ßigen Abst¨nden vom CORBA-Server
                                                       a           a
bekommt, im Browser darstellen, wenn die HTTP-Verbindung keine unmittelbare Kontrolle
des Servlets uber die Darstellung erm¨glicht? Im Folgenden werden m¨gliche L¨sungsans¨tze
             ¨                         o                               o         o         a
aufgezeigt:

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        a
das Ende mit finished() angezeigt wird, k¨nnen alle Daten als Tabelle an den Browser
                                            o
geschickt 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 den
Browser muss also schon vor dem finished() erreicht werden.

5.5.2    Server Push
Im 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
                                                                   o
Animation oder auch das aktuelle Bild einer Webcam darstellen. Im Callback-Szenario k¨nnte
                                                                                      o
das Servlet eine Tabelle mit bereits empfangenen Daten erzeugen, dieses mittels Server-Push
an den Browser schicken, auf neue Daten warten, um dann erneut so zu verfahren. Beim
Aufruf von finished() k¨nnte Socket-Verbindung schließlich geschlossen werden.
                          o
Auf 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                                                     a
Benutzer bekommt somit nacheinander immer wieder eine neue Seite geliefert, die jedes Mal
mehr Daten enth¨lt. Aber auch diese L¨sung hat vier entscheidende Nachteile:
                  a                     o
Dadurch, dass die Seite jedes Mal neu aufgebaut wird, sieht man bei jedem Neuaufbau den
5.5     Das Callback-Problem                                                                 69


Seitenanfang. 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,
                                                                         o
dass 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-
                                                                          a
braucht oder dass eine langsame Internetverbindung die Darstellung bremst, k¨nnte die Seite
                                                                                o
erneut aufgebaut werden, bevor sie komplett dargestellt wurde. Im schlimmsten Fall k¨nnteo
die Seite gar nicht angezeigt werden, da sie bereits von der n¨chsten Seite ersetzt wurde.
                                                                a
Resultat w¨re, dass auch hier erst zum Schluss Daten angezeigt w¨rden. Der dritte Nachteil
            a                                                      u
beim 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                                                   o
ist, dass sowohl der Internet Explorer als auch Opera diese Technologie nicht unterst¨tzen
                                                                                         u
und es fraglich ist, ob sie es jemals tun werden.

5.5.3    Client Pull
Wie bereits oben erw¨hnt, wird der Server auf Anfrage des Clients aktiv. Beim Client Pull
                       a
l¨sst man den Browser deshalb in bestimmten Zeitintervallen neue Anfragen an den Server
 a
starten. So k¨nnte das Servlet einen Thread starten, der im Hintergrund die bereits emp-
              o
fangenen Daten sammelt. Der Browser k¨nnte seinerseits alle N Sekunden eine Anfrage an
                                           o
das Servlet starten, dass eine Tabelle mit den bereits empfangenen Daten zur¨ckschickt. Dies
                                                                                 u
wiederholt 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
                                     a
Daten 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                                                            o
Zwischenzeit keine neuen Daten beim Servlet eingegangen sind. Ein Laden der Seite w¨re so-a
mit uberfl¨ssig. Eine unn¨tig hohe Netz- und Server-Last w¨re die Folge. Ist das Zeitintervall
     ¨     u              o                                    a
jedoch zu lang gew¨hlt, kann der entscheidende Callback-Vorteil, n¨mlich Daten just-in-time
                    a                                                 a
zu 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 Darstellung
k¨nnte unter Umst¨nden l¨nger als das Zeitintervall sein, so dass die Seite immer wieder von
  o                 a       a
einer neueren verdr¨ngt wird.
                     a

5.5.4 Client Pull + DHTML
Anstatt die Seite jedes Mal neu aufzubauen, k¨nnte eine Hilfsseite verwendet werden. Diese
                                                 o
Seite wird in ein verstecktes frame oder iframe geladen und l¨dt sich mittels Client Pull
                                                               a
in regelm¨ßigen Abst¨nden neu. Hierbei m¨ssen nicht alle gefundenen Daten vom Servlet
          a           a                       u
geliefert werden, sondern lediglich die neu hinzugekommenen. So wird die Netzlast gering
gehalten. Sobald die Hilfsseite neue Daten empfangen hat, werden diese mit JavaScript an
die eigentliche Tabelle angeh¨ngt. Auf diese Weise w¨chst die Tabelle, ohne dass die Seite
                               a                     a
neu geladen werden muss. Lediglich die Hilfsseite muss neu aufgebaut werden. Da diese aber
nicht angezeigt wird, ist dies nicht weiter schlimm.
Auch hier bleiben Nachteile:
Die Frage nach dem passenden Zeitintervall zwischen zwei Ladevorg¨ngen bleibt unge-
                                                                       a
5.5     Das Callback-Problem                                                                70


kl¨rt. Gr¨ßter Nachteil ist jedoch die noch magelnde DHTML-Unterst¨tzung der Browser-
  a      o                                                              u
Hersteller. Opera unterst¨tzt diese L¨sung beispielsweise nicht, da die Hilfsseite die Haupt-
                         u           o
Tabelle mit dem JavaScript-Befehl getElementById() ansprechen m¨sste, der von Opera
                                                                       u
noch nicht implementiert ist.

5.5.5    Daten ungepuffert schreiben
Anstatt die Seite jedes Mal neu zu laden, k¨nnte sie auch einfach nach und nach aufgebaut
                                             o
werden. Setzt das Servlet den Ausgabe-Puffer auf 0 Byte oder leert ihn explizit mit dem
flush()-Befehl, wird die Ausgabe direkt an den Browser geschickt. Wird bei jedem Aufruf
von putData() die Ausgabe erzeugt, geschrieben und mit flush() der Buffer geleert, baut
sich im Browser nach und nach die Tabelle auf.
Durch diesen L¨sungsansatz werden direkt mehrere oben genannte Nachteile umgangen:
                o
Die Seite muss nicht neu geladen werden, sie baut sich auf. Dadurch springt die Scrollposition
nicht nach oben, es entsteht kein Flackern und es erscheint ein permanentes Bild. Die Daten
werden genau dann angezeigt, wenn sie vom Server geliefert werden und sind nicht an ein
konstantes Zeitintervall gebunden. Die L¨sung ist frei von DHTML und schließt somit keine
                                          o
Browsertypen 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 wird
dies erst angezeigt, nachdem die Tabelle vollst¨ndig ausgegeben wurde, also erst nach dem
                                                 a
finished(). Dieses Problem l¨sst sich recht einfach umgehen, indem die Tabelle in ein iframe
                              a
eingebettet wird. Angenehmer Nebeneffekt hierbei ist, dass die Tabelle im Layout immer den
selben Platz einnimmt und mit Scrollbalken versehen wird.
Ein gr¨ßeres Problem stellt jedoch die Tatsache dar, dass viele Browser die Spaltenbreiten
       o
optimal an die Zelleninhalte anpassen. Um eine optimale Darstellung zu erreichen m¨ssen   u
aber erst alle Eintr¨ge bekannt sein. Schließlich kann der breiteste Spalteninhalt nicht ermit-
                    a
telt werden, wenn noch nicht alle Inhalte bekannt sind. Folge ist, dass Tabellen erst beim
abschließenden table-Tag angezeigt werden.
Werden die einzelnen Zeilen also zum Browser geschickt, zeigt dieser sie erst an, nachdem
die Tabelle komplett ubertragen wurde. Folglich sieht der Anwender keinen Unterschied zur
                      ¨
erstgenannten Sammell¨sung.
                        o
Der 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 mit
der CSS-Angabe table-property:fixed, baut der IE die Tabelle ߬ssig auf. Beim Opera
                                                                       u
bewirkt dies hingegen keine Ver¨nderung.
                                a

5.5.6    Daten ungepuffert schreiben + viele kleine Tabellen
Wie 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
                                                                               o
der Browser die bereits ubertragenen Daten schon anzeigen.
                        ¨
Eine große Tabelle wird somit durch viele kleine ersetzt. Dadurch, dass der Browser jedoch
5.5     Das Callback-Problem                                                               71


die Spaltenbreiten in Tabellen vergr¨ßert, wenn Inhalte zu groß sind, f¨hrt dies zu dem un-
                                     o                                  u
gew¨nschten Nebeneffekt, dass die Spaltenbreiten in den einzelnen Tabellen unterschiedlich
     u
breit sein k¨nnen. Es entsteht nicht mehr der Eindruck, dass es sich um eine einzige Tabelle
            o
handelt.
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
                                                              a
beim IE beheben. Die CSS-Angabe overflow:hidden in den Tabellenzellen, die ubergroßen
                                                                                  ¨
Inhalt abschneidet, bleibt wirkungslos. Deshalb wurden die Zelleninhalte mit einem div-Tag
umschlossen, der wiederum mit dem besagten overflow:hidden versehen wurde. Dadurch
werden auch bei Netscape und Mozilla breite Eintr¨ge abgeschnitten. Die Spalten haben aber
                                                   a
nicht zwangsl¨ufig die selbe Breite. Ein Grund daf¨r konnte nicht gefunden werden. Ebenso
              a                                    u
wenig f¨r das Verhalten des Opera-Browsers: Dieser schneidet zwar die Inhalte ordnungs-
         u
gem¨ß ab, die Spalten sind aber so breit, wie sie sein m¨ssten, wenn sie nicht abgeschnitten
     a                                                  u
w¨ren. Hierbei handelt es sich h¨chstwahrscheinlich um einen Browser-Bug.
  a                              o
Man sieht, dass sich das Bem¨hen des Browsers, Tabellen optimal darzustellen, selbst mit
                               u
CSS nicht vollst¨ndig abschalten l¨sst. Viele kleine Tabellen werden folglich schnell, aber
                  a                 a
unsch¨n dargestellt.
       o

5.5.7    Daten ungepuffert schreiben + Tabelle imitieren
Anstelle von table-Tabellen k¨nnen div-Elemente benutzt werden, um Tabellen zu imi-
                                o
tieren. Zelleninhalte werden in div-Bl¨cke gefasst und mit CSS auf die gew¨nschte Breite
                                        o                                     u
gebracht. So werden Callback-Daten schnell und sauber formatiert dargestellt. Einziger
Nachteil 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       o
optimal angepasst worden.

   Abschließend l¨sst sich sagen, dass nur dieser L¨sungsweg dem Callback-Ansatz gerecht
                  a                                o
wird und zugleich eine browserunabh¨ngige Darstellung erm¨glicht.
                                    a                      o

5.5.8    Asynchrones Warten
Der CORBA-Server liefert die Daten, der Browser bzw. das Servlet ist f¨r die Darstellung
                                                                            u
dieser Daten zust¨ndig. Infolgedessen muss der Server darauf warten, dass die Darstellung
                   a
beendet ist, bevor neue Daten geliefert werden k¨nnen. Dieses Warten f¨hrt u.U. zu einem
                                                   o                       u
Performanceverlust, n¨mlich genau dann, wenn die Darstellung der Daten mehr Zeit als ihre
                       a
Lieferung ben¨tigt. Abhilfe schafft hier ein asynchrones Warten.
              o
Die Situation entspricht dem klassischen Erzeuger-Verbraucher-Problem. Der CORBA-Server
erzeugt die Daten, das Servlet verbraucht diese. Beide Parteien k¨nnen asynchron laufen. Das
                                                                  o
heißt, der Erzeuger muss nicht darauf warten, dass alle Daten verbraucht wurden. Vielmehr
laufen beide Jobs in getrennten Threads. Zur Kommunikation dient eine Queue. Der Erzeuger
f¨llt die Queue mit Inhalt, woraufhin der Verbraucher die Queue-Inhalte entnehmen kann.
 u
Auf diese Weise ist es m¨glich, dass der CORBA-Server kontinuierlich Daten liefert kann.
                         o
Zur 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
5.6   Tabsheets                                                                         72


haben 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-
           a
Objekt. 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-
        ¨                                                                        u
stellung der Daten in Tabellen zust¨ndig ist. Ist die Darstellung komplett, wird uberpr¨ft,
                                    a                                             ¨     u
ob 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 der
VListStateThread in einen Wartezustand und verharrt in diesem, bis er vom CORBA-Server
resp. Callback-Klasse dar¨ber benachrichtigt wird, dass entweder neue Daten vorhanden sind
                         u
oder keine Daten mehr folgen. Durch diese asynchrone Verarbeitung beider Seiten braucht ein
Thread keine R¨cksicht auf die Verarbeitungsgeschwindigkeit des Gegen¨bers zu nehmen.
                u                                                      u

5.6 Tabsheets
Aus 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                                           o
es, 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                                          o
an die, von der Desktop-Anwendung gewohnte Oberl¨che, angelehnte GUI realisieren soll,
                                                      a
muss 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 Schritt
muss somit sein, eine grafische Nachbildung einer Karteikarte zu erstellen. Dazu wird das
table-Tag verwendet, dass eine Tabelle darstellt. Dadurch, dass mittels CSS-Angaben nur
bestimmte Zellenumrahmungen dargestellt werden, entsteht der Eindruck einer Registerkarte.
Abbildung 33 verdeutlicht diese Technik.




             Abbildung 33: Visualisierung von Tabsheets mit HTML und CSS
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 muss
der Inhalt der entsprechenden Karte in den Vordergrund verschoben werden und die anderen
Karten verdecken. HTML bietet zwar in neueren Versionen die M¨glichkeiten, entweder sog.
                                                                    o
Layer (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-a
gen Browsern ausgereift und selten kompatibel. Aus diesem Grunde muss jede Registerkarte
als eingenst¨ndige Seite dargestellt werden. Folglich gibt es eine Seite, die die Tabsheet mit
             a
aktivierter Karteikarte 1 darstellt, eine Seite, die die Tabsheet mit aktivierter Karteikarte 2
darstellt, usw. Da der Inhalt dynamisch erzeugt wird, m¨ssen hierf¨r nicht viele unterschied-
                                                           u         u
liche, sondern nur eine einzige Seite erstellt werden.
                                              ¨
Klickt der Anwender also auf eine Register-Uberschrift, wird die Seite geladen, die den Inhalt
dieses Registers anzeigt. Genauer gesagt, wird die aktuelle Seite erneut mit einem Parameter
geladen, der angibt, welche Kartei-Karte dargestellt werden soll. Je nachdem, welchen Wert
dieser Parameter erh¨lt, erzeugt das Servlet eine andere Ausgabe.
                     a
Es 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 eindeutigen
Index. Dieses Vorgehen stellt sicher, dass eine Register-Karte unabh¨ngig von der aktuellen
                                                                        a
Spracheinstellung 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                                                 u
HTML-Verweise zu realisieren, die zus¨tzlich mit dem passenden Query-String-Parameter
                                          a
f¨r den Index versehen sind. Beispielsweise k¨nnte als Spalten¨berschrift der ersten Karte
 u                                               o                u
folgende HTML-Anweisung dienen:

<a href="dasGleicheServletNochmalAufrufen?tabsheetindex=0>Erste Karte</a>

Das Servlet w¨rde hierbei einfach den Query-String-Parameter tabsheetindex abfragen und
             u
nur die Ausgabe f¨r die erste Tabsheet erzeugen.
                 u

switch(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
}
5.6   Tabsheets                                                                           74


Mit diesen Schritten w¨re eine Tabsheet bereits visualisiert und mit der Funktion f¨r das
                         a                                                             u
Umschalten der Reiter versehen. Es offenbart sich aber ein weiteres Problem. Daten in einer
Tabsheet 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
                                                                          u
ein und wechselt zur Karte f¨r die Bankverbindung, wird die gemachte Angabe verworfen.
                              u
Der Grund daf¨r ist, dass das bearbeitende Servlet zwar erf¨hrt, dass die Bankverbindungs-
                u                                            a
Karte angefordert wurde, es weiß aber nicht, welche Seite zuvor bearbeitet wurde. Dieses
Problem l¨ßt sich noch leicht dadurch beheben, dass neben dem Parameter f¨r die ange-
           a                                                                     u
forderte 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
                               u
dritten 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 Anderungen
noch immer nicht gespeichert werden. Der Grund hierf¨r ist, dass die eingegebenen Daten
                                                          u
nicht ubertragen werden. Ein Link f¨hrt einfach zur n¨chten Seite. Vielmehr m¨sste das
       ¨                                u                  a                        u
Formular, das auf der Registerkarte dargestellt wird, abgesendet werden. Zum Absenden
verwendet HTML ausschließlich Buttons und in neueren Versionen zus¨tzlich Bilder. Die
                                                                           a
Verwendung 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
                  u
eine 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 bestehende
Design 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
        u
tabClicked() auf. Diese Funktion befindet sich in der Datei varial.js, die automatisch in
jede JSP eingebettet wird.
function tabClicked(tabsheetname, tabindex)
¨
Ubergibt man der Funktion den Namen der Tabsheet (da auf einer Seite mehrere Tabsheets
verwendet 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-
              u
mular. 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
                                    o
com.varial.gui.TabSheetBean (6.3.20) erzeugt. F¨r den Entwickler bleiben die oben
                                                       u
erl¨uterten Einzelheiten verborgen. Er spezifiziert lediglich mit der API einige Eigenschaften
   a
der 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 Anderungen
persistent 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  ¨
5.7     Multimedia                                                                       75


werden. Dieser w¨rde sie in der Datenbank speichern. Dies ist jedoch nicht erw¨nscht, da
                 u                                                            u
ein BO nur dann gespeichert werden soll, wenn der Benutzer dies ausdr¨cklich durch das
                                                                       u
entsprechende Men¨-Symbol veranlasst. Tabsheets f¨hren also zu der Notwendigkeit, BOs
                    u                             u
tempor¨r auf der Client-Seite zu speichern.
        a
Um diese Anforderung zu realisieren, wurde die Klasse com.varial.base.TempData
(6.1.15) entworfen. Sie speichert BOs im session-Objekt. TempData verwaltet hierzu einen
Hashtable, 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
                                                          u
Setter-Methoden des BOs durch und veranlasst die TempData-Klasse wieder, das BO in
der Session zu speichern. Klickt der Anwender auf den Speicher-Button der Men¨lei-  u
ste, muss nun einfach die commit()-Methode des BOs aus der Session ausgef¨hrt werden.
                                                                            u
Das 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-Methode
enableSave() 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 nicht
der Fall, muss das BO nicht von TempData angefordert und aktualisiert werden. Reslutat ist
eine Zeiteinsparung und Performance-Verbesserung des Servlets.

5.7 Multimedia
Neben der reinen HTML-Erzeugung k¨nnen Servlets weitere Inhalte generieren. Bei VWE
                                      o
besteht zum Beispiel die Anforderung, Daten grafisch in Form von Diagrammen darzustellen.
Außerdem ist ein Datenexport nach Microsoft Excel zu realisieren, damit Tabelleninhalte
in Office-Dokumenten weiterverarbeitet werden k¨nnen. Als Letztes soll die Darstellung der
                                                o
Unternehmensdaten f¨r portable Kleinstger¨te wie Handys und PDAs mittels WAP m¨glich
                     u                    a                                       o
sein.

5.7.1    MIME-Typen
Der Schl¨ssel f¨r die Bereitstellung multimedialer Inhalte liegt in der Verwendung von MIME-
         u     u
Typen. MIME steht f¨r Multipurpose Internet Mail Extensions. Die Bezeichnung deutet an,
                       u
dass MIME-Typen ihren Ursprung im Bereich der eMail hatten. Durch die Versendung von
Dateien im Anhang einer Mail ist es notwendig, die einzelnen Teile der Mail zu trennen. So
muss beispielsweise eine angeh¨ngte Bild- oder Zip-Datei von dem eigentlichen Nachrichten-
                                 a
text getrennt werden. MIME ist eine Konvention dar¨ber, wie der Daten-Typ der einzelnen
                                                       u
Teile 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-
                                                            a
Type besteht aus zwei Teilen: Einem Haupt- und einem Subtyp. Beide Angaben werden
durch Schr¨gstrich voneinander getrennt. Beispiele f¨r h¨ufig verwendete MIME-Typen sind
           a                                          u a
text/html, image/jpg oder text/plain. Der MIME-Haupttyp erm¨glicht die Einordnung
                                                                         o
in eine der folgenden Gruppen:

text Textdateien
5.7     Multimedia                                                                       76


image Grafikdateien

video Videodateien

audio Sounddateien

application Dateien, die an ein bestimmtes Programm gebunden sind

multipart mehrteilige Daten

message Nachrichten

model Dateien, die mehrdimensionale Strukturen repr¨sentieren
                                                   a

    Die vom Servlet erzeugten Daten werden mit der Angabe des entsprechenden MIME-Typs
versehen. 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-
                                          u
gieren in einer solchen Situation aber normalerweise damit, einen Dialog anzuzeigen, der dem
Anwender den Download der Datei vorschl¨gt. a
Etwas problematischer ist die Verwendung eines unbekannten MIME-Typens auf der Server-
seite. Unbekannte Typen werden in der Regel nicht verarbeitet. Deshalb ist es wichtig, den
Web-Server passend zu konfigurieren, wenn exotische MIME-Typen verwendet werden.

5.7.2    Bilderzeugung
Der VWE-Web-Client soll die M¨glichkeit besitzen, Datenreihen grafisch in Form von Dia-
                                   o
grammen zu generieren. Hierzu muss wie bereits erw¨hnt, zuerst der richtige MIME-Type
                                                         a
gesetzt 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   u
die Realisierung von VWE-Web wurde auf eine Klassenbibliothek namens jChart zur¨ck-   u
gegriffen, die bei der OpenSource-Sammlung sourceforge.net zu finden ist. Mit Hilfe dieser
Klassen k¨nnen Graphen aus ubergebenen Daten erzeugt werden. F¨r die Verwendung im
           o                    ¨                                     u
VWE-Umfeld wurde eine spezielle Klasse im com.varial.base-Package entworfen. Sie tr¨gt a
den 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/gif
gesetzt. 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
                                                              u
erzeugte Diagramm in eine JSP-Seite einbetten l¨ßt.
                                               a
5.7     Multimedia                                                                       77




                     Abbildung 34: Tabellendarstellung in VWE-Web




                       Abbildung 35: Nach Excel exportierte Tabelle



5.7.3    Excel
Genau wie die Desktop-Version von VWE soll auch das Web-Interface die M¨glichkeit bie-
                                                                              o
ten, Tabelleninhalte nach Excel zu exportieren. Abbildung 34 zeigt die Tabellendarstellung
in 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 hier
muss zun¨chst der passende MIME-Typ gesetzt werden. In diesem Falle handelt es sich um
          a
die 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 Anwendung
angezeigt.
Da Excel seit der Office2000-Version die M¨glichkeit bietet, HTML-Tabellen zu importieren,
                                              o
gestaltet sich das Szenario denkbar einfach. Das Servlet muss nur den MIME-Typ setzen und
die Daten wie gewohnt senden. Nun ist es Aufgabe des Browsers, passend auf den Typ zu
reagieren, Excel zu ¨ffnen und die Daten in die Anwendung zu importieren. Einziger Unter-
                     o
schied auf der Serverseite ist also, dass ein anderer MIME-Type gesetzt wird. Die gesendeten
5.7     Multimedia                                                                         78


Daten bleiben identisch.
                                      ¨
Ein solcher Datenexport ließe sich im Ubrigen auch f¨r andere Office-Anwendungen realisie-
                                                      u
ren. Auf diese Weise w¨re auch ein Export nach Word oder Outlook m¨glich. Auf Systemen,
                       a                                               o
auf denen die passende Software nicht installiert ist (z.B. Linux), w¨rde dem Anwender ein
                                                                     u
Fenster pr¨sentiert, mit dem die Daten als xls-Datei abgespeichert werden k¨nnen.
          a                                                                  o

5.7.4    WAP
WAP ist die Abk¨rzung f¨r Wireless Application Protocol und definiert ein Protokoll f¨r
                    u       u                                                                u
kabellose Verbindungen. WAP wurde 1998 von den Firmen Ericsson, Nokia, Motorola and
Unwired Planet (sp¨ter Phone.com) entwickelt und legt fest, wie Daten in kabellosen Netzwer-
                     a
ken 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        u
Datei entsprechen muss. Dies heißt bespielsweise, dass jedes ge¨ffnete Element geschlossen
                                                                  o
werden muss und dass die Verschachtelung von Elementen einer speziellen DTD entsprechen
muss. HTML ist im Vergleich dazu nicht ganz so streng. So wird beispielsweise das br-Tag
normalerweise nicht geschlossen.
WAP und WML finden haupts¨chlich Verwendung in Kleinstger¨ten. Beispiele f¨r solche,
                                  a                                 a               u
als 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-
                                                                              o
ne normalen Internetseiten ubertragen werden. Dies d¨rfte in Verbindung mit sehr hohen
                              ¨                         u
Preisen der Grund daf¨r sein, wieso sich WAP bis heute nicht so stark durchgesetzt hat, wie
                       u
sich 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                                                 u
worfen. VWE-WAP benutzt hierbei die selbe Architektur wie die Web-Anwendung. Daten
werden auch hier von einem Servlet verwaltet, das die Darstellung einer JSP-Seite uberl¨ßt.
                                                                                      ¨    a
VWE-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 der
Diplomarbeit diese Technologie nur am Rande bearbeitet werden. Außerdem stellt sich die
Frage, inwieweit die eingeschr¨nkte Hardware eine sinnvolle ERP-Anwendung erm¨glicht.
                                a                                                       o
Dennoch soll beispielhaft ein Anwendungsfall umgesetzt werden. Die Implementierung des
TaskReminders, also einer Erinnerungsfunktion, erscheint hier vern¨nftig. Die M¨glichkeit,
                                                                      u             o
Fristen 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
                  a
dieser 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 hierbei
ist 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. Die
Beachtung des zweiten Punktes, n¨mlich die Seite in WML zu schreiben, stellt ebenfalls kein
                                    a
großes Problem dar. JSP-Seiten sind, wie bereits bei der Vorstellung der Technologie erw¨hnt
                                                                                          a
5.8   Darstellung mit verschiedenen Browsern                                              79


(2.1.2), auf keine besondere Sprache beschr¨nkt. Zwar ist die Hauptanwendung das Erzeugen
                                           a
von dynamischen HTML, aber es sind durchaus andere Formate wie XML, L TEXoder eben
                                                                           A
auch WML m¨glich. Der Adaption von VWE-Web zu VWE-WAP steht somit nichts mehr
                o
im Wege.

5.8 Darstellung mit verschiedenen Browsern
Die Tatsache, dass dem Benutzer eine Vielzahl von unterschiedlichen Browsern (mit diversen
Einstellungen), auf verschiedenen Systemen zur Verf¨gung steht, f¨hrt dazu, dass bei der
                                                      u             u
Darstellung der Daten dieser Heterogenit¨t Rechnung getragen werden muss. Die Ausgabe
                                           a
sollte auf allen g¨ngigen Browsern fehlerfrei dargestellt werden k¨nnen. Dabei sollte sie
                  a                                                  o
uberall m¨glichst gleich gestalltet sein, was nat¨rlich nicht ausschließt, dass Features, die
¨         o                                      u
nur ein gewisser Browser unterst¨tzt, nicht ausgenutzt werden sollen, wenn andere Browser
                                 u
entsprechende Alternativen zur Verf¨gung stellen.
                                     u

    Bei der Erstellung des Web-Interfaces kommen verschiedene Techniken zum Einsatz, die
bestimmte Anforderungen an den Web-Browser, der die Daten darstellen soll, stellt. Im
Spezielen ist dies die Seitenbeschreibungssprache HTML, die Formatierungssprache CSS, die
Programmiersprache JavaScript und das Document Object Model (DOM). Im Gegensatz zu
anderen clientseitigen Web-Technologien wie beispielsweise Flash handelt es sich bei allen
verwendeten Ans¨tzen um Standards. Immer wenn von Internet-Standards die Rede ist,
                   a
f¨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                                                   u
f¨hrenden Vertretern der Softwareindustrie mit Ziel, die Grundlagen f¨r eine Institution
 u                                                                       u
zu schaffen, die sich um Standards der neuen Internet-Technologie k¨mmerte. Im Sommer
                                                                       u
1995 begann das w3c dann offiziell seine Arbeit. HTML 1.0 wurde der erste Standard des
neu gegr¨ndeten Konsortiums. Seither wird jede HTML-Version vom w3c verabschiedet. In
          u
Folge dessen ist man versucht zu behaupten, dass eine standardisierte Auszeichnungssprache
problemlos auf allen Browsern darstellbar sei. Schließlich liegt den Browser-Herstellern mit
dem offiziellen HTML-Standard eine Referenz des Sprachumfangs und deren Umsetzung
vor. Die Realit¨t sind jedoch anders aus. Zwischen konkurierende Browser-Hersteller wie
                a
Microsoft mit dem Internet Explorer auf der einen und Netscape mit ihrem Navigator auf der
anderen Seite tobt bereitsseit Jahren einen als Browser-Krieg“ bezeichneter Wettbewerb.
                                                 ”
Im Kampf um Marktanteile scheut man sich nicht davor, den HTML-Standard nach
eigenen Bed¨rfnissen zu Formen. Resultat sind browsereigene Tags, also Anweisungen, die
             u
ausschließlich im firmeneigenen Browser angezeigt werden und unterschiedliche Wiedergabe
der w3c-Norm. Eine einheitliche Darstellung erweist sich in der Realit¨t schon bald als
                                                                          a
Utopie.
Bei CSS verh¨lt es sich ¨hnlich. Auch CSS steht unter der Kontrolle des w3c (erstmalig im
              a           a
Jahr 1996 ver¨ffentlicht), aber genau wie bei HTML klaffen zum Teil riesige L¨cken zwischen
              o                                                              u
den Umsetzungen in den verschiedenen Browsern. Einige Stylesheet-Angaben funktionieren
nur 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
                                                                 a
handelt es sich um eine 1995 von dem Unternehmen Netscape lizensierte Programmierspra-
5.8    Darstellung mit verschiedenen Browsern                                                 80


che. Trotzdem l¨uft JavaScript auch in den meisten anderen Browsern. Selbst der Microsoft
                 a
Internet Explorer, dem gr¨ßten Netscape-Konkurenten, unterst¨tzt JavaScript. In Wirklich-
                            o                                     u
keit verbirgt sich hier hinter jedoch die Sprache JScript, die in Anlehnung an JavaScript von
Microsoft erfunden wurde. Da JScript aber mit nahezu allen JavaScript-Befehlen zurecht
kommt, stellt dies in der Praxis keinen Unterschied dar. Unter der Bezeichnung ECMAScript
wurde JavaScript bereits fr¨hzeitig von der Organisation European Computer Manufacturers
                             u
Association (ECMA) als Industrie-Standard deklariert. Im allt¨glichen Einsatz zeigt sich
                                                                    a
hingegen auch bei JavaScript, dass die Software-Hersteller bei der Umsetzung des Standards
eigene 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
                           u
sich nicht wirklich um eine neue Technologie. DOM wurde eher als Erg¨nzung zu JavaScript
                                                                         a
entworfen. In Hinblick auf immer mehr Dynamik in Web-Seiten bestand in den Reihen der
JavaScript-Programmier schon fr¨h der Wunsch, auf Teile einer Web-Seite zugreifen und
                                    u
diese sp¨ter ver¨ndern zu k¨nnen. Die beiden Protagonisten des Browser-Kriegs entwickelten
         a       a            o
daraufhin zwei verschiedene L¨sungsans¨tze, die dieser Anforderung entsprechen sollten.
                                  o        a
Die Folge war ein doppelter Aufwand, da bei der Realisierung dynamischer Seiten beiden
Browsern Rechnung getragen werden mußte. Das w3c nahm sich dieser Problematik an und
ver¨ffentlichte schließlich im Oktober 1998 ein als Document Object Model bezeichnetes
    o
Modell. Dabei wurde DOM so entworfen, dass nicht nur der JavaScript-HTML-Kombination
ber¨cksichtigt wurde. Ziel war es, einen einheitlichen Zugriff auf alle XML-konformen
    u
Auszeichnungssprachen zu erm¨glichen. DOM wird in Zukunft die propriet¨ren Ans¨tze
                                  o                                             a        a
abl¨sen und ein gemeinsames Modell f¨r die mit JavaScript gestallteten Web-Seiten bieten.
    o                                    u
Das Problem bei DOM ist weniger die Nichtbeachtung der Norm. Zwar zeigt sich auch hier
deutlich, dass die Software-Hersteller ihre eigenen Wege gehen, aber die gr¨ßte Schwierigkeit
                                                                            o
liegt 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, wie
schnell die Architektur ins Wanken ger¨t. Zur L¨sung dieses Problems bieten sich folgende
                                      a          o
M¨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.
                                                                          a
Zuerst werden alte Browser nicht beachtet. Als Mindestanforderung ergibt sich der Microsoft
5.8   Darstellung mit verschiedenen Browsern                                           81


Internet 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 der
Implementierung nicht ber¨cksichtigt. Weiterhin wurde darauf geachtet, nur Techniken zu
                           u
verwenden, die in allen diesen Browsern lauff¨hig sind. Sollte es die Anwendung schließlich
                                             a
erfordern, werden stellenweise browserspezifische Mehrfachl¨sungen entworfen.
                                                          o
6 Die VWE-Web-API
Dieses Kapitel stellt die neue API f¨r die Erstellung von VWE-Web-Anwendungen vor.
                                      u
Hierzu 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.
                                                                                   a
Die Erkl¨rungen beschr¨nken sich teilweise auf wichtige, d.h. h¨ufig verwendete Funktionen.
         a             a                                       a
Methoden, 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                                                                            a
F¨r eine komplette Auflistung wird auf die Javadoc-Dokumentation der jeweiligen Klassen
 u
hingewiesen.

6.1 Das Packet com.varial.base
Das Packet stellt Klassen f¨r die allgemeine Verwendung zur Verf¨gung.
                           u                                    u

6.1.1   VServlet
Die Klasse VServlet wurde von HttpServlet abgeleitet und erweitert diese Klasse um einige
n¨tzliche Funktionen. Alle Servlets sollten von dieser Klasse (oder einer ihrer Unterklassen)
 u
abgeleitet 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,
    ServletException

In dieser Methode wird zun¨chst ein VContext-Objekt (6.1.10) erzeugt und anschließend
                             a
uberpr¨ft, ob der Benutzer erfolgreich ins System eingeloggt ist. Andernfalls wird der Anwen-
¨      u
der auf die entsprechende Login-Seite weitergeleitet. So wird sichergestellt, dass alle Anfragen
nur von authorisierten Benutzer erfolgen d¨rfen. Sollte ein Callback (5.5) aktiv sein, so wird
                                            u
dieser gestoppt.
Abschliessend wird die Methode getIt() aufgerufen, die den erzeugten VContext erh¨lt.     a

protected void getIt

Diese Methode (oder eine entsprechende Methode einer Unterklasse) sollte uberladen
                                                                              ¨
werden. Sicherheitsabfragen und Callback-Handling werden somit automatisch von jeder von
VServlet 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
6.1   Das Packet com.varial.base                                                      83


Die Methode waitForCallback() wird zu Beginn eines Callback-Vorgangs vom BO auf-
gerufen. Das Servlet versetzt daraufhin den aktuellen Thread mit einem wait()-Aufruf in
einen wartenden Zustand. Wird der Callback beendet, wird die endCallback()-Methode
angestossen. Der wartende Thread wird mit der notify()-Anweisung wieder gestartet.

    Außerdem k¨nnen abgeleitete Klassen Methoden zur Weiterleitung von Anfragen nutzen.
                o
Mit 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 wird
einfach die Kontrolle an die angegebene URL ubergeben.
                                              ¨
Da die forward()-Methode vollst¨ndig auf dem Web-Server behandelt wird, ist sie schneller
                                  a
als ein Aufruf von sendRedirect(), bei dem Daten zus¨tzlich den Weg vom Web-Server
                                                        a
zum 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 anderen
URL behandelt wird.
Deshalb ist darauf zu achten, dass relative Pfadangaben u.U. nicht mehr korrekt sind und
ggf. angepasst werden m¨ssen.
                         u

   Die letzte Art, die Verarbeitung umzuleiten, besteht in der Verwendung der Methode
forwardToJsp().

protected void forwardToJsp (
    VContext ctx,
    String url
)

protected void forwardToJsp (
    VContext ctx,
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) alle
Komponenten 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                                              u
det, so kann diese mit der zweiten Methode mit ubergeben werden.
                                                ¨

    Generiert ein vom VServlet abgeleitetes Servlet einen Link, so muss die Session-ID auch
in diesem Link vorhanden sein (siehe HTTP-Sessions 5.3). Andernfalls w¨rde die Anfrage
                                                                              u
nicht mehr einer Session und damit einem Benutzer zuordbar sein. Resultat w¨re ein verwei-
                                                                                 a
gerter Zugriff, da der Benutzer, der die Seite anfordert, aus Sicht des Servlets nicht eingeloggt
w¨re.
  a
Um 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 werden
soll. Die Methoden liefern die Adresse zusammen mit der jeweiligen Session-ID zur¨ck.
                                                                                 u

6.1.2    VListServlet
Das VListServlet wurde vom VServlet abgeleitet und bildet wiederum eine Oberklasse f¨r  u
alle 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
                        a
Listenansicht ein hinreichendes Zeichen daf¨r ist, dass die Detailansicht verlassen wurde.
                                              u
Weiterhin wird uberpr¨ft, ob Benutzer-Ereignisse verarbeitet werden m¨ssen. Hierzu wird
                  ¨      u                                              u
zun¨chst die Methode catchOwnActionEvents() aufgerufen.
    a

protected boolean catchOwnActionEvents(VContext ctx)

Sollte ein Servlet uber die Standard-Men¨punkte hinaus noch weitere Funktionen definieren,
                   ¨                    u
so 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
                                    u
wie gewohnt fortgef¨hrt (z.B. bei redirect() auf neue Seite), muss der R¨ckgabewert true
                     u                                                  u
sein.
6.1     Das Packet com.varial.base                                                          85


Danach uberpr¨ft das VListServlet, ob ein Men¨-Ereignis vorliegt, also ob der Benutzer
         ¨     u                                      u
einen Standard-Men¨punkt angeklickt hat.
                     u
Die 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,
                 u
wird 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    VDetailServlet
Was das VListServlet f¨r die Listen-Ansicht ist, ist das VDetailServlet f¨r die Detail-
                          u                                                    u
Ansicht. 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                   a
wie Speichern, L¨schen, BO-Navigation etc. Es ist ebenfalls von VServlet abgeleitet und
                  o
uberl¨dt auch die Methoden doGet() bzw. doPost().
¨    a
Auch hier wird getestet, ob auf Benutzer-Ereignisse reagiert werden muss. Abgeleitete Servlets
k¨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 den
Benutzer 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
                    u
die 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
                  ¨                                 u
Dialog 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
           u
catchOwnActionEvents()-Parameter ubergeben, was anzeigt, dass der Benutzer bereits
                                   ¨
gewarnt wurde. Das VDetailServlet verarbeitet außerdem selbstst¨ndig alle weiteren
                                                                  a
Ereignisse, die von den GUI-Komponenten wie z.B. der Men¨-Leiste, von Button-Feldern
                                                        u
oder List-Boxen ausgel¨st werden.
                      o

   Damit das VDetailServlet einige Funktionen wie beispielsweise das L¨schen oder Spei-
                                                                      o
chern von BOs ubernehmen kann, m¨ssen die abgeleiteten Klassen die Funtionen fillBO()
              ¨                  u
und getBO() implementieren.
6.1     Das Packet com.varial.base                                                     86


protected 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.
 u
Beim 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, die
vom 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    VSelectServlet
Die Klasse VSelectServlet ist zust¨ndig f¨r den Entwurf von Auswahl-Dialogen. Entspre-
                                      a     u
chende Servlets sollten von ihr abgeleitet werden. Genau wie die Klassen VListServlet und
VDetailServlet ist VSelectServlet von VServlet abgeleitet und uberl¨dt die Methoden
                                                                     ¨    a
getIt() und postIt().
Die Klasse sorgt daf¨r, dass Abbr¨che durch den Cancel-Button automatisch zu einer Weiter-
                    u             u
leitung an das aufrufende Servlet f¨hren. Andernfalls werden die Methoden getItSelect()
                                    u
bzw. getItSelect() aufgerufen, die die Funktionalit¨t in der abgeleiteten Klasse implemen-
                                                     a
tieren sollten.

proteted void getItSelect (VContext ctx)

6.1.5    VChartServlet
Die Klasse VChartServlet ist ebenfalls von VServlet abgeleitet und dient zur Erstellung
von Diagrammen. Beim Aufruf durch doGet() oder doPost() wird ein Diagramm erstellt
und 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 der
Abzisse bzw. der Ordinate, die Methode getTitle() liefert den Titel des Diagramms.
Mit getXAxisLabels() k¨nnen die Abschnitts-Bezeichnungen auf der Abzisse angegeben wer-
                        o
den. Beispielsweise k¨nnte getXAxisTitle() “Zeit“ zur¨ckgeben und getXAxisLabels()
                     o                                 u
6.1     Das Packet com.varial.base                                                         87


einen String-Array mit den Monaten Jan“, Feb“, Mrz“, etc. liefern.
                                        ”       ”     ”
Um die Beschriftung der Datenreihen f¨r eine Legende anzugeben, muss die Funktion
                                           u
getLabels 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
                                                                                   a
Funktion getData()).
Mit der Funktion getData werden die eigentlichen Diagramm-Werte angegeben. Die Werteta-
belle wird als zweidimensionale Matrix von double-Werten angegeben. Die erste Dimension
steht hierbei f¨r die Datenreihe, die zweite f¨r die Werte.
               u                              u
Sollen z.B. die Sinus- und Kosinus-Funktion dargestellt werden, w¨re vereinfacht folgende
                                                                 a
Matrix n¨tig:
         o

double[][] 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:
             u

new String[] {"Sinus-Werte", "Kosinus-Werte"};

Mit den ubrigen Funktionen getWidth() und getHeight() kann die Gr¨ße des Bildes
         ¨                                                       o
angegeben werden. Die Angabe erfolgt in Pixel.

   Sollen bestimmte Farben f¨r die Darstellung der Balken verwendet werden, k¨nnen diese
                            u                                                o
mit 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            u
erwartet. Wird diese Methode nicht uberladen, w¨hlt VChartServlet selbstst¨ndig sich un-
                                   ¨           a                          a
terscheidende Farben aus.

6.1.6    VState
Die Klasse VState ist zust¨ndig f¨r die Ausgabe von Tabellen. Sie ist eine direkte Unterklasse
                          a      u
von VServlet und uberl¨dt die Methoden getIt() und postIt().
                   ¨    a
Um eine Tabelle anzuzeigen, muss diese als erstes in einem vom VServlet abgeleiteten Servlet
mit dem GuiHelper (6.3.1) erzeugt worden sein. Mit der Klasse VState wird diese nun gef¨llt,
                                                                                          u
verwaltet 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
                                                                u
um 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
                     a
Ausnahmef¨llen, z.B. wenn zuvor spezielle Methoden der Tabelle aufgerufen werden m¨ssen.
            a                                                                          u
6.1   Das Packet com.varial.base                                                        88


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

protected 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
                                                                                   a
Daten. Das abgeleitete Servlet muss also erst ein Casting vornehmen, um den richtigen Type
zu erhalten und kann dann die Tabelle mit deren Methode addRow() um die neuen Daten
erweitern.

    Um die Tabelle zu formatieren stehen eine ganze Reihe von Methoden zur Verf¨gung, die
                                                                               u
die 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 abgeleiteten
Klassen VListState (6.1.7), VDetailState (6.1.8) und VSelectState (6.1.9) festgelegt, so
dass 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 (also
auch auf unterschiedlichen Tabsheets) angezeigt werden, k¨nnen deshalb durchaus die selbe
                                                          o
ID haben. Wird die Methode nicht uberladen wird standardm¨ssig die ID grid verwendet.
                                  ¨                          a

public boolean isEditable(
    VContext ctx,
    int row,
    int col
)
6.1    Das Packet com.varial.base                                                         89


Gibt an, ob eine Tabellen-Zelle in der Reihe row und der Spalte col editierbar ist. Per
Standard ist sie dies nicht. Wird true zur¨ckgegeben, wird der Zelleninhalt in einem Textfeld
                                          u
angezeigt, 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          a

public 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
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,
                                                          a
was bedeutet, dass die Ausrichtung gem¨ß des Zellentypes erfolgt. Zahlen und W¨hrungen
                                       a                                        a
werden rechtsb¨ndig, Datumsangaben, Combo- und Radio-Boxen zentriert und alle anderen
               u
Inhalte linksb¨ndig ausgerichtet.
              u

public 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
              a
handelt.

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
                                                                                      a
denen man Zeilen f¨r den L¨schvorgang ausw¨hlen kann. Standardm¨ßing wird eine solche
                   u         o                   a                      a
Spalte nicht angezeigt.
6.1     Das Packet com.varial.base                                                        91


public String[] getHeaders(
    VContext ctx
)

Liefert die Spalten¨berschriften.
                   u

public int[] getColWidth(
    VContext ctx
)

Liefert die Spaltenbreite in Pixel. Wird diese Methode nicht uberladen, wird null zur¨ckgege-
                                                             ¨                       u
ben. Die Spaltenbreite wird dann optimal an die L¨nge der Eintr¨ge angepasst. Die Methode
                                                   a              a
sollte 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    u
wird. Die Methode gibt null zur¨ck, so dass folgende Werte bei neuen Zeilen eingetragen
                                 u
werden: Check- und Radio-Boxen sind deaktiviert, bei Datumsfeldern wird das aktuelle
Datum eingetragen, alle anderen Felder sind leer. Sollen sich die Zellen von neu eingef¨gten
                                                                                       u
Spalten 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
            a
W¨hrungsfeld handelt. Der Zelleninhalt wird gem¨ß den W¨hrungseigenschaften (Nachkom-
  a                                            a        a
mestellen, Rundungsverfahren, W¨hrungszeichen etc.) formatiert. Standardm¨ssig liefert die
                                a                                        a
Methode die Hausw¨hrung der aktuellen Firma.
                  a

6.1.7    VListState
Die Klasse VListState wurde von VState abgeleitet. Alle Servlets, die f¨r die Bearbeitung
                                                                         u
von Tabellen in der Listenansicht zust¨ndig sind, sollten wiederum von dieser Klasse abge-
                                         a
leitet 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
                                                                                      a
werden.
6.1     Das Packet com.varial.base                                                       92


6.1.8    VDetailState
VDetailState ist ebenfalls von VServlet abgeleitet und ist f¨r Tabellendarstellung in der
                                                               u
Detail-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
                                                    ¨                          u
die meisten Tabellen in der Detail-Ansicht eine L¨schfunktion besitzen und dementsprechend
                                                  o
eine Auswahlspalte brauchen.
Als letzte Methode enth¨lt die Klasse die zus¨tzliche Hilfs-Methode getCellName().
                         a                    a

protected String getCellName (int row, int col)

Mit Hilfe dieser Methode k¨nnen abgeleitete Klassen den Namen von Formularfeldern aus
                            o
der Tabelle erfragen. Hat eine Tabelle z.B. die ID mygrid wird der Wert der Zelle in der 3
Zeile und 5 Spalte als mygrid 2 4 im Query-String ubertragen. Genau diese Angabe liefert
                                                    ¨
die Methode.

6.1.9    VSelectState
Auch die Klasse VSelectServlet wurde von VServlet abgeleitet. Genau wie VListState
und VDetailState uberl¨dt auch sie die Methode getStyle(). Diese gibt hier die Infor-
                     ¨    a
mation zur¨ck, dass die Tabelle in einem Auswahl-Dialog Verwendung findet. Dementspre-
           u
chend sollten alle Servlets, die f¨r Tabellen in solchen Auswahldialogen zust¨ndig sind, von
                                  u                                          a
VSelectState ableiten.
Außerdem uberl¨dt die Klasse die Methode getGrid(). Hier wird im Gegensatz zur Super-
           ¨     a
klasse VState nicht nur eine neue Instanz einer Tabelle zur¨ckgeliefert, sondern es werden
                                                             u
noch die Methoden setBackURI() und addQueryString aufgerufen. Dies ist notwendig, weil
eine Tabelle in der Auswahl-Ansicht Links auf das aufrufende Servlet enth¨lt. Diese Links
                                                                            a
werden u.a. mit diesen beiden Methoden konstruiert.

6.1.10    VContext
Das VContext-Objekt ist zentraler Bestandteil der VWE-Web-Architektur. Es erm¨glicht es,
                                                                              o
auf einfache Weise auf alle f¨r die Anwendung relevanten Daten zuzugreifen. So stellt der
                             u
VContext beispielsweise Methoden f¨r das Parameter-Handling zur Verf¨gung, kontrolliert
                                    u                                u
den Zugriffsschutz auf Daten oder koordiniert den Callback-Mechanismus (5.5).
Beim Aufruf eines VServlets (6.1.1) wird automatisch ein VContext erzeugt. Dieser wird
dann an die entsprechende Methode zur Verarbeitung einer Anfrage weitergegeben.

Erzeugen eines VContexts Die Klasse VContext stellt zwei Konstruktoren zur Verf¨gung.
                                                                                  u
Im Normalfall sollte eine Instanz mit dem dreiparametrigen Konstruktor erzeugt werden:

public VContext(
    HttpServlet servlet,
    HttpServletRequest req,
    HttpServletResponse res
)
6.1    Das Packet com.varial.base                                                          93


¨
Ubergeben wird neben dem aufrufenden Servlet das Request- und das Response-Objekt. Der
Konstruktor initialisiert darauf hin alle n¨tigen Objekte, um sp¨ter auf Cookies, Parameter,
                                           o                    a
Session- und Request-Attribute zugreifen zu k¨nnen.
                                                o
Der 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 entsprechenden
Methoden f¨r das Verarbeiten der Anfragen weitergegeben.
           u
Der zweite Konstruktor erwartet nur einen Parameter, n¨mlich ein HttpSession-Objekt:
                                                          a

public VContext (HttpSession session)

Dieser Konstruktor sollte ausschließlich in Ausnahmef¨llen aufgerufen werden, in denen auf
                                                        a
keine andere Weise ein Zugriff auf ein VContext-Objekt m¨glich ist. Ein VContext, der auf
                                                           o
diese Weise erzeugt wurde, kann nur f¨r den Zugriff auf Session-Attribute verwendet werden.
                                       u
Eine 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
                            o
werden, kann hier der Notfall-Konstruktor verwendet werden. Eine solche Verwendung sollte
jedoch stets die Ausnahme bleiben.

Attribute-Handling Der VContext erm¨glicht es, auf einfache und einheitliche Weise, auf
                                        o
Attribute zuzugreifen. So k¨nnen Informationen auf folgenden Bereichen verarbeitet werden:
                            o
session-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, definiert
die 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
                                                            a
Parameter mehrmals im Query-String vorkommen kann. PARAMETER liefert in diesem Fall
den 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
)
6.1   Das Packet com.varial.base                                                        94


Sie erwartet als ersten Parameter eine Angabe dar¨ber, woher das Attribute gelesen werden
                                                 u
soll. Hierzu dienen die bereits beschriebenen Konstanten. Als zweiter Parameter wird der
Name 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
                                                     u
nicht gefunden wurde. Wird ein unbekannter Bereich ubergeben, wirft getAttribute() eine
                                                   ¨
VException (6.1.14).
Weiterhin kann mit der Methode hasAttribute() abgefragt werden, ob ein entsprechendes
Attribute vorhanden ist:

public boolean hasAttribute(
    int scope,
    String name
)

Der Aufruf liefert true, falls ein Attribute mit dem angebenen Namen im entsprechenden
Bereich existiert, andernfalls false.
Außerdem kann mit hasNonEmptyAttribute() abgefragt werden, ob ein Attribute existiert
und 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 entsprechenden
Bereich existiert und dieses kein Leerstring ist, andernfalls false.
Um nicht jedesmal die Existenz eines Attributes zu uberpr¨fen und auf ein Fehlen entspre-
                                                      ¨       u
chend zu reagieren, bietet der VContext ebenfalls eine getAttribute()-Methode, die bei
erfolgloser Suche einen Standardwert zur¨ckgibt. Sie erwartet zus¨tzlich zur oben genannten
                                          u                        a
Methode 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      a
muss lediglich ein Casting in den entsprechenden Typ stattfinden.
H¨ufig m¨ssen Objekte des Typs String gelesen werden.
 a       u

String lastVisitCookie = (String)ctx.getAttribute(VContext.Cookie, "Last visit");
6.1   Das Packet com.varial.base                                                       95


Um diesen Aufruf zu vereinfachen, stellt der VContext eine spezielle Methode
getStringAttribute() zur Verf¨gung:
                             u

public 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 ein
boolean zur¨ckgibt. Auch diese drei Methoden k¨nnen mit einem dritten Parameter
             u                                    o
aufgerufen werden, der den Default-Wert angibt.
Die Methoden getDateAttribute() und getCurrencyAttribute() lesen ein Attribut und
formatieren es anschließend in einen f¨r den CORBA-Aufruf geeignetes Textformat, liefern
                                      u
also einen String zur¨ck.
                     u
Lautet 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-
                                                                    o
de wird beim Speichern eines Cookies immer der R¨ckgabewert der Methode getString()
                                                    u
gespeichert.
Sowohl Query-String- als auch Initialisierungs-Attribute k¨nnen nicht geschrieben werden.
                                                            o
Hier 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       o
dient die Funktion removeAttribute():
6.1   Das Packet com.varial.base                                                         96


public void removeAttribute(
    int scope,
    String name
)
Der VContext bietet neben diesen Methoden noch die M¨glichkeit, auf spezielle Parameter
                                                        o
zuzugreifen. So kann z.B. mit hasChanged() abgefragt werden, ob der Parameter changed
gesetzt wurde.
Tabelle 1 zeigt, welche Methoden welche Parameter abfragen. Da diese Methoden oft zus¨tz-
                                                                                     a
lich Konsistenzbedingung pr¨fen oder auf Fehler reagieren, sollten sie stets der direkten
                             u
Attribute-Abfrage vorgezogen werden.

    F¨r das Arbeiten mit dem Query-String einer Anfrage stellt die Klasse zwei weitere Funk-
     u
tionen zur Verf¨gung.
               u
public 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,
                                                                                      a
die dem Servlet zu Beginn uber den Men¨baum mitgegeben wurden. VWE erlaubt es im
                           ¨             u
Administrationsmodus 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-
                                             u
te. Dazu wird nach erfolgreicher Anmeldung des Benutzers von dem Servlet
com.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-Objekt
ubergeben werden. Das BO wiederum erh¨lt mit getAccessToken() das n¨tige AccessToken
¨                                    a                             o
f¨r den Server-Aufruf.
 u

    Um zu uberpr¨fen, ob die Seite, von einem eingeloggten Benutzer angefordert wurde, wird
          ¨     u
die Methode checkLogin() aufgerufen.
public void checkLogin()
throws
    AccessDeniedException,
    IOException
Sollte der Benutzer nicht eingeloggt sein, wird eine AccessDeniedException() geworfen und
der Zugriff verweigert. Das VServlet (6.1.1) ruft diese Methode automatisch auf, so dass kein
explizieter Aufruf erforderlich ist.
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
6.1   Das Packet com.varial.base                                                          98


BO-Navigation Der Benutzer kann in der Detail-Ansicht mit der Men¨leiste von einem
                                                                      u
BO zum n¨chsten springen. Der VContext beinhaltet die daf¨r n¨tigen Funktionen. Zuerst
          a                                                u o
m¨ssen alle BOs registriert werden. Dazu dient die Methode registerBos():
 u
public void registerBos (
    String oidParent,
    BO[] bos
)
Der erste Parameter gibt die ObjectID des Parent-Objekts an, also das Objekt, zu dem die
BOs geh¨ren. In der Regel ist das die Firma, beim TaskReminder ist dies jedoch beispielsweise
        o
der 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
                a
minimiert werden:
public void registerBos (BO[] bos)
Neue BOs k¨nnen mit addBo() der BO-Liste hinzugef¨gt werden. Das neue BO reiht sich
          o                                      u
am 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 bei
registerBO() 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)
6.1   Das Packet com.varial.base                                                           99


Callback 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-
                                                               u
Funktionen, von denen hier die wichtigsten aufgef¨hrt werden.
                                                 u

public CompanyShortBO getCompany()

Dies liefert die Firma, die zur Zeit ausgew¨hlt ist. Die Funktion sucht zuerst in der Session.
                                           a
Sollte dort keine Firma gefunden werden (dies ist der Fall, wenn der Benutzer sich neu
einloggt), wird nach einem Cookie mit der ObjectID der Firma gesucht. Wird ein solcher
Cookie gefunden, wird die Firma mit der ObjectID vom Server angefordert. Sollte jedoch
kein Cookie gefunden werden, oder ist die Firma seit Erstellung des Cookies gel¨scht worden,
                                                                                o
wird einfach die erste Firma aus der Datenbank zur¨ckgegeben.
                                                      u

public 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       a

public LanguageBO getLanguage()

Mit Hilfe dieser Funktion kann die eingestellte Sprache abgefragt werden. Gesucht wird zuerst
in der Session. Ist die Suche erfolglos, wird die Default-Sprache vom Server zur¨ckgegeben.
                                                                                u

public AdminUserBO getUser()

Liefert den eingeloggten Benutzer.
6.1   Das Packet com.varial.base                                                        100


6.1.11   Instance
Die Klasse Instance ist lediglich dazu da, auf Initialisierung-Parameter, also Parameter
der Datei web.xml zuzugreifen. Sie ist als Singleton implementiert, so dass immer nur eine
Instanz der Klasse erzeugt werden kann. F¨r den Zugriff auf Initialisierungsparameter dienen
                                          u
die 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 benutzt
sie die Klasse VContext (6.1.10), die die selbe Funktionalit¨t mit dem Befehl
                                                            a
getAttribute(VContext.INIT, name) besitzt.

6.1.12   BO
Die Klasse BO dient als gemeinsame Oberklasse aller Businsess-Objekte (5.4). Als Methoden
stellt sie zur Verf¨gung:
                   u

protected ObjectStruct getOidTs()

Diese Methode liefert den ObjektStruct des BOs. Wird sie nicht uberladen, wird eine neue
                                                               ¨
Instanz einer ObjectStruct zur¨ckgegeben.
                               u

public String getObjectID()

public String getTimeStamp()

public String getLastUserID()
                                                             ¨
Hiermit k¨nnen die ID des BOs, Datum und Uhrzeit der letzten Anderung und der Benutzer,
         o
der das BO als letztes ver¨nderte, angefragt werden.
                          a

public 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 es
in 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
                 o
sie die selbe ObjectID besitzen. Die ObjectID wird vom CORBA-Server vergeben, sobald das
BO in der Datenbank gespeichert wurde. Folglich ist darauf zu achten, dass zwei neue BOs
immer als identisch gelten!
6.1   Das Packet com.varial.base                                                         101


protected 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
 o
VContext 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 des
Web-Servers schreiben k¨nnen.
                         o

protected static void log (String msg)

protected static void log (String msg, Throwable throwable)

6.1.13   VBean
Die Klasse dient als Oberklasse aller f¨r VWE-Web entwickelten Beans.
                                         u
Sie stellt als einzige Funktionalit¨t die Methode isFirstOneOfClass() zur Verf¨gung.
                                   a                                          u

protected boolean isFirstOneOfClass()

Mit Hilfe dieser Methoden kann festgestellt werden, ob es sich bei einem Objekt um die erste
erzeugte Instanz seiner Klasse handelt. Dies ist beispielsweise notwendig, bei der Verwendung
von 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              u
werden, wenn tats¨chlich Tabsheets verwendet werden. Werden nun mehrere Tabsheets auf
                   a
einer Seite verwendet, darf trotzdem jedes Feld nur einmal vorkommen. Alle Tabsheets teilen
sich dann diese Felder.
W¨rde jedes Tabsheets diese versteckten Felder erneut erzeugen, w¨rde dies zu JavaScript-
   u                                                                  u
Fehlern f¨hren. Zur L¨sung dieses Problems schreibt ausschließlich die erste Instanz die Fel-
          u           o
der.
Bei Verwendung der Methode wird also nur beim ersten Methodenaufruf true zur¨ckgegeben;
                                                                                   u
alle weiteren Aufrufe erzeugen false als R¨ckgabewert.
                                            u

6.1.14   VException
Bei der Klasse VException handelt es sich um eine Unterklasse von Exception, genauer
                                           ¨
gesagt von der Klasse RuntimeException. Uberall, wo Programmfehler auftauchen, auf die
nicht passend reagiert werden kann, wird eine VException erzeugt und geworfen. Das ver-
arbeitende Servlet kann diese dann ggf. behandeln oder einfach als Fehlermeldung an den
Benutzer 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 komplett
neue VException erzeugt werden.
6.1   Das Packet com.varial.base                                                     102


Soll 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: Eine
Dom¨ne, eine Fehlerbezeichnung und eine Fehlernummer. Die Dom¨ne gibt an, in welchem
     a                                                           a
Programm-Packet der Fehler auftrat, die Bezeichnung gibt an, was f¨r ein Fehler auftrat
                                                                   u
und die Fehlernummer dient dazu, den Fehler eindeutig in der Dom¨ne zu identifizieren. Mit
                                                                a
diesen drei Angaben ist es auch m¨glich, Fehlermeldungen mit dem Translator (6.2.1) in
                                    o
die 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
                                              u
getOriginalException().

public Throwable getOriginalException()

F¨r den zweiten Fall gibt es hingegen folgenden Methoden:
 u

public String getDomain()

public String getWhat()

public int getErrorNumber()

   Um zu unterscheiden, auf welche Art eine VException erzeugt wurde, steht der Befehl
hasOriginalException() zur Verf¨gung.
                                u

public boolean hasOriginalException()

Wurde eine vorhandene Exception mit einer VException verpackt“ liefert er true, andern-
                                                       ”
falls wird false zur¨ckgegeben.
                    u
Sehr h¨ufig vorkommende Fehler sind die von VWE verwendeten Exceptions
         a
vom Typ PersistencyException, DomainException, AccessDeniedException und
ApplicationLayerException. Um abzufragen, ob es sich bei der VException um einen der
aufgef¨hrten Typen handelt dienen folgende Funktionen:
       u

public boolean isPersistencyException() {

public boolean isAccessDeniedException() {
6.1   Das Packet com.varial.base                                                       103



public 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,
                                                 u
sondern 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                                      ¨     u
VExpeptions sind gleich, wenn Dom¨ne und Fehlernummer ubereinstimmen.
                                   a                      ¨

6.1.15   TempData
Die Klasse TempData erm¨glicht es, BOs tempor¨r zwischenzuspeichern. Dies ist u.a. notwen-
                          o                     a
dig, 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
                                                             u
in der Datenbank persistent gemacht werden. Die Klasse TempData verwendet die aktuelle
              ¨
Session, um Anderungen zu behalten. Hierzu wird eine Hashtable angelegt. Die URLs der
Seite bilden die Schl¨ssel, denen das zu speichernde BO zugeordnet ist.
                     u
Die Klasse bietet drei Arten von Funktionen: BOs k¨nnen gespeichert und geladen werden.
                                                     o
Außerdem k¨nnen BOs aus dem Speicher entfernt werden.
             o
Um 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
6.1   Das Packet com.varial.base                                                       104


ubergeben 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                        u
den.

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
                                                                         u
werden.
Gespeicherte BOs k¨nnen verworfen werden, indem die Methode resetBO() aufgerufen wird.
                  o

public static void resetBO (VContext ctx)

public static void resetBO (
    VContext ctx,
    String uri
)

6.1.16   AbstractCallback
Die Klasse AbstractCallback ist eine abstrakte Oberklasse f¨r alle Callbacks. Bei Verwen-
                                                            u
dung des Callback-Mechanismuses (5.5) sollte die Callback-Klasse hiervon abgeleitet werden.
Die Klasse besitzt einen Konstruktor:

protected AbstractCallback (
    VContext ctx,
    VState state
)
throws
    AdministrationException

Neben dem VContext-Objekt muss ein passender VState (6.1.6), also eine Klasse, die f¨r die
                                                                                    u
Ausgabe der Tabelle zust¨ndig ist, ubergeben werden. Der Konstruktor sorgt nach Aufruf f¨r
                         a         ¨                                                    u
eine Verbindung mit dem ORB und startet einen Thread der Klasse VListStateThread, der
im folgenden auf eingehenden Daten wartet. In Analogie zum Erzeuger-Verbraucher-Problem
stellt 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 VListStateThread
abgefragt wird, benachrichtigt den Thread dar¨ber, dass neue Daten vorliegen und wartet
                                              u
auf neue Daten vom Server. Die Klasse stellt somit den Erzeuger im Erzeuger-Verbraucher-
Modell dar.
6.1   Das Packet com.varial.base                                                     105


AbstractCallback und VListStateThread laufen asynchron, so dass der CORBA-Server
beim Liefern der Daten nicht auf die Darstellung der Tabelle warten muss.
Die bereits ubertragenen Daten k¨nnen mit der Funktion getCollectedData() abgefragt
            ¨                     o
werden.

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()
                                  u
aufgerufen.

public void finished()

Diese Methode beendet den VListStateThread, dieser ruft zuvor noch die Methode
disconnect() auf, die den Callback wieder vom ORB entfernt.

public final void disconnect()
throws
    AdministrationException

Als 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ßend
geworfen. Das aufrufende Servlet kann dann entsprechend reagieren.
Wie bereits erw¨hnt, werden Callback-Klassen von AbstractCallback abgeleitet. Durch die-
                a
se Vererbung besitzen sie schon die oben aufgef¨hrten Funktionen. Damit diese Funktionen
                                               u
aber in einer solchen Oberklasse zusammengef¨hrt werden k¨nnen, m¨ssen die abgeleiteten
                                             u             o       u
Klassen 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-
                        a
zifiziert werden k¨nnen.
                 o

6.1.17   VListStateThread
Die Klasse VListStateThread implementiert einen Thread der beim Callback-Mechanismus
im Hintergrund l¨uft, auf Daten wartet und diese dann zur Darstellung an den passenden
                 a
VState (6.1.6) weitergibt. Sie sorgt also daf¨r, dass der CORBA-Server auf der einen und
                                             u
der VState auf der anderen Seite asynchron zusammenarbeiten.
Beide Parteien (AbstractCallback als Repr¨sentant des CORBA-Servers und VListState
                                             a
als Client) werden im Konstruktor ubergeben:
                                   ¨
6.1   Das Packet com.varial.base                                                        106


protected 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, versetzt
sich der Thread mit dem Befehl wait() solange in einen wartenden Zustand, bis er von
AbstractCallback wieder geweckt“ wird. Dies wiederholt sich solange, bis die Methode
                            ”
finished() des Callbacks aufgerufen wird, die ihrerseits den Thread beendet.

6.1.18   ExceptionHelper
Der ExceptionHelper stellt als einzige Funktionalit¨t die statische Methode
                                                   a
handleException() bereit. Mit ihr k¨nnen dem Anwender Exceptions als Fehlermel-
                                      o
dungen 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     ¨    u
diese eine eingepackte“ Exception enth¨lt. Ist dies der Fall, wird diese angezeigt.
                                       a
           ”

6.1.19   StringMapper
Die Klasse StringMapper beinhaltet statische Methoden, die bei der Verarbeitung von
Strings (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. Diese
Methode 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 zu
wandeln, steht die Methode nullToEmpty() zur Verf¨gung.
                                                    u

public static String nullToEmpty (String txt)
6.1   Das Packet com.varial.base                                                       107


6.1.20   VCurrency
Die Klasse VCurrency dient dazu, W¨hrungsangaben aus der Datenbank f¨r die Bildschir-
                                    a                                     u
mausgabe zu formatieren, bzw. um solche Angaben wieder zur¨ck ins Datenbankformat zu
                                                              u
wandeln.
Um Werte aus der Datenbank f¨r die Bildschirmdarstellung zu formatieren, kann die statische
                            u
Methode 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
                                                                         a
formatierenden Betrag. Bei der ersten Methode wird der Betrag gem¨ß der Hausw¨hrung der
                                                                 a           a
aktuellen Firma formatiert, w¨hrend beim zweiten Funktionsaufruf eine W¨hrung expliziet
                             a                                            a
angegeben werden kann. Die Ausgabe erfolgt gem¨ß Sprach- und W¨hrungseinstellung.
                                                   a                   a
Das bedeutet, der zur¨ckgegebene String besteht aus gruppierten Tausendern, wird
                       u
entsprechend der W¨hrungseinstellung gerundet und besitzt das passende W¨hrungssymbol.
                    a                                                      a
Soll kein W¨hrungssymbol angehangen werden, kann alternativ die Methode
               a
getViewCurrencyWithoutCurrencyCode() verwendet werden, die ebenfalls in zwei
Ausf¨hrungen mit den oben genannten Parametern existiert.
     u
Bevor W¨hrungsangaben wieder in der Datenbank gespeichert werden k¨nnen, m¨ssen sie in
         a                                                           o       u
ein 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
                    a
zu formatierende Betrag und optional eine W¨hrung angegeben.
                                           a
Abschließend zeigt Tabelle 2 einige Beispiele f¨r korrekte Formatierungen. Es wird die
                                               u
Datenbank-Angabe 123456.789“ in die folgenden W¨hrung formatiert:
                                                  a
                   ”
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                        a



6.1.21 VNumber
Die Klasse VNumber dient einer ¨hnlichen Verwendung wie VCurrency (6.1.20), allerdings
                                 a
werden hier lediglich Zahlen und keine W¨hrungsangaben formatiert.
                                        a
public 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
                             o
VCurrency (6.1.20) k¨nnen Datenbank-Angaben f¨r die Bildschirmausgabe formatiert werden
                    o                        u
bzw. diese wieder zur¨ckgewandelt werden.
                     u
public static String getViewDate(
    VContext ctx,
    String date
)

public static String getDBDate(
    VContext ctx,
    String date
)
6.1   Das Packet com.varial.base                                                     109


Mit 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 werden
kann.
           o                              ¨
Weiterhin k¨nnen sog. Timestamps, die das Anderungsdatum eines BOs angeben, f¨r die Bild-
                                                                             u
schirmausgabe aufbereitet werden. Die Funktion getViewTimeStamp() leifert hierf¨r einen
                                                                                u
passenden String zur¨ck.
                     u

public static String getViewTimeStamp (
    VContext ctx,
    String timestamp
)

Außerdem k¨nnen diverse Datumsberechnungen mit der Klasse VDate durchgef¨hrt werden.
             o                                                          u
So 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 folgenden
Methoden:

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
6.2     Das Packet com.varial.translation                                                110


diesen beiden Datumsangaben liegen. Auch eine Vorw¨rtsrechnung ist m¨glich. Auf diese
                                                    a                  o
Weise kann ein Datum bestimmt werden, das eine gewisse Zeitspanne nach einem gegebenen
Datum 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 ist
m¨glich. In diesem Fall werden das Zeitintervall abgezogen. Zur¨ckgegeben wird das berech-
  o                                                            u
netete Datum im Datenbankformat.

6.2 Das Packet com.varial.translation
                                                                  ¨
Das Packet com.varial.translation beinhaltet Klassen, die f¨r die Ubersetzung aller angezeig-
                                                           u
ten Texte zust¨ndig sind.
              a

6.2.1    Translator
                                             ¨
Die Klasse Translator stellt Methoden zur Ubersetzung von Texten zur Verf¨gung. Um
                                                                         u
einen 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“
                               ¨
                                                             ”
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
                                                                           ¨
        soll

Damit man nun einen ubersetzten Text erh¨lt, gibt es zwei M¨glichkeiten.
                     ¨                   a                  o
paragraphM¨glichkeit 1 Es wird zun¨chst eine Translator-Instanz mit dem Konstruktor, der
            o                     a
die 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-
       o
fragt 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().
 o

public static String getCaption(
    VContext ctx,
    String module,
    String parent,
    String component
)

public static String getHint(
    VContext ctx,
    String module,
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    TranslatorCache
Diese 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-
                                                  a
artet werden, um den Cache zu l¨schen.
                                  o

6.3 Das Packet com.varial.gui
Das Packet com.varial.gui umfasst s¨mtliche Klassen, die f¨r die Erstellung von grafischen
                                   a                      u
Benutzeroberfl¨chen zust¨ndig sind.
             a          a

6.3.1    GuiHelper
Der GuiHelper besitzt eine Reihe von statischen Methoden, mit denen auf einfache Weise
Web-Oberfl¨chen zusammengestellt werden k¨nnen. Es handelt sich hierbei um eine Factory-
            a                               o
Klasse, einem Entwurfsmuster, das f¨r die Erzeugung von Objekten zust¨ndig ist. Das heißt
                                   u                                    a
im Detail, dass GUI-Klassen nie direkt instanziiert werden, sondern dass die Factory-Klasse
dies durch seine statischen Methoden erledigt.
Mit dem GuiHelper werden GUI-Elemente erzeugt und in dem Request-Objekt, also in der
Seitenanfrage, abgelegt. Eine JSP-Seite kann die Objekte sp¨ter auslesen und entsprechend
                                                             a
ausgeben.
Eine Oberfl¨chenkomponente besteht i.d.R. aus einer sprachabh¨ngigen Beschriftung (Label),
            a                                                  a
einem Feld f¨r Eingabe und einem Wert, der in diesem Feld steht. Außerdem besitzen die
              u
meisten Komponenten einen Namen, mit denen eine eindeutige Identifizierung m¨glich ist.
                                                                                o
Die 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
6.3    Das Packet com.varial.gui                                                            113


den 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 Sprache
ubersetzt.
¨
Unter Umst¨nden ist es notwendig, eine erzeugte Komponente nachtr¨glich zu ¨ndern. Bei-
             a                                                            a         a
spielsweise k¨nnte ein Textfeld erzeugt werden, dass unter bestimmten Bedingungen aktiviert
             o
bzw. deaktiviert ist. Ein Servlet m¨chte folglich nicht nur ein Textfeld erzeugen, sondern es im
                                   o
Anschluss auch noch ver¨ndern. In diesem Beispiel also deaktivieren. Damit solche Aktionen
                          a
m¨glich sind, liefern alle Methoden der GuiHelper-Klasse das erzeugte Objekt zur¨ck.
  o                                                                                   u
Damit 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 in
den 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,
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                      a
ubergeben werden.
¨
allowFloat gibt an, ob auch Flieskommazahlen erlaubt sind, allowNegative gibt an, ob
negative Eingaben m¨glich sind. Werden die Parameter nicht angegeben, ist beides, also
                    o
negative und Kommazahlen, m¨glich.
                             o

      Erzeugen eines Datumfeldes (6.3.6):
public static LabeledDateField addDateField(
    VContext ctx,
    Translator translator,
    String name,
    String label,
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):
                      a

public 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                                                         a
ubergeben, 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                                                                  a
Firma 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,
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
     a
werden, gibt es hier noch einen Parameter href, der angibt, was bei einem Klick auf den
Button geschehen soll. Es kann sich hierbei um einen Verweis auf eine HTML-Seite, eine
JavaScript-Anweisung oder alle sonstigen Angaben handeln, die im href-Attribute des
HTML-a-Tags stehen d¨rfen.
                         u
Bei der zweiten Methode kann zus¨tzlich angegeben werden, ob der Feldinhalt vom An-
                                     a
wender 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
                                                                         o
Parameter auf true gesetzt wird.
Die dritte Methode wird verwendet, wenn der Inhalt des Feldes im Browser darstellbar
ist. Beispiele hierf¨r w¨ren eine Homepage-URL oder eine Mail-Adresse. Solche Felder sind
                    u a
grunds¨tzlich direkt editierbar, ein Klick auf den Button ¨ffnet die angegebene Seite bzw.
       a                                                   o
sendet eine Mail an die angegebene Adresse. Als zus¨tzlichen Parameter muss ein Zielfenster
                                                    a
angegeben werden, in dem die neue Seite ge¨ffnet werden soll.
                                            o

      Erzeugen einer Check-Box (6.3.9):
public static LabeledCheckBox addCheckBox(
    VContext ctx,
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
                                        ¨                            a
Elementen definiert. Zum Beispiel k¨nnte der JavaScript-Code angeben, dass einige Felder
                                     o
nur dann editierbar sein sollen, wenn die Check-Box aktiviert ist. N¨heres hierzu findet man
                                                                    a
bei 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 Eintrag
selektiert werden kann. Radio-Buttons sind immer in Gruppen zusammengefasst, wobei
jeweils nur ein Eintrag der Gruppe ausgew¨hlt sein kann. Aus diesem Grunde erwarten die
                                         a
Methoden im Gegensatz zu den Methoden f¨r die Erzeugung von Check-Boxen auch noch
                                           u
6.3    Das Packet com.varial.gui                                                      118


den 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 aus
mehreren Eintr¨gen. Folglich wird hier nicht ein Wert f¨r das Feld, sondern eine Liste von
                a                                      u
Werten ubergeben. Optional kann der Index des selektierten Objekts angegeben werden. Die
        ¨
Combo-Box zeigt dann den entsprechenden Wert. Andernfalls wird der erste Eintrag der
Liste 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,
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 editierbare
statt 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
)
6.3   Das Packet com.varial.gui                                                     120



public 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
                                                                  a
hier 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 Liste
anzuzeigen. Eine Selektion ist hier gar nicht erw¨nscht. Nun w¨rde beim Senden kein Wert
                                                 u            u
6.3    Das Packet com.varial.gui                                                        121


ubertragen, die Liste w¨re also scheinbar leer. Um dies zu verhindern, muss der List-Box
¨                        a
eine sog. Schl¨sselliste gesetzt werden. Eine solche Schl¨sselliste wird auf jeden Fall beim
               u                                          u
Absenden des Formulars ubertragen. Zeigt die List-Box z.B. eine Liste von BOs, w¨ren die
                           ¨                                                        a
IDs der BOs eine sinnvolle Schl¨sselliste.
                                 u
In einer List-Box kann ein, kein oder viele Eintr¨ge ausgew¨hlt sein. Wird ein Parameter
                                                   a          a
selectedIndex 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.
                                                       a
Unter Umst¨nden kann es sinnvoll sein, die List-Box mit gewissen Funktionalit¨ten auszu-
             a                                                                   a
statten. Beispiele hierf¨r ist die M¨glichkeit, einen Eintrag hinzuzuf¨gen bzw. zu l¨schen.
                        u           o                                  u             o
Da HTML keine PopUp-Men¨s unterst¨tzt, m¨ssen solche Funktionen als Icons unterhalb
                               u         u       u
der 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, sondern
einen VState (6.1.6), der f¨r die Behandlung der Tabelle zust¨ndig ist. Sollte die Tabelle
                           u                                  a
keine Beschriftung haben (dies ist oftmals der Fall, wenn die Tabelle das einzige Element
einer Tabsheet ist. Dann beschreibt die Tabsheet-Bezeichnung auch die Tabelle), kann auf
die 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 (
6.3    Das Packet com.varial.gui                                                         122


       VContext ctx
)
Die erste Methode erstellt eine Suchfeld, also ein Textfeld, in dem ein Suchbegriff eingegeben
werden 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 zweite
Methode erstellt einen Button, mit dem der Auswahlvorgang abgebrochen werden kann. Die
letzte Methode dient dazu, sowohl einen Best¨tigungs- als auch einen Abbruch-Button zu
                                                 a
erstellen.

      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          a
der Anwender bei Best¨tigungen die Wahl zwischen zwei Optionen (ja oder nein) hat,
                       a
werden 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     a
anzuzeigende 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.
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.
                                                       u
Diese wird analog zu der Label-Angabe der anderen GUI-Komponenten behandelt. Die URL
gibt 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    VGuiBean
Alle beschrifteten GUI-Elemente sind von der Klasse VGuiBean abgeleitet. Auf diese Wei-
se besitzen alle Elemente bereits einige wichtige Attribute bzw. Methoden. Alle Attribute
beschreiben bestimmte Eigenschaften einer GUI-Komponente und k¨nnen mit ¨ffentlichen
                                                                    o           o
Setter-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)
6.3   Das Packet com.varial.gui                                                       124



public 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
      u
die Ober߬che dynamisch anzupassen. Als Beispiel wird angenommen, es existiere eine
           a
Check-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 mit
der Eigenschaft interdependence eine Abh¨ngigkeit zwischen Check-Box und Textfeld
                                              a
beschrieben 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 der
Name des Textfeldes. Man erh¨lt JavaScriptCode, der daf¨r sorgt, dass das Textfeld f¨r die
                               a                           u                        u
Adresseneingabe solange deaktiviert ist, bis die Check-Box angew¨hlt wurde. Dieser Code
                                                                   a
muss nun nur noch der Check-Box als Eigenschaft ubergeben werden.
                                                    ¨
Zusammen mit dem JavaScriptHelper bietet die Eigenschaft interdependence also die
M¨glichkeit, einfache Abh¨ngigkeiten zwichen beliebig vielen Elementen zu definieren.
  o                       a
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
6.3     Das Packet com.varial.gui                                                        126


   Neben den Eigenschaften f¨r abgeleitete Klassen bietet die VGuiBean auch drei Hilfsme-
                            u
thoden.

protected void writeLabel (Writer out) throws IOException

protected StringBuffer getNameIdAndTabIndex()

protected StringBuffer getWidthAndHeight()

Der ersten wird eine Instanz der Klasse Writer ubergeben. Daraufhin wird HTML-Code f¨r
                                               ¨                                     u
die Beschriftung der aktuelle Komponente erzeugt. Die zweite Methode kann von abgelei-
teten Klassen aufgerufen werden, um die HTML-Attribute name, id und tabindex aus den
Komponenten-Eigenschaften zu erzeugen. Die letzte Methode getWidthAndHeight() kon-
struiert Style-Sheet-Angaben f¨r die Gr¨ße der Komponente.
                               u        o
Zur 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    LabeledTextField
Die Klasse LabeledTextField stellt ein beschriftetes Textfeld dar.
Oberklasse ist VGuiBean (6.3.2). Zus¨tzlich k¨nnen der Klasse folgende Eigenschaften gesetzt
                                    a        o
werden:

public void setValue (String value)

public void setMaxlength (int maxlength)

    Die Eigenschaft value gibt den Wert an, der als Inhalt in dem Textfeld eingetragen werden
soll. Maxlength legt die maximale Anzahl der Zeichen fest, die in das Textfeld eingetragen
werden kann.

6.3.4 LabeledNumberField
Die Klasse LabeledNumberField definiert ein Textfeld f¨r die Eingabe von Zahlen.
                                                       u
Das Feld unterscheidet sich ¨ußerlich nicht von einem Textfeld, jedoch sorgen eine Reihe von
                            a




                              Abbildung 36: LabeledNumberField

JavaScript-Funktionen daf¨r, dass ausschließlich Zahlen in dieses Feld eingegeben werden. Die
                         u
Eingabe von Buchstaben und Sonderzeichen wird gesperrt. Große Zahlen werden automatisch
schon w¨hrend der Eingabe in Tausenderbl¨cken mit dem f¨r die aktuelle Sprache typischen
       a                                   o                u
6.3   Das Packet com.varial.gui                                                        127


Trennzeichen 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 auch
von LabeledTextField abgeleitet. Sie erg¨nzt diese Klasse um zwei weitere Eigenschaften.
                                         a

public 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 des
Dezimaltrennzeichens, beipielsweise ein Komma im deutschen, gesperrt.
Mit allowNegative kann festgelegt werden, ob auch negative Zahlen eingegeben werden
k¨nnen. Bei false wird ebenfalls die Eingabe eines Minus-Zeichens gesperrt.
 o

6.3.5 LabeledCurrencyField
Die Klasse LabeledCurrencyField repr¨sentiert eine Textfeld, das die Eingabe eines Geld-
                                        a
betrages erwartet.
Auch ein W¨hrungsfeld unterscheidet sich auf den ersten Blick nicht von einem Text- oder
              a
Zahlenfeld, 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
                                     a
Feld die M¨glichkeiten eines Zahlenfeldes, so dass die Klasse von LabeledNumberField ab-
            o
geleitet wurde.
Zus¨tzlich zu den Funktionen eines Zahlenfeldes, wird dem Betrag ein W¨hrunszeichen an-
    a                                                                   a
gehangen. W¨hrend ein Zahlenfeld also f¨r Eintr¨ge wie “1.234,56“ gedacht ist, kann bei
               a                         u        a
einem 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
                          a
wieder angef¨gt.
              u
Durch die Vererbung kann auch bei der Klasse LabeledCurrencyField angegeben werden,
ob negative und Fließkommazahlen erlaubt sein sollen. Durch die Angabe einer W¨hrunga
wird ferner festgelegt, wieviele Nachkommastellen erlaubt sind und wie Angaben gerundet
werden. LabeledCurrencyField stellt hierzu zwei zus¨tzliche Methoden zur Verf¨gung.
                                                      a                         u

public void setCurrency (CurrencyBO currency)

public void setShowCurrencyCode (boolean showCurrencyCode)

Mit setCurrency() wird die W¨hrung gesetzt, setShowCurrenyCode() gibt an, ob das
                                   a
W¨hrungszeichen angezeigt werden soll. Wird diese Eigenschaft auf false gesetzt, verh¨lt
   a                                                                                  a
sich das Feld wie ein Zahlenfeld, begrenzt jedoch Nachkommastellen gem¨ß der ubergebenen
                                                                      a      ¨
W¨hrung.
   a
6.3     Das Packet com.varial.gui                                                       128


6.3.6     LabeledTextField
Die Klasse LabeledDateField definiert ein Textfeld f¨r die Eingabe eines Datums.
                                                   u
Die Eingabe muss gem¨ß des Datumsformates der aktuellen Sprache vorgenommen werden.
                     a




                                    Abbildung 37: LabeledDateField

Erlaubt sind somit nur Ziffern und das jeweilige Datums-Trennzeichen, wie beispielsweise der
Punkt. Alle anderen Eingaben, wie Buchstaben oder Sonderzeichen werden gesperrt. Das Feld
verf¨gt weiterhin uber einen Mechanismus, der das Datum auf Korrektheit uberpr¨ft. Eine
    u             ¨                                                          ¨     u
ung¨ltige Eingabe (z.B. “32.12.“) wird erkannt und blockiert. Zur schnelleren Eingabe ist
    u
es außerdem m¨glich, ein Datum ohne Trennzeichen einzugeben. Die Eingabe “160578“ wird
               o
automatisch 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
                                                                      a
kein Jahr angegeben, wird das aktuelle Jahr eingef¨gt. Ebenso wird eine fehlende Monatsan-
                                                   u
gabe mit dem aktuellen Monat versehen. So ist es m¨glich, mit der Eingabe “15“ auf den 15.
                                                     o
Tag des aktuellen Monats im aktuellen Jahr zuzugreifen. Diese eingebaute Programmlogik,
die mit JavaScript realistiert wird, erm¨glicht eine schnelle und unkomplizierte Datumsein-
                                        o
gabe.
Oberklasse ist VGuiBean (6.3.2). Zus¨tzlich k¨nnen der Klasse folgende Eigenschaften gesetzt
                                     a       o
werden:

public void setValue (String value)

Genau wie bei einem normalen Textfeld kann so der Inhalt des Feldes angegeben werden. Die
Eingabe kann im Datenbankformat erfolgen. Die Ausgabe wird automatisch in ein Format
gem¨ß der aktuellen Sprache formatiert.
    a


6.3.7     LabeledMemo
Die Klasse LabeledMemo stellt ein mehrzeiliges Textfeld dar.
Dieses Feld erweitert die Klasse LabeledTextField, um die M¨glichkeit auch mehrzeiligen
                                                               o
Text 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
6.3   Das Packet com.varial.gui                                                           129


Die Eigenschaft height gibt die H¨he des Textfelds an, warp beschreibt, wie Texteingaben
                                  o
umgebrochen werden. Hier sind alle Angaben erlaubt, die dem wrap-Attribute des textarea-
Tags zugeordnet werden k¨nnen. Typische Angaben sind virtual (automatischer Umbruch
                         o
am Zeilenende) oder off (kein automatsicher Zeilenumbruch).


6.3.8 LabeledButtonTextField
Die Klasse LabeledButtonTextField stellt ein Textfeld mit einem verkn¨pften Button dar.
                                                                        u
Bei einem sog. Drei-Punkte-Button handelt es sich um ein normales Textfeld, das mit einem
nebenstehenden Button um eine Funktion erweitert werden kann. Anwendung findet eine
solche Komponente u.a. zur Auswahl von Konten. Das Feld zeigt die aktuelle Auswahl, mit
einem Klick auf den Button wird ein Dialog ge¨ffnet, in dem eine neue Auswahl getroffen
                                                o
werden kann. Ein weiteres Beispiel f¨r die Verwendung eines Drei-Punkte-Buttons ist die
                                    u
Darstellung von Mail-Adressen. In das Textfeld kann eine Adresse eingegeben werden, an die
auf Knopfdruck eine Nachricht geschickt wird.
Die Klasse leitet von LabeledTextField ab und f¨gt folgende Eigenschaften hinzu:
                                                  u
public 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
                a
es 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
          u
Frame die Ausgabe erfolgen soll. Voreinstellung ist, dass die aufgerufenen Seiten im aktuellen
Frame erscheinen. M¨glich w¨re allerdings auch, Ausgaben in einem neuen Fenster oder
                     o         a
in 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.
                o

6.3.9 LabeledCheckBox
Die Klasse LabeledCheckBox dient zur Ausgabe eines beschrifteten Kontrolk¨stchens. Die
                                                                         a
Klasse definiert eine Eigenschaft
public void setValue (boolean value)
Hiermit wird angegeben, ob die Check-Box selektiert werden soll oder nicht.

6.3.10   LabeledRadioButton
Die Klasse LabeledRadioButtons erzeugt genau wie LabeledCheckBox Auswahllisten, bei
denen jedoch keine Mehrfachauswahl m¨glich ist. Radio-Buttons sind eine Gruppe von be-
                                      o
schrifteten Kn¨pfen, von denen der Anwender immer nur einen ausw¨hlen kann. Die Klasse
              o                                                  a
wurde von LabeledCheckBox abgeleitet und erweitert diese um eine weitere Eigenschaft.
6.3   Das Packet com.varial.gui                                                        130


public void setGroup (String group)

Die Angabe group weißt den Radio-Button einer Gruppe zu. Alle Buttons, die der selben
Gruppe angeh¨ren, schließen sich in der Auswahl gegenseitig aus.
            o


6.3.11   LabeledComboBox
Die Klasse LabeledComboBox erzeugt eine beschriftete Combo-Box. Aus einer Liste von




                             Abbildung 38: LabeledComboBox

Werten kann jeweils einer ausgew¨hlt werden. Hierzu besitzt die Klasse zwei Eigenschaften.
                                a

public void setValues (String[] values)

public void setSelectedIndex (int selectedIndex)

Die Eigenschaft values definiert die Liste mit Auswahlm¨glichkeiten. Mit selectedIndex
                                                           o
wird angegeben, welcher Eintrag vorselektiert werden soll.

6.3.12   LabeledEditableComboBox
Die Klasse LabeledEditableComboBox stellt eine editierbare Combo-Box dar. Im Gegensatz
zu der Klasse LabeledComboBox (6.3.11) kann hier nicht nur ein Wert aus einer Liste gew¨hlt
                                                                                       a
werden, sondern der Benutzer kann zus¨tzlich eigene Werte eingeben. Die Klasse leitet von
                                      a
LabeledComboBox ab und definiert zus¨tzlich einen weiteren Parameter.
                                     a

public void setValue (String value)

Die Eigenschaft value gibt den Wert an, der ausgew¨hlt bzw. eingegeben wurde. Durch
                                                       a
die Vererbung besitzt die Klasse weiterhin das Attribute values. Der Unterschied zwischen
value und values besteht darin, dass values die Auswahlliste definiert, w¨hrend value nur
                                                                        a
den jeweils aktuellen Wert angibt.

6.3.13   LabeledListBox
Die 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                                                a
m¨glich, die Auswahl eines Eintrags zu verhindern. In diesem Fall dient die Komponente
  o
lediglich zur Anzeige von Elementen. Außerdem k¨nnen Auswahllisten um zus¨tzliche Funk-
                                               o                            a
tionen, wie bespielsweise das Hinzuf¨gen oder Entfernen von Elementen erweitert werden.
                                    u
6.3   Das Packet com.varial.gui                                                          131


Die Klasse wurde von LabeledComboBox (6.3.11) abgeleitet. Die Erweiterung besteht darin,
dass im Gegensatz zu einer Combo-Box mehrere Listenelemente sichtbar sind. Die Klasse
besitzt 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-
                                        o
ser Eigenschaft gibt an, wieviele Elemente gleichzeitig sichtbar sind. Bei einem Wert von 1
entspricht die Auswahlliste einer Combo-Box.
Mit multiple kann angegeben werden, ob eine Mehrfachauswahl m¨glich ist. Steht diese
                                                                       o
Eigenschaft auf true, k¨nnen mehrere Eintr¨ge gleichzeitig selektiert werden. Bei false ist
                         o                     a
lediglich die Auswahl eines Elements m¨glich.
                                          o
Um anzugeben, welche Listeneintr¨ge bereits selektiert sein sollen, wird selectedIndexes
                                     a
gesetzt. Als Wert wird eine Array von int-Werten erwartet, die die Indizes der angew¨hlten
                                                                                       a
Eintr¨gen angeben.
      a
Mit der Eigenschaft buttons k¨nnen der Auswahlliste weitere Funktionen zugewiesen wer-
                                 o
      ¨
den. Ubergeben wird eine Instanz der Klasse LabeledListBoxButtons (6.3.14), die Buttons
mit weiteren Funktionalit¨ten implementiert.
                            a
Als 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                                                            u
Tatsache, 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 zur
Darstellung von Werten benutzt wird. Eine Auswahl ist nicht erw¨nscht. Stattdessen k¨nnen
                                                                  u                    o
weitere Elemente mit den entsprechenden Buttons hinzugef¨gt bzw. wieder entfernt wer-
                                                              u
den. Da eine Auswahl hier nicht gew¨nscht ist, w¨rden beim Absenden des Formulars keine
                                       u           u
Werte ubertragen. F¨r das verarbeitende Servlet entst¨nde der Eindruck, dass die Liste leer
        ¨            u                                  a
sei. Um dies zu verhindern, wird die keylist-Eigenschaft gesetzt. Die Klasse erzeugt dann
automatisch 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                                         u
Listeneintr¨ge w¨re beispielsweise die ID des Business Objektes.
            a    a

6.3.14   LabeledListBoxButtons
Mit der Klasse LabeledListBoxButtons k¨nnen einer List-Box (6.3.13) weitere Funktio-
                                            o
nen zugewiesen werden. Manchmal is es sinnvoll, einer Auswahlliste zus¨tzliche Funktiona-
                                                                      a
lit¨t zu verleihen. Ein Bespiel hierf¨r w¨ren Funktionen zum Hinzuf¨gen bzw. zum Ent-
   a                                 u   a                          u
fernen von Elementen der Liste. Da HTML keine PopUp-Men¨s unterst¨tzt, werden sol-
                                                             u          u
che zus¨tzlichen Funktionen bei VWE-Web in Form von Icons angezeigt. Mit der Klasse
        a
6.3   Das Packet com.varial.gui                                                         132


LabeledListBoxButtons k¨nnen solche Icons implementiert werden. Sie werden im Anschluss
                           o
der 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                                           u
aus der Liste und das Anfordern weiterer Einzelheiten zu einem ausgew¨hlten Element. F¨r
                                                                        a               u
diese 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(
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.
                                       o
Tabelle 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 LabeledListBoxButtons


mit oder ohne den Parameter tooltip aufgerufen werden. Wird dieser Parameter ubergeben,
                                                                             ¨
werden die ubergebenen Texte als Hinweistext bei den Icons angezeigt.
           ¨

6.3.15 LabeledGrid
Die Klasse LabeledGrid stellt eine beschriftete Tabelle dar. Tabellen sind eine zentrale GUI-
Komponente in VWE. Mit ihr werden Daten strukturiert dargestellt. Außerdem kann der
Benutzer Zelleninhalte ver¨ndern. In HTML sind zwar Tabellendarstellungen m¨glich, eine
                           a                                                      o
Komponente mit editierbaren Zellen gibt es hingegen nicht. Deshalb wurde selbst eine solche
Komponente entworfen. Sie befindet sich in der Klasse GridBean (6.3.16). Die Handhabung
von 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 einer
Beschriftung 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
                                o
geregelt, die die H¨he und Breite der Tabelle angeben. Mit showMenu kann definiert wer-
                   o
den, ob die Tabelle eine Men¨zeile mit zus¨tzlichen Funktionen erhalten soll. Als weitere
                               u             a
Eigenschaft kann mit headerAlign die Ausrichtung der Beschriftung ge¨ndert werden. Stan-
                                                                       a
dardm¨ssig wird die Beschriftung der Tabelle links neben ihr angezeigt. Alternativ kann die
      a
Eingschaft auf auch top“ gesetzt werden, so dass die Beschriftung oberhalb erscheint.
                     ”
6.3   Das Packet com.varial.gui                                                            134


Genau wie bei der Klasse LabeledListBox (6.3.13) werden Funktionalit¨ten in Form von
                                                                         a
Icons unterhalb der Tabelle angezeigt. Um Icons einzuf¨gen, dient die Methode addEntry().
                                                      u

public 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                           u
Bildes an, description liefert die Beschreibung der Aktion, die als Tooltip erscheinen soll und
mit action wird der Aktion ein Name gegeben. Dieser Namen wird bei Klick auf den Button
ubertragen. Das Servlet kann mit catchActionEvent() darauf reagieren. R¨ckgabewert ist
¨                                                                              u
der Index des neuen Symbols in der Men¨leiste.
                                          u
Trennsymbole zwischen den Icons lassen sich mit addSeparator() einf¨gen: u

public 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-
                                                   u
blenden 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
                                                           u
bzw. versteckt. Um Icons ein- bzw. auszublenden dienen die Methoden turnIconOn() und
turnIconOff().

public void turnIconOn (int iconindex)

public void turnIconOff (int iconindex)

Die Klasse bietet weiterhin die M¨glichkeit, fest definierte Zust¨nde anzunehmen.
                                 o                              a

public void toInfoView()

public void toListView()

Bei dem Aufruf von toListView() nimmt das Tabellen-Men¨ das f¨r Listenansicht typi-
                                                            u      u
sche Aussehen an. Das Hinzuf¨gen und Entfernen von Zeilen wird ausgeblendet, alle anderen
                             u
Symbbole bleiben stehen. Bei der zweiten Methode wird das Men¨ in eine Info-Ansicht ver-
                                                               u
setzt. Auch hier werden die Aktionen f¨r das Hinz¨gen und Entfernen deaktiviert.
                                      u          u
6.3   Das Packet com.varial.gui                                                         135


6.3.16   GridBean
Die Klasse GridBean ist f¨r die Darstellung einer editierbaren Tabelle zust¨ndig. Die Be-
                          u                                                 a
handlung von Aktionen sowie die Formatierung der Tabelle wird wie bereits beschrieben von
der 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
         ¨                                                                    u
als einzige Aufgabe der GridBean, neue Datens¨tze zu den bestehenden Daten hinzuzuf¨gen
                                               a                                     u
bzw. diese zu l¨schen. Um die Tabelle mit Inhalt zu f¨llen dient die Methode addRow().
               o                                     u

public 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 ersten
Position des Arrays befindet sich der Wert f¨r die linkeste Spalte, die ¨ußerste rechte Spal-
                                            u                          a
te wird mit dem letzten Wert gef¨llt. Da als Typ ein Object m¨glich ist, k¨nnen beliebige
                                  u                              o          o
Typen ubergeben werden. So ist es m¨glich, Strings, Integer, Vectoren f¨r Combo-Boxen
        ¨                            o                                    u
oder 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 Array
mit Strings als Parameter mit angegeben werden. Dieser kann Verweise aufnehmen, zu denen
gesprungen wird, wenn der Benutzer einen Tabelleneintrag anklickt. So k¨nnen beispielsweise
                                                                        o
Detailansichten zu Eintr¨gen definiert werden. Die Verweise, mit denen der Anwender von ei-
                        a
ner normalen Listendarstellung zur Detaildarstellung navigieren kann, m¨ssen ubrigens nicht
                                                                        u     ¨
expliziet angegeben werden. Wird der Tabelle ein VListState (6.1.7) zugewiesen und wird
der addRow()-Methode ein BO bekannt gemacht, werden die Tabellenzeilen automatisch mit
Links zu Detailansicht versehen.
Weitere Aktionen, wie das Hinzuf¨gen einer neuen, d.h. leeren Zeile und das entfernen von
                                  u
vorhandenen Werten behandelt die Klasse bzw. der entsprechende State selbstst¨ndig, so
                                                                                   a
dass die addRow()-Methode in der Regel die einzige Methode sein wird, die aufgerufen wird.
6.3   Das Packet com.varial.gui                                                          136


6.3.17   DivGridBean
Die 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 Einsatz
als Callback (5.5) m¨glich. Dem Vorteil einer schnellen Darstellung von großen Tabellen steht
                     o
der 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       a
ner GridBean optimal an die jeweiligen Eintr¨ge angepasst werden. Die Klasse DivGridBean
                                              a
kommt 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                                                   o
transparent. Unterschiede in der Benutzung gibt es keine. Der Entwickler muss lediglich im
in 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
                         ¨    a
eigenen Funktionen.

6.3.18   GraphBean
Die 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      a
der Klasse VChartServlet erzeugt. Der GraphBean muss lediglich eine Instanz dieser Klasse
ubergeben werden.
¨

public void setServlet (VChartServlet servlet)

6.3.19   ImageBean
Mit Hilfe dieser Klasse k¨nnen Bilder dargestellt werden. Der ImageBean muss mit der Me-
                         o
thode setUrl() die Adresse der Bilddatei gesetzt werden.

public void setUrl (String url)

6.3.20   TabSheetBean
Die Klasse TabSheetBean stellt eine Tabsheet dar. Bei einer Tabsheet handelt es sich um
eine Komponente, die oft auch als Reiter oder Register bezeichnet wird. Die Darstellung ist
angelehnt an eine Karteikartenregister. Durch Anklicken der Karteikarten¨berschriften wird
                                                                         u
der entsprechende Inhalt angezeigt. Eine solche grafische Komponente findet sich in einer
Vielzahl von Desktop-Anwendungen, aud Web-Seiten ist sie hingegen seltener zu finden, da
HTML keine entsprechende Komponente zur Verf¨gung stellt. Eine Tabsheet musste somit
                                                  u
selbst entwickelt werden (siehe auch 6.4.20).
                                                         ¨
Der Tabsheet muss als einzige Eigenschaft eine Liste von Uberschriften ubergeben werden.
                                                                       ¨

public void setTabSheets (String[] tabsheets)
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 Reihen
aufgeteilt. Die Reihe mit der jeweils ausgew¨hlten Registerkarte befindet sich hierbei immer
                                              a
unten.
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 ausblenden
lassen. Ein praktisches Beispiel findet sich in der Finanzbuchf¨hrung bei den Debitoren- und
                                                               u
Kreditoren-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 Ober߬che besitzt folglich einige Regi-
                                                             a
sterkarten mehr. Bei der Kreditorenverwaltung wird dort, wo die Debitorenverwaltung die
entsprechenen 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
                                                                               u
ber¨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
                            u
einfach ausgeblendet. Die Registerkarte f¨r Bankverbindung erh¨lt genau wie in der Debi-
                                         u                      a
torenverwaltung den Index 3. Da nun bei Wechsel der Karte nicht die Bezeichnung (diese
ist ja abh¨ngig von der aktuellen Sprache), sondern der Index an das Servlet geliefert wird,
          a
kann das Servlet den Index 3 eindeutig der Bankverbindung zuordnen. W¨rde bei Kreditoren
                                                                       u
anstelle von null nichts ubergeben, w¨re die Ausgabe der TabSheetBean zwar identisch, das
                         ¨            a
Servlet m¨sste aber die Bankverbindungsdaten einmal bei dem Index 2 und das andere mal
          u
beim Index 3 liefern. Ein gemeinsame Bearbeitung von mehreren Use-Cases durch ein Servlet
w¨re nicht m¨glich.
  a           o

6.3.21   MenuBarBean
Die MenuBarBean erzeugt eine Men¨leiste und stellt diese dar. Die Men¨leiste setzt sich aus
                                    u                                   u
drei Teilen zusammen: Icons vor der Combo-Box, die Combo-Box selbst und Icons hinter
der Combo-Box. Symbole links neben der Combobox sind in der Regel fest vorgegeben. Hier
k¨nnen keine neuen Symbole hinzugef¨gt oder bestehende entfernt werden. Die Combobox
 o                                     u
selbst beinhaltet standardm¨ssig eine Firmenauswahl, kann aber auch ge¨ndert werden. Icons,
                            a                                          a
die rechts neben der Combobox stehen, sind spezifisch f¨r den jeweiligen Use-Case, sie werden
                                                       u
also expliziet hinzugef¨gt. Dazu bietet die Klasse die Methode addEntry.
                       u

public int addEntry (
    String img,
    String description
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-
              a
tionale 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
                                   o
Zusammenhang einige n¨tzliche Methoden wie getMenuAction() etc. Wird keine Aktion an-
                       u
gegeben, 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                   u
addSeparator() aufgerufen werden.

public int addSeparartor()

Alle diese Methoden liefern eine Zahl zur¨ck. Sie zeigt an, welchen Index das eingef¨gte
                                          u                                          u
Icon in der Men¨leiste einnimmt. Mit diesem Index k¨nnen die Symbole sp¨ter angesprochen
               u                                   o                   a
werden. Sie k¨nnen ein- und ausgeblendet werden und aktiviert bzw. deaktiviert werden.
             o

public 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,
                                                         u
hideIcon() blendet Symbole aus, showIcon() sorgt daf¨r, dass sie wieder angezeigt wer-
                                                           u
den. 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()
6.3   Das Packet com.varial.gui                                                        139


In der Listenansicht sollte die Men¨leiste mit Aufruf von toListView() in die passende
                                     u
Ansicht 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,
                                                                          u
L¨schen und Speichern von Objekten. Diese Ansicht sollte gew¨hlt werden, wenn die Detail-
  o                                                           a
Ansicht keine schreibende Zugriffe erm¨glicht, sondern nur Informationen zur Verf¨gung
                                        o                                          u
stellt. Die Kontenliste im Use-Case NominalLedgerAccountInformation“, die vorhande-
                                      ”
ne Kontenst¨nde zeigt w¨re ein Beispiel f¨r eine solche Ansicht.
              a           a              u
Es 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                 u
des Ladevorgangs angezeigt. Alternativ kann man auch mit der showCallback()-Methode
daf¨r sorgen.
    u
Als 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
                                                                 a
nicht 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
                                                                                  a
werden.

public void setComboBox(MenuBarComponentInterface combobox)
    ¨
Das Ubergebene Objekt muss das MenuBarComponentInterface (6.3.24) implementieren.

6.3.22   MenuEntryTreeBean
Mit der Klasse MenuEntryTreeBean wird der Men¨baum erstellt. Die Daten f¨r die
                                                         u                           u
Men¨punkte liefert der Server aus der Datenbank. Diese Daten k¨nnen im VWE-
     u                                                                   o
Administrationsmodus gepflegt werden, d.h. es k¨nnen vorhandene Programmmodule aus-
                                                    o
geblendet oder gel¨scht werden oder es k¨nnen neue Use-Cases aufgenommen werden. Da
                    o                       o
dies 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().
             o

public String getOutput()

6.3.23   MenuEntry
Die Klasse MenuEntry wird ausschließlich von MenuEntryTreeBean (6.3.22) verwendet und
ist deshalb außerhalb des Packets nicht zug¨nglich. Sie repr¨sentiert einen einzelnen Men¨-
                                           a                a                            u
Eintrag mit dessen Eigenschaften.

6.3.24   MenuBarComponentInterface
Das Interface MenuBarComponentInterface legt fest, dass alle Objekte, die als Combo-Box
in der Men¨leiste erscheinen sollen, die Methode getOutput() implementieren.
           u
6.3   Das Packet com.varial.gui                                                          140


public String getOutput(
    VContext ctx,
    boolean enable
)

6.3.25   SelectCompanyBean
Die Klasse SelectCompanyBean implementiert das Interface MenuBarComponentInterface
(6.3.24) und erstellt die Combo-Box zur Firmenauswahl, die in der Men¨leiste erscheint.
                                                                     u

6.3.26   SelectOkCancelButtonBean
Mit der Klasse SelectOkCancelButtonBean k¨nnen Buttons f¨r Auswahldialogen erzeugt
                                              o              u
werden. Als Buttom k¨nnen Best¨tigungs- und Abruch-Buttons erstellt werden. Ein Abbruch-
                     o           a
Button 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          a
gung erzeugt, andernfalls nicht. Oft wird die Klasse in Verbindung mit Tabellen und der
SelectSearchBean-Klasse (6.3.27) verwendet. Der Auswahldialog zeigt dann eine Tabelle
mit einer Reihe von Eintr¨gen. Ein Eintrag wird durch einfaches Anklicken ausgew¨hlt, so
                          a                                                     a
dass ein OK-Button in diesem Fall nicht notwendig ist.

6.3.27   SelectSearchBean
Auch die Klasse SelectSearchBean findet in Auswahldialogen Verwendung. Sie erzeugt ein
Textfeld, dessen Eingabe zum Filtern von Tabellen-Inhalten verwendet wird. Der Inhalt der
Tabelle 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
     a
sich rechts neben dem Textfeld ein Icon, mit dem die Tabellenausgabe aktualisiert wird. Der
Anwender gibt also zun¨chst das Suchkriterium ein und klickt dann auf das Icon. Die Tabel-
                       a
lenansicht wird entsprechend aktuallisiert. Um diesen Vorgang zu automatisieren, befindet
sich neben dem Icon ein Check-Box. Ist diese angew¨hlt, f¨hren alle Angaben sofort zur Aus-
                                                   a     u
gaben¨nderung. Die Tabelle wird unmittelbar an den Filter angepasst. Da dies bei langsamen
       a
Verbindungen einige Zeit in Anspruch nehmen kann, k¨nnte der Bedienungskonfort der An-
                                                       o
wendung deutlich darunter leiden. Aus diesem Grunde, wurde dem Anwender die M¨glichkeit
                                                                                    o
gegeben, die automatische Aktuallisierung auszuschalten.

6.3.28   JavaScriptBean
Die Klasse JavaScriptBean ist daf¨r zust¨ndig, JavaScript-Code f¨r die HTML-Ausgabe
                                    u      a                        u
vorzubereiten. Erzeugt ein Servlet, eine GuiBean oder sonstige Klassen JavaScript-Code, so
kann dieser Code durch die JavaScriptBean in die JSP-Seite eingebettet werden. Alle auf
6.3   Das Packet com.varial.gui                                                        141


diese Weise erzeugten JavaScript-Befehle befinden sich dann automatisch im head-Bereich
der 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 alle
Befehle von allen Browsern unterst¨tzt. Um anzugeben, dass die Ausf¨hrung nur ab einer
                                   u                                u
bestimmten 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
                                                                           u
JavaCode-Befehle, die mit der Version INIT“ erzeugt werden, sorgt die JavaScriptBean
                                        ”
daf¨r, dass sie zu Beginn ausgef¨hrt werden.
   u                            u
Der ubergebene Code wird von der Klasse (unter Ber¨cksichtigung evtl. spezifizierten Versi-
     ¨                                              u
onsnummern) in ein passendes script-Element eingebettet und in die JSP-Ausgabe einge-
baut.

6.3.29   JavaScriptHelper
Mit der Klasse JavaScriptHelper k¨nnen oft wiederkehrende JavaScript-Fragmente erstellt
                                    o
werden. Die Klasse beitet dazu eine Reihe statischer Funktionen. Ein Bespiel f¨r solche Me-
                                                                              u
thoden sind die mailto- und http-Anweisung.

public final static String mailto (String fieldname)
6.3   Das Packet com.varial.gui                                                        142



public 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.
                                   o
Ein Klick auf den Button ¨ffnet in diesem Fall die Adresse. Um eine solche Funktionalit¨t zu
                          o                                                           a
erreichen, ist die Verwendung von JavaScript erforderlich. Die beiden Methoden implemen-
tieren diesen JavaScriptCode f¨r http- bzw. mailto-Adressen. Sie erwarten als Parameter
                              u
den Namen des Feldes, dass die Adresse enth¨lt. Die erzeugte Ausgabe kann dann dem Drei-
                                            a
Punkte-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                     u
die http()-Funktion verwendet, um eine Internet-Seite zu ¨ffnen.
                                                         o

   Der zweite Anwendung des JavaScriptHelpers liegt darin, Abh¨ngigkeiten zwischen zwei
                                                               a
oder mehreren GUI-Komponenten zu definieren. Beispielsweise k¨nnte eine Check-Box ein
                                                               o
Eingabefeld aktivieren bzw. deaktivieren. Der JavaScriptHelper bietet die M¨glichkeit der
                                                                           o
Abh¨ngigkeitsdefinition f¨r Check-Boxen, Radio-Buttons und Combo-Boxen.
    a                    u
Abh¨ngigkeiten von Check-Boxen werden wie folgt definiert:
    a
public 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
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
                                    a
werden k¨nnen, gibt es sowohl eine Methode namens enableByCheckBox() als auch
           o
disableByCheckBox(). Weil weiterhin eine einzelne Komponente oder eine Reihe von Kom-
ponenten gesteuert werden k¨nne, gibt es jede Methode in zweifacher Ausfertigung.
                             o
Als Parameter wird zum einen der Name der Check-Box angegeben, die f¨r die Aktivie-
                                                                            u
rung/Deaktivierung verantwortlich ist, zum anderen wird das Feld oder die Felder ubergeben,
                                                                                 ¨
die aktiviert/deaktiviert werden. Die Ausgabe dieser Funktionen k¨nnen den entsprechenden
                                                                 o
Methoden 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
                                                              u
mit 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.
               u
public final static StringBuffer enableByRadioButton(
    String group,
    int index,
    String field
)

public final static StringBuffer enableByRadioButton(
    String group,
    int index,
    String[] fields
6.3   Das Packet com.varial.gui                                                         144


)

    Ein wenig anders verh¨lt es sich bei Combo-Boxen. Diese haben im Gegensatz zu Check-
                          a
Boxen oder Radio-Buttons keinen boolschen Wert, der angibt, ob die Komponente ausgew¨hlt
                                                                                      a
ist oder nicht. Vielmehr kann eine Combo-Box eine Reihe von m¨glichen Werten annehmen.
                                                               o
Es muss also zus¨tzlich angegeben werden, wann die Aktivierung/Deaktivierung erfolgen soll.
                 a
Hierzu 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                                                            a
folgende 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                                a
be der Zahlen-/Buchstabenfolge soll nur dann m¨glich sein, wenn ein L¨ndercode ausgew¨hlt
                                               o                      a               a
wurde. Da der erste Eintrag der Combo-Box leer ist, muss gepr¨ft werden, ob ein Eintrag
                                                                u
ungleich dem ersten ausgew¨hlt ist. Erst dann darf das Textfeld aktiviert werden.
                            a

GuiHelper.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
        u
Feld address ECVATRegNr“ f¨r die Eingabe freigegeben.
                             u
    ”
6.3   Das Packet com.varial.gui                                                       145


6.3.30   Theme
Mit 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                                                      a
dem momentan eingestellten Theme geladen werden. Dazu bietet sie zwei Arten von statischen
Methoden. 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
                                                                         u
getImg() bezeichnet die URL eines angeforderten Bildes. Je nach Situation, aus der die
                                                  ¨
Methoden aufgerufen werden, ist entweder die Ubergabe eines VContexts (6.1.10), oder
die Angabe eines Servlets und dem passenden Request-Objekts leichter. Die Methoden
der Klasse Theme unterst¨tzen beide Vorgehensweisen. Es f¨llt auf, dass ein weiterer
                           u                                   a
Parameter namens move angegeben werden muss. In der Regel ist dies der Wert 0, der
besagt, dass Theme die richtige Adresse liefert. Durch Umleitung einer Anfrage mittels des
sendRedirect()-Befehls der Klasse VServlet (6.1.1) kann es vorkommen, dass der Aufruf
der Theme-Funktion von einer anderen Seite, als der angeforderten durchgef¨hrt wird. Wenn
                                                                          u
6.4   Das Packet com.varial.taglib                                                       146


sich beide Seiten in verschiedenen Verzeichnistiefen befinden, liefert die Klasse Theme ein
falsches Ergebnis, das aber mit dem move-Parameter korrigiert werden kann. Positive Zahlen
bedeuten, dass die aufgerufene Datei um die entsprechende Anzahl von Verzeichnissen tiefer
liegt. 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-
                   u
ten 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.
                     u

6.4 Das Packet com.varial.taglib
Das Packet enth¨lt benutzerdefinierte Tags, die sich genau wie HTML-Tags in JSP-Seiten
                a
einbetten lassen und dort f¨r die Ausf¨hrung von Java-Code zust¨ndig sind. Eine solche
                           u          u                           a
Sammlung von selbsterstellten Tags wird auch als Taglib bezeichnet.


6.4.1 varial.tld
Bei der Datei varial.tld handelt es sich um eine sog. Taglib Descriptor, also um
die Beschreibung von benutzerdefinierten Tags. Es ist eine XMl-Datei, die dem in der
DTD 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. Weiterhin
wird definiert, welche Attribute die Tags haben, ob diese optional oder obligatorisch sind und
ob bzw. welche Art von Inhalt die Tags haben d¨rfen.
                                                u
Jedesmal, 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-
                                       o
sen 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).
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 currencyfield



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



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



grid    Behandelt durch die Klasse VGrid (6.4.14).

graph    Behandelt durch die Klasse VGraph (6.4.15).
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 graph



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



tabsheetcontrol 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 tabsheet



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



csslink 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 hiddenfield



hiddenextrafield Behandelt durch die Klasse HiddenExtraField (6.4.29).

                  Attribute     Bedeutung                      Default-Wert
                  name          Name des Feldes/Parameters     obligatorisch

                      Tabelle 25: Attribute des Tags hiddenextrafield



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



languagestring   Behandelt durch die Klasse LanguageString (6.4.31).
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 languagestring


6.4.2    VComponent
Die Klasse VComponent ist keinem Tag der Taglib direkt zugeordnet. Vielmehr stellt sie eine
abstrakte Oberklasse f¨r eine Vielzahl von anderen Klassen dar. Bei der Betrachtung der
                       u
Taglib Descriptor (6.4.1) f¨llt auf, dass viele Elemente die gleichen Attribute besitzen. Weil
                           a
diese Attribute entsprechende Setter-Methoden in den verantwortlichen Klassen ben¨tigen,
                                                                                       o
bietet es sich an, diese in einer gemeinsamen Oberklasse zu implementierung und durch
Vererbung 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 einem
Objekt zuzuweisen.
protected void fillBean (VGuiBean bean)
Die Funktionsweise der abgeleiteten Taglib-Klasse soll nun am Beispiel der Klasse VTextField
etwas genauer erl¨utert werden.
                 a

6.4.3    VTextField
Die Klasse VTextField wird verwendet, wenn das textfield-Tag der Varial Taglib in eine
JSP-Seite eingebettet ist. Zun¨chst werden f¨r alle Attribute, die in der JSP-Seite gesetzt
                              a             u
6.4     Das Packet com.varial.taglib                                                   154


werden, die entsprechenden Setter-Methoden aufgerufen. Die Namensgebung der Methoden
muss daf¨r den Regeln einer JavaBean folgen, d.h. eine Methode tr¨gt immer den Namen,
          u                                                      a
der sich aus set“ und dem großgeschriebenen Attributenamen zusammensetzt. Dementspre-
            ”
chend implementiert die Klasse f¨r das Attribute maxlength die Methode setMaxlength.
                                u
public 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
                                                              u
zum Beispiel id, align oder enable. Klassen der Taglib m¨ssen deshalb nur noch f¨r sie
                                                           u                        u
spezifische Attribut-Setter implementieren.
Nachdem die Attribute gesetzt wurden, wird vom Server die Methode doEndTag() aufgerufen.
public int doEndTag() throws JspException
In dieser Methode wird die Instanz der Klasse LabeledTextField (6.3.3), die zuvor
vom verarbeitenden Servlet mit dem GuiHelper (6.3.1) erzeugt wurde, wieder aus dem
Request-Objekt geholt und die restlichen Attribute werden gesetzt. Schließlich wird die
getOutput()-Methode des LabeledTextField aufgerufen, die daf¨r sorgt, dass die entspre-
                                                                  u
chende HTML-Ausgabe geschrieben wird.
Viele Klassen der Taglib verhalten sich genau so wie die Klasse VTextField. Sie sind
von VComponent abgeleitet, implementieren spezifische Setter-Methoden und holen in der
doEndtag()-Methode die erzeugten GUI-Elemente aus dem Request-Objekt um nach
Wertzuweisung 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 entsprechenden
Klasse des Packets com.varial.gui. Die Klassen des Packets com.varial.taglib sorgen
nur daf¨r, dass die HTML-Tags mit den richtigen GUI-Klassen verkn¨pft werden. Hierdurch
        u                                                            u
l¨ßt sich eine Programmierung nach dem bereits beschriebenen MVC-Modell (5.2) erreichen.
 a


6.4.4    VNumberField
Die Klasse VNumberField wird verwendet, wenn das numberfield-Tag der Varial Taglib
in eine JSP-Seite eingebettet ist. Die Klasse wurde von VTextField (6.4.3) abgeleitet und
definiert keine weiteren Setter-Methoden. Das numberfield-Tag wird durch die Ausgabe
der entsprechenden Instanz der Klasse LabeledNumberField (6.3.4) ersetzt.

Oberklasse: VTextField (6.4.3)
Zus¨tzliche Setter-Methoden: keine
   a
Ausgabe der Klasse: LabeledNumberField (6.3.4)

6.4.5    VCurrencyField
Oberklasse: VNumberField (6.4.4)
Zus¨tzliche Setter-Methoden: keine
   a
Ausgabe der Klasse: LabeledCurrencyField (6.3.5)
6.4     Das Packet com.varial.taglib                                         155


6.4.6    VDateField
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: LabeledDateField (6.3.6)

6.4.7    VMemo
Oberklasse: 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    VButtonTextField
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden:
   a                               • public void setTarget (String target)

Ausgabe der Klasse: LabeledButtonTextField (6.3.8)

6.4.9    VCheckBox
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: LabeledCheckBox (6.3.9)

6.4.10    VRadioButton
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: LabeledRadioButton (6.3.10)

6.4.11    VComboBox
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: LabeledComboBox (6.3.11)
6.4   Das Packet com.varial.taglib                                                       156


6.4.12   VEditableComboBox
Oberklasse: VComboBox (6.4.11)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: LabeledEditableComboBox (6.3.12)

6.4.13   VListBox
Oberklasse: VComboBox (6.4.11)

Zus¨tzliche Setter-Methoden:
   a                             • public void setSize (int size)

Ausgabe der Klasse: LabeledListBox (6.3.13)

6.4.14   VGrid
Oberklasse: 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   VGraph
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: GraphBean (6.3.18)

6.4.16   VImage
Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: ImageBean (6.3.19)

6.4.17   Empty
Die Klasse Empty behandelt das Tag empty und gibt leeren Inhalt aus. Die mag auf den
ersten Blick verwunderlich erscheinen, eine solche leere Ausgabe hat aber durchaus Sinn. Um
die 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 Rasters
nicht belegt, sollte in diese Tabellenzelle ein empty-Tag gelegt werden. Dieser erzeugt nicht
wirklich leeren, sondern lediglich unsichtbaren Inhalt. Die Ausgabe des Tags bzw. der Klasse
sorgt daf¨r, dass die Tabellenstruktur gem¨ß HTML-Standard gef¨llt ist. W¨rde hier einfach
         u                                   a                    u         u
nichts stehen, w¨re das Dokument nicht mehr valide.
                 a
6.4    Das Packet com.varial.taglib                                                      157


Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: -

6.4.18   Vspacer
Die 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-
                                                                     a
ponenten zu erzeugen. Dazu kann eine H¨he in Pixel angegeben werden. Zus¨tzlich zu dem
                                         o                                a
normalen Abstand wird dann ein weiterer Leerraum erzeugt. So k¨nnen Komponenten auf
                                                                  o
der Ober߬che optisch von einander getrennt werden.
           a

Oberklasse: VComponent (6.4.2)

Zus¨tzliche Setter-Methoden:
   a                              • public void setHeight (int height)

Ausgabe der Klasse: -

6.4.19   TabSheetControl
Oberklasse: BodyTagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: TabSheetBean (6.3.20)

6.4.20   TabSheet
Die Klasse TabSheet wird aufgerufen, wenn ein tabsheet-Tag in der JSP-Datei steht. Wie
der Taglib Descriptor (6.4.1) zu entnehmen ist, besitzt dieses Tag nur ein Attribute, n¨mlich
                                                                                       a
das Attribute index. Mit Hilfe des Tags lassen sich Inhalte zusammenfassen, die nur dann
angezeigt werden, wenn die Registerkarte mit dem angegebenen Index aktiv ist. So kann
die JSP-Seite eine Reihe von Ausgaben definieren, wovon jeweils eine angezeigt wird. Die
Klasse Tabsheet sorgt daf¨r, dass die anderen Teile nicht dargestellt werden. Hierzu wird die
                          u
Methode doStartTag() so uberladen, dass der Inhalt des Tags nur dann ausgef¨hrt wird,
                             ¨                                                     u
wenn 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.
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   MenuBar
Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: MenuBarBean (6.3.21)

6.4.22   SelectOkCancel
Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: SelectOkCancelButtonBean (6.3.26)

6.4.23   SelectSearch
Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe 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
                        o
zuvor mit Hilfe der setHeadLine()-Methode des GuiHelpers (6.3.1) dar.

Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: -
6.4   Das Packet com.varial.taglib                                                   159


6.4.25   LastChange
Die Klasse LastChange behandelt das lastchange-Tag und gibt ein kurze Statusmeldung
aus, wann das aktuelle Objekte von wem das letzte Mal ge¨ndert wurde.
                                                        a

Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden:
   a                             • public void setAlign (String align)

Ausgabe der Klasse: -

6.4.26   JavaScript
Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: JavaScriptBean (6.3.28)

6.4.27   CssLink
Die Klasse CssLink ist zust¨ndig f¨r das csslink-Tag. Dieses Tag erzeugt als Ausgabe eine
                           a      u
Zeile mit HTML-Code, der eine CSS-Datei einbettet. Die Klasse sorgt daf¨r, dass die Datei
                                                                        u
gem¨ß des aktuell eingestellten Corporate Designs (4.4.2) eingebunden wird. Dazu wird die
    a
getCss()-Methode der Klasse Theme (6.3.30) verwendet.

Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: -

6.4.28   HiddenField
Mit dem hiddenfield-Tag und der zugeh¨rigen Klasse HiddenField k¨nnen Parameter in
                                         o                           o
versteckten Feldern zwischengespeichert werden. Damit Query-String-Parameter und Attri-
bute im Request-Objekt auch bei Absenden eines Formulars ubergeben werden, m¨ssen sie
                                                          ¨                    u
selbst Teil des Formulars sein. Das hiddenfield-Tag sorgt daf¨r, dass die Parameter mit
                                                             u
dem als Tag-Attribute angegebenen Namen als versteckte Felder in das Formular integriert
werden.

Oberklasse: TagSupport

Zus¨tzliche Setter-Methoden:
   a                             • public void setName (String name)

Ausgabe der Klasse: -
6.4   Das Packet com.varial.taglib                                                     160


6.4.29   HiddenExtraField
Die Klasse HiddenExtraField verh¨lt sich ¨hnlich zu der Klasse HiddenField. Allerdings
                                     a       a
werden hier speziell die Werte in versteckten Formularfelder verwaltet, die dem Servlet vom
Men¨baum mitgegeben wurden. VWE erlaubt es im Administrations-Modus die Men¨bau-
     u                                                                                u
me der Programms zu editieren. Hier k¨nnen u.a. auch Parameter f¨r die aufgerufenen
                                          o                             u
Programm-Module angegeben werden. Diese Parameter werden dem Servlet bei Start uber-   ¨
geben und k¨nnen mit dem hiddenextrafield-Tag gespeichert werden. Eine Anwendung
            o
f¨r einen Men¨-Parameter findet sich beispielsweise in der Verwaltung von Debitoren und
 u            u
Kreditoren. 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                                         u
der Parameter TYPE=SUPPLIER bzw. TYPE=CUSTOMER ubergeben.
                                                     ¨
Oberklasse: HiddenField (6.4.28)

Zus¨tzliche Setter-Methoden: keine
   a

Ausgabe der Klasse: -

6.4.30 Translator
Sollen 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. Die
letzte Angabe wird vom zu ubersetzenden Text angegeben. Die anderen Angaben m¨ssen als
                           ¨                                                    u
Tag-Attribute spezifiziert werden. Da die Klasse TagSupport, von der die Klasse ableitet,
bereits eine setParent()-Methode besitzt, musste der Parent-Parameter umbenannt werden
und heißt nun Owner. Werden mehrere Translator in die Seite integriert, muss diesen das
id-Attribute gesetzt werden, damit sie sp¨ter zu unterscheiden sind.
                                         a
Nach Initialisierung des Translators k¨nnen Texte mit demlanguagestring-Tag (6.4.31)
                                       o
ubersetzt werden.
¨
Oberklasse: TagSupport

Zus¨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 Translator
man sich bezieht.
6.4   Das Packet com.varial.taglib                                                161


Oberklasse: TagSupport

Zus¨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
                                                               u
vom CORBA-Server erfragen und ausgeben.
6.4   Das Packet com.varial.taglib                                  162




                      Abbildung 39: LabeledComboBox (ausgeklappt)
7 Beispiel fur die Verwenung der VWE-Web-API
            ¨
Nachdem im letzen Kapitel die neu entwickelte Klassenbibliothek f¨r die Umsetzung einer
                                                                     u
Web-Oberfl¨che f¨r die Varial World Edition vorgestellt wurde, soll nun deren Verwendung
            a     u
an einem Anwendungsfall praktisch erkl¨rt werden. Als Programm-Modul soll die W¨hrungs-
                                        a                                         a
verwaltung 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
                                                                a
Vorteile von VWE gegen¨ber anderen ERP-Systemen ist die Mehrw¨hrungsf¨higkeit. D.h.
                          u                                            a      a
Buchungen und andere Transaktionen lassen sich flexibel in verschiedenen, frei definierbaren
W¨hrungen durchf¨hren und umrechnen. Hierdurch wird die M¨glichkeit eines internationa-
   a                u                                           o
len Einsatzes m¨glich. Die Umsetzung der W¨hrungen-Pflege dient in diesem Kapitel lediglich
                o                           a
als Beispiel, da sie zum einen im Vergleich zu anderen Programmpunkten nicht besonders
umfangreich ist, zum anderen aber f¨r ihren Umfang viele verschiedene GUI-Komponenten
                                     u
enth¨lt. Der Frage, inwieweit eine solche Funktionalit¨t im Internet-Umfeld uberhaupt Sinn
     a                                                a                     ¨
macht, soll deshalb hier nicht nachgegangen werden.

7.1 Vorbereitung
7.1.1   Die IDL-Beschreibung
Am 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
                    a
entsprechende Methoden f¨r die Bearbeitung der BOs zur Verf¨gung stellt. Die Beschreibung
                        u                                  u
der 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
7.1    Vorbereitung                                                                   164


      • Eine Notiz

      • Den Importcode

      • Angabe, ob es sich bei der W¨hrung um den Euro handelt
                                    a

Diese Angaben werden in einer entsprechenden IDL-Datei festgehalten. Da VWE den
Use-Case bereits f¨r die Desktop-Version definiert, existiert bereits eine IDL-Beschreibung
                   u
f¨r W¨hrungen. Sie befindet sich im Verzeichnis source/corba/framework/Currency.idl.
 u    a
Dort 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                           u
das Abfragen aller Einheiten und getCurrencyByOid() um eine W¨hrung durch die Angabe
                                                                  a
der ObjectID zu finden. Außerdem wird eine Methode ben¨tigt, mit der eine Liste aller ISO-
                                                          o
Codes abgefragt werden kann. Diese Funktionalit¨t bietet findSwiftcodes. Das folgende
                                                   a
Listing 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;
                      };
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,
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 (
7.1     Vorbereitung                                                                  167


                                 serverbase::applicationexception::AccessDeniedException,
                                 serverbase::applicationexception::ApplicationLayerException,
                                 serverbase::applicationexception::PersistencyException,
                                 serverbase::applicationexception::DomainException
                            );

                       };
                  };
             };
        };
};

#endif // CURRENCY_IDL

7.1.2    Die Server-Funktion
Der n¨chste Schritt zur Umsetzung der Anwendung ist die Implementierung des IDL-
       a
Interfaces als Server-Funktion. Dadurch, dass VWE bereits die W¨hrungsverwaltung an-
                                                                  a
bietet, kann auf die vorhanden Server-Methoden zugegriffen werden. Der CORBA-Server ist
hier also schon vorhanden.

7.1.3    Die Client-BOs
Als n¨chstes m¨ssen die IDL-Strukturen in Java-Klassen abgebildet werden, damit die Serv-
      a        u
lets auf die Daten zugreifen k¨nnen. Diese Klassen werden auch als Business-Objekte (5.4)
                               o
bezeichnet. Es handelt sich hierbei um JavaBeans, die den Namen der Struct, allerdings mit
der 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-
        u
dern, wurde ein Perl-Skript namens WebBOBuilder geschrieben. Es befindet sich im Verzeich-
nis source/web/templates und erwartet als Kommandozeilen-Parameter den Namen der
IDL und die Bezeichnung der Struktur, aus der die Klasse generiert werden soll. Der Aufruf
lautet demzufolge:

perl WebBoBuilder.pl framework/Currency.idl CurrencyStruct
perl WebBoBuilder.pl framework/Currency.idl EmuDataStruct
perl WebBoBuilder.pl framework/Currency.idl SwiftcodeStruct

Das      Perl-Skript   erzeugt    automatisch    eine    Java-Datei     im     Verzeichnis
source/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
                                           a
untergebracht werden. Mehr dazu folgt sp¨ter.
                                         a
Die erzeugte Java-Datei l¨ßt sich nun schon fast vollst¨ndig und l¨ßt sich fehlerfrei kom-
                          a                            a          a
pilieren. Bei komplexeren Strukturen ist unter Umst¨nden eine kleine manuelle Korrektur
                                                    a
7.1   Vorbereitung                                                                   168


notwendig. Jedenfalls hat das Perl-Skript dem Entwickler bereits eine Menge Arbeit
abgenommen.
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
                                                                                  o
eines BOs werden von den commit() bzw. delete() Methoden der Klasse ubernommen.
                                                                          ¨
Sie werden bereits vom Perl-Skript generiert. Weitere Methoden werden meist als statische
Methoden wie folgt hinzugef¨gt.
                           u

public 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
                                             a
mitgegeben bekommt, damit die Zugriffsberechtigung uberpr¨ft werden kann. Mit der au-
                                                      ¨     u
tomatisch generierten Funktion getServant() wird zun¨cht ein Servant geholt. Nun kann
                                                        a
die passende Methode aus der IDL (hier getCurrencies()) mit diesem Servant aufgerufen
werden. Die vom Perl-Skript geschriebenen Hilfsfunktion toBoArray() sorgt daf¨r, dass die
                                                                             u
IDL-Sequenz in eine Array mit CurrencyBOs umgewandelt wird. Alle Ausnahmen werden
pauschal 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
                                                                                     a
ableitet, gefangen und behandelt.
Sollte anstelle mehrere BOs nur ein BO zur¨ckgegeben werden, kann der Konstrukter der
                                           u
Klasse 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(),
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-Server
zugegriffen werden. F¨r das Servlet und alle Klassen, die das BO verwenden, erscheint das
                     u
Objekt lokal. Die Verteilung der Anwendung gestalltet sich folglich v¨llig transparent.
                                                                     o

7.1.4    Die Enumerations
Die IDL beschreibt weiterhin eine Aufz¨hlung (Enumeration). Diese kann ebenfalls mit einem
                                      a
Perl-Skript in eine Java-Klasse exportiert werden. Hierzu muss das Skript WebEnumBuilder
aufgerufen werden.

perl WebEnumBuilder.pl framework/Currency.idl RoundingEnum

Ergebnis ist eine Java-Datei mit dem Namen RoundingHelper.java im selben Verzeichnis
wie 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
               u
Translator-Objektes (6.2.1) angepasst werden, zum anderen muss in der init()-Methode
die 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
                                   u
aus 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                                                                  o
Servlets umgesetzt werden.

7.2 Listen-Ansicht
7.2.1 Das ListServlet
Die W¨hrungen-Verwaltung unterteilt sich wie die meisten Anwendung der VWE in eine
        a
Listen- und eine Detail-Ansicht. Der Anwender bekommt zu Beginn als erstes eine Listen¨ber-
                                                                                      u
sicht geboten, die die BOs mit den wichtigsten Attributen auff¨hrt. Die Frage, welche Daten
                                                               u
die Listen-Ansicht zur Verf¨gung stellen soll, wird bereits vom vorhandenen C++-Client be-
                           u
antwortet. Es sind Code, Name, ISO-Code, W¨hrungseinheit, Untereinheit, Dezimalstellen,
                                                a
Rundung 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 die
Klasse 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
7.2   Listen-Ansicht                                                                     170


                                                                                    ¨
CurrencyListServlet tragen. Die Klasse definiert zuerst den Translator, der f¨r die Uber-
                                                                             u
setzung zust¨ndig ist, als konstante Klassenvariabel. Die Angabe f¨r die Parameter lassen
             a                                                    u
sich 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
                                                ¨                 u
GET-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
                               a
GuiHelper (6.3.1) eine statische Methode addGrid() bereit. Sie erwartet als Parameter den
VContext und eine sog. State-Klasse. Eine State-Klasse, oder kurz State genannt, formatiert
die Tabelle und behandelt Benutzereingaben in Tabellenzellen. Oberklasse aller States ist
VState (6.1.6). Ein solcher State wird im n¨chsten Schritt entworfen. F¨r das ListServlet ist
                                           a                            u
es zun¨chst nur wichtig zu wissen, dass ein solcher State existiert. Er wird der GuiHelper-
      a
Methode 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 Sprache
erscheint, wird sie mit dem Translator-Objekt erstellt.

GuiHelper.setHeadLine(
    ctx,
    translator.getCaption(
         ctx,
         "vcurrencyform"
    )
);
7.2     Listen-Ansicht                                                                 171


Als n¨chstes muss noch die Men¨leiste angepasst werden. Listenansichten erlauben als
       a                         u
Men¨-Aktion lediglich das Anlegen eines neuen Objektes. Alle anderen Icons sind akti-
     u
viert. Die Klasse MenuBarBean (6.3.21 besitzt zur Herstellung dieses Layouts die Methode
toListView().

MenuBarBean menu = new MenuBarBean(ctx);
menu.toListView();

Die Verarbeitung ist nun abgeschlossen. Zum Schluß muss nun nur noch die Kontrolle an
eine JSP-Seite abgegeben werden, die die Angaben darstellt. Diese Vorgehensweise entspricht
dem unter 5.2 angesprochenen MVC-Modell.

7.2.2    Der ListState
Wie 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
                                                      o
die Formatierung ubernommen werden.
                  ¨
States f¨r Listenansicht sollten von der Klasse VListServlet (6.1.2) ableiten.
        u

public class CurrencyListGridState extends VListState

                      a                                                  u      ¨
Auch hier sollte zun¨chst ein Translator-Objekt angelegt werden, das f¨r die Ubersetzung
zust¨ndig ist. Außerdem ist es ratsam, alle Spaltennamen als int-Konstanten zu definieren.
    a
Hierdurch 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
                                                                              u
sehen 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
                                                             u
writeData(), 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 a
werd mit der statischen Methode des BOs alle Objekte vom CORBA-Server erfragt. In einer
Schleife werden die Objekte durchlaufen und f¨r jedes Objekt eine neue Zeile an die Tabelle
                                              u
angehangen. Hierzu dient die Methode addRow() der GridBean, die als Parameter die Liste
der Spaltenwerte besitzt. Diese Spaltenwerte, also der Code, Name, Rundung etc, wird mit
den Getter-Methoden des BOs abgefragt. Dementsprechend sieht die Funktion wie folgt aus.
7.2   Listen-Ansicht                                                                     172


public 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       a
ver angefordert wurden, mit der Methode registerBos() beim VContext angemeldet. Dies
                                                              ¨
erm¨glicht es, eine Statusmeldung mit den Daten der letzen Anderungen anzuzeigen, wenn
    o
der 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                a
was anderes, wie beispielsweise ein Ordner im TaskReminder-Use-Case sein. W¨hrungen sind
                                                                               a
unabh¨ngig von einem Parent-Objekt. Deshalb wird hier einfach der Leerstring angegeben.
       a
Als zweites f¨llt auf, dass das Ergebnis der getDecimalplaces()-Funktion in einen Short-
              a
Konstruktor gepackt wurde. Der Grund daf¨r ist der, dass die addRow()-Methode einen Array
                                           u
von Objects erwartet. Da der R¨ckgabewert der Getter-Funktion vom Typ short ist, der
                                   u
als 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            u
Als drittes und letztes soll noch auf den Wert f¨r den Rundungsmodus eingegangen werden.
                                                u
Hier zeigt sich die Verwendung der in der Vorbereitungsphase erzeugten Helper-Klasse. Die
Funktion getString() des RoundingHelpers sorgt daf¨r, dass ein RoundingEnum-Objekt als
                                                       u
String in der aktuellen Sprache angezeigt wird.
    Bevor die Bearbeitung der State-Klasse entg¨ltig abgeschlossen werden kann, m¨ssen
                                                   u                                   u
noch die Formatierungsangaben gemacht werden. Weil die Listenansicht keine M¨glichkeit
                                                                                   o
7.2   Listen-Ansicht                                                                       173


bietet, Daten einzugeben bzw. diese zu ver¨ndern, m¨ssen in VListState-Klassen in der Regel
                                           a         u
nur wenig Formatierungsangaben gemacht werden. Hier m¨ssen nur Spalten¨berschriften
                                                              u                u
gesetzt werden und evtl. die Art der Zelleninhalte angegeben werden. Letzteres geschieht
mit 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
                                                                     u
W¨hrungsliste soll jedoch die Angabe f¨r die Dezimalstellen als Zahl und somit rechtsb¨ndig
  a                                     u                                              u
angezeigt werden. Die Methode getEditor() muss folglich angeben, dass es sich bei Werte
dieser 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                             u
den.
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.
                                                                    a
Nun sind alle Java-Klassen f¨r die Listen-Ansicht implementiert worden. Was fehlt ist die
                             u
Darstellung. Diese wird mit einer JSP-Seite realisiert, an die das ListServlet wie oben gezeigt
die Kontrolle ubergibt.
              ¨

7.2.3 Die JSP-Listen-Seite
Die 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
7.2    Listen-Ansicht                                                                  174


Klassen implementiert, kann ein Designer sich mit dem Design der Ausgabe besch¨ftigen.
                                                                                   a
Die Bearbeitung geschiet hier parallel und vollkommen unabh¨ngig voneinander. Dabei ha-
                                                              a
ben JSP-Seiten unter normalen Umst¨nden immer einen sehr ¨hnlichen Aufbau. Es bietet
                                      a                        a
sich 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¨ru
die Programm-Teile entsprechende Unterverzeichnisse. So sollte die W¨hrungs-Seite unter
                                                                       a
framework/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 positionieren

Dies 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/>
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 von
Java-Klassen der Taglib (6.4) behandelt. Deren Ausgabe erscheint dann anstelle der Tags. So
k¨nnen die Daten, die von dem Servlet erzeugt werden, in eine JSP-Seite eingebettet werden.
 o

7.2.4    Zusammenfassung
Nach den oben beschriebenen Schritten ist die Listenansicht komplett. Der Ablauf ist
dabei immer identisch. Man erzeugt zuerst aus der Use-Case-Beschreibung die IDL und
implementiert den Server. Sehr oft sind diese Schritte bereits vollzogen. Die Perl-Skripte
WebBoBuilder und WebEnumBuilder bilden Structs und Enumerations in Java-Klassen,
die Servlets verwenden k¨nnen. Das Servlet leitet von VListServlet ab, erzeugt mit
                           o
dem GuiHelper eine Tabelle, der eine VListState-Klasse ubergeben wird. Diese f¨llt und
                                                           ¨                       u
formatiert 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           u
identisch. 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           u
um das Laden abzubrechen. Der State muss die Methode isCallback() so uberladen,
                                                                           ¨
7.3     Detail-Ansicht                                                                 176


dass sie true zur¨ckgibt und das F¨llen der Tabelle in die Methode putDataRows() ver-
                 u                  u
schieben. F¨r ein Beispiel sei auf die Klasse PersonalAccountListGridState im Packet
           u
com.varial.accounting.servlet verwiesen.

7.3 Detail-Ansicht
7.3.1    Das DetailServlet
Nachdem der Anwender ein BO aus der Listenansicht ausgew¨hlt hat, werden ihm in der
                                                                a
Detail-Ansicht weitere Informationen zur Verf¨gung gestellt. Hier befinden sich dann auch
                                               u
die Objekt-Attribute, die in der Listen-Ansicht nicht angezeigt wurden. Da die W¨hrungen-
                                                                                a
Verwaltung im Verh¨ltnis zu anderen Programm-Modulen nur wenige Daten anzeigt, verwen-
                     a
det VWE hier keine Tabsheet um die Daten zu strukturieren. Dies macht zwar durchaus Sinn,
im Rahmen der Beispielumsetzung sollen aber Registerkarten verwendet werden, um einen
m¨glichst breiten Funktionsumfang der VWE-Web-API zu demonstrieren. Deshalb werden
  o
die 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 VDetailServlet

Als n¨chster Schritt ist auch beim DetailServlet die Angabe eines Translators notwendig,
      a
um Bildschirmtexte zu ubersetzen. Ein Blick in Sophia oder die Datenbank verr¨t die Anga-
                        ¨                                                       a
ben currency“ und vcurrencydetailframe1“ als Parameter. Weiterhin ist auch in dieser
     ”                ”
Klasse die Einf¨hrung von int-Konstanten hilfreich. Die drei Tabsheet-Register werden als
               u
Konstanten definiert, so dass ein benannter Zugriff anstelle des nichtssagenden Index m¨glich
                                                                                     o
sein 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 bearbeitet
werden. Hierzu erzeugt man eine neue MenuBarBean und ruft deren Methode hideIcon()
mit dem Parameter MenuBarBean.COMBOBOX auf. Dadurch wird die Men¨leiste erstellt und
                                                                      u
die 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);
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-Angabe
zu 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-
             a
den. Hierzu bietet jede VDetailServlet-Klasse die Funktion fillBO(), auf die sp¨ter genauer
                                                                               a
eingegangen wird. An dieser Stelle ist es ausreichend zu wissen, dass diese Funktion immer
den aktuellen Stand des BOs liefert. Der R¨ckgabewert ist jedoch immer vom Typ Object.
                                            u
Ein 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       a
den m¨ssen nur noch die GUI-Elemente mit dem GuiHelper erstellt werden. Den Anfang
      u
macht 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 der
Methode 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                        u
sich auf der aktiven Karte befinden, ist es uberfl¨ssig, alle Komponenten zu erzeugen. Eine
                                           ¨    u
bessere Performance wird dadurch erreicht, dass lediglich die Felder im Servlet erzeugt und
gef¨llt werden, die sp¨ter auch angezeigt werden. Aus diesem Grunde wird die Erzeugung
   u                   a
der Felder in drei Bl¨cke einer switch-Anweisung unterteilt, die jeweils nur dann ausgef¨hrt
                     o                                                                  u
werden, wenn die jeweilige Karte ausgew¨hlt wurde.
                                        a
7.3   Detail-Ansicht                                                                     178


switch (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;
} // switch
Dadurch, dass zu Beginn Konstanten f¨r die Tabsheet-Register definiert wurden, k¨nnen
                                        u                                              o
hier die Namen der Karten verwendet werden, was die Lesbarkeit und die Wartung des
Codes deutlich verbessert. Im ersten Register wird zun¨chste ein Textfeld f¨r die Eingabe
                                                       a                     u
der Code-Bezeichnung erstellt. Hierf¨r wird die Methode addTextField() des GuiHelpers
                                    u
aufgerufen. Als Parameter erwartet diese den VContext, den Translator, den Namen, den
das Feld bekommen soll, die Beschriftungsbezeichnung, mit derren Hilfe der Translator die
Feldbeschriftung ubersetzt und nat¨rlich den Wert, den das Feld anzeigen soll. In diesem Fall
                  ¨               u
ist es der Code der W¨hrung, der mit der Funktion getCode() abgefragt wird. Folglich lautet
                     a
der Aufruf:
// Code
GuiHelper.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                                                                     a
k¨nnen analog dazu erstellt werden.
 o
// Name
GuiHelper.addTextField(
    ctx,
    translator,
    "details__namelabel",
    "namelabellabel",
    mBo.getDescription()
);

// Unit
GuiHelper.addTextField(
    ctx,
    translator,
7.3   Detail-Ansicht                                                                     179


      "details__unitlabel",
      "unitlabellabel",
      mBo.getUnitname()
);

// Subunit
GuiHelper.addTextField(
    ctx,
    translator,
    "details__subunitlabel",
    "subunitlabellabel",
    mBo.getSubunitname()
);


// Import Code
GuiHelper.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            o
kann entweder frei eingegeben werden oder der Benutzer w¨hlt die passende Bezeichnung aus
                                                         a
einer Liste vorgefertigter ISO-Codes aus. Eine solche Funktionalit¨t stellt der Drei-Punkte-
                                                                  a
Button repr¨sentiert durch die Klasse LabeledButtonTextField (6.3.8) zur Verf¨gung. Die
             a                                                                   u
GuiHelper-Funktion addButtonField() erzeugt die Komponente. Als zus¨tzlichen Parame-
                                                                           a
ter erwartet die Methode die URL einer Seite bzw. eines Servlets, das den Auswahldialog
darstellt. 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
                                                   a
StringBuffers und der Methodenaufruf setDirectEdit(true). Der StringBuffer spezi-
fiziert die Adresse des Servlets, das sp¨ter die Auswahlseite darstellt. Dieser Seite wird als
                                       a
7.3   Detail-Ansicht                                                                    180


Query-String-Parameter der aktuelle ISO-Code ubergeben. Da das Zusammenf¨gen zwei-
                                                    ¨                            u
er String-Objekte intern relativ viel Speicher und dadurch auch viel Rechenzeit ben¨tigt,
                                                                                       o
wird ein StringBuffer verwendet, der diese Aufgabe schneller erledigt. Die Funktion
setDirectEdit() sorgt daf¨r, dass auch freie Eingaben in das Feld m¨glich sind. Ohne
                              u                                            o
diesen Aufruf k¨nnten Werte f¨r das Feld ausschließlich durch die Auswahl vordefinierter
                 o               u
Angaben ge¨ndert werden. Da die addButtonField()-Methode wie jede add()-Methode des
             a
GuiHelpers das erzeugte Objekt zur¨ckliefert, kann die Methode direkt mit der dem Funk-
                                       u
tionsaufruf verbunden werden.
Bei den Feldern f¨r die Angabe der Dezimalstellen und des Rundungsverfahrens handelt es
                   u
sich um Combo-Boxen. Sie werden durch den GuiHelper und dessen addComboBox()-Methode
erzeugt. Diese Methode erwartet neben einer Liste von Eintr¨gen f¨r die Combo-Box den In-
                                                             a     u
dex des aktuell ausgew¨hlten Eintrags. Die Erstellung der Combo-Box f¨r die Rundungsart
                        a                                                u
ist recht einfach. Gl¨cklicherweise stellt der RoundingHelper, der zuvor von dem Perl-Skript
                     u
erzeugt wurde, alle n¨tigen Methoden zur Verf¨gung. Die getStrings()-Methode liefert alle
                      o                          u
Eintr¨ge f¨r die Combo-Box, mit indexOfEnum() kann der Index eines Eintrags abgefragt
      a    u
werden. Als Befehl zum Erzeugen der Combo-Box ergibt sich damit:

// Rounding Mode
GuiHelper.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                                                                               u
Enumeration definiert. Vielmehr beschreibt sie zwei Konstanten MIN DECIMAL PLACES und
MAX DECIMAL PLACES. F¨r das Servlet ist dadurch noch ein wenig Java-Code erforderlich.
                      u

int 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);
}
7.3   Detail-Ansicht                                                                    181


Diese Zeilen erzeugen einen String-Array, der die Eintr¨ge f¨r die Dezimalstellen-Auswahl
                                                        a   u
beinhaltet. 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                              a
aktuellen 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                                                  u
G¨ltigkeitsdatums. Hierf¨r wird die addDateField()-Methode des GuiHelpers verwendet,
  u                      u
die ein Feld f¨r eine Datumseingabe, ein sog. DateField (6.3.6) erstellt. Die Verwendung
              u
entspricht der eines normalen Textfeldes.
// Use Until
GuiHelper.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,
                                                                        u
die Angaben zur Verwendung im Rahmen der Europ¨ischen W¨hrungsunion enth¨lt. Dort
                                                        a          a               a
befindet sich zuerst eine Check-Box, die angibt, ob es sich bei der W¨hrung um den Euro han-
                                                                     a
delt oder nicht. Zur Erstellung einer solchen Check-Box kann die addCheckBox()-Methode
des GuiHelpers verwendet werden. Wie jede add()-Methode der Klasse liefert sie als R¨ck-
                                                                                       u
gabewert die erzeugte Komponente. In den meisten F¨llen wird diese R¨ckgabe ignoriert,
                                                          a               u
in diesem Fall kann sie aber dazu genutzt werden, weitere Eigenschaften der Check-Box zu
setzen. Da die Eigenschaft nicht vom Benutzer gesetzt werden kann, ist dieses Feld nicht
editierbar. Deshalb wird die Eigenschaft enable auf false gesetzt. Es entsteht folgender
Aufruf.
// Is Euro
GuiHelper.addCheckBox(
    ctx,
    translator,
    "emu__iseurolabel",
    "iseurolabel",
    mBo.isTheEuro()
).setEnable(false);
7.3   Detail-Ansicht                                                                     182


Die zweite Check-Box f¨r die Angabe, ob es sich um eine W¨hrung der EWU handelt, kann
                       u                                    a
genauso implementiert werden. Allerdings werden hier Abh¨ngigkeiten von Feldern definiert.
                                                          a
Eine Eingabe in die Felder f¨r das Startdatum der G¨ltigkeit und den Umrechnungskurs zum
                            u                      u
Euro ist nur dann sinnvoll, wenn diese Check-Box aktiviert ist. Folglich muss beim Erzeugen
der Check-Box angegeben werden, dass die anderen Felder nur im Falle einer Aktivierung zur
Verf¨gung stehen. Hierzu dient die Klasse JavaScriptHelper (6.3.29), die f¨r ein solches Sze-
    u                                                                      u
nario 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                 u
der enableByCheckBox()-Funktion kann wiederum der GuiHelper-Methode als zus¨tzlichera
Parameter ubergeben werden. Zusammen ergibt sich der folgende Funktionsaufruf.
           ¨
// EMU Currency
GuiHelper.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 Currency
GuiHelper.addDateField(
    ctx,
    translator,
    "emu__dateemucurrencylabel",
    "dateemucurrencylabel",
    mBo.getisEmuCurrencyUnion().getDateEmuCurrency()
);

// EMU Rate
GuiHelper.addNumberField(
    ctx,
    translator,
    "emu__emuratelabel",
    "emuratelabel",
    mBo.getisEmuCurrencyUnion().getEmuRate()
);
7.3   Detail-Ansicht                                                                     183


Somit w¨re auch der zweite Tabsheet-Reiter vollst¨ndig. Der letzte Reiter besteht nur aus
         a                                          a
einem Feld. Es handelt sich hierbei um ein mehrzeiliges Textfeld, das zur Angabe von diversen
Notizen gedacht ist. Um ein mehrzeiliges Textfeld zu erzeugen, sollte die addTextArea()-
Funktion der GuiHelper-Klasse verwendet werden. Die Handhabung entspricht exakt der
eines 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                                               ¨                            a
Beschriftung ausschalten. Eine Feldbezeichnung ist hier nicht notwendig, weil das Tabsheet-
                                                                         ¨
Register keine weitern Felder enth¨lt. Somit bildet bereits die Register-Uberschrift eine Be-
                                    a
zeichnung f¨r das Eingabefeld.
            u
Nachdem nun alle GUI-Elemente erzeugt wurden, kann auch hier die Verarbeitung an eine
JSP-Seite weitergegeben werden. Genau wir bei der VListServlet-Klasse dient hierzu der
Aufruf von forwardToJsp().

forwardToJsp(
    ctx,
    "/framework/currency/CurrencyDetail.jsp",
    menu
);

Nachdem die Ober߬che erzeugt wurde, sollen nun noch die Methoden getBO() und fillBO()
                     a
der Klasse angesprochen werden. Beide Methoden sind in der Oberklasse VDetailServlet
als abstrakt gekennzeichnet. Das bedeutet, dass alle abgeleiteten Klassen diese Methoden
implementieren m¨ssen. Die Methoden dienen dazu, das jeweils aktuelle BO zu erfragen.
                   u
fillBO() 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 nicht
in der Datenbank gespeichert wurde. Damit BOs auf eine solche Weise tempor¨r zwischen-
                                                                              a
gespeichert werden k¨nnen, ohne dass ein Speichern in der Datenbank notwendig ist, wurde
                       o
die Klasse TempData (6.1.15) entworfen. Mit ihr k¨nnen BOs in der Session gespeichert und
                                                 o
aus dieser geladen werden. Genau diesen Mechanismus stellt getBO() bereit.
In dieser Methode wird das BO aus dem TempData-Speicher geladen. Wird dort ein BO
gefunden, wird es zur¨ckgegeben. Sollte kein BO gefunden werden, gibt es zwei weitere
                         u
M¨glichkeiten. Erstens kann es sein, dass das BO gerade vom Benutzer neu angelegt wurde.
  o
In diesem Fall wird eine neue Instanz des BOs zur¨ckgegeben. Zweitens k¨nnte die Anfra-
                                                   u                     o
ge die erste sein. Folglich wurde noch kein BO in den TempData-Speicher geschrieben. Die
getBO()-Methode muss dann mit der Server-Funktion das BO mit der ObjectID erfragen.
       ¨
Diese Uberlegungen f¨hren zu folgender Implementierung:
                       u

protected BO getBO (VContext ctx) {
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-
                                                a
Speicher 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
     a
das 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
                                                                 a
Tabsheet-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;
} // switch
Das BO wird auf den neusten Stand gebracht, indem zuerst die Formularwerte mit einer der
getAttribute()-Methoden des VContexts abgefragt werden und diese dann an die Setter-
Methoden des BOs ubergeben werden.
                  ¨
// Code
mBo.setCode(
    ctx.getStringAttribute(PARAMETER, "details__codelabel")
);
7.3   Detail-Ansicht                                                                   185


Hier 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,
                                                                               u
Haupt-, Untereinheit und Importcode gesetzt. Auch der Wert des LabeledButtonTextFields
wird so gesetzt.

// Code
// SWIFT
mBo.setSwift(
    ctx.getStringAttribute(PARAMETER, "details__swiftlabel")
);

Bei der Eingabe der G¨ltigkeitsdauer wurde ein Datumsfeld verwendet. Solche Parameter
                        u
sollten mit getDateAttribute() abgefragt werdebm da dieser Methode den R¨ckgabewert
                                                                          u
bereits in ein passendes Format f¨r den Serveraufruf formatiert.
                                 u

// Use Until
mBo.setStopDate(
    ctx.getDateAttribute(PARAMETER, "details__useuntillabel")
);

Als letztes fehlen die beiden Combo-Boxen. Ihr Wert kann mit getIntAttribute() abgefragt
werden. Man erh¨lt den Index des selektierten Eintrags. Auch f¨r die Umwandlung des Index
                  a                                           u
in ein Enum-Objekt bietet der automatisch erzeugte RoundingHelper eine passende Funktion
getIdl().

// Rounding
mBo.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                                                               u
MIN DECIMAL PLACES addiert werden muss.

// DecimalPlaces
mBo.setDecimalplaces(
    (short)(
        ctx.getShortAttribute(PARAMETER, "details__decimalplaceslabel") +
        MIN_DECIMAL_PLACES.value
    )
);

Beim zweiten Tabsheet-Register ist zu beachten, dass die IDL-Struktur hier eine Union
enth¨lt. Unions erm¨glichen es, in verschiedenen Situationen unterschiedliche Datentypen zu
    a              o
verwenden. In diesem Fall bedeutet das konkret, dass die Klasse CurrencyBO eine Instanz der
7.3   Detail-Ansicht                                                                    186


Klasse EmuDataBO enthalten kann oder nicht. Ist die Check-Box f¨r die EWU aktiviert, enth¨lt
                                                               u                         a
das W¨hrungs-BO auch ein EmuDataBO, andernfalls nicht. Die Attribute des EmuDataBOs wer-
      a
den durch die jeweiligen Setter-Methoden an die Benutzereingaben angepasst.
// EMU Currency
if (!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 bei
den Textfeldern des ersten Registers.
// Notes
mBo.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 der
fillBO()-Funktion zur¨ckgeliefert werden.
                     u
// Notes
TempData.storeBO(ctx, mBo);
return mBo;
7.3     Detail-Ansicht                                                                 187


7.3.2    Die JSP-Detail-Seite
Genau 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-
                          o
zugriff 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 (Index
in der Navigationsreihenfolge), oidparent (ObjectID des Parent-Objekts) und enablesave
(Angabe, ob der Speicher-Button aktiviert ist). Durch die Verwendung des hiddenfield-Tags
der Varial-Taglib wird garantiert, dass die Parameterwerte w¨hrend der Verarbeitung nicht
                                                              a
verloren 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 der
Oberfl¨che ver¨ndert, wird von ihnen die JavaScript-Methode enableSave() aufgerufen, die
      a       a
den 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                                                                                  u
werden. 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 Tabelle
angeordnet. 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");
%>
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"/>
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"/>
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 dem
tabsheetcontrol-Tag umrandet. Jedes einzelne Register befindet sich wiederum in einem
tabsheet-Tag, das daf¨r sorgt, dass der Inhalt nur dann angezeigt wird, wenn die jeweilige
                      u
Register-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    Zusammenfassung
Nach 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 dem
GuiHelper passende Elemente, die als Wert die Ergebnisse der Getter-Methoden erhalten.
Anschließend wird die Bearbeitung an eine JSP-Seite zwecks Visualisierung abgegeben. Ein
DetailServlet definiert ferner die Methoden getBO() und fillBO(). W¨hrend getBO() nur
                                                                      a
das 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
          u
Setter-Methoden des BOs die Query-String-Parameter ubergeben.
                                                        ¨

7.4 Auswahl-Dialog
Einige Use-Cases beinhalten diverse Auswahl-Dialoge. Im Beispiel ist dies die Auswahl des
ISO-Codes aus einer Liste vordefinierter Angaben.

7.4.1    Das SelectServlet
Servlets, 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");
7.4     Auswahl-Dialog                                                                  191


Um 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 beispielsweise
ein 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
                                                                        u
erfolgen. Ein Klick auf das Reload-Icon aktuallisiert die Tabelle. Durch Aktivierung der ne-
benstehenden Check-Box erfolgt die Aktuallisierung automatisch nach jedem eingegebenen
Zeichen.

// Headline
GuiHelper.setHeadLine(ctx, translator.getCaption(ctx, "vsearchswiftform"));

// Search
GuiHelper.setSearch(ctx, translator.getCaption(ctx, "vsearchswiftform"));

// Grid
GuiHelper.addGrid (
    ctx,
    new SelectIsoCodeGridState()
);

// Forward to JSP
forwardToJsp(
    ctx,
    "/framework/currency/SelectIsoCode.jsp"
);

7.4.2    Der SelectState
Durch die Verwendung einer Tabelle auf der Auswahlseite muss eine passende State-
Klasse entworfen werden. Sie tr¨gt den Namen SelectIsoCodeGridState und wird von
                                 a
VSelectState (6.1.9) abgeleitet. Sie beinhaltet einige bekannte Elemente. So wird auch hier
ein 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)
7.4   Auswahl-Dialog                                                                    192


In der Methode wird zun¨chst der Query-String-Parameter search gelesen, der angibt,
                           a
welche Eingabe bereits vom Benutzer get¨tigt wurde. Der Tabelleninhalt soll ja entsprechend
                                        a
angepasst 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 Accounts
SwiftcodeBO[] swifts =
    SwiftcodeBO.findSwiftcodes(
        ctx,
        code
    );
Nun wird die Tabelle durch Aufruf der addRow()-Methode in einer Schleife genau wie bei der
Listen-Ansicht gef¨llt.
                  u
// Fill grid
grid.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                 a
Query-String-Parameter gesetzt wird. Es ist der jeweilige ISO-Code, der als selectedCode
ubergeben wird. Diese Angabe dient dazu, dass das SelectServlet erf¨hrt, welcher Eintrag der
¨                                                                   a
Liste ausgew¨hlt wurde. Normalerweise liefert jede Zeile in einem VSelectGrid die ObjectID
             a
des jeweiligen Eintrags. Das SelectServlet kann dar¨ber das passende Objekt finden. Da der
                                                   u
CORBA-Server aber in der IDL aber keine Methode bereit stellt, mit der ein SwiftcodeBO
7.4     Auswahl-Dialog                                                                193


bzw. ein SwiftcodeStruct¨ber die ObjectID erfragt werden kann, muss statdessen die Code-
                        u
Angabe verwendet werden.
Wie gewohnt definiert auch diese State-Klasse die Tabellen¨berschriften.
                                                         u

public 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
                                                                          u
des 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 Aktionsbezeichnung
an das Select-Servlet ubertragen. Das Servlet weiß dann, welche Aktion ausgef¨hrt wurde.
                      ¨                                                          u
Bei 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-Seite
Die JSP-Seite unterscheidet sich nicht viel von der Listen-Ansicht. Jedoch wird zus¨tzlich
                                                                                   a
das Suchfeld durch das selectsearch-Tag eingebunden. Außerdem m¨ssen genau wie bei
                                                                      u
der JSP-Seite f¨r die Detaildarstellung einige Parameter mit versteckten Formularfeldern
                u
zwischengespeichert werden, damit die entsprechenden Werte nicht w¨hrend der Verarbeitung
                                                                   a
verloren 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);
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>
7.5     Abschluss                                                                        195


7.4.4    Zusammenfassung
Auswahldialoge bestehen zumeist aus einem Servlet, das von der Klasse VSelectServlet
abgeleitet wird, und einer State-Klasse, einer Unterklasse von 6.1.9. Der Aufbau ist fast
identisch mit der Listenansicht, jedoch kann zus¨tzlich ein Suchfeld erstellt werden, das den
                                                a
Inhalt der Tabelle filtert. Jede Auswahl hat eine eindeutige Aktionsbezeichnung, durch die
die Auswahl vom DetailServlet erkannt wird.

7.5 Abschluss
Die VWE-Web-GUI erm¨glicht den Entwurf grafischer Benutzeroberfl¨chen f¨r die Browser-
                        o                                             a      u
Darstellung. 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                                                       u
Web implementiert werden. Die Umsetzung der W¨hrungsverwaltung war beispielsweise
                                                       a
in knapp zwei Stunden m¨glich. Dadurch, dass die API die Feinheiten von CORBA und
                          o
das typische Request-/Response-Modell mit all seinen T¨cken vor dem Entwickler ver-
                                                            u
bergen, ist eine Entwicklung auf einer recht hohen Abstraktionsebene m¨glich. Bevor der
                                                                           o
Use-Case endg¨ltig abgschlossen ist, muss er jetzt nur noch in der Men¨struktur ver-
               u                                                              u
linkt werden. Dazu ist VWE im Administrationsmodus zu starten. Dort k¨nnen berech-
                                                                              o
tigte User die Men¨darstellung von VWE ver¨ndern. Nach Auswahl des Web-Men¨s kann
                   u                            a                                    u
die W¨hrungen-Pflege als neuer Men¨punkt aufgenommen werden. Neben einer Bezeich-
       a                               u
nung wird das Packet (com.varial.framework.servlet.currency) und der Servlet-Name
                                                    ¨
(CurrencyListServlet) angegeben. Nachdem die Anderungen gespeichert wurden, befindet
sich die W¨hrungen-Pflege im Web-Men¨. Um eine h¨here Performance zu erreichen, werden
           a                             u            o
Men¨daten jedoch im Server gecacht. In der Regel ¨ndert sich die Men¨struktur nur sehr
     u                                                a                  u
selten oder uberhaupt nicht. Infolgedessen ist die Zwischenspeicherung nicht weiter schlimm.
             ¨
Sollten neue Punkte ins Web-Men¨ aufgenommen werden. Muss der Web-Server neu gestar-
                                   u
tet werden, bevor die neuen Programmmodule angezeigt werden.
Der komplette Source-Code kann im Anhang noch einmal zusammengefasst betrachtet wer-
den.
8 Aufbau und Bedienung der Web-Oberflache
                                    ¨




                             196
9 Zusammenfassung und Ausblicke
Im Rahmen der Diplomarbeit wurde eine Klassenbibliothek entwickelt, mit der das ERP-
System Varial World Edition um ein Web-Interface erweitert werden kann. Es wurden
Techniken und Konzepte diskutiert und an Hand ausgew¨hlter Beispiele eine Realisierung
                                                           a
demonstriert.
Die Diplomarbeit zeigt zum einen, dass eine Web-Anbindung nicht nur sinnvoll ist, sondern
dass sie auch mit dem hier entworfenen System umsetzbar ist. Zum anderen zeigte sich
jedoch auch deutlich, dass der momentane Stand der Technik f¨r solche Anwendungen noch
                                                               u
nicht als ausgereift bezeichnet werden kann. Zwar bietet CORBA eine optimale Infrastruktur
f¨r verteilte Anwendungen, in der problemlos ein Servlet den Platz eines Client einnehmen
 u
kann, jedoch liegen die Schwachstellen f¨r die Entwicklung von webbasierten Anwendungen
                                         u
deutlich im Bereicht HTTP und HTML.
Da das Servlet lediglich eine HTML-Seite erzeugen kann, die dann vom Web-Server an
der Browser geschickt wird, ist es ihm nicht m¨glich, unmittelbar auf die Verarbeitung der
                                                o
Eingaben zu reagieren. Mit HTTP werden Aktionen des Web-Servers ausschließlich auf
Client-Anfrage hin ber¨cksichtigt. Somit fehlt der erzeugten HTML-Seite teilweise die n¨tige
                        u                                                              o
Programmlogik, um auf Ober߬chenereignisse und Benutzeraktionen passend zu reagieren.
                                 a
JavaScript stellt auf Grund seines eher rudiment¨ren Charakters keine wirkliche Alternative
                                                  a
zur m¨chtigen Java-API dar.
      a
Weiterhin hat sich gezeigt, dass sich die Browser unterschiedlicher Hersteller zum Teil
so stark unterscheiden, dass eine allgemein g¨ltige und auf allen Systemen lauff¨hige
                                                  u                                    a
Internet-Applikation sehr schwer und nur mit vielen Umwegen zu realisieren sind. Vor allem
in der Handhabung von DOM (Document Object Modell) unterscheiden sich die einzelnen
Browser sehr stark. Einige Varianten unterst¨tzten das Modell erst gar nicht.
                                             u
Eine weitere H¨rde, die auf dem Weg zur Realisierung eines Web-Interfaces genommen
                u
werden musste, war die Tatsache, dass einige allgemein gebr¨uchliche grafische Ober-
                                                                 a
߬chenelemement von HTML nicht angeboten werden. So gibt es beispielsweise keine
  a
editierbare Combo-Box, so dass eine entsprechende Komponente selbst aus den vorhandenen
M¨glichkeiten entwickelt werden musste.
   o
Zusammenfassend l¨ßt sich sagen, dass eine Realisierung eines webbasierten ERP-Systems
                     a
trotz der noch nicht ausgereiften Technik, erm¨glicht wurde. In Zukunft werden die entspre-
                                               o
chenden Web-Technologien sicherlich entsprechend erweitert, so dass Internet-Applikation
den gewohnten Desktop-Anwendungen in nichts nachstehen. Eventuell werden die Grenzen
zwischen diesen beiden Arten von Software bald sogar ganz verwischen, so dass zuk¨nftig
                                                                                      u
kein Unterschied zwischen Online- und Offline-Applikation mehr bestehen wird.

   Leider konnten nicht alle Ideen, die zu Beginn im Vorfeld entworfen wurden, umgesetzt
werden, da sie den Umfang der Arbeit gespregt h¨tten. Einige Vision werden vorraussichtlich
                                                a
im Anschluss an die Arbeit bei Varial in Angriff genommen werden.




                                            197
198


Erklarung
    ¨
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
             a
habe. Gleichzeitig versichere ich, daß diese Arbeit in keiner Weise, gleich oder ¨hnlich, weder
                                                                                 a
ver¨ffentlicht noch einer anderen Pr¨fungsbeh¨rde vorgelegt habe.
   o                                 u         o

Siegen, den 28. August 2002.
199


A Anhang

Tabellenverzeichnis
  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
A.1    Abbildungsverzeichnis                                                                                    200


A.1 Abbildungsverzeichnis

Abbildungsverzeichnis
  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-Ober߬che in Englisch . . . . . . . . . . . . . . . . . .
                         a                                                      .   .   .   .   .   .   .   .    39
  25     Die Web-Ober߬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
A.2   Glossar                                                                         201


A.2 Glossar
Applets Ein in Java geschriebenes Programm, das uber das Internet ubertragen und im
                                                ¨                 ¨
     Browser ausgef¨hrt wird.
                     u

BO Business-Objekt

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

Byte-Code Java-Programme werden in sog. Byte-Code kompiliert. Dieser Byte-Code ist
     plattformunabh¨ngig und kann mit einer JVM ausgef¨hrt werden,
                   a                                   u

C++ 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.
              o

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

Design Pattern Entwurfsmuster. Designvorschl¨ge f¨r den Entwurf objektorientierter Softwa-
                                             a u
     resysteme, die vordefinierte L¨sungen f¨r konkrete Programmierprobleme darstellen.
                                  o        u

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

DTD Document Type Definition. Schemadefinitionssprache, die den Aufbau einer XML-
    Datei festlegt.

Embedded-Systeme
A.2   Glossar                                                                          202


ERP Enterprise Resource Planning. Software, die ein Unternehmen bei der Abwicklung von
    Gesch¨ftsprozessen unterst¨tzt.
         a                    u

GUI Graphical User Interface. Grafische Benutzeroberfl¨che.
                                                    a

HTML Hypertext Text Markup Language. Sprache, die Hypertext-Dokumente beschriebt.
                                  ¨
HTTP Hypertext Transfer Protocol. Ubertragungsprotokoll f¨r HTML-Seiten.
                                                         u

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

IIS Internet Information Server. Web-Server von Microsoft.

Java Moderne objektorientierte Programmiersprache von der Firma Sun Microsystems

JDBC 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               u

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

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

POA 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.
A.2   Glossar                                                                          203


Regular 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.
                                                                 a
Session-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                                       u
Tag Auszeihnungsbefehl, der ein Element in HTML bzw. XML markiert.
Taglib Sammlung von zusammenh¨ngenden Tags zu einer Bibliothek.
                             a
TCP/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.
                                                                            o
URL 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 AG
VBScript Eine von Microsoft entwicklete Skriptsprachem, die sich sehr stark an Visual Basic
    anlehnt. H¨ufig verwendet f¨r die Programmierung von ASP-Seietn.
               a               u
W3C 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.
                                                         u
Web-Browser Browser
World-Wide-Web Internet
XML 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.

Diplomarbeit

  • 1.
    Diplomarbeit Entwicklung eines webbasiertenCORBA-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 i Inhaltsverzeichnis 1 Einleitung 3 2 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 . . . . . . . . . . . . . . . . . . . 25 3 Varial World Edition 26 3.1 Leistungsumfang VWE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3 Das Web-Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4 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 . . . . . . . . . . . . . . . . . . . 47 5 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 . . . . . . . . . . . . . . . . . . . . . 79 6 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 7 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 8 Aufbau und Bedienung der Web-Oberfl¨che a 196
  • 6.
    INHALTSVERZEICHNIS 1 9 Zusammenfassung und Ausblicke 197 A Anhang 199 Tabellenverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 A.1 Abbildungsverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 A.2 Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
  • 7.
    Vorwort Die vorliegende Diplomarbeitbeschreibt die Entwicklung einer Internet-Schnittstelle f¨r u das 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 a war. Aus meinem Interesse sowohl an modernen Internet-Technologien als auch an der Java- ¨ Programmierung und den strategischen Uberlegungen des Unternehmens Varial entstand die Idee, eine Anbindung der World Edition f¨r das World Wide Web zu konstruieren. Der u Grundstein f¨r VWE-Web war gelegt. u Die Arbeit ist schließlich recht umfangreich ausgefallen, da sie neben den verwendeten Technologien sowohl die Bedienung des Web-Interfaces als auch dessen Entwicklung be- schreibt. Durch die Dokumentation aller wichtigen Klassen und die beispielhafte Umsetzung einer Anwendung, soll es dem Leser erm¨glicht werden, die entwickelte API selbstst¨ndig zu o a verwenden 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 u besonderer 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 ein sehr 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 u Korrekturlesen der Arbeit opferte. Auch bei meinen Kommilitonen Maik, der neben der Korrektur f¨r viele interessante fachliche Diskussionen zur Stelle war, und Tobi f¨r seine u u Erkl¨rungen zu DCOM, SOAP & Co m¨chte ich mich an dieser Stelle herzlich bedanken. a o Ihr wart mir eine große Hilfe. Ebenfalls haben die vielen unz¨hligen User diverser Internet-Foren, wie vorzugweiße dem a SELFHTML-Forum, zum Gelingen dieser Arbeit beigetragen. Danke f¨r die vielen guten u Ratschl¨ge, Meinungen und Kritiken. a Außerdem sei meinen Mitmenschen gedankt, die mich in den letzen Monaten unterst¨tzt, u gelobt, ertragen und getr¨stet haben und mit ihrem Verst¨ndnis den n¨tigen Freiraum f¨r o a o u die Erstellung der Arbeit gegeben haben und damit deren Realisierung erst erm¨glichten. Zu o guter Letzt gilt mein besonderer Dank nat¨rlich Julia, die mir nicht nur in Zeiten technischer u Schwierigkeiten 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 mancher Tiefphase und f¨r die Fertigstellung der Arbeit lieferte. Danke! u
  • 8.
    1 Einleitung Die Industriebefindet sich zur Zeit im Wandel. Die traditionelle Wirtschaft bewegt sich hin 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 u Informations- und Kommunikationsmedium schlechthin. W¨hrend vor Jahren das Internet lediglich statische Inhalte zur Verf¨gung stellte, nimmt a u mittlerweile mehr und mehr dynamischer Content das Netz ein. Das Potential reicht jedoch weit uber die M¨glichkeiten eines einfachen eShops oder eines G¨stebuchs hinaus. So bieten ¨ o a sich auch einem modernen ERP-System interessante M¨glichkeiten, das Internet f¨r eine o u unternehmens- und weltweite Abwicklung von Gesch¨ftsf¨llen zu nutzen. a a Diese Diplomarbeit beschreibt hierzu die Entwicklung eines Systems, mit dessen Hilfe webbasierte 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. Der Server wird in Java implementiert, w¨hrend clientseitig C++ zum Einsatz kommt. a Im Rahmen der Diplomarbeit wird die Software um die M¨glichkeit erweitert, auf aus- o gew¨hlte Datenbest¨nde mittels Web-Browser zugreifen zu k¨nnen. Auf diese Weise wird a a o es dem Benutzer erm¨glicht, VWE via Intra-, Extra- oder Internet von jedem beliebigen o Arbeitsplatz zu nutzen. Hierbei kommen Java Servlets zum Einsatz. Die Arbeit gliedert sich in neun Abschnitte. Nach dieser Einf¨hrung werden im zweiten u Kapitel zun¨chst die beiden Techniken CORBA und Java Servlets vorgestellt. Hierbei werden a insbesondere Alternativen zu diesen Technologien aufgezeigt und diskutiert. Die Vorteile des verwendeten L¨sungsansatzes werden herausgestellt und die Entscheidung f¨r CORBA und o u Java Servlets begr¨ndet. u Kapitel 3 beschreibt das ERP-System VWE. Es wird ein Einblick in den Leistungsumfang und den Aufbau von VWE gegeben. Außerdem wird gezeigt, wie ein Web-Interface die bestehenden Funktionalit¨ten sinnvoll erweitern bzw. erg¨nzen kann. a a Das vierte Kapitel fasst anschließend alle Anforderungen, die an eine Browser-Oberfl¨che a gestellt werden, zusammen. Kapitel 5 zeigt, wie diese Anforderungen umgesetzt wurden und welche Fragestellungen und Probleme sich bei der Entwicklung ergaben. Kapitel 6 erl¨utert die Komponenten, die zur Realisierung entwickelt wurden. Zentrale a Packete werden aufgef¨hrt und die Funktionen der Klassen im Einzelnen erl¨utert. u a Im siebten Kapitel wird aufgezeigt, wie die entwickelten Komponenten zur Realisierung eines Use-Cases eingesetzt werden k¨nnen. Hier wird eine kleine Anwendung beispielhaft o
  • 9.
    4 umgesetzt. Kapitel 8 widmet sich der Bedienung der Web-Oberfl¨che. Der Aufbau sowie die a Handhabung des Web-Interfaces werden erl¨utert. a Das abschließende neunte Kapitel fasst noch einmal alle gewonnenen Erkenntnisse zusammen und bietet einen Ausblick auf zuk¨nftige Entwicklungen. u
  • 10.
    2 Technologie 2.1 JavaServlets Servlets 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 u sp¨ter das Interesse an Java durch den Einsatz als Applets. Bei Applets handelt es sich um a Java-Code, der in einem Web-Umfeld clientseitig, also im Browser, ausgef¨hrt wird. Dank u Javas Plattformunabh¨ngigkeit ist der Byte-Code auf jedem Betriebssytem ausf¨hrbar. Dies a u f¨hrte zusammen mit der Tatsache, dass eine solche Funktionalit¨t im Browser bislang u a unbekannt 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 u keinesfalls auf die Behandlung von HTTP-Anfragen beschr¨nkt. Denkbar w¨re auch, ein a a Servlet in einen Mail- oder FTP-Server einzubetten, um dessen Funktionalit¨t zu erweitern. a In der Praxis bilden solche Einsatzm¨glichkeiten jedoch eher die Ausnahme, so dass Servlets o uberwiegend f¨r HTTP-Anfragen verwendet werden. ¨ u 2.1.1 Entstehungsgeschichte Urspr¨nglich bestand die Aufgabe des Internets darin, Informationen in Form von statischen u Seiten zur Verf¨gung zu stellen. Der Web-Server konnte die Anfrage eines Clients durch u ¨ die einfache Ubermittlung vorgefertigter Dokumente befriedigen. Mittlerweile hat sich das Internet jedoch stark gewandelt, so dass die Bereitstellung statischer Seiten u.U. nicht mehr ausreichend ist, sondern dass f¨r jede Anfrage eine andere Seite generiert werden muss. Es u gibt 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 a nach dynamischen Web-Seiten entsprachen, gesucht. 2.1.2 Alternative Ans¨tze a Common 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 6 Bei CGI nimmt der Web-Server wie gewohnt eine Client-Anfrage entgegen, startet dann aber ein externes Programm und leitet die Bearbeitung an dieses Programm weiter. Das Programm generiert daraufhin die Antwortseite. Diese Seite kann nun vom Web-Server an den Client gesendet werden. Mit CGI k¨nnen dynamsiche Seiten in fast jeder Programmiersprache erzeugt werden. CGI o ruft lediglich ein Programm auf und erwartet eine R¨ckgabe, die an den Browser geschickt u wird. In welcher Sprache das Programm geschrieben ist spielt hierbei keine Rolle. Allerdings hat sich Perl als Programmiersprache durchgestetzt, da Perl m¨chtige Befehle zur Verar- a beitung von Texten bereitstellt (u.a. Regular Expressions), die sich im Umfeld von CGI als große Hilfe herausstellen. Auf diese Weise war es erstmals m¨glich, dynamsiche Seiten zu o erzeugen. Schnell verbreitete sich CGI und immer mehr Web-Server stellten dieses Interface zur Verf¨gung. u Der Nachteil von CGI ist jedoch, dass nicht gerade sparsam mit Serverresourcen umgegangen wird. F¨r jede Anfrage wird das verarbeitende Programm als eigener Prozess gestartet. Bei u hochfrequentierten 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 u bei CGI jedesmal der Perl-Interpreter gestartet werden. Abbildung 1 zeigt die Funktionsweise von 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 o beispielsweise nicht in das Logfile des Servers schreiben. Außerdem k¨nnen CGI-Skripte nur o recht 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 a Die Firma Open Market entwickelte eine Alternative namens FastCGI, die im Gegensatz zu CGI ein Programm immer im selben Prozess laufen l¨sst. So wird nur noch ein Prozess pro a Programm, und nicht mehr pro Anfrage gestartet. Dies f¨hrt zwar zu einer Performance- u Verbesserung, 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 7 Speziell f¨r Perl-Skripte auf dem Apache-Server wurde mod perl entwickelt. Bei mod perl u Abbildung 2: Web-Server mit FastCGI handelt es sich um ein Modul f¨r den Apache-Server, das den Perl-Interpreter direkt in den u Server einbettet. Perl-Skripte laufen so wesentlich schneller als zuvor. Dieser Ansatz ist jedoch ausschließlich f¨r Perl-Skripte, die auf dem Apache-Server laufen, geeignet. u Server-Extension-API Einige Serverhersteller entwickelten sog. Extension-APIs f¨r ihre u Web-Server. Auf diese Weise k¨nnen Server um weitere Funktionalit¨ten erweitert werden. o a Beispiele hierf¨r sind ISAPI f¨r Microsofts Internet Information Server (IIS) oder WAI (ur- u u spr¨nglich ver¨ffentlicht unter der Bezeichnung NSAPI) von iPlanet/Netscape f¨r deren Ser- u o u ver. Abbildung 3 stellt die Funktionsweise der Server-Extensions dar. Diese Erweiterungen sind i.d.R. in C++ geschrieben, was eine hohe Performance zur Folge hat. Jedoch hat auch diese L¨sung einige Nachteile: Durch die enge Verbindung mit dem Web- o Server kann eine abgest¨rzte Server-Erweiterung den kompletten Server lahm legen. Außer- u ¨ dem sind Erweiterungen immer auf einen bestimmten Servertyp festgelegt. Eine Ubertragung auf andere Server ist somit nicht m¨glich. o Server Side Includes Mit Hilfe von Server Side Includes (SSI) k¨nnen dynamische Infor- o mation direkt innerhalb von HTML-Dateien eingebunden werden. Server Side Includes sind generell 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 u ubertragbar. Jedoch ist der Funktionsumfang recht beschr¨nkt, so dass SSI nicht f¨r gr¨ßere ¨ a u o Projekte geeignet ist. ASP, PHP, SSJS Eine weitere M¨glichkeit zum Erstellen dynamischer Web-Seiten bieten o die Technologien ASP (Active Server Pages), PHP (benannt nach einem Vor¨ngerprodukt a namens 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-API angefordert, wird der eingebettete Code zuerst vom Web-Server ausgef¨hrt, bevor er zum u Client geschickt wird. Diese Technik ist vor allem hilfreich bei Seiten, die nur sehr wenig dynamischen Inhalt bieten und uberwiegend aus statischen Teilen bestehen, da hier lediglich ein paar zus¨tzliche Zeilen ¨ a in den bestehenden HTML-Code eingef¨gt werden m¨ssen. Ein Beispiel ist ein Seite, die den u u Besucher namentlich begr¨ßt, sonst aber keine benutzerabh¨ngigen Informationen enth¨lt. u a a Ein anderes Beispiel ist ein Besucherz¨hler auf einer sonst statischen Seite. a Besteht die Seite jedoch aus sehr vielen dymanischen Teilen, zeigen sich die Schw¨chen dieser a Technologie. 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. ¨ o Außerdem sind ASP und SSJS serverabh¨ngig. So verwendet ASP in der Regel VBScript a oder JScript und l¨uft nur auf Microsofts IIS. Zwar gibt es bereits kommerzielle Software wie a z.B. InstantASP von Halcyon Software oder OpenASP von ActiveScripting.org, die ASP auch auf anderen Servern m¨glich macht, jedoch ist dies mit großem Aufwand verbunden und bis o heute nicht vollkommen ausgereift. SSJS wurde von iPlanet/Netscape entwickelt und bettet JavaScript-Fraktmente in HTML ein. SSJS l¨uft jedoch ausschließlich auf iPlanet/Netscape- a Servern. Lediglich PHP, das sich stark an dem vielen CGI-Programmiern bekannte Perl anlehnt, l¨uft a auf nahezu allen Servern. So verwundert es auch nicht, dass PHP die verbreitetste dieser drei Sprachen ist. Der Nachteil, dass große Projekte schnell un¨bersichtlich werden, bleibt u allerdings 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 9 nannt 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 a mittlerweile viele n¨tzliche Features, die jedoch in ihrer M¨chtigkeit der Java-API deutlich u a unterlegen sind. Die neuste Version von ColdFusion er¨ffnet jedoch die M¨glichkeit, benutzerdefinierte Ele- o o mente zu entwickeln, die mit JavaServlets kommunizieren k¨nnen. ColdFusion bietet sich o somit als Erg¨nzung von Servlets an, wobei allerdings zu abzuw¨gen ist, ob die Verwendung a a von JavaServer Pages, die sp¨ter beschrieben werden, nicht die bessere Alternative ist. a Servlets Ein Java Servlet l¨uft ¨hnlich wie Server-Extensions im Web-Server und erweitert a a dessen Funktionalit¨t. Jedoch laufen Servlets als Java-Programme in einer Java Virtual Ma- a chine (JVM), so dass sie erstens sicher sind und zweitens, dank Byte-Code, leicht auf andere Plattformen ubertragen werden k¨nnen. Servlet-Unterst¨tzungen sind bereits f¨r viele Web- ¨ o u u Server erh¨ltlich. a Der große Vorteil von Servlets besteht darin, dass Client-Anfragen nicht zu einer Unmenge von Prozessen f¨hren. Vielmehr ist es mit Servlets m¨glich, separate Threads zu erzeugen, u o die in ein und dem selben Prozess laufen. Abbildung 4 zeigt diese Vorgehensweise. Denkbar Abbildung 4: Web-Server mit Servlet-Unterst¨tzung u w¨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. o Gleichzeitig ist es Servlets m¨glich, eng mit dem Web-Server zusammen zu arbeiten, da sie o direkt in diesen eingebettet werden. Eine solche Art der Kommunikation w¨re beispielsweise a mit CGI nicht m¨glich. o Dies 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 schwergewichtiger Betriebssystem-Prozess, sondern als resourcenschonender Thread. CGI-Progamme m¨ssten u bei N parallelen Anfragen N mal in den Arbeitsspeicher geladen werden. Bei Servlets g¨be a es 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- u frage der (Perl-)Interpreter erneut geladen werden muss, kann ein Servlet somit, wenn es erst einmal geladen wurde, jede weiter Anfrage quasi unmittelbar ausf¨hren. Weiterhin ist es Serv- u lets m¨glich, einen Zustand uber mehrere Anfragen hinweg bei zu behalten. Daten k¨nnen o ¨ o als Klassenvariablen zwischengespeichert werden, vorangegangene Berechnungen k¨nnen ge- o cachet werden oder externe Resourcen, wie z.B. eine Datenbank-Verbindung, k¨nnen gehalten o werden, 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 o Datenbank-Verbindungen mit JDBC, Multithreading, Datenkomprimierung, Internationali- sierung, Grafikerzeugung oder Serialisierung sind nur einige Beispiele f¨r die M¨glichkeiten, u o die sich Servlets bieten. Kommuniziert ein Servlet mit einem Applet, k¨nnte auf die M¨glich- o o keit von Remote Method Invokation (RMI) zur¨ckgegriffen werden. Zus¨tzlich zu den auf- u a gef¨hrten Gebieten decken Klassen von Drittanbietern fast jedes andere Einsatzgebiet ab. u Das Parsen von XML, die Verwendung von regul¨ren Ausdr¨cken oder das Erzeugen von a u Diagrammen seien als Beispiel genannt. Alles in allem bietet die Java-API eine M¨chtigkeit, die kaum oder nur schwer von CGI- a Programmen oder Skriptsprachen erreicht werden kann. Portierbarkeit Da Servlets in Java geschrieben sind, k¨nnen sie problemlos zwischen o verschiedenen 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 a einen 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 u erst entstehen. Javas Garbage Collector und das Fehlen von Zeigern stellt sicher, dass Speicherprobleme wie beispielsweise Memory Leaks, ung¨ltige oder gar b¨swillig ver¨nderte Pointer, nicht m¨glich u o a o sind. In C++ k¨nnte beispielsweise auf die 1000-te Position eines Arrays mit nur 200 Ein- o tr¨gen zugegriffen werden. Dies w¨rde dazu f¨hren, dass so in Bereiche des Arbeitsspeichers a u u geschrieben w¨rde, auf die sonst kein Zugriff best¨nde. Tats¨chlich ist dies eine oft benutzte u u a Hintert¨r f¨r Angriffe. Servlets bieten diese M¨glichkeit nicht, da automatsich Array-Grenzen u u o uberpr¨ft werden. ¨ u Fehler 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 u eine Exception, die entweder vom Servlet selbst oder aber vom Server abgefangen werden. Ein Absturz des Servers ist nicht mehr m¨glich. o Zu guter Letzt werden bei Servlets keine externen Programme ausgef¨hrt, wie es bei CGI u
  • 16.
    2.1 Java Servlets 11 der 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 u verschickt, indem das Unix-Programm sendmail verwendet wird. Auf den ersten Blick ist es ausreichend, die Adresse, die der Benutzer in ein Formular eingegeben hat, an sendmail weiter zu reichen. Da jedoch auch mehrere Befehle in einer Unix-Shell mit einem Semikolon getrennt 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 a mmo@varial.de;rm -rf /. Resultat w¨re neben dem Senden einer Mail auch die Ausf¨hrung a u des rm-Befehls, der die Festplatte des Servers l¨schen w¨rde. o u Dies ist nur eines von vielen Beispielen, das zeigt, dass die Ausf¨hrung von externen Pro- u grammen ein erhebliches Sicherheitsrisiko darstellt. Servlets hingegen verwenden keine Shell, selbst dann nicht, wenn ein Remote-Systemaufruf ausgef¨hrt wird. u Man 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 o URLs in absolute Pfadangaben ubersetzen oder auch Benutzerberechtigungen uberpr¨fen. ¨ ¨ u CGI-Programme laufen hingegen getrennt vom eigentlichen Server, so dass eine solche Art der Zusammenarbeit dort unm¨glich ist. o JavaServerPages JavaServer Pages oder kurz JSP verbinden die Vorteile von Servlets, Cold- Fusion und eingebetteten Skript-Sprachen. JavaServer Pages ¨hneln vom Aufbau recht stark a dem ASP- oder PHP-Ansatz. In statischen HTML-Code 1 werden Elemente f¨ r dynamischen u Inhalt eingef¨gt. Seiten, die nur wenig dynamische Teile beinhalten, k¨nnen so ohne großen u o Aufwand erstellt werden. Sollte der dynamische Inhalt einen gr¨ßeren Teil der Seite ausmachen, k¨nnen JSP-Seiten o o leicht mit Servlets zusammen arbeiten. Hierzu k¨nnen sog. Taglibs entwickelt werden. Dies o sind Bibliotheken mit benutzerdefinierten Elementen. Dem Entwickler wird es auf diese Weise erm¨glicht, eigene Tags zu entwerfen. Die Funktion der Tags wird von einer Java-Klasse im- o plementiert. Der Vorteil dieser Vorgehensweise ist, dass Ausgabe (JSP) und Funktion (Java- Klasse) klar voneinander getrennt sind. Die JSP-Seite unterscheidet sich vom Aufbau her kaum von herk¨mmlichen HTML-Seiten, da alle Elemente der XML-Syntax folgen. So k¨nnen o o Web-Designer, die mit dem Umgang mit HTML-Seiten vertraut sind, fast ohne Einarbei- tungszeit komplexe Seiten gestallten. Die Funktionalit¨t wird hingegen von Programmierern a ubernommen, die sich ihrerseits nicht mit dem Seitenlayout belasten m¨ssen. Beide Parteien ¨ u erstellen so gemeinsam ein Projekt, arbeiten aber unabh¨ngig von einander. a Mit JSP und Taglibs kann so spielend einfach das Seitenlayout ge¨ndert werden, ohne dass a die Programmlogik angepasst werden muss und umgekehrt. Dies macht auch die Pflege eines Projekts denkbar einfach. Der JSP-Ansatz beinhaltet dar¨ber hinaus auch alle Vorteile von Servlets, da es sich bei JSP- u Seiten nur um eine andere Darstellung von Servlets handelt. JSP-Code wird bei erstmaliger Ausf¨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 a werden. Denkbar w¨ren ebenso XML- oder L TEX-Dokumente. a A 2 JSP-Code kann auch vorkompiliert werden.
  • 17.
    2.2 CORBA 12 vom Server somit als Servlet betrachtet, sie sind also genauso effizient, m¨chtig, portierbar a und sicher wie Servlets. 2.1.3 Die Zukunft Mit Java Servlets setzt die Programmiersprache Java ihren Siegeszug der letzen Jahre weiter fort. Java besticht durch die M¨chtigkeit und Eleganz der Sprache, die eine saubere, objek- a torientierte, modulare und einfache Programmierung erm¨glicht. Mit Java Servlets k¨nnen o o diese 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 u lets auf lange Sicht auf Grund ihrer Performance-Vorteile und Portierbarkeit den weitverbrei- teten CGI-Ansatz abl¨sen werden. o 2.2 CORBA Die Common Object Request Broker Architecture oder kurz CORBA ist eine Spezifikation, die von der Object Managment Group (OMG) entwickelt wurde. CORBA unterst¨tzt die u Realisierung verteilter Objekte. So k¨nnen Objekte zusammen agieren ohne voneinander zu o wissen, wo sich das Gegen¨ber befindet, oder in welcher Sprache es implementiert wurde. u CORBA ist in der letzten Zeit immer mehr zu dem Standard f¨r die Entwicklung von Middle- u ware geworden. Die OMG umfasst mittlerweile mehr als 800 Firmen, die das ganze Spektrum der Computerindustrie repr¨sentieren. Die einzige bemerkenswerte Ausnahme bildet Micro- a soft mit einem eigenen konkurierenden Objektbus namens Distributed Component Object Model (DCOM). 2.2.1 Die OMG OMG ist die Abk¨rzung f¨r Object Managment Group. Sie wurde im April 1989 gegr¨ndet u u u und bestand urspr¨nglich aus 11 Firmen, darunter u.a. 3Com Corporation, American Air- u lines, Canon Inc., Data General, Hewlett-Packard, Philips Telecommunications N.V., Sun Microsystems und Unisys Corporation. Mittlerweile umfasst die OMG uber 800 Mitglieder. ¨ Auf der Basis eines Vorschlags, Request for Comment (RFC) genannt, wird zun¨chst disku- a tiert, was standardisiert werden soll. Dann k¨nnen zu einem festgelegten Anforderungsprofil, o als Request for Proposal (RFP) bezeichnet, Technologien zur Standardisierung vorgeschlagen werden. Ziel der OMG ist es, herstellerunabh¨ngige, technisch ausgereifte und kommerziell a erfolgreiche Spezifikationen zu erarbeiten und zu standardisieren. Diese Spezifikationen sollen es erm¨glichen, objektorientierte Modelle unter Abstraktion von der verwendeten Hardware o und des Betriebsystems zu gestalten. 2.2.2 Object Management Architecture Die OMG ver¨ffentlichte im Herbst 1990 die Object Management Architecture (OMA) im o Rahmen 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 a Einzelheiten der sog. Common Facilities hinzugef¨gt. Der endg¨ltige Stand der Spezifikation u u ist 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 Architecture sich 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 a Dinge des realen Lebens. Wichtige Einzelheiten werden mit entsprechenden Attributen mo- deliert, unwichtige Details wegabstrahiert. Im Folgendem werden diese Objekte, bzw. die Java-Klassen, die diese implementieren, als Business-Objekte (BO) bezeichnet. Die Business-Objekte werden speziell f¨r die jeweilige Anwendung programmiert. Folglich u werden diese von der OMG nicht n¨her spezifiziert. Die Business Object Task Force der a OMG definiert lediglich, dass ein BO eine Komponente der Applikationsebene ist, die sich entsprechend des Prinzips der Wiederverwendbarkeit, vielseitig einsetzen l¨ßt. a Common 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 u zur Verf¨gung. Dazu z¨hlen beispielsweise grafische Benutzeroberfl¨chen, Drucker- und Da- u a a tenbankdienste, mobile Agenten oder auch Frameworks f¨r Internationalisierung. Das Reper- u toire an CORBAfacilities wird laufend weiterentwickelt und wird in Zukunft praktisch jeden verteilten 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 u sind Sammlungen von elementare Diensten auf Systemebene, die f¨r die Entwicklung von u
  • 19.
    2.2 CORBA 14 verteilten 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 15 Object Request Broker Die OMG definiert mit CORBA einen offenen Standard, liefert selbst jedoch keine Implementierung. Software, die die CORBA-Spezifikation implementiert, heißt Object Request Broker (ORB). Als Beispiele seien hier VisiBroker von Visigenic, Orbix von Iona oder Suns Java IDL genannt. Der ORB trennt die Anfrage eines Services (Client) von dessen Bereitstellung (Server). Der ORB ist das Herzst¨ck der CORBA-Technologie. Alle Aufrufe von Objekten (ob lokal oder u entfernt) 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 u wird und leitet Auftr¨ge an diese Objekte weiter. Dies geschieht automatisch, ohne dass sich a der Entwickler Gedanken dar¨ber machen muss, wo und ob ein Serverobjekt zur Zeit aktiv u ist. Der Objektadapter sorgt daf¨r, dass aus Sicht des Clients alle Serverobjekte aktiv und u lokal 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 u war, entwickelten sich viele herstellerabh¨ngige BOAs, die zwar alle den CORBA-Standard a erf¨llten, jedoch u.U. nicht richtig zusammen arbeiteten. Aus diesem Grunde wurde CORBA u 2.0 um den Portable Object Adapter (POA) erweitert. Durch zus¨tzliche Spezifikationen der a OMG ist nun sichergestellt, dass POAs zueinander kompatibel sind, w¨hrend das bei BOAs a nicht unbedingt der Fall sein muss. Da die ORB-Implementierungen an die Spezifikation der OMG gebunden sind, k¨nnen ORBs o verschiedener 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, u dass 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, a die als gemeinsames Backbone-Protokoll dienen. 2.2.3 Interface Definition Language CORBA ist ein selbstbeschreibendes System. Damit Objekte sprachenunabh¨ngig mitein- a ander agieren k¨nnen, wird klar zwischen Schnittstellenbeschreibung und Implementierung o unterschieden. Hierzu dient die Interface Definition Language (IDL). Mit dieser neutralen Sprache, 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. u Komponenten, die in IDL geschrieben sind, sollten zu anderen Sprachen, Betriebssystemen und Netzwerken hin kompatibel sein (Abbildung 8). Hierzu generiert der Compiler aus der Abbildung 8: Sprachunanh¨ngigkeit durch IDL a IDL-Beschreibung f¨r die jeweilige Programmiersprache passende Interfaces. Diese Interfa- u ces heißen serverseitig Skeletons, w¨hrend sie clientseitig als Stubs bezeichnet werden. Diese a Interfaces 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 o und Java-Server implementiert und auf verschiedenen Rechnern platziert wird. Die IDL stellt hierf¨r die programmiersprachenunabh¨ngige Verbindung her, der ORB sorgt f¨r die Loka- u a u lisierung der verteilten Objekte. F¨r den Programmierer gestaltet sich das Szenario dank u CORBA v¨llig transparent. o 2.2.4 Alternative Ans¨tze a Sockets Sockets stellen die wohl primitivste Art der Netzwerkkommunikation dar. Ein Socket ist ein Peer-to-Peer-Kommunikationsendpunkt uber TCP/IP. 1981 wurden Sockets ¨
  • 22.
    2.2 CORBA 17 im 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. u Ein Socket besteht aus einem Namen und einer Netzwerkadresse und l¨ßt sich in eine von a drei 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 auch einige Nachteile. So bieten Sockets weder Parameter Marshaling noch dynamische Service- Bindung. Der Entwickler muss eigene Protokolle entwickeln, die die Methodenaufrufe des Clients den Methoden des Servers zuordnen. Bedenkt man, dass große Systeme leicht einige hundert Funktionen umfassen, k¨nnte dies zu einem gewaltigen Aufwand f¨hren. Die Pflege o u und Wartung der Software w¨rde schnell eine un¨berschaubare Aufgabe. Folglich stellen u u Sockets f¨r die Anforderung moderner Systeme keine ausreichende L¨sung dar. u o RMI Remote Method Invocation oder kurz RMI ist eine von der Firma Sun Microsystems entwickelte 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 o Entwicklung von RMI war es, ein verteiltes Objektmodel in Java zu integrieren, ohne dabei das 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 o Client-Server-Architektur, die sich f¨r den Entwickler fast vollkommen transparent gestaltet. u RMI 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. u Genau 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- a munikation transparent erscheinen lassen. Der Client hat Zugriff auf eine Stub-Klasse, die das Server-Interface implementiert. Methodenaufrufe des Stubs werden uber das Netzwerk ¨ ubertragen und von dem Gegenst¨ck auf der Serverseite, dem Skeleton, an das jeweilige ¨ u Server-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 a den Anforderungen besser gerecht wird. RMI stellt eine wesentlich einfachere Architektur als CORBA zur Verf¨gung, was dazu f¨hrt, dass RMI besonders f¨r kleinere Projekte geeignet ist. u u u Dar¨ber hinaus ist es einfacher zu erlernen und direkt in neueren JDK-Versionen eingebettet. u
  • 24.
    2.2 CORBA 19 Der Nachteil gegen¨ber CORBA ist allerdings, dass gerade große Projekte durch verschie- u dene CORBA-Features (CORBAservices und CORBAfacilities) besser mit die Technologie der OMG umsetzbar sind. Außerdem k¨nnen mit RMI nur reine Java-Projekte implementiert o werden. Eine Kommunikation zwischen Objekte, die in unterscheidlichen Programmierspra- chen geschrieben wurden, ist im Gegensatz zu CORBA nicht m¨glich. RMI stellt folglich bei o heterogenen Projekten keine Alternative dar. DCOM Das Distributed Component Object Model (DCOM) ist Microsofts Antwort auf den OMG-Standard. Mit DCOM stellt Microsoft eine weitere M¨glichkeit zur Realisierung verteil- o ter Anwendungen zur Verf¨gung. Dabei gehen die Wurzeln von DCOM weit in die Vergangen- u heit zur¨ck. Strenggenommen wurde 1987 mit Einf¨hrung der Zwischenablage in Windows u u der Grundstein f¨r DCOM gelegt (Abbildung 10). Mit der Zwischenablage war es erstmals u Abbildung 10: Entwicklung von DCOM aus COM und RPC m¨glich, Texte aus einem Programm zu kopieren und in anderen Applikationen einzusetzen. o 1992 wurde diese Technik erweitert und als OLE (Object Linking & Embedding) ver¨ffent-o licht. Nun war es nicht nur m¨glich, Texte zwischen zwei Applikationen auszutauschen, son- o dern es wurde gar erm¨glicht, komplexere Objekte durch die Zwischenablage zu kopieren. o Ein oft zitiertes Beispiel ist das Einbinden einer Excel-Tabelle in einem Word-Dokument. Bei Doppelklick 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 ¨ ¨ a Anwendungen jedoch unabh¨ngig von einander entwickelt werden, bedarf es einem standar- a disierten Verfahrens, das die Kommunikation zwischen den Windows-Applikationen regelt. OLE bot mit DDE (Dynamic Data Exchange) die grundlegende Kommunikationsschicht f¨r u den Datenaustausch. Da sich DDE jedoch schon schnell als zu langsam und unflexibel her- ausstellte, konnte sich die Technologie nicht wie gew¨nscht durchsetzen. u Microsoft entwickelte daraufhin OLE 2. Die Fragestellung, wie zwei Windows-Programme miteinander Daten austauschen k¨nnen, wurde jetzt ein wenig ausgeweitet. Als zentrales Ziel o wurde definiert, dass eine Applikation die Funktionalit¨t beliebiger bin¨rer Komponenten in a a einer objektorientierten Art und Weise nutzen solle. Dies unabh¨ngig von den verwendeten a
  • 25.
    2.2 CORBA 20 Implementierungssprachen 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 u COM bilden sollte. COM ist die Kurzbezeichnung f¨r Component Object Model und definiert einen Standard f¨r u u die 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 a Schnittstellen zur Verf¨gung stellt. Bei der Verwendung der Komponente ist es hierbei v¨llig u o egal, wie und in welcher Programmiersprache sie geschrieben ist. Mit Hilfe der Interfaces kann die Komponente von anderen Anwendungen genutzt werden ohne den inneren Aufbau zu kennen (Abbildung 11). Schnell fand ein neues Zauberwort Einzug in die Windows-Welt: ActiveX. ActiveX beinhaltet Abbildung 11: Software-Komponente nach COM: Aufbau und Zugriff dabei lediglich COM. Der Grund f¨r die babylonische Sprachverwirrung, in der auch VBX, u das Software-Komponenten f¨r Visual-Basic-Steuerelemente beschreibt, und das allgemeinere u OCX, 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 u alte Technologie. Mit Windows NT und einer Version f¨r Windows 95 fand ActiveX schnell u erste Einsatzgebiete in der Windows-Welt. Fortan sollte das Component Object Model bzw. ActiveX eine entscheidende S¨ule in der Entwicklung von Windows-Applikationen spielen. a W¨hrend COM lediglich das Zusammenspiel von Software-Komponenten auf dem selben a Rechner erlaubt, hebt DCOM als verteiltes COM diese Grenzen auf. DCOM erm¨glicht nun o auch 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 auf RPC. 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 von deren 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 o Microsoft 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 a verkauft. COM+ bezeichnet somit keine wirkliche Neuentwicklung des Standards, sondern nur ein neu zusammengestelltes Microsoft Produkt.
  • 26.
    2.2 CORBA 21 Abbildung 12: Verteilte Anwendung mit DCOM Der propriet¨re DCOM-Standard stellt eine f¨r Windows-Produkte optimierte Technik f¨r a u u die Umsetzung verteilter Systeme dar. Dementsprechend einfach gestaltet sich die Entwick- lung auf der Microsoft-Plattform. Auf der anderen Seite bietet DCOM keine oder kaum Unterst¨tzung f¨r andere Betriebssysteme. Die Firma Software AG portierte ActiveX un- u u ter dem Namen EntireX zwar auf verschiedene Plattformen wie Linux, Sun Solaris, Digital Unix, HP-UX oder OS/390, eine komplette Kompatibilit¨t wurde hingegen noch nicht er- a reicht. Außerdem ist DCOM ein Bin¨rstandard. Die Folge ist eine enge Bindung an die a x86-Prozessorarchitektur. ¨ Alle diese Uberlegungen zeigen, dass DCOM in einem reinen Windows-System sicherlich eine gute L¨sung darstellt. F¨r die Verwendung in heterogenen Systemen stellt CORBA jedoch o u die bessere Wahl dar. SOAP Das Simple Open Access Protocol oder kurz SOAP ist die neuste Entwicklung aus dem Hause Mircrosoft und definiert ein Transportprotokoll, das die wesentlichen Merkmale von 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 direkte Bindung 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 a in heterogenen Systemen. SOAP beruht im Prinzip auf der Verwendung von sog. Remote Procedure Calls (RPC). Wie der Name bereits andeutet, werden mit dieser Technik entfernte Funktionsaufrufe erm¨glicht. o Durch gestiegene Sicherheitsbed¨rfnisse in Netzwerken bzw. dem Internet werden aber immer u mehr Netzwerke durch Firewalls gesichert. Diese Firewalls sch¨tzen an das WWW angeschlos- u sene Netzwerke, indem sie Ports blockieren und Anfragen filtern. In der Regel werden nur Anfragen 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 23 SMTP (Port 25) zugelassen. Die Folge ist, dass RPC-Aufrufe des Clients von der Firewall blockiert werden. Zur L¨sung dieses Problems verwendet SOAP den offenen Port 80, indem o RPC-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 Envelope terteilt sich wiederum in einen SOAP Header und einen SOAP Body. Der Header enth¨lt a Informationen dar¨ber, was f¨r eine Art von Nachricht vorliegt, den Empf¨nger der Nach- u u a richt und welche Bestandteile der Nachricht optional bzw. obligatorisch sein m¨ssen, um u eine g¨ltige SOAP-Nachricht darzustellen. Der SOAP-Body enth¨lt den eigentlichen Inhalt u a der Nachricht. Außerdem kann eine SOAP-Nachricht noch einen Block mit der Bezeichnung Fault 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-Informationen Mit 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 o auf prinzipiell jeder Plattform auszuf¨hren. Andererseits entstehen gerade bei komplexen u Anwendungen u.U. schnell sehr große Datenmengen, da XML-Dateien neben den reinen In- formationen große Mengen von Formatierungs- bzw. Gliederungsanweisungen in Form von Tags besitzen. Beachtet man weiterhin den Aufwand f¨r das Parsen des Dokuments, erfolgt u die Verarbeitung dementsprechend langsamer als bei CORBA oder DCOM. SOAP bietet
  • 29.
    2.2 CORBA 24 daf¨r jedoch eine einfachere Zusammenarbeit mit Firewalls. Zusammenfassend l¨ßt sich sa- u a gen, dass Microsoft bei der Entwicklung von SOAP eher die Verwendung im Internet im Auge hatte, w¨hrend DCOM in kleineren, homogenen LANs St¨rken offenbart. a a Als Erg¨nzung sei an dieser Stelle ein ¨hnliches Verfahren genannt, dass unter der Bezeich- a a nung 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 ausgereift und findet deshalb nur in kleineren Projekten Anwendung. 2.2.5 Vorteile von CORBA Stellt man CORBA und andere Techniken f¨r die Entwicklung verteilter Anwendungen ge- u gen¨ber, zeigen sich schnell die St¨rken des OMG-Standards. Die reine Socket-Verbindung u a bietet 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 Abstraktion bieten. RMI bietet bereits eine sehr hohe Abstraktionsebene. Die Kommunikation erfolgt in einem standardisieren Protokoll und Verbindsdetails werden f¨r den Entwickler verborgen, so dass u dieser 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- a formen. Bei der Verteilung von Java-Applikationen stellt RMI sicherlich die beste L¨sung dar. o Allerdings erm¨glicht RMI nicht das Zusammenspiel zwischen verschiedenen Programmier- o sprachen. Microsofts DCOM-Architekur erm¨glicht im Gegensatz zu RMI zwar eine Kommunikati- o on zwischen Software-Komponenten, die in verschiedenen Sprachen implementiert werden k¨nnen. Zugleich wurde auch hier eine hohe Abstraktionsebene erreicht. Der Nachteil von o DCOM ist hingegen die enge Bindung an das Microsoft-Betriebssystem und die Prozessor- Architektur. In einer reinen Windows-Applikation bietet DCOM somit eine gute Alternative zu CORBA. In heterogenen Systemen offenbart DCOM aber seine Schw¨chen. a SOAP 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 ¨ a uber Port 80 und somit die Zusammenarbeit mit Firewalls. Die Unabh¨ngigkeit von XML ¨ a wird jedoch mit einem hohen Mass an Overhead f¨r Strukturierungsbefehle bezahlt. Dadurch, u dass die XML-Beschreibungen gerade in großen Projekten sehr groß werden, und dass diese Dokumente vor der Verarbeitung entsprechend geparst werden m¨ssen, zeigen sich deutliche u Performance-Schw¨chen bei SOAP. Mit dem selben Problem ist auch XML-RPC behaftet. a Außerdem bietet sich hier ein geringerer Funktionsumfang. Mit CORBA l¨ßt sich Middleware auf einer sehr hohen Abstraktionsebene realisieren. a Dar¨ber hinaus bietet CORBA ein Optimum an Unabh¨ngigkeit. Der Standard ist weder u a an Betriebssysteme, noch an Programmiersprachen gebunden. Außerdem stellt CORBA mit den CORBAfacilities und den CORBAservices viele sehr n¨tzliche Dienste zur Verf¨gung. u u Die 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 25 2.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 o vierschichtige webbasierte Anwendungen zu bauen. Mit Java Servlets steht eine effiziente und m¨chtige M¨glichkeit zur Verf¨gung, mit der die a o u Vorteile von Java nun auch auf Web-Servern genutzt werden k¨nnen. CORBA erm¨glicht o o wiederum die Entwicklung leistungsf¨higer Middleware. a Die Verbindung beider Technologien ist geradezu optimal. Java Servlets sind von Natur aus plattformunabh¨ngig. CORBA ist dar¨ber hinaus nicht nur unabh¨ngig vom Betriebssystem, a u a sondern auch von der Programmiersprache. So l¨ßt sich ein Servlet-CORBA-System nicht nur a beliebig auf andere Betriebssysteme ubertragen, sondern es ist auch m¨glich, Servlets mit je- ¨ o dem beliebigen CORBA-Server zusammen arbeiten zu lassen, gleichg¨ltig in welcher Sprache u dieser geschrieben ist oder auf welchem Betriebssystem er l¨uft. a Zusammen stellen CORBA und Servlets ein Optimum an Leistungsf¨higkeit und Unabh¨ngig- a a keit dar.
  • 31.
    3 Varial WorldEdition 3.1 Leistungsumfang VWE Die Varial World Edition ist ein neu entwickeltes ERP-System der Firma Varial Software AG. Neben der Personalwirtschaft bietet VWE u.a. auch L¨sungen f¨r das Finanzwesen und o u Controlling. VWE wurde erstmalig auf der CeBIT 2000 vorgestellt und liegt momentan in einer deutschen und einer englischen Version vor. Seit September 2001 befindet sich VWE bei einem Pilotkunden, der britischen Firma Espera Scales Ltd. aus Dorking, s¨dlich von u London, im Testbetrieb. VWE wurde speziell f¨r den Einsatz in international operierenden Unternehmen entwickelt. u Dabei k¨nnen Firmengruppen (Holdings) problemlos mehrere Firmen getrennt in einem Pro- o gramm verwalten. VWE ist nicht nur mehrsprachen-, sondern auch mehrw¨hrungsf¨hig. D.h. a a im System k¨nnen Buchungen in mehreren W¨hrungen vorgenommen werden. Umrechnungen o a finden zu fixen oder auf Basis tagesgenauer Umrechungskurse aus dem Internet statt. Auch die Anpassung an landesspezifische Formate ist gew¨hrleistet. Selbst fachliche Besonderheiten, a wie beispielsweise unterschiedliche gesetzliche Bestimmungen, k¨nnen mit VWE verwaltet o werden. Hierzu wurde eine spezielle Berechnungslogik entwickelt, die einfache Anpassung, oft- mals sogar vom Anwender selbst, ohne Programmieraufwand, erm¨glicht. L¨nder-, branchen- o a oder unternehmensspezifische Versionen lassen sich somit schnell und effektiv umsetzen. Auf Grund des Vertriebsmodels mit OEM-Partnern wurde bereits bei dem Entwurf von VWE darauf geachtet, dass ein hohes Maß an Integration erreicht wird. VWE l¨ßt sich leicht an ein a bestehendes Design anpassen und in vorhandene Systeme integrieren. Durch einen modularen Aufbau, bei dem Funktionalit¨ten bzw. Use-Cases in Programmbausteinen gekapselt sind, ist a es m¨glich, nur einzelne Funktionen zur Verf¨gung zu stellen. Auf diese Weise k¨nnen indi- o u o viduelle ERP-Systeme zusammengestellt werden, die den Anforderungen des Endanwenders gerecht 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. u 3.2 Architektur Neben 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. a Der Presentation Layer ist die Oberfl¨che der VWE und ist f¨r die Darstellung der fachlichen a u Inhalte verantwortlich. Neben der ergonomischen Gestaltung zeichnet sich die Oberfl¨che a durch die Integration von Office Standards und der M¨glichkeit der flexiblen Anpassung o an bestehendes Corporate Design aus. OEM-Partnern wird mit dem Varial Client SDK (Software Development Kit) eine vollst¨ndige und nahtlose Integration mit anderen Produk- a ten erm¨glicht. Ein einheitliches Look and Feel“ mit gleichen Symbolen, Oberfl¨chen und o a ” ergonomischen Prinzipien ist sichergestellt. Beim Anwender treten Wiedererkennungseffekte auf, 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 WVE fischen Formaten vereinfacht sich die Anpassung an andere Sprachen und L¨nder.a Zusammenfassend l¨ßt sich sagen, dass der Presentation Layer eine sehr flexible Oberfl¨chen- a a gestaltung zul¨ßt. Diese Entwicklungsweise bewahrt vor monolithischen Strukturen, deren a Adaption an andere Sprachen und reginale Sonderheiten massive Ver¨nderungen erfordern a w¨rde. u Beim Application Layer handelt es sich um das Kernst¨ck der VWE. In ihm ist die u Funktionalit¨t aller Anwendungen realisiert. Er stellt eine fachliche Korrektheit, also eine a ordnungsgem¨ße kaufm¨nnische Buchf¨hrung, sicher und deckt auch technische Erfordernisse a a u wie Transaktionsicherheit und Performance ab. Der Application Layer folgt einem modularen Aufbau, bei dem alle verwendeten Entit¨ten in a sog. Business Objekten gekapselt sind, die den Regeln der objektoriertierten Programmierung entsprechen. Diese modulare Bauweise vereinfacht sowohl die Wartung und Erweiterungen als auch die Anpassung der Software. Ferner sorgt der Application Layer f¨r Transaktionssicherheit und optimalen Datendurchsatz u in Richtung Persistency und Presentation Layer. Dabei wird die Verarbeitung durch den Einsatz von Callbacks, einem Mechanismus, bei dem Daten asynchron geliefert werden, auch großen Datenmengen gerecht. Der Persitency Layer sorgt f¨r die Datenhaltung in VWE. Obgleich er den kleinsten Anteil u am Gesamtcode des Systems ausmacht, entscheidet er uber Stabilit¨t und Anwendungsbreite ¨ a der 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 mit allen Datenbanken auf SQL-92-Basis kommunizieren kann. Datenbankunterschiede werden vom Persistency Layer ausgeglichen, damit die Datenhaltung in den verschiedensten RDBS m¨glich ist. Derzeit l¨uft VWE mit Oracle, Interbase, Informix, Sybase und dem SQL-Server o a von Microsoft. Durch die Verwendung von CORBA und die klare Trennung der Schichten, insbesondere
  • 33.
    3.3 Das Web-Interface 28 des Presentation und Application Layers, wurde es nicht nur m¨glich, die Gesch¨ftslogik von o a der Darstellung zu trennen, sondern es konnte bei der Realisierung auch auf unterschied- liche Programmiersprachen zur¨ckgegriffen werden. Der Presentation Layer (Client) wurde u in C++ geschrieben, w¨hrend auf der Serverseite im Application Layer Java zum Einsatz a kommt. Im Rahmen der Diplomarbeit wird nun zus¨tzlich zum bestehenden Client eine wei- a tere Anwendung entwickelt, mit der es m¨glich ist, VWE uber das Internet zu nutzen. o ¨ 3.3 Das Web-Interface Ein Web-Interface erm¨glicht es dem Anwender, VWE mit einem Browser von nahezu o jedem beliebigen Arbeitsplatz aus zu nutzen. Hierdurch ergeben sich ein Reihe von neuen Anwendungsm¨glichkeiten der Varial World Edition. Zu Beginn muss erst einmal gekl¨rt o a werden, welche Funktionalit¨ten die zu entwickelnde Anwendung zur Verf¨gung stellen soll. a u Es soll also der Frage nachgegangen werden, welche Daten welchem Benutzer zug¨nglich a gemacht werden sollen, welche Gesch¨ftsprozesse im Umfeld einer Internet-Anwendung a sinnvoll sind und welche eher nicht. Prinzipiell lassen sich alle Benutzer in zwei Gruppen unterteilen: Betriebsinterne und betriebsexterne Anwender. Als betriebsintern gilt beispielsweise der Vorstand, der Buchhal- ter oder Mitarbeiter im Außendienst. Zur Gruppe der betriebsexternen Anwender z¨hlen a z.B. die Kunden, der Steuerberater oder der Wirtschaftspr¨fer. Um nun die verschiedenen u M¨glichkeiten eines Web-Interfaces zu demonstrieren, seien hier beispielhaft einige Use-Cases o aufgef¨hrt: u Ein Vorstandsmitglied geh¨rt, wie bereits oben erw¨hnt, zu den betriebsinternen Anwendern, o a hat somit tendenziell mehr Zugriffsrechte als externe Anwender. Es hat Zugriff auf s¨mtliche a Daten. Jedoch ist man eher daran interessiert, schnell Daten in aggregierter Form, wie z.B. Bilanzen, Jahresstatistiken etc, geliefert zu bekommen. Einzelheiten sind hier nicht von Interesse, behindern zuweilen sogar bei der Auswertung der Daten. Eine denkbare Anwendung des Web-Interfaces w¨re, dass der Vorstandschef auf Dienstreise im Hotelzimmer a die 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 a zugegriffen werden kann, deutlich eingeschr¨nkter, beinhalten daf¨r aber mehr Einzelheiten. a u Der Außendienst kann uber das Web-Interface s¨mtliche Kundendaten auswerten und auf ¨ a einzelne schreibend zugreifen. Beispielsweise kann hier im Außendienst direkt der Name des Ansprechpartners 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 a ein 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- u on sinnvoll erg¨nzen kann, findet sich im Bereich Personalwirtschaft. Den Mitarbeitern a des Unternehmens k¨nnen pers¨nliche Daten zur Verf¨gung gestellt werden. Auf diese o o u Weise 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 a Daten nur gelesen, diese aber nicht ver¨ndert werden d¨rfen. Einem externen User wird des- a u halb in der Regel nur ein sog. Pr¨ferarbeitsplatz eingerichtet. u So 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 o Betriebspr¨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. u Einem Wirtschaftspr¨fer kann ubers Internet Zugang zu Informationen gew¨hrt werden, u ¨ a die f¨r Pr¨fungen notwendig sind. Weitere Daten sollten aber selbstverst¨ndlich verborgen u u a bleiben. Ein Web-Interface w¨rde diesen neuen Anforderungen gerecht werden. u Weiterhin k¨nnen Kunden die Software dazu nutzen, um offene Rechnungsbetr¨ge einzu- o a sehen. Kunden des Unternehmens k¨nnen sich so von jedem Browser aus ansehen, welche o Rechnungen noch bezahlt werden m¨ssen. Eine Bonit¨tseinsch¨tzung hingegen sollte dem u a a Kunden nicht gezeigt werden. Man sieht, dass es eine Reihe von Einsatzm¨glichkeiten und Anwendungsf¨llen f¨r ein o a u Web-Interface im Rahmen eines modernen ERP-Systems gibt, bei dem jedem Benutzer eine an die entsprechende Rolle angepasste Datensicht zur Verf¨gung gestellt wird. u Dadurch, dass bei VWE klar zwischen der Darstellung und Verarbeitung von fachlichen Inhalten 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. a Abbildung 18 zeigt den neuen vierschichtigen Aufbau der Software mit Webanbindung. Die Aufgabe, die den normalen Desktop-Client zukommt, wird von einem Java Servlet ubernom- ¨ men, das auf einem Web-Server (beispielsweise Apache Tomcat, JRun von Macromedia oder BEA WebLogic Server) l¨uft. Da das Servlet selbst jedoch nur die Ausgabe erzeugen bzw. a vorbereiten kann, diese aber selbst nicht dargestellen kann, wird ein Browser ben¨tigt. Dieser o stellt die vierte Schicht im Modell dar. Die vom Servlet erzeugten Daten werden mit HTTP bzw. HTTPS an den Browser geschickt. Dieser stellt sie dann f¨r den Anwender dar und u dient zur Bedienung der Anwendung.
  • 35.
    3.3 Das Web-Interface 30 Abbildung 18: Der vierschichtige Aufbau von WVE-Web
  • 36.
    4 Anforderungen andas Web-Interface 4.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 Daten haben. 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 a der Benutzung muss sich der Anwender mit einem Login und dem dazugeh¨rigen Passwort o anmelden. Ein Zugriff auf die Applikation wird nur dann gew¨hrt, wenn der Benutzerna- a me g¨ltig ist und das Passwort korrekt eingegeben wurde. Unter der Annahme, dass das u Passwort geheim gehalten wird, ist gew¨hrleistet, dass ausschließlich authorisierte Benutzer a Zugang zum System erhalten. Da das Passwort f¨r jeden Anwender unterschiedlich ist, ist es u weiterhin nicht m¨glich, sich f¨r jemand anderes auszugeben. Ein erfolgreicher Login ist des- o u halb ein relativ sicheres Zeichen daf¨r, dass es sich bei dem Anwender um die Person mit der u angegebenen Benutzerkennung handelt. Die Authentizit¨t des Benutzers ist sichergestellt. a Diese Art der Benutzerverwaltung ist weiterhin hilfreich, um Genehmigungen zu definieren. Da der Benutzer eindeutig identifiziert wurde, k¨nnen ihm Zugriffsrechte gegeben bzw. die- o se eingeschr¨nkt werden. So ist es m¨glich, dass verschiedene Benutzer auf unterschiedliche a o Programmteile zugreifen d¨rfen. Der VWE-Administrations-Modus bietet hier eine rollen- u basierte 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 o Name, Adresse, Funktion, Abteilung, Durchwahl etc. angegeben werden. Weiterhin kann ein Benutzer 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 a noch nicht gel¨scht, aber zwischenzeitlich aus dem System genommen) oder die G¨ltigkeit o u des Passworts kann festgelegt werden. So kann beispielsweise angegeben werden, dass das Passwort alle 14 Tage ge¨ndert werden muss. a Ist ein solcher Benutzer angelegt, k¨nnen ihm Rechte zugewiesen werden. Dies geschieht o jedoch 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 Benutzers der 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 o angelegt und verwaltet werden. Nach Erzeugung der Verkauf-Rolle k¨nnen ihr die n¨tigen o o Rechte zugewiesen werden. VWE stellt hierzu eine detaillierte Liste mit Rechten, die in der Applikation vergeben werden k¨nnen, zur Verf¨gung. Der erzeugten Rolle wird beispielsweise o u das 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 bei der Verwaltung mehrere Firmen beispielsweise nur die Mitarbeiter einer speziellen Firma bearbeiten. 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 a Einschr¨nkung code LIKE ’A%’ AND code LIKE ’M%’“ angegeben werden. Der Benutzer a ” hat somit nur Zugriff auf die von ihm ben¨tigten Daten. o Im Zusammenhang mit der Zugriffskontrolle ist das sog. AccessToken zu erw¨hnen. Dies a ist ein Objekt, das Benutzer-Informationen nach einem erfolgreichen Login beinhaltet. Der Benutzer 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 33 AccessToken-Objekt zur¨ck. Dieses Token gilt im Folgenden als eine Art Schl¨ssel. Das Ac- u u cessToken wird jedem Funktionsaufruf des Servers mitgegeben, der anhand dieses Schl¨ssels u pr¨ft, ob der Zugriff erlaubt ist. u Der Vorgang entspricht in etwa einem Hotelbesuch. Zu Begin meldet sich der Gast an der Rezeption an und erh¨lt dort nach erfolgreicher Identifizierung einen Zimmerschl¨ssel. Mit a u diesem Schl¨ssel kann er sich nun im Hotel bewegen, hat aber nur Zutritt zu bestimmten u Bereichen. 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 u muss nur eine evtl. auftretende AccessDeniedException abfangen, die bei einem erfolglosen Anmeldungsversuch 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 o noch Vertraulichkeit der Daten ist gew¨hrleistet. Außerdem wird lediglich ein Kommuni- a kationspartner, n¨mlich der Benutzer, identifiziert. Die Frage, ob es sich auf der anderen a Seite 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 o andere, d.h. verf¨lschte URLs geleitet w¨rden. Dem Anwender w¨rde eine vertrauliche a u u Seite somit nur vorget¨uscht. Wegen dieser als DNS-Spoofing bekannten Methode, muss a f¨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 u ren und sog. digitale Zertifikate. Sinn von Verschl¨sselung (Kryptographie) ist es, Daten vor u unberechtigtem Lesen zu sch¨tzen. Die Kryptographie besch¨ftigt sich deshalb mit der Ge- u a heimhaltung von gespeicherten und ubertragenen Daten. In der modernen Kryptographie ¨ arbeiten alle Verfahren auf der Basis von Schl¨sseln. Hierbei unterscheidet man prinzipiell u zwei Arten von Algorithmen: • Symmetrische Algorithmen (secret-key) • Asymmetrische Algorithmen (public-key) Symmetrische Algorithmen basieren auf dem Prinzip, dass eine Nachricht mit ein und dem selben Schl¨ssel ver- und entschl¨sselt werden kann (Abbildung 20). Das heißt, dass nur u u der Schl¨ssel, der zur Verschl¨sselung der Nachricht verwendet wurde, diese auch wieder u u entschl¨sseln kann. Dies hat zur Folge, dass sowohl der Sender als auch der Empf¨nger einer u a Nachricht im Besitz dieses Schl¨ssels sein m¨ssen. Da die Nachricht nicht von Unbefugten u u gelesen werden darf, muss der Schl¨ssel selbstverst¨ndlich geheim gehalten werden. Es stellt u a sich somit die Frage, wie Sender und Empf¨nger sich auf einen Schl¨ssel einigen oder, besser a u gesagt, 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. u Der bekannteste symmetrische Algorithmus ist wohl DES (Data Encryption Standard). Diese Methode der symmetrischen Verschl¨sselung wurde 1977 vorgestellt und 1981 als u Data Encryption Algorithm, ANSI-Standard X3.92-1981 ubernommen. DES verwendet eine ¨
  • 39.
    4.1 Sicherheit 34 Abbildung 20: Prinzip der symmetrischen Verschl¨sselung u Schl¨ssell¨nge von 64 Bits (davon 56 signifikant) und galt lange Zeit als sicher. Im Fr¨hjahr u a u 1999 gelang es jedoch einem Projekt namens Deep Crack“, einem speziellen Rechner, ” der von tausenden ubers Internet angeschlossenen Computern unterst¨tzt wurde, einen ¨ u DES-Schl¨ssel in weniger als 24 Stunden zu knacken. Seitdem gilt ein 64 Bit-Schl¨ssel nicht u u mehr als sicher. Symmetrische Algorithmen sollten vielmehr eine Schl¨ssell¨nge von 128 Bits u a verwenden. Dadurch ergibt sich eine Schl¨sselmenge von 2128 Schl¨sseln. Dies entspricht u u im Klartext 340.282.366.920.938.463.463.374.607.431.768.211.456 (≈ 3, 4 · 1038 ) m¨glichen o Schl¨ssel. Diese Schl¨ssell¨nge gilt nach heutigem Stand der Technik als nahezu sicher. u u a Bedenkt 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, bis auch diese Schl¨ssell¨nge geknackt werden wird. Was auf jeden Fall bleibt, ist die Notwendig- u a keit, den gemeinsamen Schl¨ssel zwichen den Kommunikationspartnern sicher auszutauschen. u Diese Problematik wird von asymmetrischen Algorithmen vermieden. Bei ihnen gibt es zwei Schl¨ssel: Einen geheimen privaten Schl¨ssel und einen offentlichen Schl¨ssel, der f¨r u u ¨ u u jedermann zug¨nglich ist. Das Prinzip von asymmetrischen Algorithmen besagt, dass eine a Nachricht, die mit dem einen Schl¨ssel kodiert wurde, nur mit dem jeweils anderen dekodiert u werden kann. Dies hat zur Folge, dass Kommunikationspartner keine geheimen Schl¨ssel aus- u tauschen m¨ssen. Der Sender kodiert einfach die Nachricht mit dem ¨ffentlichen Schl¨ssel u o u des Empf¨ngers, dieser entschl¨sselt sie wieder mit seinem privaten Schl¨ssel. Abbildung 21 a u u zeigt das Prinzip der asymmetrischen Verschl¨sselung. Wird die Nachricht unterwegs abge- u fangen, kann sie nicht dekodiert werden, da hierzu der private und damit geheime Schl¨ssel u notwendig ist. Es ist also dem Besitzer des privaten Schl¨ssels vorbehalten, Nachrichten zu u entschl¨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 u asymmetrische Verschl¨sselungsverfahren basieren auf dem Prinzip, dass es mathematische u Funktionen gibt, deren Umkehrung nur mit einem erheblich h¨heren Aufwand m¨glich ist. o o Public-Key-Kodierungen verwenden deshalb solche als Trapdoor-Einwegfunktion bezeichnete Algorithmen. 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 u die Funktion schnell umkehren l¨ßt. F¨r einen Außenstehenden, d.h. unberechtigten Mitleser a u ist es allerdings nicht m¨glich, die Nachricht in einer akzeptablen Zeitspanne zu entschl¨sseln. o u Der berechtigte Empf¨nger kann hingegen die Nachricht mit der nur ihm bekannten Gehei- a minformation 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 bisher aber nicht m¨glich gewesen, die Sicherheit von RSA zu best¨tigen oder zu widerlegen. RSA o a gilt deshalb bis heute als sicherer Verschl¨sselungsalgorithmus. u Als Trapdoor-Funktion verwendet RSA die Faktorisierung von Primzahlen. Diese Funktion beruht auf der Annahme, dass zwei große Primzahlen leicht miteinander multipliziert werden k¨nnen, dass aber eine Invertierung, also die Faktorisierung eines Produktes zweier großer o Primzahlen, ein wesentlich gr¨ßeres Problem darstellt. RSA stellt somit die Vertraulichkeit o und Echtheit der Daten¨bertragung sicher. u Mit Einf¨hrung des Secure Socket Layer (SSL) hat die Verschl¨sselung Einzug ins Inter- u u net gehalten. Normale Internet-Kommunikation beruht auf dem TCP/IP-Protokol, das eine vierschichtige Implementierung des OSI-Modells darstellt. Als TCP/IP vor ca. 30 Jahren erfunden wurde, lag das Hauptaugenmerk darin, eine ausfallsichere und stabile Verbindung zwischen einer hohen Anzahl von Systemen zu schaffen. Die Authentizit¨t spielte zun¨chst a a
  • 41.
    4.1 Sicherheit 36 keine 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 a TCP/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/IP Socket Layer liegt zwischen Transportschicht und Verarbeitungsschicht und verh¨lt sich hier- a bei v¨llig transparent, so dass weder Anwender noch die anderen Schichten im Modell von o SSL und deren Aktivit¨ten etwas mitbekommen. a SSL verwendet sog. digitale Zertifikate. Ein Zertifikat besteht aus Angaben uber die Identit¨t ¨ a des Besitzers und beinhaltet außerdem den ¨ffentlichen Schl¨ssel des Inhabers. Es garantiert o u folglich, dass der ¨ffentliche Schl¨ssel auch tats¨chlich zu der angegebenen Person geh¨rt. o u a o Damit sichergestellt ist, dass die Angaben zur Identit¨t korrekt sind und dass sich niemand a f¨r jemand anders ausgeben kann, muss ein Zertifikat zuvor zertifiziert werden. Dies geschieht u von einem Dritten, der das Vertrauen des Empf¨ngers genießt. Dies entspricht in etwa der a Situation, dass A nicht B kennt, B aber C bekannt ist. Da A nun C vertraut, best¨tigt C a die 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) bezeichneten Stellen pr¨fen auf Antrag die Identit¨t des Zertifikat-Inhabers und best¨tigen diese. Dazu be- u a a sitzen solche kommerziellen Anbieter sog. Root-Zertifikate, die auch allen g¨ngigen Browsern a bekannt 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 u zustimmen und so das Vertrauen herstellen. Die Indentit¨tsangaben von Zertifikaten stellen a also 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. u Man sieht, dass SSL einerseits eine verschl¨sselte Verbindung garantiert, anderseits aber auch u die Authentizit¨t des Servers gew¨hrleistet. Seit SSL 3.0 k¨nnen Zertifikate auch auf dem a a o Client-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 a von jedem beliebigen Arbeitsplatz aus durchgef¨hrt werden kann. Außerdem k¨nnte es zu u o Problemen kommen, wenn sich mehrere Nutzer einen PC teilen. Jedenfalls ist es dank SSL m¨glich, sensible Daten auf sicherem Wege durch das Internet zu o transportieren. Die Verschl¨sselung macht das Abh¨ren und Ver¨ndern der Daten unm¨glich; u o a o Echtheit und Vertraulichkeit ist garantiert. Die Zertifizierung gew¨hrleistet dar¨ber hinaus, a u dass Kommunikationspartner eindeutig identifiziert werden k¨nnen. o 4.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 u f¨r den internationalen Einsatz entwickelt. Eine durchdachte Gesch¨ftslogik erm¨glicht die u a o Anpassung an national unterschiedliche Bed¨rfnisse und Richtlinien. Gerade eine Oberl¨che u a f¨rs World Wide Web muss diesen Anforderungen gerecht werden. u Internationalisierung, 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 u die Anpassung auf l¨nderspezifische Eigenheiten zu gestalten. Eine Lokalisierung (l10n), al- a so die Anpassung eines Programms an l¨nderspezifische Eigenheiten, ist notwendig, da sich a die L¨nder dieser Erde nicht nur durch ihre Sprache und die zugrunde liegenden Schrift- a und Zahlzeichen, sondern auch durch abweichende Zahlen-, Zeit- und Datumsformatierun- gen, eigene W¨hrungen, unterschiedliche Telefonnummern- und Anschriftenkonventionen und a so weiter unterscheiden. ¨ 4.2.1 Ubersetzung der sprachlichen Inhalte Das 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 u Die Abbildungen 24 und 25 zeigen zwei Screenshots der Web-Oberfl¨che mit jeweils englischer a und 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 a in der Datenbank gespeichert und werden von dieser entsprechend der eingestellten Sprache abgefragt. 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 a Die Umstellung bzw. Erweiterung des Web-Interfaces auf andere Sprachen kann sp¨ter pro- a ¨ blemlos vorgenommen werden. Hierzu kann der Ubersetzer alle Sprachbezeichnungen mit einem von Varial speziell hierf¨r entwickelten Programm namens Sophia bearbeiten und er- u weitern.
  • 45.
    4.2 Internationalisierung 40 4.2.2 Zeichens¨tze a Genau wie es auf der Erde eine Vielzahl von unterschiedlichen Sprachen gibt, existieren auch verschiedene Schriftzeichen. Chinesische oder kyrillische Schriftzeichen oder auch die in un- seren Breiten verwendeten lateinischen Zeichen sind nur einige wenige Beispiele. Selbst in Europa verwenden einige Sprachen Sonderzeichen, sog. diakritische Zeichen. Beispiele sind das 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- a fangstagen der Zeichens¨tze war Speicher ¨ußerst kostbar. Dementsprechend wurde jedes nur a a m¨gliche Bit gespart, um nicht unn¨tig Platten- oder Arbeitsspeicher zu belegen und um o o nicht unn¨tig viele Daten in Netzwerken zu versenden. Da die Hardware sehr teuer war, wa- o ren zus¨tzliche Bits eine kostspielige Angelegenheit. Auch bei Zeichens¨tzen wurde gespart, a a so dass Schriftzeichen urspr¨nglich nur mit sieben Bits repr¨sentiert wurden. Diese Darstel- u a lung gen¨gte f¨r alle Buchstaben des englischen Alphabets, den Ziffern 0 bis 9, Zeichen der u u Interpunktion sowie einigen Steuerzeichen. Da die urspr¨ngliche Aufgabe von Computern u darin 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 u bald zeigte sich, dass sieben Bits nicht ausreichen. Durch die Hinzunahmen eines achten Bits wurde sp¨ter auch die Darstellung aller westeurop¨ischen Sprachen m¨glich. a a o Es dauerte nicht lange, da zeigte sich, dass die 256 zur Verf¨gung stehenden Zeichen f¨r die u u internationale Verwendung zu wenig waren. Man l¨ste das Problem damit, dass man eine o Reihe von Untermengen, jeweils bestehend aus acht Bits, einf¨hrte. So wurden zehn ISO- u 8859-Standards verabschiedet, die jeweils einen Zeichensatz, also die Zuordnung von acht Bits zu einem Zeichen definieren. ISO-8859-1, ein Standard, der auch als Latin-1 bezeichnet wird, ist beispielsweise f¨r west- u europ¨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- u europ¨ischen L¨nder wie Ungarn oder Polen ab, ISO-8859-5 stellt kyrillische Zeichen f¨r a a u Russisch, Bulgarisch oder Mazedonisch bereit. Mit ISO-8859 war es somit m¨glich, einen Großteil der europ¨ischen Sprachen abzudecken. o a Ein Problem bestand aber nach wie vor beim japanischen oder chinesischen Alphabet, die aus 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 u EUC-KR f¨r Koreanisch oder auch Shift JIS f¨r Japanisch entwickelt, die aus mehr als acht u u Bits 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 a Zeichen unterschiedlich kodiert wurden. Im Jahre 1991 gr¨ndete sich das Unicode-Konsortium u aus 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 war der Unicode-Standard, ein Zeichensatz aus 16 Bits. So lassen sich bis zu 65.536 verschiedene Zeichen in dem System unterbringen. Nach und nach wurden immer mehr Zeichen in Unicode ubernommen. 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 a neu aufgenommen, z.B. Zeichen aus historischen Schriften. Version 3.1 beinhaltet also bereits
  • 46.
    4.2 Internationalisierung 41 94.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 o 32 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 Zeichen einheitlich darstellen lassen, sondern der auch einen Austausch von Informationen normiert. 4.2.3 L¨nderspezifische Formate a Fast jedes Land hat seine eigenen Formate, beispielsweise f¨r Zahlen- oder Zeit-Angaben. Ge- u rade die Darstellung von Datumsangaben k¨nnte in den einzelnen L¨ndern unterschiedlicher o a nicht 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. u Weitere Eigenheiten findet man in der Darstellung von Uhrzeiten. In manchen Regionen ist eine 24-Std-Angabe (23:12 Uhr) gebr¨uchlich, f¨r den anderen Teil der Weltbev¨lkerung ist a u o die 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. u Selbst 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- a sprachigen Raum bei großen Zahlen Tausenderstellen durch einen Punkt trennt, verwendet der angels¨chsische Raum hier ein Komma. Bei Nachkommastellen, die, wie es das Wort be- a reits zum Ausdruck bringt, im Deutschen durch ein Komma getrennt werden, verwendet man in englischensprachigen Gebieten den Punkt. Eine Anwendung, die nicht f¨r eine Region zugeschnitten sein soll, sondern in vielen (theore- u tisch allen) L¨ndern zum Einsatz kommen kann, muss auf diese Besonderheiten achten. Was a einem 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 a mate ber¨cksichtigt und korrekt dargestellt werden. u 4.2.4 Lokalisierung der fachlichen Inhalte Die Software muss landesspezifischen Funktionalit¨ten gerecht werden. So m¨ssen unter- a u schiedliche 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ßen Aufwand an landes- oder unternehmenseigene Bestimmungen anpassbar sind. Gl¨cklicherweise b¨ndelt VWE die Business-Logik im Application-Layer, also im CORBA- u u Server. Folglich ist die Anpassung des Clients verh¨ltnism¨ßig einfach. Die ordnungsgem¨ße a a a Buchf¨hrung unter Ber¨cksichtigung landeseigener Bestimmungen wird bereits beim Server u u durchgef¨hrt. Der Client muss lediglich einige wenige Kleinigkeiten bei der Oberfl¨chenge- u a staltung ¨ndern. a
  • 47.
    4.3 Performance 42 4.3 Performance Auch bei der Entwicklung einer Web-Applikation bestehen Anforderungen im Bereich Per- formance. Der Begriff Performance beschreibt hierbei im besonderen die Anforderung, dass die Verarbeitung der Daten schnell erfolgt bzw. dass die Applikation im ganzen eine hohe Verarbeitungsgeschwindigkeit vorweist. 4.3.1 Verteiltes Rechnen CORBA unterst¨tzt die Entwicklung von Middleware. Dabei unterteilt sich die Anwendung u in drei Schichten. Auf der einen Seite befindet sich die Darstellung der Daten (Client), auf der anderen Seite die Datenhaltung. Die Middleware stellt als Server die Verbindung zwischen den beiden Enden dar. Die Performance der Anwendung l¨ßt sich u.a. dadurch steigern, a dass die Verarbeitung auf verschiedene Rechner aufgeteilt wird. So ubernehmen sowohl der ¨ Client als auch der Server verschiedene Programmaufgaben. Die Verarbeitung verteilt sich somit auf mehrere Rechner, was eine h¨here Gesamtleistung zur Folge hat. Weiterhin k¨nnen o o Anfragen 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. Der Administration-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 a sich somit die Aufgaben. Die dritte serverseitige Applikation stellt der Dispatcher dar. Seine Aufgabe ist es, Client-Anfragen auf mehrere Server-Instanzen zu verteilen. VWE erm¨glicht o es n¨mlich, gleich mehrere Application-Server parallel laufen zu lassen. Der Dispatcher sorgt a dann daf¨r, dass Anfragen nach einer fairen Zuteilungsstrategie auf die einzelnen Instan- u zen verteilt werden. Auf diese Weise ist es m¨glich, auch bei hohen Anfrage-Aufkommen die o Server-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 Vorkehrungen zu treffen. 4.3.2 Verteilung von Server-Last Nicht nur die CORBA-Anfragen k¨nnen auf mehrere Server verteilt werden. Auch die o HTTP-Anfragen k¨nnen auf mehrere Web-Server-Instanzen aufgeteilt werden. Ein sog. Load- o Balancer sorgt daf¨r, dass Anfragen des Browser auf verschiedene Web-Server gelenkt wer- u den. Abbildung 26 zeigt die Aufteilung der Anfragen. Ziel dieser Verteilung ist, dass eine Reihe von gleichzeitigen Anfragen so auf die Server verteilt werden, dass die Anzahl gleich- zeitig laufender Servlet-Threads in einem Server reduziert wird. Durch diese Verringerung der Thread-Anzahl k¨nnen Servlet-Klassen u.U. sogar exklusiv und damit um ein Vielfaches o schneller 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 u stellt. Bei Erzeugung dynamischer Seiten werden jedoch sog. Sessions verwendet (auf die Notwendigkeit von Sessions wird in Abschnitt 5.3 n¨her eingegangen werden). Da Sitzungs- a daten im Speicher des Server-Rechners verwaltet werden, muss entweder der Load-Balancer alle 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-Balancers in einer zentralen, f¨r alle Server zugreifbaren Resource gespeichert werden. Im letzen Fall u muss 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. u VWE-Web verzichtet deshalb auf die Anwendung der zweiten Verteilungsm¨glichkeit. Der o Aufwand, den eine Verteilung der Anfragen und der Sitzungsdaten zur Folge h¨tte, steht a in keinem Verh¨ltnis zu dem daraus resultierenden Nutzen. Sehr wahrscheinlich wird die a kritische Masse an Anfragen von der Applikation bei weitem nicht erreicht, so dass eine Last- verteilung hier nicht n¨tig erscheint. o Sollte es hingegen denoch zu der Notwendigkeit kommen, Serverlast zu verteilen, kann immer noch ein Load-Balancer eingesetzt werden, der darauf achtet, dass Sitzungsanfragen immer vom 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 u Anwendungsgebietes 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 o zu versenden. Anwendung finden hierbei vor allem die Formate zip bzw. gzip. Ein Servlet kann von dieser M¨glichkeit Gebrauch machen, und die erzeugten Inhalte in komprimierter o Form ubertragen. ¨ Der Browser sendet bei jeder Anfrage eine Reihe von zus¨tzlichen Daten im HTTP-Header. a Ein 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- u Angabe auslesen und uberpr¨fen, ob und welches Komprimierungsverfahren unterst¨tzt wird. ¨ u u Mit dem Packet java.util.zip des JDKs besitzt Java bereits die passende Funktionalit¨t, a
  • 49.
    4.4 Anpassbarkeit 44 um 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 Zeit f¨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- o samtperformance zu verbessern. 4.3.4 Zwischenspeicherung Viele 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 u oder 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 a h¨ufig verwendet. Die Folge sind eine Reihe von Aufrufen, die den CORBA-Server betreffen. a Da diese Aufrufe nach Annahme aber sowieso immer das selbe Ergebnis liefern, k¨nnen die o Ergebnisdaten auch nach dem ersten Aufruf clientseitig gespeichert werden. Sp¨ter ist es dann a nicht mehr n¨tig, eine Server-Methode aufzurufen, die verh¨ltnism¨ssig lange Zeit ben¨tigt, o a a o sondern es kann auf den bereits vorhandenen Datenbestand zur¨ckgegriffen werden. u Bei 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 u alle 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 a der Men¨baum mi den jeweiligen Favoriten. Da sich jeder Anwender eine pers¨nliche Ansicht u o seiner h¨ufig benutzen Men¨-Punkte zusammenstellen kann, m¨ssen diese Daten auch f¨r a u u u jeden 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 Anpassbarkeit Das Web-Interface muss sich – gerade im auf Hinblick auf das Varial Vertriebsmodell mit OEM-Partnern und den Best-of-breed“-Gedanken – leicht an individuelle Bed¨rfnisse an- u ” passen lassen. 4.4.1 Konfiguration Die 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 o beinhaltet. Eine solche war-Datei entspricht einer jar-Datei, besitzt aber zur Unterscheidung eine unterschiedliche Endung. Tomcat und eine Reihe weiterer Web-Server unterst¨tzen mitt- u lerweile diese Technik, so dass die Applikation ohne großen Aufwand auf andere Systeme ubertragbar ist. ¨ Die Datei varial.war muss lediglich in das Verzeichnis webapp beim Tomcat-Server oder ein vergleichbares Verzeichnis eines anderen Servers kopiert werden. Klassenpfade m¨ssen nicht u
  • 50.
    4.4 Anpassbarkeit 45 mehr angepasst werden. So ist VWE-Web schnell nahezu uberall einsetzbar. ¨ Weitere Konfigurationen und individuelle Anpassungen k¨nnen in der Datei web.xml, dem o sog. Deployment-Descriptor vorgenommen werden. Wie der Name bereits verr¨t, handelt es a sich 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 im Folgenden 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- u Tag gekapselt sind. Die ersten drei Angaben AdminPort, AdminClientAuthPort und ClientAuthPort geben die Port-Adressen an, unter der die verschiedenen CORBA-Server ansprechbar sind. Diese Angaben finden sich außerdem in der Server-Konfiguration, in den Dateien 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 Angabe localhost 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 46 beschrieben. 4.4.2 Corporate Design Corporate Design bedeutet, dass zusammenh¨ngende Inhalte einer einheitlichen Darstellung a folgen. 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 margentafarbene T assoziiert man mit der Deutschen Telekom und UPS pr¨sentiert sich im einheitlichen a Braunton. Das Design ist Teil der Unternehmenskultur und so ist es selbstverst¨ndlich, dass a auch 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 werden kann. Das Aussehen des Web-Interfaces muss sich also komplett an unternehmensspezifische Layout-Richtlinien anpassen lassen. Um dieser Anforderung gerecht zu werden, verwendet VWE-Web sog. Themes. Ein Theme ist eine Sammlung von Darstellungsbesonderheiten und beschreibt das Aussehen der grafischen Benutzeroberfl¨che. So l¨ßt sich f¨r jede Darstellung ein Theme entwerfen, a a u dass detailliert Farben, Schriftarten und -gr¨ße, Grafiken, Umrandungen und vieles mehr o definiert. 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 o werden. Weitere Einstellungen k¨nnen in der Datei styles.css vorgenommen werden. o Hierbei 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 a von HTML entworfen wurde. CSS wurde im Jahr 1996 vom W3C-Konsortium spezifiziert und liegt mittlerweile in Version 2.0 vor, wobei selbst Browser der neusten Generation diesen Standard noch nicht vollkommen unterst¨tzen. u Sinn 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 o HTML-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 o alle 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 u rot, 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, die auf der Oberfl¨che angezeigt wird, eine Formatklasse. Die Eigenschaften dieser Formatklassen a k¨nnen beliebig an die jeweiligen Gestaltungsw¨nsche, an das Corporate Design, angepasst o u
  • 52.
    4.5 Analogie zu bestehender VWE-Oberfl¨che a 47 werden. ¨ 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 einem Blauton. Als Schriftart wird Arial verwendet. Sollte diese Schriftart nicht verf¨gbar sein, u wird 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 erscheinen sollen. Dies alles geschieht in einer standardisierten Sprache und ist v¨llig unabh¨ngig von o a der Implementierung. Die Abbildungen 27, 28 und 29 zeigen einige Beispiele f¨r die unter- u schiedliche 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 a Das Web-Interface sollte im Aufbau dem Desktop-Client entsprechen. Durch gleiche Navi- gationsstruktur und identisch angeordnete Icons erf¨hrt der Anwender einen Wiedererken- a nungwert, der die Einarbeitung in die Browser-Oberfl¨che erleichtert. Der Mitarbeiter aus a dem Verkauf m¨chte auch im Außendienst die gewohnte Men¨f¨hrung und Oberfl¨chenmas- o uu a ke 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 a Programmmodule 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 a Objektes springt die Ansicht in eine Detaildarstellung. Hier werden weitere, detaiierte Infor- mationen pr¨sentiert. Oftmals verteilen sich diese Informationen auf mehrere Register einer a Tabsheet. In der Detailansicht soll es weiterhin m¨glich sein, zwischen den Objekten zu navigieren. Eine o Men¨leiste bietet daf¨r Icons, um zum ersten, vorherigen, n¨chsten oder zum letzen Objekt u u a zu springen. Auch diese Funktionalit¨t soll genau wie die Icons f¨r das Anlegen eines neuen, a u das L¨schen eines vorhandenen oder das Speichern eines Business-Objektes im Web-Client o
  • 54.
    4.5 Analogie zu bestehender VWE-Oberfl¨che a 49 implementiert sein. Weiterhin sollen Tabelleninhalte ausgedruckt und nach Excel exportiert werden k¨nnen. o Zusammenfassend l¨ßt sich sagen, dass der Web-Client trotz Flexibilit¨t im Oberfl¨chende- a a a sign eine an die bestehende VWE angelehnte Benutzerf¨hrung gew¨hrleisten muss. u a
  • 55.
    5 Konzeptioneller Neuentwurfeines Web-Interfaces 5.1 Multi-Tier-Architektur VWE-Web erweitert den dreischichtigen Aufbau von VWE um eine weitere Schicht. Die dadurch entstandene Architektur wurde bereit in Abschitt 3.3 mit Abbildung 18 skizziert. Die Kommunikation zwischen den einzelnen Schichten beruht auf offenen Standards. Durch die Multi-Tier-Architektur wird dar¨ber hinaus ein hohes Mass an Modularit¨t und Skalier- u a barkeit erreicht. So ist es theoretisch m¨glich, dass einzelne Schichten ausgetauscht werden o k¨nnen, es kann beispielsweise eine andere Datenbank gew¨hlt werden oder es k¨nnen ver- o a o schiedene Web-Server zum Einsatz kommen. 5.2 Das MVC-Modell Bei der Betrachtung großer Software-Projekte fallen immer wieder Schlagworte wie Modu- larit¨t, Skalierbarkeit und Wiederverwendbarkeit. Gerade beim Entwurf komplexer Systeme a muss 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 u MVC-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 a angewandt wurde. Heute h¨lt das MVC-Modell auch Einzug in moderne objektorientierte a Sprachen 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 a f¨r die Datenhaltung), View (verantwortlich f¨r die Darstellung der Daten) und Controller u u (Verbindung zwischen beiden, bearbeitet eingehende Ereignisse). Abbildung 30 zeigt den MVC-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 51 Web-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 als Model 2 bezeichnet wird. Abbildung 31 zeigt den ver¨nderten Aufbau von Model 2. a Abbildung 31: Das MVC Model 2 5.2.1 Model – Das Modell Das Modell verwaltet die Business-Logik und ist f¨r die Datenhaltung zust¨ndig. Typischer- u a weise 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 o nur spezifisch f¨r diese Web-Anwendung zu entwickeln. u VWE-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 o auch außerhalb der Web-Anwendung verwendet werden. 5.2.2 View – Die Ansicht Die View ist f¨r die grafische Darstellung der Daten verantwortlich. Sie stellt die Daten, u die das Model zur Verf¨gung stellt, f¨r den Benutzer dar. View-Komponenten werden durch u u JavaServer Pages realisiert. Zus¨tzlich zu dem normalen HTML-Code enthalten JSP-Seiten a Java-Fragmente oder auch benutzerdefinierte Elemente (Custom Tags). Solche Custom Tags entsprechen der HTML- oder, genauer gesagt, der XML-Syntax und k¨nnen als Platzhalter o f¨r Java-Code gesehen werden. Custom Tags werden in Bibliotheken, sog. Taglibs, zusam- u mengefasst. VWE-Web implementiert eine Taglib namens varial.tld, die eine Reihe von benutzerdefinierten Tags enth¨lt. a Custom 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. u Durch die Verwendung von Custom Tags ist es m¨glich, dass Designer die Oberfl¨che entwer- o a fen, ohne sich mit Programmieraufgaben zu besch¨ftigen. Sie verwenden einfach die Tags, wie a sie es von HTML bereits gew¨hnt sind. Die Algorithmen, die dahinter stecken, bleiben ihnen o
  • 57.
    5.3 HTTP und das Session-Problem 52 verborgen. Wichtig ist einzig und allein die Ausgabe des Tags. Designer m¨ssen nicht Java u verstehen, w¨hrend sich Programmierer umgekehrt nicht um das Layout k¨mmern m¨ssen. a u u 5.2.3 Controller – Die Steuerung Der Controller dient als Bindeglied zwischen Model und View. Er verwaltet Benutzerein- gaben und setzt die Daten im Modell mit entsprechenden Setter-Methoden. Anschließend gibt er die Verarbeitung an die View weiter, die das Ergebnis schließlich ausgibt. Dieser zentrale Teil wird von Servlets realisiert. Die VWE-Web-API bietet bereits in dem Packet com.varial.base (6.1) einige Oberklassen, von denen Servlets abgeleitet werden k¨nnen, so o dass typische Aufgaben des Controllers, wie das Dispatchen der Anfrage, mit vorgefertigten Methoden erledigt werden k¨nnen. o 5.2.4 Zusammenspiel der Komponenten Das 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 der Verarbeitung wird die Anfrage an eine JSP-Seite geleitet. Dort wird der Oberfl¨chenaufbau a durch HTML- und Custom Tags beschrieben. Die Taglib-Elemente rufen die zugeh¨rigen o Java-Klassen auf, die als View f¨r die Darstellung der Daten zust¨ndig sind. Diese Klassen u a bedienen sich der Daten, die das Model zur Verf¨gung stellt, generieren eine HTML-Ausgabe u und schicken diese abschließend wieder zum Browser zur¨ck. u 5.2.5 Vorteile von MVC Durch die Verwendung der MVC-Architektur k¨nnen Darstellung und Gesch¨ftslogik sauber o a voneinander 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-Problem Das HTTP-Protokoll ist zustandslos. Das bedeutet, dass der Web-Server eingehende Anfragen unabh¨ngig voneinander abarbeitet. Zusammenh¨nge zwischen mehreren Anfragen a a kann er hingegen nicht erkennen. Fordert ein Anwender z.B. drei Seiten nacheinander an, ist es dem Server nicht m¨glich, zu erkennen, dass die drei Anfragen von dem selben Benutzer o
  • 58.
    5.3 HTTP und das Session-Problem 53 gekommen sind. Dieses Verhalten ist in einem rein statischen Internet durchaus akzeptabel. Zu Problemen kommt es hingegen dann, wenn mehr dynamischer Inhalt mit ins Spiel kommt. Als Beispiel sei ein Online-Shop aufgef¨hrt. Der Besucher durchst¨bert das Angebot u o des H¨ndlers und legt, nachdem er das erste Mal f¨ndig geworden ist, einen Artikel in den a u Warenkorb. 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 trivialen Situation im Internet geworden. Wie gestaltet sich diese Szenario jedoch aus der Sicht des Web-Servers? Er erh¨lt zun¨chst eine Reihe von Anfragen, die das Angebot des Shops a a zeigen. 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 schon Artikel ausgew¨hlt wurden. Genauso steht die sp¨ter folgende zweite Warenkorb-Anfrage a a aus der Sicht des Servers v¨llig losgel¨st von der ersten Anfrage. Nimmt man weiterhin an, o o dass gleichzeitig mehrere Personen das System nutzen, erh¨lt der Server eine Reihe von a Anfragen, deren Zuordnung unm¨glich ist. o HTTP braucht also Zust¨nde. Durch einen Zustand muss es m¨glich sein, Sitzungen zu a o erkennen. Zusammengeh¨rende Anfragen m¨ssen als solche identifiziert werden. Im Beispiel o u des Online-Shops heißt das, dass alle Anforderungen des Anwenders auch vom Server als zusammenh¨ngend erkannt werden, so dass dieser den Warenkorb verwalten kann. a Um solche Sitzungen oder auch Sessions zu erkennen, dient eine sog. Session-ID. Dies ist ein eindeutiger Schl¨ssel, den die Sitzung vom Server zugeordnet bekommt. Bei der ersten u Anfrage erzeugt der Server die Session-ID und liefert sie dem Browser. Dieser muss im Folgenden jeder Anfrage die Session-ID hinzuf¨gen. Der Server weiß so, dass gleiche Session- u IDs zur selben Sitzung geh¨ren. Auch parallele Anfragen von mehreren Nutzer lassen sich o so auseinanderhalten und richtig zuordnen. Vorraussetzung ist, dass der Algorithmus, der serverseitig die Session-ID generiert, verschiedene Schl¨ssel erzeugt. Sollten zwei Anwender u die gleiche Session-ID bekommen, w¨rden sie aus der Sicht des Servers ein und die selbe u Person darstellen. Resultat w¨re in der Regel ein ziemliches Chaos. a Damit der Browser die Session-ID bei jeder Anfrage mitliefert, k¨nnen verschiedene o Techniken benutzt werden (Abbildung 32). Zum einen k¨nnen Session-IDs in sog. Cookies o gespeichert werden. Dies sind sehr kleine Textdateien, die von Web-Seiten auf der Festplatte des Benutzers gespeichert werden k¨nnen. Die Informationen, die in den Cookies gespeichert o werden, k¨nnen sp¨ter von der Seite wieder abgefragt werden. Bei jedem Seitenbesuch w¨rde o a u die 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 o im 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 ¨ u erkennen k¨nnte. o Eine weitere M¨glichkeit besteht darin, versteckte Formfelder in eine Internetseite o einzubauen. 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 anderen Feldern 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 a in 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 u Diese 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. Anstatt die Adresse http://www.abc.de/eineSeite.jsp?param=xy anzufordern, wird http://www.abc.de/eineSeite.jsp;sessionid=0123456789?param=xy angefordert. Der Server zerlegt nun die Adresse wieder in die einzelnen Bestandteile. Die Servlet-API bietet hierf¨r bereits vorgefertigte Methoden, so dass sich das URL-Rewritting f¨r den u u Entwickler 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ßerdem stellen Servlets bereits ein session-Objekt bereit, in dem Sitzungsdaten gespeichert werden k¨nnen. o Zum Schluss bleibt die Frage, wie das Ende einer Sitzung erkannt wird. Angelegte Sessions
  • 60.
    5.4 Business-Objekt und Enumerations 55 sollten nicht ewig existieren, da dies unn¨tige Systemresourcen verbrauchen w¨rde. Deshalb o u gibt es zwei Arten, wie eine Session beendet werden kann. Zum einen kann der Anwender explizit das Ende einer Session bestimmen. Sobald er sich von dem Web-Client durch Anklicken des entsprechenden Symbols abmeldet, wird das Session-Objekt und die zugeh¨ri- o ge ID verworfen. Nun kann es jedoch auch vorkommen, dass der Anwender die Sitzung nicht durch ein Logout beendet. Er k¨nnte genauso gut einfach den Browser schließen o oder durch die Eingabe einer anderen Adresse die Seite verlassen. Auch ein System- oder Programmabsturz k¨nnte Ursache f¨r ein fehlendes Logout sein. Der Web-Server kann daher o u Sessions nach einer gewissen Zeitspanne verwerfen. Sobald eine Sitzung f¨r das angegebene u Intervall keine neuen Anfragen mehr startet, wird sie als ung¨ltig erkl¨rt und gel¨scht. Die u a o Angabe, wie lange dieses Zeitinterval dauern soll, kann im Development Descriptor web.xml angegeben werden. Die Voreinstellung betr¨gt 30 Minuten. a Mit der Verwendung von Session-IDs wird das zustandslose HTTP um die M¨glichkeit von o Sitzungsverwaltungen erweitert; komplexe Web-Applikationen werden erm¨glicht. o 5.4 Business-Objekt und Enumerations Alle CORBA-Objekte werden in der IDL als sog. Structs beschrieben. Hierbei werden in der IDL alle Attribute, die ein Objekt besitzt, beschrieben. Um auf solche Objekte zugreifen zu 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 Hilfe werden f¨r IDL-Structs automatisch passende Java-Klassen erzeugt. u Jede 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 a Beispiel: IDL-Struct:
  • 62.
    5.4 Business-Objekt und Enumerations 57 struct 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 a hinzugef¨gt. Sie zeigen, wie Methoden des Servants aufgerufen und IDL-Typen in BOs u umgewandelt 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). a Um sie in den Java-Klassen zug¨nglich zu machen, dient das Perl-Skript WebEnumBuilder. a Dieses Skript erzeugt eine Java-Klasse, die es erm¨glicht, Enumerations als eine Liste von o Strings zu erhalten. N¨tzlich ist dies z.B. dann, wenn eine Combo-Box gef¨llt werden soll. u u Die 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 64 import 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-Problem Typisch f¨r ERP-Systeme sind Suchanfragen auf großen Datenmengen. Da die Zeit f¨r die u u Suche mit der Menge der Daten zunimmt, muss der Benutzer unter Umst¨nden lange War- a tezeiten bis zur Ergebnis-Ausgabe hinnehmen. Sucht man z.B. alle Kunden, die ihren Sitz in Deutschland haben, so kann das bei einem entsprechend großen Kundenstamm zu einer recht großen Ergebnismenge f¨hren. Es ist nicht u praktikabel, den Anwender lange auf das Suchergebnis warten zu lassen und ihm alle Daten auf einmal zu pr¨sentieren. Vielmehr ist es sinnvoller, Daten St¨ck f¨r St¨ck anzuzeigen, a u u u die Liste der Suchergebnisse also schon w¨hrend der Suche aufbauen zu lassen. So kann der a Anwender die Daten bereits lesen, w¨hrend weitere Daten noch gesucht werden. Evtl. ist der a gesuchte Datenbestand bereits dabei, so dass die Suche vorzeitig vom Benutzer abgebrochen werden kann. Eine solche Funktionalit¨t wird von VWE mit dem sog. Callback-Mechanismus a erm¨glicht. o Unter 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 ist ein CORBA-ORB beides: Client und Server. Dem Server wird eine Objektreferenz f¨r einu Client-Callback-Objekt ubergeben, mit dem er Funktionen des Clients aufrufen kann. Auf ¨
  • 72.
    5.5 Das Callback-Problem 67 diese Weise kann der Server, wenn er eine gewisse Anzahl von Daten gefunden hat 4 , eine Methode des Clients aufrufen und die gefundenen Daten ubergeben. Der Client wiederum ¨ kann diese Ergebnisse darstellen und auf weitere Daten warten. Um einen Callback-Aufruf zu erm¨glichen, muss der Client als Erstes das IDL-Interface AllCallback implementieren: o interface 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 u weiteren 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 o es wird f¨r den jeweiligen Datentyp ein entsprechendes Interface abgeleitet: u interface 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 u durch Vererbung die beiden Methoden des AllCallback-Interfaces und spezifiziert dar¨ber u hinaus die typspezifische Methode putData(). Diese Methode erwartet einen Parameter: PersonalAccountShortSeq. Dies ist eine Liste von Personen-Konten. Der Server kann also gefundene Daten mit putData() an den Client ubergeben. ¨ Beim Aufruf der Server-Methode wird dieses Callback-Objekt mit ubergeben: ¨ // get personalaccounts by filter void 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 68 Man erkennt als dritten Parameter den PersonalAccountStructCallback. Der Server kann nun entsprechende Abfragen auf der Datenbank durchf¨hren, Teilergebnisse durch u den 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 u Client 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 a ligen. Der CORBA-Client ist in diesem Fall ein Servlet. Dieses Servlet erzeugt HTML-Code, den es 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 geschickt wurde, l¨sst sich nicht mehr ver¨ndern. Bei HTTP sind die Client- und Server- Rollen strikt a a verteilt, so dass der Server ausschließlich auf Anfrage des Clients t¨tig werden kann. Wie a kann das Servlet nun die Daten, die es in unregelm¨ßigen Abst¨nden vom CORBA-Server a a bekommt, im Browser darstellen, wenn die HTTP-Verbindung keine unmittelbare Kontrolle des Servlets uber die Darstellung erm¨glicht? Im Folgenden werden m¨gliche L¨sungsans¨tze ¨ o o o a aufgezeigt: 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 a das Ende mit finished() angezeigt wird, k¨nnen alle Daten als Tabelle an den Browser o geschickt 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 den Browser muss also schon vor dem finished() erreicht werden. 5.5.2 Server Push Im 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 o Animation oder auch das aktuelle Bild einer Webcam darstellen. Im Callback-Szenario k¨nnte o das Servlet eine Tabelle mit bereits empfangenen Daten erzeugen, dieses mittels Server-Push an den Browser schicken, auf neue Daten warten, um dann erneut so zu verfahren. Beim Aufruf von finished() k¨nnte Socket-Verbindung schließlich geschlossen werden. o Auf 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 a Benutzer bekommt somit nacheinander immer wieder eine neue Seite geliefert, die jedes Mal mehr Daten enth¨lt. Aber auch diese L¨sung hat vier entscheidende Nachteile: a o Dadurch, dass die Seite jedes Mal neu aufgebaut wird, sieht man bei jedem Neuaufbau den
  • 74.
    5.5 Das Callback-Problem 69 Seitenanfang. 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, o dass 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- a braucht oder dass eine langsame Internetverbindung die Darstellung bremst, k¨nnte die Seite o erneut aufgebaut werden, bevor sie komplett dargestellt wurde. Im schlimmsten Fall k¨nnteo die Seite gar nicht angezeigt werden, da sie bereits von der n¨chsten Seite ersetzt wurde. a Resultat w¨re, dass auch hier erst zum Schluss Daten angezeigt w¨rden. Der dritte Nachteil a u beim 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 o ist, dass sowohl der Internet Explorer als auch Opera diese Technologie nicht unterst¨tzen u und es fraglich ist, ob sie es jemals tun werden. 5.5.3 Client Pull Wie bereits oben erw¨hnt, wird der Server auf Anfrage des Clients aktiv. Beim Client Pull a l¨sst man den Browser deshalb in bestimmten Zeitintervallen neue Anfragen an den Server a starten. So k¨nnte das Servlet einen Thread starten, der im Hintergrund die bereits emp- o fangenen Daten sammelt. Der Browser k¨nnte seinerseits alle N Sekunden eine Anfrage an o das Servlet starten, dass eine Tabelle mit den bereits empfangenen Daten zur¨ckschickt. Dies u wiederholt 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 a Daten 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 o Zwischenzeit keine neuen Daten beim Servlet eingegangen sind. Ein Laden der Seite w¨re so-a mit uberfl¨ssig. Eine unn¨tig hohe Netz- und Server-Last w¨re die Folge. Ist das Zeitintervall ¨ u o a jedoch zu lang gew¨hlt, kann der entscheidende Callback-Vorteil, n¨mlich Daten just-in-time a a zu 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 Darstellung k¨nnte unter Umst¨nden l¨nger als das Zeitintervall sein, so dass die Seite immer wieder von o a a einer neueren verdr¨ngt wird. a 5.5.4 Client Pull + DHTML Anstatt die Seite jedes Mal neu aufzubauen, k¨nnte eine Hilfsseite verwendet werden. Diese o Seite wird in ein verstecktes frame oder iframe geladen und l¨dt sich mittels Client Pull a in regelm¨ßigen Abst¨nden neu. Hierbei m¨ssen nicht alle gefundenen Daten vom Servlet a a u geliefert werden, sondern lediglich die neu hinzugekommenen. So wird die Netzlast gering gehalten. Sobald die Hilfsseite neue Daten empfangen hat, werden diese mit JavaScript an die eigentliche Tabelle angeh¨ngt. Auf diese Weise w¨chst die Tabelle, ohne dass die Seite a a neu geladen werden muss. Lediglich die Hilfsseite muss neu aufgebaut werden. Da diese aber nicht 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 70 kl¨rt. Gr¨ßter Nachteil ist jedoch die noch magelnde DHTML-Unterst¨tzung der Browser- a o u Hersteller. Opera unterst¨tzt diese L¨sung beispielsweise nicht, da die Hilfsseite die Haupt- u o Tabelle mit dem JavaScript-Befehl getElementById() ansprechen m¨sste, der von Opera u noch nicht implementiert ist. 5.5.5 Daten ungepuffert schreiben Anstatt die Seite jedes Mal neu zu laden, k¨nnte sie auch einfach nach und nach aufgebaut o werden. Setzt das Servlet den Ausgabe-Puffer auf 0 Byte oder leert ihn explizit mit dem flush()-Befehl, wird die Ausgabe direkt an den Browser geschickt. Wird bei jedem Aufruf von putData() die Ausgabe erzeugt, geschrieben und mit flush() der Buffer geleert, baut sich im Browser nach und nach die Tabelle auf. Durch diesen L¨sungsansatz werden direkt mehrere oben genannte Nachteile umgangen: o Die Seite muss nicht neu geladen werden, sie baut sich auf. Dadurch springt die Scrollposition nicht nach oben, es entsteht kein Flackern und es erscheint ein permanentes Bild. Die Daten werden genau dann angezeigt, wenn sie vom Server geliefert werden und sind nicht an ein konstantes Zeitintervall gebunden. Die L¨sung ist frei von DHTML und schließt somit keine o Browsertypen 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 wird dies erst angezeigt, nachdem die Tabelle vollst¨ndig ausgegeben wurde, also erst nach dem a finished(). Dieses Problem l¨sst sich recht einfach umgehen, indem die Tabelle in ein iframe a eingebettet wird. Angenehmer Nebeneffekt hierbei ist, dass die Tabelle im Layout immer den selben Platz einnimmt und mit Scrollbalken versehen wird. Ein gr¨ßeres Problem stellt jedoch die Tatsache dar, dass viele Browser die Spaltenbreiten o optimal an die Zelleninhalte anpassen. Um eine optimale Darstellung zu erreichen m¨ssen u aber erst alle Eintr¨ge bekannt sein. Schließlich kann der breiteste Spalteninhalt nicht ermit- a telt werden, wenn noch nicht alle Inhalte bekannt sind. Folge ist, dass Tabellen erst beim abschließenden table-Tag angezeigt werden. Werden die einzelnen Zeilen also zum Browser geschickt, zeigt dieser sie erst an, nachdem die Tabelle komplett ubertragen wurde. Folglich sieht der Anwender keinen Unterschied zur ¨ erstgenannten Sammell¨sung. o Der 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 mit der CSS-Angabe table-property:fixed, baut der IE die Tabelle fl¨ssig auf. Beim Opera u bewirkt dies hingegen keine Ver¨nderung. a 5.5.6 Daten ungepuffert schreiben + viele kleine Tabellen Wie 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 o der 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 71 die Spaltenbreiten in Tabellen vergr¨ßert, wenn Inhalte zu groß sind, f¨hrt dies zu dem un- o u gew¨nschten Nebeneffekt, dass die Spaltenbreiten in den einzelnen Tabellen unterschiedlich u breit sein k¨nnen. Es entsteht nicht mehr der Eindruck, dass es sich um eine einzige Tabelle o handelt. 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 a beim IE beheben. Die CSS-Angabe overflow:hidden in den Tabellenzellen, die ubergroßen ¨ Inhalt abschneidet, bleibt wirkungslos. Deshalb wurden die Zelleninhalte mit einem div-Tag umschlossen, der wiederum mit dem besagten overflow:hidden versehen wurde. Dadurch werden auch bei Netscape und Mozilla breite Eintr¨ge abgeschnitten. Die Spalten haben aber a nicht zwangsl¨ufig die selbe Breite. Ein Grund daf¨r konnte nicht gefunden werden. Ebenso a u wenig f¨r das Verhalten des Opera-Browsers: Dieser schneidet zwar die Inhalte ordnungs- u gem¨ß ab, die Spalten sind aber so breit, wie sie sein m¨ssten, wenn sie nicht abgeschnitten a u w¨ren. Hierbei handelt es sich h¨chstwahrscheinlich um einen Browser-Bug. a o Man sieht, dass sich das Bem¨hen des Browsers, Tabellen optimal darzustellen, selbst mit u CSS nicht vollst¨ndig abschalten l¨sst. Viele kleine Tabellen werden folglich schnell, aber a a unsch¨n dargestellt. o 5.5.7 Daten ungepuffert schreiben + Tabelle imitieren Anstelle von table-Tabellen k¨nnen div-Elemente benutzt werden, um Tabellen zu imi- o tieren. Zelleninhalte werden in div-Bl¨cke gefasst und mit CSS auf die gew¨nschte Breite o u gebracht. So werden Callback-Daten schnell und sauber formatiert dargestellt. Einziger Nachteil 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 o optimal angepasst worden. Abschließend l¨sst sich sagen, dass nur dieser L¨sungsweg dem Callback-Ansatz gerecht a o wird und zugleich eine browserunabh¨ngige Darstellung erm¨glicht. a o 5.5.8 Asynchrones Warten Der CORBA-Server liefert die Daten, der Browser bzw. das Servlet ist f¨r die Darstellung u dieser Daten zust¨ndig. Infolgedessen muss der Server darauf warten, dass die Darstellung a beendet ist, bevor neue Daten geliefert werden k¨nnen. Dieses Warten f¨hrt u.U. zu einem o u Performanceverlust, n¨mlich genau dann, wenn die Darstellung der Daten mehr Zeit als ihre a Lieferung ben¨tigt. Abhilfe schafft hier ein asynchrones Warten. o Die Situation entspricht dem klassischen Erzeuger-Verbraucher-Problem. Der CORBA-Server erzeugt die Daten, das Servlet verbraucht diese. Beide Parteien k¨nnen asynchron laufen. Das o heißt, der Erzeuger muss nicht darauf warten, dass alle Daten verbraucht wurden. Vielmehr laufen beide Jobs in getrennten Threads. Zur Kommunikation dient eine Queue. Der Erzeuger f¨llt die Queue mit Inhalt, woraufhin der Verbraucher die Queue-Inhalte entnehmen kann. u Auf diese Weise ist es m¨glich, dass der CORBA-Server kontinuierlich Daten liefert kann. o Zur 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 72 haben 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- a Objekt. 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- ¨ u stellung der Daten in Tabellen zust¨ndig ist. Ist die Darstellung komplett, wird uberpr¨ft, a ¨ u ob 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 der VListStateThread in einen Wartezustand und verharrt in diesem, bis er vom CORBA-Server resp. Callback-Klasse dar¨ber benachrichtigt wird, dass entweder neue Daten vorhanden sind u oder keine Daten mehr folgen. Durch diese asynchrone Verarbeitung beider Seiten braucht ein Thread keine R¨cksicht auf die Verarbeitungsgeschwindigkeit des Gegen¨bers zu nehmen. u u 5.6 Tabsheets Aus 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 o es, 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 o an die, von der Desktop-Anwendung gewohnte Oberl¨che, angelehnte GUI realisieren soll, a muss 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 Schritt muss somit sein, eine grafische Nachbildung einer Karteikarte zu erstellen. Dazu wird das table-Tag verwendet, dass eine Tabelle darstellt. Dadurch, dass mittels CSS-Angaben nur bestimmte 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 muss der Inhalt der entsprechenden Karte in den Vordergrund verschoben werden und die anderen Karten verdecken. HTML bietet zwar in neueren Versionen die M¨glichkeiten, entweder sog. o Layer (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-a gen Browsern ausgereift und selten kompatibel. Aus diesem Grunde muss jede Registerkarte als eingenst¨ndige Seite dargestellt werden. Folglich gibt es eine Seite, die die Tabsheet mit a aktivierter Karteikarte 1 darstellt, eine Seite, die die Tabsheet mit aktivierter Karteikarte 2 darstellt, usw. Da der Inhalt dynamisch erzeugt wird, m¨ssen hierf¨r nicht viele unterschied- u u liche, sondern nur eine einzige Seite erstellt werden. ¨ Klickt der Anwender also auf eine Register-Uberschrift, wird die Seite geladen, die den Inhalt dieses Registers anzeigt. Genauer gesagt, wird die aktuelle Seite erneut mit einem Parameter geladen, der angibt, welche Kartei-Karte dargestellt werden soll. Je nachdem, welchen Wert dieser Parameter erh¨lt, erzeugt das Servlet eine andere Ausgabe. a Es 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 eindeutigen Index. Dieses Vorgehen stellt sicher, dass eine Register-Karte unabh¨ngig von der aktuellen a Spracheinstellung 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 u HTML-Verweise zu realisieren, die zus¨tzlich mit dem passenden Query-String-Parameter a f¨r den Index versehen sind. Beispielsweise k¨nnte als Spalten¨berschrift der ersten Karte u o u folgende HTML-Anweisung dienen: <a href="dasGleicheServletNochmalAufrufen?tabsheetindex=0>Erste Karte</a> Das Servlet w¨rde hierbei einfach den Query-String-Parameter tabsheetindex abfragen und u nur die Ausgabe f¨r die erste Tabsheet erzeugen. u switch(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 74 Mit diesen Schritten w¨re eine Tabsheet bereits visualisiert und mit der Funktion f¨r das a u Umschalten der Reiter versehen. Es offenbart sich aber ein weiteres Problem. Daten in einer Tabsheet 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 u ein und wechselt zur Karte f¨r die Bankverbindung, wird die gemachte Angabe verworfen. u Der Grund daf¨r ist, dass das bearbeitende Servlet zwar erf¨hrt, dass die Bankverbindungs- u a Karte angefordert wurde, es weiß aber nicht, welche Seite zuvor bearbeitet wurde. Dieses Problem l¨ßt sich noch leicht dadurch beheben, dass neben dem Parameter f¨r die ange- a u forderte 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 u dritten 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 Anderungen noch immer nicht gespeichert werden. Der Grund hierf¨r ist, dass die eingegebenen Daten u nicht ubertragen werden. Ein Link f¨hrt einfach zur n¨chten Seite. Vielmehr m¨sste das ¨ u a u Formular, das auf der Registerkarte dargestellt wird, abgesendet werden. Zum Absenden verwendet HTML ausschließlich Buttons und in neueren Versionen zus¨tzlich Bilder. Die a Verwendung 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 u eine 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 bestehende Design 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 u tabClicked() auf. Diese Funktion befindet sich in der Datei varial.js, die automatisch in jede JSP eingebettet wird. function tabClicked(tabsheetname, tabindex) ¨ Ubergibt man der Funktion den Namen der Tabsheet (da auf einer Seite mehrere Tabsheets verwendet 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- u mular. 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 o com.varial.gui.TabSheetBean (6.3.20) erzeugt. F¨r den Entwickler bleiben die oben u erl¨uterten Einzelheiten verborgen. Er spezifiziert lediglich mit der API einige Eigenschaften a der 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 Anderungen persistent 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 75 werden. Dieser w¨rde sie in der Datenbank speichern. Dies ist jedoch nicht erw¨nscht, da u u ein BO nur dann gespeichert werden soll, wenn der Benutzer dies ausdr¨cklich durch das u entsprechende Men¨-Symbol veranlasst. Tabsheets f¨hren also zu der Notwendigkeit, BOs u u tempor¨r auf der Client-Seite zu speichern. a Um diese Anforderung zu realisieren, wurde die Klasse com.varial.base.TempData (6.1.15) entworfen. Sie speichert BOs im session-Objekt. TempData verwaltet hierzu einen Hashtable, 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 u Setter-Methoden des BOs durch und veranlasst die TempData-Klasse wieder, das BO in der Session zu speichern. Klickt der Anwender auf den Speicher-Button der Men¨lei- u ste, muss nun einfach die commit()-Methode des BOs aus der Session ausgef¨hrt werden. u Das 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-Methode enableSave() 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 nicht der Fall, muss das BO nicht von TempData angefordert und aktualisiert werden. Reslutat ist eine Zeiteinsparung und Performance-Verbesserung des Servlets. 5.7 Multimedia Neben der reinen HTML-Erzeugung k¨nnen Servlets weitere Inhalte generieren. Bei VWE o besteht zum Beispiel die Anforderung, Daten grafisch in Form von Diagrammen darzustellen. Außerdem ist ein Datenexport nach Microsoft Excel zu realisieren, damit Tabelleninhalte in Office-Dokumenten weiterverarbeitet werden k¨nnen. Als Letztes soll die Darstellung der o Unternehmensdaten f¨r portable Kleinstger¨te wie Handys und PDAs mittels WAP m¨glich u a o sein. 5.7.1 MIME-Typen Der Schl¨ssel f¨r die Bereitstellung multimedialer Inhalte liegt in der Verwendung von MIME- u u Typen. MIME steht f¨r Multipurpose Internet Mail Extensions. Die Bezeichnung deutet an, u dass MIME-Typen ihren Ursprung im Bereich der eMail hatten. Durch die Versendung von Dateien im Anhang einer Mail ist es notwendig, die einzelnen Teile der Mail zu trennen. So muss beispielsweise eine angeh¨ngte Bild- oder Zip-Datei von dem eigentlichen Nachrichten- a text getrennt werden. MIME ist eine Konvention dar¨ber, wie der Daten-Typ der einzelnen u Teile 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- a Type besteht aus zwei Teilen: Einem Haupt- und einem Subtyp. Beide Angaben werden durch Schr¨gstrich voneinander getrennt. Beispiele f¨r h¨ufig verwendete MIME-Typen sind a u a text/html, image/jpg oder text/plain. Der MIME-Haupttyp erm¨glicht die Einordnung o in eine der folgenden Gruppen: text Textdateien
  • 81.
    5.7 Multimedia 76 image Grafikdateien video Videodateien audio Sounddateien application Dateien, die an ein bestimmtes Programm gebunden sind multipart mehrteilige Daten message Nachrichten model Dateien, die mehrdimensionale Strukturen repr¨sentieren a Die vom Servlet erzeugten Daten werden mit der Angabe des entsprechenden MIME-Typs versehen. 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- u gieren in einer solchen Situation aber normalerweise damit, einen Dialog anzuzeigen, der dem Anwender den Download der Datei vorschl¨gt. a Etwas problematischer ist die Verwendung eines unbekannten MIME-Typens auf der Server- seite. Unbekannte Typen werden in der Regel nicht verarbeitet. Deshalb ist es wichtig, den Web-Server passend zu konfigurieren, wenn exotische MIME-Typen verwendet werden. 5.7.2 Bilderzeugung Der VWE-Web-Client soll die M¨glichkeit besitzen, Datenreihen grafisch in Form von Dia- o grammen zu generieren. Hierzu muss wie bereits erw¨hnt, zuerst der richtige MIME-Type a gesetzt 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 u die Realisierung von VWE-Web wurde auf eine Klassenbibliothek namens jChart zur¨ck- u gegriffen, die bei der OpenSource-Sammlung sourceforge.net zu finden ist. Mit Hilfe dieser Klassen k¨nnen Graphen aus ubergebenen Daten erzeugt werden. F¨r die Verwendung im o ¨ u VWE-Umfeld wurde eine spezielle Klasse im com.varial.base-Package entworfen. Sie tr¨gt a den 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/gif gesetzt. 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 u erzeugte 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 Tabelle 5.7.3 Excel Genau wie die Desktop-Version von VWE soll auch das Web-Interface die M¨glichkeit bie- o ten, Tabelleninhalte nach Excel zu exportieren. Abbildung 34 zeigt die Tabellendarstellung in 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 hier muss zun¨chst der passende MIME-Typ gesetzt werden. In diesem Falle handelt es sich um a die 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 Anwendung angezeigt. Da Excel seit der Office2000-Version die M¨glichkeit bietet, HTML-Tabellen zu importieren, o gestaltet sich das Szenario denkbar einfach. Das Servlet muss nur den MIME-Typ setzen und die Daten wie gewohnt senden. Nun ist es Aufgabe des Browsers, passend auf den Typ zu reagieren, Excel zu ¨ffnen und die Daten in die Anwendung zu importieren. Einziger Unter- o schied auf der Serverseite ist also, dass ein anderer MIME-Type gesetzt wird. Die gesendeten
  • 83.
    5.7 Multimedia 78 Daten bleiben identisch. ¨ Ein solcher Datenexport ließe sich im Ubrigen auch f¨r andere Office-Anwendungen realisie- u ren. Auf diese Weise w¨re auch ein Export nach Word oder Outlook m¨glich. Auf Systemen, a o auf denen die passende Software nicht installiert ist (z.B. Linux), w¨rde dem Anwender ein u Fenster pr¨sentiert, mit dem die Daten als xls-Datei abgespeichert werden k¨nnen. a o 5.7.4 WAP WAP ist die Abk¨rzung f¨r Wireless Application Protocol und definiert ein Protokoll f¨r u u u kabellose Verbindungen. WAP wurde 1998 von den Firmen Ericsson, Nokia, Motorola and Unwired Planet (sp¨ter Phone.com) entwickelt und legt fest, wie Daten in kabellosen Netzwer- a ken 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 u Datei entsprechen muss. Dies heißt bespielsweise, dass jedes ge¨ffnete Element geschlossen o werden muss und dass die Verschachtelung von Elementen einer speziellen DTD entsprechen muss. HTML ist im Vergleich dazu nicht ganz so streng. So wird beispielsweise das br-Tag normalerweise nicht geschlossen. WAP und WML finden haupts¨chlich Verwendung in Kleinstger¨ten. Beispiele f¨r solche, a a u als 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- o ne normalen Internetseiten ubertragen werden. Dies d¨rfte in Verbindung mit sehr hohen ¨ u Preisen der Grund daf¨r sein, wieso sich WAP bis heute nicht so stark durchgesetzt hat, wie u sich 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 u worfen. VWE-WAP benutzt hierbei die selbe Architektur wie die Web-Anwendung. Daten werden auch hier von einem Servlet verwaltet, das die Darstellung einer JSP-Seite uberl¨ßt. ¨ a VWE-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 der Diplomarbeit diese Technologie nur am Rande bearbeitet werden. Außerdem stellt sich die Frage, inwieweit die eingeschr¨nkte Hardware eine sinnvolle ERP-Anwendung erm¨glicht. a o Dennoch soll beispielhaft ein Anwendungsfall umgesetzt werden. Die Implementierung des TaskReminders, also einer Erinnerungsfunktion, erscheint hier vern¨nftig. Die M¨glichkeit, u o Fristen 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 a dieser 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 hierbei ist 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. Die Beachtung des zweiten Punktes, n¨mlich die Seite in WML zu schreiben, stellt ebenfalls kein a groß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 a von dynamischen HTML, aber es sind durchaus andere Formate wie XML, L TEXoder eben A auch WML m¨glich. Der Adaption von VWE-Web zu VWE-WAP steht somit nichts mehr o im Wege. 5.8 Darstellung mit verschiedenen Browsern Die Tatsache, dass dem Benutzer eine Vielzahl von unterschiedlichen Browsern (mit diversen Einstellungen), auf verschiedenen Systemen zur Verf¨gung steht, f¨hrt dazu, dass bei der u u Darstellung der Daten dieser Heterogenit¨t Rechnung getragen werden muss. Die Ausgabe a sollte auf allen g¨ngigen Browsern fehlerfrei dargestellt werden k¨nnen. Dabei sollte sie a o uberall m¨glichst gleich gestalltet sein, was nat¨rlich nicht ausschließt, dass Features, die ¨ o u nur ein gewisser Browser unterst¨tzt, nicht ausgenutzt werden sollen, wenn andere Browser u entsprechende Alternativen zur Verf¨gung stellen. u Bei der Erstellung des Web-Interfaces kommen verschiedene Techniken zum Einsatz, die bestimmte Anforderungen an den Web-Browser, der die Daten darstellen soll, stellt. Im Spezielen ist dies die Seitenbeschreibungssprache HTML, die Formatierungssprache CSS, die Programmiersprache JavaScript und das Document Object Model (DOM). Im Gegensatz zu anderen clientseitigen Web-Technologien wie beispielsweise Flash handelt es sich bei allen verwendeten Ans¨tzen um Standards. Immer wenn von Internet-Standards die Rede ist, a f¨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 u f¨hrenden Vertretern der Softwareindustrie mit Ziel, die Grundlagen f¨r eine Institution u u zu schaffen, die sich um Standards der neuen Internet-Technologie k¨mmerte. Im Sommer u 1995 begann das w3c dann offiziell seine Arbeit. HTML 1.0 wurde der erste Standard des neu gegr¨ndeten Konsortiums. Seither wird jede HTML-Version vom w3c verabschiedet. In u Folge dessen ist man versucht zu behaupten, dass eine standardisierte Auszeichnungssprache problemlos auf allen Browsern darstellbar sei. Schließlich liegt den Browser-Herstellern mit dem offiziellen HTML-Standard eine Referenz des Sprachumfangs und deren Umsetzung vor. Die Realit¨t sind jedoch anders aus. Zwischen konkurierende Browser-Hersteller wie a Microsoft mit dem Internet Explorer auf der einen und Netscape mit ihrem Navigator auf der anderen Seite tobt bereitsseit Jahren einen als Browser-Krieg“ bezeichneter Wettbewerb. ” Im Kampf um Marktanteile scheut man sich nicht davor, den HTML-Standard nach eigenen Bed¨rfnissen zu Formen. Resultat sind browsereigene Tags, also Anweisungen, die u ausschließlich im firmeneigenen Browser angezeigt werden und unterschiedliche Wiedergabe der w3c-Norm. Eine einheitliche Darstellung erweist sich in der Realit¨t schon bald als a Utopie. Bei CSS verh¨lt es sich ¨hnlich. Auch CSS steht unter der Kontrolle des w3c (erstmalig im a a Jahr 1996 ver¨ffentlicht), aber genau wie bei HTML klaffen zum Teil riesige L¨cken zwischen o u den Umsetzungen in den verschiedenen Browsern. Einige Stylesheet-Angaben funktionieren nur 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 a handelt es sich um eine 1995 von dem Unternehmen Netscape lizensierte Programmierspra-
  • 85.
    5.8 Darstellung mit verschiedenen Browsern 80 che. Trotzdem l¨uft JavaScript auch in den meisten anderen Browsern. Selbst der Microsoft a Internet Explorer, dem gr¨ßten Netscape-Konkurenten, unterst¨tzt JavaScript. In Wirklich- o u keit verbirgt sich hier hinter jedoch die Sprache JScript, die in Anlehnung an JavaScript von Microsoft erfunden wurde. Da JScript aber mit nahezu allen JavaScript-Befehlen zurecht kommt, stellt dies in der Praxis keinen Unterschied dar. Unter der Bezeichnung ECMAScript wurde JavaScript bereits fr¨hzeitig von der Organisation European Computer Manufacturers u Association (ECMA) als Industrie-Standard deklariert. Im allt¨glichen Einsatz zeigt sich a hingegen auch bei JavaScript, dass die Software-Hersteller bei der Umsetzung des Standards eigene 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 u sich nicht wirklich um eine neue Technologie. DOM wurde eher als Erg¨nzung zu JavaScript a entworfen. In Hinblick auf immer mehr Dynamik in Web-Seiten bestand in den Reihen der JavaScript-Programmier schon fr¨h der Wunsch, auf Teile einer Web-Seite zugreifen und u diese sp¨ter ver¨ndern zu k¨nnen. Die beiden Protagonisten des Browser-Kriegs entwickelten a a o daraufhin zwei verschiedene L¨sungsans¨tze, die dieser Anforderung entsprechen sollten. o a Die Folge war ein doppelter Aufwand, da bei der Realisierung dynamischer Seiten beiden Browsern Rechnung getragen werden mußte. Das w3c nahm sich dieser Problematik an und ver¨ffentlichte schließlich im Oktober 1998 ein als Document Object Model bezeichnetes o Modell. Dabei wurde DOM so entworfen, dass nicht nur der JavaScript-HTML-Kombination ber¨cksichtigt wurde. Ziel war es, einen einheitlichen Zugriff auf alle XML-konformen u Auszeichnungssprachen zu erm¨glichen. DOM wird in Zukunft die propriet¨ren Ans¨tze o a a abl¨sen und ein gemeinsames Modell f¨r die mit JavaScript gestallteten Web-Seiten bieten. o u Das Problem bei DOM ist weniger die Nichtbeachtung der Norm. Zwar zeigt sich auch hier deutlich, dass die Software-Hersteller ihre eigenen Wege gehen, aber die gr¨ßte Schwierigkeit o liegt 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, wie schnell die Architektur ins Wanken ger¨t. Zur L¨sung dieses Problems bieten sich folgende a o M¨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. a Zuerst werden alte Browser nicht beachtet. Als Mindestanforderung ergibt sich der Microsoft
  • 86.
    5.8 Darstellung mit verschiedenen Browsern 81 Internet 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 der Implementierung nicht ber¨cksichtigt. Weiterhin wurde darauf geachtet, nur Techniken zu u verwenden, die in allen diesen Browsern lauff¨hig sind. Sollte es die Anwendung schließlich a erfordern, werden stellenweise browserspezifische Mehrfachl¨sungen entworfen. o
  • 87.
    6 Die VWE-Web-API DiesesKapitel stellt die neue API f¨r die Erstellung von VWE-Web-Anwendungen vor. u Hierzu 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. a Die Erkl¨rungen beschr¨nken sich teilweise auf wichtige, d.h. h¨ufig verwendete Funktionen. a a a Methoden, 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 a F¨r eine komplette Auflistung wird auf die Javadoc-Dokumentation der jeweiligen Klassen u hingewiesen. 6.1 Das Packet com.varial.base Das Packet stellt Klassen f¨r die allgemeine Verwendung zur Verf¨gung. u u 6.1.1 VServlet Die Klasse VServlet wurde von HttpServlet abgeleitet und erweitert diese Klasse um einige n¨tzliche Funktionen. Alle Servlets sollten von dieser Klasse (oder einer ihrer Unterklassen) u abgeleitet 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, ServletException In dieser Methode wird zun¨chst ein VContext-Objekt (6.1.10) erzeugt und anschließend a uberpr¨ft, ob der Benutzer erfolgreich ins System eingeloggt ist. Andernfalls wird der Anwen- ¨ u der auf die entsprechende Login-Seite weitergeleitet. So wird sichergestellt, dass alle Anfragen nur von authorisierten Benutzer erfolgen d¨rfen. Sollte ein Callback (5.5) aktiv sein, so wird u dieser gestoppt. Abschliessend wird die Methode getIt() aufgerufen, die den erzeugten VContext erh¨lt. a protected void getIt Diese Methode (oder eine entsprechende Methode einer Unterklasse) sollte uberladen ¨ werden. Sicherheitsabfragen und Callback-Handling werden somit automatisch von jeder von VServlet 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 83 Die Methode waitForCallback() wird zu Beginn eines Callback-Vorgangs vom BO auf- gerufen. Das Servlet versetzt daraufhin den aktuellen Thread mit einem wait()-Aufruf in einen wartenden Zustand. Wird der Callback beendet, wird die endCallback()-Methode angestossen. Der wartende Thread wird mit der notify()-Anweisung wieder gestartet. Außerdem k¨nnen abgeleitete Klassen Methoden zur Weiterleitung von Anfragen nutzen. o Mit 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 wird einfach die Kontrolle an die angegebene URL ubergeben. ¨ Da die forward()-Methode vollst¨ndig auf dem Web-Server behandelt wird, ist sie schneller a als ein Aufruf von sendRedirect(), bei dem Daten zus¨tzlich den Weg vom Web-Server a zum 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 anderen URL behandelt wird. Deshalb ist darauf zu achten, dass relative Pfadangaben u.U. nicht mehr korrekt sind und ggf. angepasst werden m¨ssen. u Die letzte Art, die Verarbeitung umzuleiten, besteht in der Verwendung der Methode forwardToJsp(). 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) alle Komponenten 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 u det, so kann diese mit der zweiten Methode mit ubergeben werden. ¨ Generiert ein vom VServlet abgeleitetes Servlet einen Link, so muss die Session-ID auch in diesem Link vorhanden sein (siehe HTTP-Sessions 5.3). Andernfalls w¨rde die Anfrage u nicht mehr einer Session und damit einem Benutzer zuordbar sein. Resultat w¨re ein verwei- a gerter Zugriff, da der Benutzer, der die Seite anfordert, aus Sicht des Servlets nicht eingeloggt w¨re. a Um 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 werden soll. Die Methoden liefern die Adresse zusammen mit der jeweiligen Session-ID zur¨ck. u 6.1.2 VListServlet Das VListServlet wurde vom VServlet abgeleitet und bildet wiederum eine Oberklasse f¨r u alle 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 a Listenansicht ein hinreichendes Zeichen daf¨r ist, dass die Detailansicht verlassen wurde. u Weiterhin wird uberpr¨ft, ob Benutzer-Ereignisse verarbeitet werden m¨ssen. Hierzu wird ¨ u u zun¨chst die Methode catchOwnActionEvents() aufgerufen. a protected boolean catchOwnActionEvents(VContext ctx) Sollte ein Servlet uber die Standard-Men¨punkte hinaus noch weitere Funktionen definieren, ¨ u so 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 u wie gewohnt fortgef¨hrt (z.B. bei redirect() auf neue Seite), muss der R¨ckgabewert true u u sein.
  • 90.
    6.1 Das Packet com.varial.base 85 Danach uberpr¨ft das VListServlet, ob ein Men¨-Ereignis vorliegt, also ob der Benutzer ¨ u u einen Standard-Men¨punkt angeklickt hat. u Die 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, u wird 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 VDetailServlet Was das VListServlet f¨r die Listen-Ansicht ist, ist das VDetailServlet f¨r die Detail- u u Ansicht. 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 a wie Speichern, L¨schen, BO-Navigation etc. Es ist ebenfalls von VServlet abgeleitet und o uberl¨dt auch die Methoden doGet() bzw. doPost(). ¨ a Auch hier wird getestet, ob auf Benutzer-Ereignisse reagiert werden muss. Abgeleitete Servlets k¨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 den Benutzer 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 u die 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 ¨ u Dialog 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 u catchOwnActionEvents()-Parameter ubergeben, was anzeigt, dass der Benutzer bereits ¨ gewarnt wurde. Das VDetailServlet verarbeitet außerdem selbstst¨ndig alle weiteren a Ereignisse, die von den GUI-Komponenten wie z.B. der Men¨-Leiste, von Button-Feldern u oder List-Boxen ausgel¨st werden. o Damit das VDetailServlet einige Funktionen wie beispielsweise das L¨schen oder Spei- o chern von BOs ubernehmen kann, m¨ssen die abgeleiteten Klassen die Funtionen fillBO() ¨ u und getBO() implementieren.
  • 91.
    6.1 Das Packet com.varial.base 86 protected 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. u Beim 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, die vom 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 VSelectServlet Die Klasse VSelectServlet ist zust¨ndig f¨r den Entwurf von Auswahl-Dialogen. Entspre- a u chende Servlets sollten von ihr abgeleitet werden. Genau wie die Klassen VListServlet und VDetailServlet ist VSelectServlet von VServlet abgeleitet und uberl¨dt die Methoden ¨ a getIt() und postIt(). Die Klasse sorgt daf¨r, dass Abbr¨che durch den Cancel-Button automatisch zu einer Weiter- u u leitung an das aufrufende Servlet f¨hren. Andernfalls werden die Methoden getItSelect() u bzw. getItSelect() aufgerufen, die die Funktionalit¨t in der abgeleiteten Klasse implemen- a tieren sollten. proteted void getItSelect (VContext ctx) 6.1.5 VChartServlet Die Klasse VChartServlet ist ebenfalls von VServlet abgeleitet und dient zur Erstellung von Diagrammen. Beim Aufruf durch doGet() oder doPost() wird ein Diagramm erstellt und 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 der Abzisse bzw. der Ordinate, die Methode getTitle() liefert den Titel des Diagramms. Mit getXAxisLabels() k¨nnen die Abschnitts-Bezeichnungen auf der Abzisse angegeben wer- o den. Beispielsweise k¨nnte getXAxisTitle() “Zeit“ zur¨ckgeben und getXAxisLabels() o u
  • 92.
    6.1 Das Packet com.varial.base 87 einen String-Array mit den Monaten Jan“, Feb“, Mrz“, etc. liefern. ” ” ” Um die Beschriftung der Datenreihen f¨r eine Legende anzugeben, muss die Funktion u getLabels 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 a Funktion getData()). Mit der Funktion getData werden die eigentlichen Diagramm-Werte angegeben. Die Werteta- belle wird als zweidimensionale Matrix von double-Werten angegeben. Die erste Dimension steht hierbei f¨r die Datenreihe, die zweite f¨r die Werte. u u Sollen z.B. die Sinus- und Kosinus-Funktion dargestellt werden, w¨re vereinfacht folgende a Matrix n¨tig: o double[][] 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: u new String[] {"Sinus-Werte", "Kosinus-Werte"}; Mit den ubrigen Funktionen getWidth() und getHeight() kann die Gr¨ße des Bildes ¨ o angegeben werden. Die Angabe erfolgt in Pixel. Sollen bestimmte Farben f¨r die Darstellung der Balken verwendet werden, k¨nnen diese u o mit 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 u erwartet. Wird diese Methode nicht uberladen, w¨hlt VChartServlet selbstst¨ndig sich un- ¨ a a terscheidende Farben aus. 6.1.6 VState Die Klasse VState ist zust¨ndig f¨r die Ausgabe von Tabellen. Sie ist eine direkte Unterklasse a u von VServlet und uberl¨dt die Methoden getIt() und postIt(). ¨ a Um eine Tabelle anzuzeigen, muss diese als erstes in einem vom VServlet abgeleiteten Servlet mit dem GuiHelper (6.3.1) erzeugt worden sein. Mit der Klasse VState wird diese nun gef¨llt, u verwaltet 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 u um 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 a Ausnahmef¨llen, z.B. wenn zuvor spezielle Methoden der Tabelle aufgerufen werden m¨ssen. a u
  • 93.
    6.1 Das Packet com.varial.base 88 protected 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. u protected 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 a Daten. Das abgeleitete Servlet muss also erst ein Casting vornehmen, um den richtigen Type zu erhalten und kann dann die Tabelle mit deren Methode addRow() um die neuen Daten erweitern. Um die Tabelle zu formatieren stehen eine ganze Reihe von Methoden zur Verf¨gung, die u die 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 abgeleiteten Klassen VListState (6.1.7), VDetailState (6.1.8) und VSelectState (6.1.9) festgelegt, so dass 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 (also auch auf unterschiedlichen Tabsheets) angezeigt werden, k¨nnen deshalb durchaus die selbe o ID haben. Wird die Methode nicht uberladen wird standardm¨ssig die ID grid verwendet. ¨ a public boolean isEditable( VContext ctx, int row, int col )
  • 94.
    6.1 Das Packet com.varial.base 89 Gibt an, ob eine Tabellen-Zelle in der Reihe row und der Spalte col editierbar ist. Per Standard ist sie dies nicht. Wird true zur¨ckgegeben, wird der Zelleninhalt in einem Textfeld u angezeigt, 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 a public 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, a was bedeutet, dass die Ausrichtung gem¨ß des Zellentypes erfolgt. Zahlen und W¨hrungen a a werden rechtsb¨ndig, Datumsangaben, Combo- und Radio-Boxen zentriert und alle anderen u Inhalte linksb¨ndig ausgerichtet. u public 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 a handelt. 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 a denen man Zeilen f¨r den L¨schvorgang ausw¨hlen kann. Standardm¨ßing wird eine solche u o a a Spalte nicht angezeigt.
  • 96.
    6.1 Das Packet com.varial.base 91 public String[] getHeaders( VContext ctx ) Liefert die Spalten¨berschriften. u public int[] getColWidth( VContext ctx ) Liefert die Spaltenbreite in Pixel. Wird diese Methode nicht uberladen, wird null zur¨ckgege- ¨ u ben. Die Spaltenbreite wird dann optimal an die L¨nge der Eintr¨ge angepasst. Die Methode a a sollte 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 u wird. Die Methode gibt null zur¨ck, so dass folgende Werte bei neuen Zeilen eingetragen u werden: Check- und Radio-Boxen sind deaktiviert, bei Datumsfeldern wird das aktuelle Datum eingetragen, alle anderen Felder sind leer. Sollen sich die Zellen von neu eingef¨gten u Spalten 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 a W¨hrungsfeld handelt. Der Zelleninhalt wird gem¨ß den W¨hrungseigenschaften (Nachkom- a a a mestellen, Rundungsverfahren, W¨hrungszeichen etc.) formatiert. Standardm¨ssig liefert die a a Methode die Hausw¨hrung der aktuellen Firma. a 6.1.7 VListState Die Klasse VListState wurde von VState abgeleitet. Alle Servlets, die f¨r die Bearbeitung u von Tabellen in der Listenansicht zust¨ndig sind, sollten wiederum von dieser Klasse abge- a leitet 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 a werden.
  • 97.
    6.1 Das Packet com.varial.base 92 6.1.8 VDetailState VDetailState ist ebenfalls von VServlet abgeleitet und ist f¨r Tabellendarstellung in der u Detail-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 ¨ u die meisten Tabellen in der Detail-Ansicht eine L¨schfunktion besitzen und dementsprechend o eine Auswahlspalte brauchen. Als letzte Methode enth¨lt die Klasse die zus¨tzliche Hilfs-Methode getCellName(). a a protected String getCellName (int row, int col) Mit Hilfe dieser Methode k¨nnen abgeleitete Klassen den Namen von Formularfeldern aus o der Tabelle erfragen. Hat eine Tabelle z.B. die ID mygrid wird der Wert der Zelle in der 3 Zeile und 5 Spalte als mygrid 2 4 im Query-String ubertragen. Genau diese Angabe liefert ¨ die Methode. 6.1.9 VSelectState Auch die Klasse VSelectServlet wurde von VServlet abgeleitet. Genau wie VListState und VDetailState uberl¨dt auch sie die Methode getStyle(). Diese gibt hier die Infor- ¨ a mation zur¨ck, dass die Tabelle in einem Auswahl-Dialog Verwendung findet. Dementspre- u chend sollten alle Servlets, die f¨r Tabellen in solchen Auswahldialogen zust¨ndig sind, von u a VSelectState ableiten. Außerdem uberl¨dt die Klasse die Methode getGrid(). Hier wird im Gegensatz zur Super- ¨ a klasse VState nicht nur eine neue Instanz einer Tabelle zur¨ckgeliefert, sondern es werden u noch die Methoden setBackURI() und addQueryString aufgerufen. Dies ist notwendig, weil eine Tabelle in der Auswahl-Ansicht Links auf das aufrufende Servlet enth¨lt. Diese Links a werden u.a. mit diesen beiden Methoden konstruiert. 6.1.10 VContext Das VContext-Objekt ist zentraler Bestandteil der VWE-Web-Architektur. Es erm¨glicht es, o auf einfache Weise auf alle f¨r die Anwendung relevanten Daten zuzugreifen. So stellt der u VContext beispielsweise Methoden f¨r das Parameter-Handling zur Verf¨gung, kontrolliert u u den Zugriffsschutz auf Daten oder koordiniert den Callback-Mechanismus (5.5). Beim Aufruf eines VServlets (6.1.1) wird automatisch ein VContext erzeugt. Dieser wird dann an die entsprechende Methode zur Verarbeitung einer Anfrage weitergegeben. Erzeugen eines VContexts Die Klasse VContext stellt zwei Konstruktoren zur Verf¨gung. u Im 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. Der Konstruktor initialisiert darauf hin alle n¨tigen Objekte, um sp¨ter auf Cookies, Parameter, o a Session- und Request-Attribute zugreifen zu k¨nnen. o Der 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 entsprechenden Methoden f¨r das Verarbeiten der Anfragen weitergegeben. u Der zweite Konstruktor erwartet nur einen Parameter, n¨mlich ein HttpSession-Objekt: a public VContext (HttpSession session) Dieser Konstruktor sollte ausschließlich in Ausnahmef¨llen aufgerufen werden, in denen auf a keine andere Weise ein Zugriff auf ein VContext-Objekt m¨glich ist. Ein VContext, der auf o diese Weise erzeugt wurde, kann nur f¨r den Zugriff auf Session-Attribute verwendet werden. u Eine 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 o werden, kann hier der Notfall-Konstruktor verwendet werden. Eine solche Verwendung sollte jedoch stets die Ausnahme bleiben. Attribute-Handling Der VContext erm¨glicht es, auf einfache und einheitliche Weise, auf o Attribute zuzugreifen. So k¨nnen Informationen auf folgenden Bereichen verarbeitet werden: o session-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, definiert die 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 a Parameter mehrmals im Query-String vorkommen kann. PARAMETER liefert in diesem Fall den 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 94 Sie erwartet als ersten Parameter eine Angabe dar¨ber, woher das Attribute gelesen werden u soll. Hierzu dienen die bereits beschriebenen Konstanten. Als zweiter Parameter wird der Name 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 u nicht gefunden wurde. Wird ein unbekannter Bereich ubergeben, wirft getAttribute() eine ¨ VException (6.1.14). Weiterhin kann mit der Methode hasAttribute() abgefragt werden, ob ein entsprechendes Attribute vorhanden ist: public boolean hasAttribute( int scope, String name ) Der Aufruf liefert true, falls ein Attribute mit dem angebenen Namen im entsprechenden Bereich existiert, andernfalls false. Außerdem kann mit hasNonEmptyAttribute() abgefragt werden, ob ein Attribute existiert und 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 entsprechenden Bereich existiert und dieses kein Leerstring ist, andernfalls false. Um nicht jedesmal die Existenz eines Attributes zu uberpr¨fen und auf ein Fehlen entspre- ¨ u chend zu reagieren, bietet der VContext ebenfalls eine getAttribute()-Methode, die bei erfolgloser Suche einen Standardwert zur¨ckgibt. Sie erwartet zus¨tzlich zur oben genannten u a Methode 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 a muss lediglich ein Casting in den entsprechenden Typ stattfinden. H¨ufig m¨ssen Objekte des Typs String gelesen werden. a u String lastVisitCookie = (String)ctx.getAttribute(VContext.Cookie, "Last visit");
  • 100.
    6.1 Das Packet com.varial.base 95 Um diesen Aufruf zu vereinfachen, stellt der VContext eine spezielle Methode getStringAttribute() zur Verf¨gung: u public 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 ein boolean zur¨ckgibt. Auch diese drei Methoden k¨nnen mit einem dritten Parameter u o aufgerufen werden, der den Default-Wert angibt. Die Methoden getDateAttribute() und getCurrencyAttribute() lesen ein Attribut und formatieren es anschließend in einen f¨r den CORBA-Aufruf geeignetes Textformat, liefern u also einen String zur¨ck. u Lautet 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- o de wird beim Speichern eines Cookies immer der R¨ckgabewert der Methode getString() u gespeichert. Sowohl Query-String- als auch Initialisierungs-Attribute k¨nnen nicht geschrieben werden. o Hier 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 o dient die Funktion removeAttribute():
  • 101.
    6.1 Das Packet com.varial.base 96 public void removeAttribute( int scope, String name ) Der VContext bietet neben diesen Methoden noch die M¨glichkeit, auf spezielle Parameter o zuzugreifen. So kann z.B. mit hasChanged() abgefragt werden, ob der Parameter changed gesetzt wurde. Tabelle 1 zeigt, welche Methoden welche Parameter abfragen. Da diese Methoden oft zus¨tz- a lich Konsistenzbedingung pr¨fen oder auf Fehler reagieren, sollten sie stets der direkten u Attribute-Abfrage vorgezogen werden. F¨r das Arbeiten mit dem Query-String einer Anfrage stellt die Klasse zwei weitere Funk- u tionen zur Verf¨gung. u public 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, a die dem Servlet zu Beginn uber den Men¨baum mitgegeben wurden. VWE erlaubt es im ¨ u Administrationsmodus 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- u te. Dazu wird nach erfolgreicher Anmeldung des Benutzers von dem Servlet com.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-Objekt ubergeben werden. Das BO wiederum erh¨lt mit getAccessToken() das n¨tige AccessToken ¨ a o f¨r den Server-Aufruf. u Um zu uberpr¨fen, ob die Seite, von einem eingeloggten Benutzer angefordert wurde, wird ¨ u die Methode checkLogin() aufgerufen. public void checkLogin() throws AccessDeniedException, IOException Sollte der Benutzer nicht eingeloggt sein, wird eine AccessDeniedException() geworfen und der Zugriff verweigert. Das VServlet (6.1.1) ruft diese Methode automatisch auf, so dass kein explizieter 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 98 BO-Navigation Der Benutzer kann in der Detail-Ansicht mit der Men¨leiste von einem u BO zum n¨chsten springen. Der VContext beinhaltet die daf¨r n¨tigen Funktionen. Zuerst a u o m¨ssen alle BOs registriert werden. Dazu dient die Methode registerBos(): u public void registerBos ( String oidParent, BO[] bos ) Der erste Parameter gibt die ObjectID des Parent-Objekts an, also das Objekt, zu dem die BOs geh¨ren. In der Regel ist das die Firma, beim TaskReminder ist dies jedoch beispielsweise o der 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 a minimiert werden: public void registerBos (BO[] bos) Neue BOs k¨nnen mit addBo() der BO-Liste hinzugef¨gt werden. Das neue BO reiht sich o u am 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 bei registerBO() 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 99 Callback 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- u Funktionen, von denen hier die wichtigsten aufgef¨hrt werden. u public CompanyShortBO getCompany() Dies liefert die Firma, die zur Zeit ausgew¨hlt ist. Die Funktion sucht zuerst in der Session. a Sollte dort keine Firma gefunden werden (dies ist der Fall, wenn der Benutzer sich neu einloggt), wird nach einem Cookie mit der ObjectID der Firma gesucht. Wird ein solcher Cookie gefunden, wird die Firma mit der ObjectID vom Server angefordert. Sollte jedoch kein Cookie gefunden werden, oder ist die Firma seit Erstellung des Cookies gel¨scht worden, o wird einfach die erste Firma aus der Datenbank zur¨ckgegeben. u public 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 a public LanguageBO getLanguage() Mit Hilfe dieser Funktion kann die eingestellte Sprache abgefragt werden. Gesucht wird zuerst in der Session. Ist die Suche erfolglos, wird die Default-Sprache vom Server zur¨ckgegeben. u public AdminUserBO getUser() Liefert den eingeloggten Benutzer.
  • 105.
    6.1 Das Packet com.varial.base 100 6.1.11 Instance Die Klasse Instance ist lediglich dazu da, auf Initialisierung-Parameter, also Parameter der Datei web.xml zuzugreifen. Sie ist als Singleton implementiert, so dass immer nur eine Instanz der Klasse erzeugt werden kann. F¨r den Zugriff auf Initialisierungsparameter dienen u die 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 benutzt sie die Klasse VContext (6.1.10), die die selbe Funktionalit¨t mit dem Befehl a getAttribute(VContext.INIT, name) besitzt. 6.1.12 BO Die Klasse BO dient als gemeinsame Oberklasse aller Businsess-Objekte (5.4). Als Methoden stellt sie zur Verf¨gung: u protected ObjectStruct getOidTs() Diese Methode liefert den ObjektStruct des BOs. Wird sie nicht uberladen, wird eine neue ¨ Instanz einer ObjectStruct zur¨ckgegeben. u public String getObjectID() public String getTimeStamp() public String getLastUserID() ¨ Hiermit k¨nnen die ID des BOs, Datum und Uhrzeit der letzten Anderung und der Benutzer, o der das BO als letztes ver¨nderte, angefragt werden. a public 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 es in 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 o sie die selbe ObjectID besitzen. Die ObjectID wird vom CORBA-Server vergeben, sobald das BO in der Datenbank gespeichert wurde. Folglich ist darauf zu achten, dass zwei neue BOs immer als identisch gelten!
  • 106.
    6.1 Das Packet com.varial.base 101 protected 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 o VContext 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 des Web-Servers schreiben k¨nnen. o protected static void log (String msg) protected static void log (String msg, Throwable throwable) 6.1.13 VBean Die Klasse dient als Oberklasse aller f¨r VWE-Web entwickelten Beans. u Sie stellt als einzige Funktionalit¨t die Methode isFirstOneOfClass() zur Verf¨gung. a u protected boolean isFirstOneOfClass() Mit Hilfe dieser Methoden kann festgestellt werden, ob es sich bei einem Objekt um die erste erzeugte Instanz seiner Klasse handelt. Dies ist beispielsweise notwendig, bei der Verwendung von 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 u werden, wenn tats¨chlich Tabsheets verwendet werden. Werden nun mehrere Tabsheets auf a einer Seite verwendet, darf trotzdem jedes Feld nur einmal vorkommen. Alle Tabsheets teilen sich dann diese Felder. W¨rde jedes Tabsheets diese versteckten Felder erneut erzeugen, w¨rde dies zu JavaScript- u u Fehlern f¨hren. Zur L¨sung dieses Problems schreibt ausschließlich die erste Instanz die Fel- u o der. Bei Verwendung der Methode wird also nur beim ersten Methodenaufruf true zur¨ckgegeben; u alle weiteren Aufrufe erzeugen false als R¨ckgabewert. u 6.1.14 VException Bei der Klasse VException handelt es sich um eine Unterklasse von Exception, genauer ¨ gesagt von der Klasse RuntimeException. Uberall, wo Programmfehler auftauchen, auf die nicht passend reagiert werden kann, wird eine VException erzeugt und geworfen. Das ver- arbeitende Servlet kann diese dann ggf. behandeln oder einfach als Fehlermeldung an den Benutzer 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 komplett neue VException erzeugt werden.
  • 107.
    6.1 Das Packet com.varial.base 102 Soll 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: Eine Dom¨ne, eine Fehlerbezeichnung und eine Fehlernummer. Die Dom¨ne gibt an, in welchem a a Programm-Packet der Fehler auftrat, die Bezeichnung gibt an, was f¨r ein Fehler auftrat u und die Fehlernummer dient dazu, den Fehler eindeutig in der Dom¨ne zu identifizieren. Mit a diesen drei Angaben ist es auch m¨glich, Fehlermeldungen mit dem Translator (6.2.1) in o die 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 u getOriginalException(). public Throwable getOriginalException() F¨r den zweiten Fall gibt es hingegen folgenden Methoden: u public String getDomain() public String getWhat() public int getErrorNumber() Um zu unterscheiden, auf welche Art eine VException erzeugt wurde, steht der Befehl hasOriginalException() zur Verf¨gung. u public boolean hasOriginalException() Wurde eine vorhandene Exception mit einer VException verpackt“ liefert er true, andern- ” falls wird false zur¨ckgegeben. u Sehr h¨ufig vorkommende Fehler sind die von VWE verwendeten Exceptions a vom Typ PersistencyException, DomainException, AccessDeniedException und ApplicationLayerException. Um abzufragen, ob es sich bei der VException um einen der aufgef¨hrten Typen handelt dienen folgende Funktionen: u public boolean isPersistencyException() { public boolean isAccessDeniedException() {
  • 108.
    6.1 Das Packet com.varial.base 103 public 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, u sondern 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 ¨ u VExpeptions sind gleich, wenn Dom¨ne und Fehlernummer ubereinstimmen. a ¨ 6.1.15 TempData Die Klasse TempData erm¨glicht es, BOs tempor¨r zwischenzuspeichern. Dies ist u.a. notwen- o a dig, 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 u in der Datenbank persistent gemacht werden. Die Klasse TempData verwendet die aktuelle ¨ Session, um Anderungen zu behalten. Hierzu wird eine Hashtable angelegt. Die URLs der Seite bilden die Schl¨ssel, denen das zu speichernde BO zugeordnet ist. u Die Klasse bietet drei Arten von Funktionen: BOs k¨nnen gespeichert und geladen werden. o Außerdem k¨nnen BOs aus dem Speicher entfernt werden. o Um 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 104 ubergeben 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 u den. 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 u werden. Gespeicherte BOs k¨nnen verworfen werden, indem die Methode resetBO() aufgerufen wird. o public static void resetBO (VContext ctx) public static void resetBO ( VContext ctx, String uri ) 6.1.16 AbstractCallback Die Klasse AbstractCallback ist eine abstrakte Oberklasse f¨r alle Callbacks. Bei Verwen- u dung des Callback-Mechanismuses (5.5) sollte die Callback-Klasse hiervon abgeleitet werden. Die Klasse besitzt einen Konstruktor: protected AbstractCallback ( VContext ctx, VState state ) throws AdministrationException Neben dem VContext-Objekt muss ein passender VState (6.1.6), also eine Klasse, die f¨r die u Ausgabe der Tabelle zust¨ndig ist, ubergeben werden. Der Konstruktor sorgt nach Aufruf f¨r a ¨ u eine Verbindung mit dem ORB und startet einen Thread der Klasse VListStateThread, der im folgenden auf eingehenden Daten wartet. In Analogie zum Erzeuger-Verbraucher-Problem stellt 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 VListStateThread abgefragt wird, benachrichtigt den Thread dar¨ber, dass neue Daten vorliegen und wartet u auf neue Daten vom Server. Die Klasse stellt somit den Erzeuger im Erzeuger-Verbraucher- Modell dar.
  • 110.
    6.1 Das Packet com.varial.base 105 AbstractCallback und VListStateThread laufen asynchron, so dass der CORBA-Server beim Liefern der Daten nicht auf die Darstellung der Tabelle warten muss. Die bereits ubertragenen Daten k¨nnen mit der Funktion getCollectedData() abgefragt ¨ o werden. 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() u aufgerufen. public void finished() Diese Methode beendet den VListStateThread, dieser ruft zuvor noch die Methode disconnect() auf, die den Callback wieder vom ORB entfernt. public final void disconnect() throws AdministrationException Als 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ßend geworfen. Das aufrufende Servlet kann dann entsprechend reagieren. Wie bereits erw¨hnt, werden Callback-Klassen von AbstractCallback abgeleitet. Durch die- a se Vererbung besitzen sie schon die oben aufgef¨hrten Funktionen. Damit diese Funktionen u aber in einer solchen Oberklasse zusammengef¨hrt werden k¨nnen, m¨ssen die abgeleiteten u o u Klassen 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- a zifiziert werden k¨nnen. o 6.1.17 VListStateThread Die Klasse VListStateThread implementiert einen Thread der beim Callback-Mechanismus im Hintergrund l¨uft, auf Daten wartet und diese dann zur Darstellung an den passenden a VState (6.1.6) weitergibt. Sie sorgt also daf¨r, dass der CORBA-Server auf der einen und u der VState auf der anderen Seite asynchron zusammenarbeiten. Beide Parteien (AbstractCallback als Repr¨sentant des CORBA-Servers und VListState a als Client) werden im Konstruktor ubergeben: ¨
  • 111.
    6.1 Das Packet com.varial.base 106 protected 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, versetzt sich der Thread mit dem Befehl wait() solange in einen wartenden Zustand, bis er von AbstractCallback wieder geweckt“ wird. Dies wiederholt sich solange, bis die Methode ” finished() des Callbacks aufgerufen wird, die ihrerseits den Thread beendet. 6.1.18 ExceptionHelper Der ExceptionHelper stellt als einzige Funktionalit¨t die statische Methode a handleException() bereit. Mit ihr k¨nnen dem Anwender Exceptions als Fehlermel- o dungen 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 ¨ u diese eine eingepackte“ Exception enth¨lt. Ist dies der Fall, wird diese angezeigt. a ” 6.1.19 StringMapper Die Klasse StringMapper beinhaltet statische Methoden, die bei der Verarbeitung von Strings (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. Diese Methode 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 zu wandeln, steht die Methode nullToEmpty() zur Verf¨gung. u public static String nullToEmpty (String txt)
  • 112.
    6.1 Das Packet com.varial.base 107 6.1.20 VCurrency Die Klasse VCurrency dient dazu, W¨hrungsangaben aus der Datenbank f¨r die Bildschir- a u mausgabe zu formatieren, bzw. um solche Angaben wieder zur¨ck ins Datenbankformat zu u wandeln. Um Werte aus der Datenbank f¨r die Bildschirmdarstellung zu formatieren, kann die statische u Methode 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 a formatierenden Betrag. Bei der ersten Methode wird der Betrag gem¨ß der Hausw¨hrung der a a aktuellen Firma formatiert, w¨hrend beim zweiten Funktionsaufruf eine W¨hrung expliziet a a angegeben werden kann. Die Ausgabe erfolgt gem¨ß Sprach- und W¨hrungseinstellung. a a Das bedeutet, der zur¨ckgegebene String besteht aus gruppierten Tausendern, wird u entsprechend der W¨hrungseinstellung gerundet und besitzt das passende W¨hrungssymbol. a a Soll kein W¨hrungssymbol angehangen werden, kann alternativ die Methode a getViewCurrencyWithoutCurrencyCode() verwendet werden, die ebenfalls in zwei Ausf¨hrungen mit den oben genannten Parametern existiert. u Bevor W¨hrungsangaben wieder in der Datenbank gespeichert werden k¨nnen, m¨ssen sie in a o u ein 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 a zu formatierende Betrag und optional eine W¨hrung angegeben. a Abschließend zeigt Tabelle 2 einige Beispiele f¨r korrekte Formatierungen. Es wird die u Datenbank-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 a 6.1.21 VNumber Die Klasse VNumber dient einer ¨hnlichen Verwendung wie VCurrency (6.1.20), allerdings a werden hier lediglich Zahlen und keine W¨hrungsangaben formatiert. a public 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 o VCurrency (6.1.20) k¨nnen Datenbank-Angaben f¨r die Bildschirmausgabe formatiert werden o u bzw. diese wieder zur¨ckgewandelt werden. u public static String getViewDate( VContext ctx, String date ) public static String getDBDate( VContext ctx, String date )
  • 114.
    6.1 Das Packet com.varial.base 109 Mit 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 werden kann. o ¨ Weiterhin k¨nnen sog. Timestamps, die das Anderungsdatum eines BOs angeben, f¨r die Bild- u schirmausgabe aufbereitet werden. Die Funktion getViewTimeStamp() leifert hierf¨r einen u passenden String zur¨ck. u public static String getViewTimeStamp ( VContext ctx, String timestamp ) Außerdem k¨nnen diverse Datumsberechnungen mit der Klasse VDate durchgef¨hrt werden. o u So 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 folgenden Methoden: 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 110 diesen beiden Datumsangaben liegen. Auch eine Vorw¨rtsrechnung ist m¨glich. Auf diese a o Weise kann ein Datum bestimmt werden, das eine gewisse Zeitspanne nach einem gegebenen Datum 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 ist m¨glich. In diesem Fall werden das Zeitintervall abgezogen. Zur¨ckgegeben wird das berech- o u netete Datum im Datenbankformat. 6.2 Das Packet com.varial.translation ¨ Das Packet com.varial.translation beinhaltet Klassen, die f¨r die Ubersetzung aller angezeig- u ten Texte zust¨ndig sind. a 6.2.1 Translator ¨ Die Klasse Translator stellt Methoden zur Ubersetzung von Texten zur Verf¨gung. Um u einen 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 ¨ soll Damit man nun einen ubersetzten Text erh¨lt, gibt es zwei M¨glichkeiten. ¨ a o paragraphM¨glichkeit 1 Es wird zun¨chst eine Translator-Instanz mit dem Konstruktor, der o a die 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- o fragt 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(). o public 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 TranslatorCache Diese 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- a artet werden, um den Cache zu l¨schen. o 6.3 Das Packet com.varial.gui Das Packet com.varial.gui umfasst s¨mtliche Klassen, die f¨r die Erstellung von grafischen a u Benutzeroberfl¨chen zust¨ndig sind. a a 6.3.1 GuiHelper Der GuiHelper besitzt eine Reihe von statischen Methoden, mit denen auf einfache Weise Web-Oberfl¨chen zusammengestellt werden k¨nnen. Es handelt sich hierbei um eine Factory- a o Klasse, einem Entwurfsmuster, das f¨r die Erzeugung von Objekten zust¨ndig ist. Das heißt u a im Detail, dass GUI-Klassen nie direkt instanziiert werden, sondern dass die Factory-Klasse dies durch seine statischen Methoden erledigt. Mit dem GuiHelper werden GUI-Elemente erzeugt und in dem Request-Objekt, also in der Seitenanfrage, abgelegt. Eine JSP-Seite kann die Objekte sp¨ter auslesen und entsprechend a ausgeben. Eine Oberfl¨chenkomponente besteht i.d.R. aus einer sprachabh¨ngigen Beschriftung (Label), a a einem Feld f¨r Eingabe und einem Wert, der in diesem Feld steht. Außerdem besitzen die u meisten Komponenten einen Namen, mit denen eine eindeutige Identifizierung m¨glich ist. o Die 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 113 den 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 Sprache ubersetzt. ¨ Unter Umst¨nden ist es notwendig, eine erzeugte Komponente nachtr¨glich zu ¨ndern. Bei- a a a spielsweise k¨nnte ein Textfeld erzeugt werden, dass unter bestimmten Bedingungen aktiviert o bzw. deaktiviert ist. Ein Servlet m¨chte folglich nicht nur ein Textfeld erzeugen, sondern es im o Anschluss auch noch ver¨ndern. In diesem Beispiel also deaktivieren. Damit solche Aktionen a m¨glich sind, liefern alle Methoden der GuiHelper-Klasse das erzeugte Objekt zur¨ck. o u Damit 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 in den 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 a ubergeben werden. ¨ allowFloat gibt an, ob auch Flieskommazahlen erlaubt sind, allowNegative gibt an, ob negative Eingaben m¨glich sind. Werden die Parameter nicht angegeben, ist beides, also o negative 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): a public 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 a ubergeben, 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 a Firma 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 a werden, gibt es hier noch einen Parameter href, der angibt, was bei einem Klick auf den Button geschehen soll. Es kann sich hierbei um einen Verweis auf eine HTML-Seite, eine JavaScript-Anweisung oder alle sonstigen Angaben handeln, die im href-Attribute des HTML-a-Tags stehen d¨rfen. u Bei der zweiten Methode kann zus¨tzlich angegeben werden, ob der Feldinhalt vom An- a wender 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 o Parameter auf true gesetzt wird. Die dritte Methode wird verwendet, wenn der Inhalt des Feldes im Browser darstellbar ist. Beispiele hierf¨r w¨ren eine Homepage-URL oder eine Mail-Adresse. Solche Felder sind u a grunds¨tzlich direkt editierbar, ein Klick auf den Button ¨ffnet die angegebene Seite bzw. a o sendet eine Mail an die angegebene Adresse. Als zus¨tzlichen Parameter muss ein Zielfenster a angegeben 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 ¨ a Elementen definiert. Zum Beispiel k¨nnte der JavaScript-Code angeben, dass einige Felder o nur dann editierbar sein sollen, wenn die Check-Box aktiviert ist. N¨heres hierzu findet man a bei 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 Eintrag selektiert werden kann. Radio-Buttons sind immer in Gruppen zusammengefasst, wobei jeweils nur ein Eintrag der Gruppe ausgew¨hlt sein kann. Aus diesem Grunde erwarten die a Methoden im Gegensatz zu den Methoden f¨r die Erzeugung von Check-Boxen auch noch u
  • 123.
    6.3 Das Packet com.varial.gui 118 den 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 aus mehreren Eintr¨gen. Folglich wird hier nicht ein Wert f¨r das Feld, sondern eine Liste von a u Werten ubergeben. Optional kann der Index des selektierten Objekts angegeben werden. Die ¨ Combo-Box zeigt dann den entsprechenden Wert. Andernfalls wird der erste Eintrag der Liste 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 editierbare statt 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 120 public 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 a hier 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 Liste anzuzeigen. 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 121 ubertragen, die Liste w¨re also scheinbar leer. Um dies zu verhindern, muss der List-Box ¨ a eine sog. Schl¨sselliste gesetzt werden. Eine solche Schl¨sselliste wird auf jeden Fall beim u u Absenden des Formulars ubertragen. Zeigt die List-Box z.B. eine Liste von BOs, w¨ren die ¨ a IDs der BOs eine sinnvolle Schl¨sselliste. u In einer List-Box kann ein, kein oder viele Eintr¨ge ausgew¨hlt sein. Wird ein Parameter a a selectedIndex 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. a Unter Umst¨nden kann es sinnvoll sein, die List-Box mit gewissen Funktionalit¨ten auszu- a a statten. Beispiele hierf¨r ist die M¨glichkeit, einen Eintrag hinzuzuf¨gen bzw. zu l¨schen. u o u o Da HTML keine PopUp-Men¨s unterst¨tzt, m¨ssen solche Funktionen als Icons unterhalb u u u der 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, sondern einen VState (6.1.6), der f¨r die Behandlung der Tabelle zust¨ndig ist. Sollte die Tabelle u a keine Beschriftung haben (dies ist oftmals der Fall, wenn die Tabelle das einzige Element einer Tabsheet ist. Dann beschreibt die Tabsheet-Bezeichnung auch die Tabelle), kann auf die 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 eingegeben werden 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 zweite Methode erstellt einen Button, mit dem der Auswahlvorgang abgebrochen werden kann. Die letzte Methode dient dazu, sowohl einen Best¨tigungs- als auch einen Abbruch-Button zu a erstellen. 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 a der Anwender bei Best¨tigungen die Wahl zwischen zwei Optionen (ja oder nein) hat, a werden 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 a anzuzeigende 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. u Diese wird analog zu der Label-Angabe der anderen GUI-Komponenten behandelt. Die URL gibt 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 VGuiBean Alle beschrifteten GUI-Elemente sind von der Klasse VGuiBean abgeleitet. Auf diese Wei- se besitzen alle Elemente bereits einige wichtige Attribute bzw. Methoden. Alle Attribute beschreiben bestimmte Eigenschaften einer GUI-Komponente und k¨nnen mit ¨ffentlichen o o Setter-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 124 public 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 u die Oberfl¨che dynamisch anzupassen. Als Beispiel wird angenommen, es existiere eine a Check-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 mit der Eigenschaft interdependence eine Abh¨ngigkeit zwischen Check-Box und Textfeld a beschrieben 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 der Name des Textfeldes. Man erh¨lt JavaScriptCode, der daf¨r sorgt, dass das Textfeld f¨r die a u u Adresseneingabe solange deaktiviert ist, bis die Check-Box angew¨hlt wurde. Dieser Code a muss nun nur noch der Check-Box als Eigenschaft ubergeben werden. ¨ Zusammen mit dem JavaScriptHelper bietet die Eigenschaft interdependence also die M¨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- u thoden. protected void writeLabel (Writer out) throws IOException protected StringBuffer getNameIdAndTabIndex() protected StringBuffer getWidthAndHeight() Der ersten wird eine Instanz der Klasse Writer ubergeben. Daraufhin wird HTML-Code f¨r ¨ u die Beschriftung der aktuelle Komponente erzeugt. Die zweite Methode kann von abgelei- teten Klassen aufgerufen werden, um die HTML-Attribute name, id und tabindex aus den Komponenten-Eigenschaften zu erzeugen. Die letzte Methode getWidthAndHeight() kon- struiert Style-Sheet-Angaben f¨r die Gr¨ße der Komponente. u o Zur 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 LabeledTextField Die Klasse LabeledTextField stellt ein beschriftetes Textfeld dar. Oberklasse ist VGuiBean (6.3.2). Zus¨tzlich k¨nnen der Klasse folgende Eigenschaften gesetzt a o werden: public void setValue (String value) public void setMaxlength (int maxlength) Die Eigenschaft value gibt den Wert an, der als Inhalt in dem Textfeld eingetragen werden soll. Maxlength legt die maximale Anzahl der Zeichen fest, die in das Textfeld eingetragen werden kann. 6.3.4 LabeledNumberField Die Klasse LabeledNumberField definiert ein Textfeld f¨r die Eingabe von Zahlen. u Das Feld unterscheidet sich ¨ußerlich nicht von einem Textfeld, jedoch sorgen eine Reihe von a Abbildung 36: LabeledNumberField JavaScript-Funktionen daf¨r, dass ausschließlich Zahlen in dieses Feld eingegeben werden. Die u Eingabe von Buchstaben und Sonderzeichen wird gesperrt. Große Zahlen werden automatisch schon 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 127 Trennzeichen 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 auch von LabeledTextField abgeleitet. Sie erg¨nzt diese Klasse um zwei weitere Eigenschaften. a public 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 des Dezimaltrennzeichens, beipielsweise ein Komma im deutschen, gesperrt. Mit allowNegative kann festgelegt werden, ob auch negative Zahlen eingegeben werden k¨nnen. Bei false wird ebenfalls die Eingabe eines Minus-Zeichens gesperrt. o 6.3.5 LabeledCurrencyField Die Klasse LabeledCurrencyField repr¨sentiert eine Textfeld, das die Eingabe eines Geld- a betrages erwartet. Auch ein W¨hrungsfeld unterscheidet sich auf den ersten Blick nicht von einem Text- oder a Zahlenfeld, 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 a Feld die M¨glichkeiten eines Zahlenfeldes, so dass die Klasse von LabeledNumberField ab- o geleitet wurde. Zus¨tzlich zu den Funktionen eines Zahlenfeldes, wird dem Betrag ein W¨hrunszeichen an- a a gehangen. W¨hrend ein Zahlenfeld also f¨r Eintr¨ge wie “1.234,56“ gedacht ist, kann bei a u a einem 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 a wieder angef¨gt. u Durch die Vererbung kann auch bei der Klasse LabeledCurrencyField angegeben werden, ob negative und Fließkommazahlen erlaubt sein sollen. Durch die Angabe einer W¨hrunga wird ferner festgelegt, wieviele Nachkommastellen erlaubt sind und wie Angaben gerundet werden. LabeledCurrencyField stellt hierzu zwei zus¨tzliche Methoden zur Verf¨gung. a u public void setCurrency (CurrencyBO currency) public void setShowCurrencyCode (boolean showCurrencyCode) Mit setCurrency() wird die W¨hrung gesetzt, setShowCurrenyCode() gibt an, ob das a W¨hrungszeichen angezeigt werden soll. Wird diese Eigenschaft auf false gesetzt, verh¨lt a a sich das Feld wie ein Zahlenfeld, begrenzt jedoch Nachkommastellen gem¨ß der ubergebenen a ¨ W¨hrung. a
  • 133.
    6.3 Das Packet com.varial.gui 128 6.3.6 LabeledTextField Die Klasse LabeledDateField definiert ein Textfeld f¨r die Eingabe eines Datums. u Die Eingabe muss gem¨ß des Datumsformates der aktuellen Sprache vorgenommen werden. a Abbildung 37: LabeledDateField Erlaubt sind somit nur Ziffern und das jeweilige Datums-Trennzeichen, wie beispielsweise der Punkt. Alle anderen Eingaben, wie Buchstaben oder Sonderzeichen werden gesperrt. Das Feld verf¨gt weiterhin uber einen Mechanismus, der das Datum auf Korrektheit uberpr¨ft. Eine u ¨ ¨ u ung¨ltige Eingabe (z.B. “32.12.“) wird erkannt und blockiert. Zur schnelleren Eingabe ist u es außerdem m¨glich, ein Datum ohne Trennzeichen einzugeben. Die Eingabe “160578“ wird o automatisch 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 a kein Jahr angegeben, wird das aktuelle Jahr eingef¨gt. Ebenso wird eine fehlende Monatsan- u gabe mit dem aktuellen Monat versehen. So ist es m¨glich, mit der Eingabe “15“ auf den 15. o Tag des aktuellen Monats im aktuellen Jahr zuzugreifen. Diese eingebaute Programmlogik, die mit JavaScript realistiert wird, erm¨glicht eine schnelle und unkomplizierte Datumsein- o gabe. Oberklasse ist VGuiBean (6.3.2). Zus¨tzlich k¨nnen der Klasse folgende Eigenschaften gesetzt a o werden: public void setValue (String value) Genau wie bei einem normalen Textfeld kann so der Inhalt des Feldes angegeben werden. Die Eingabe kann im Datenbankformat erfolgen. Die Ausgabe wird automatisch in ein Format gem¨ß der aktuellen Sprache formatiert. a 6.3.7 LabeledMemo Die Klasse LabeledMemo stellt ein mehrzeiliges Textfeld dar. Dieses Feld erweitert die Klasse LabeledTextField, um die M¨glichkeit auch mehrzeiligen o Text 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 129 Die Eigenschaft height gibt die H¨he des Textfelds an, warp beschreibt, wie Texteingaben o umgebrochen werden. Hier sind alle Angaben erlaubt, die dem wrap-Attribute des textarea- Tags zugeordnet werden k¨nnen. Typische Angaben sind virtual (automatischer Umbruch o am Zeilenende) oder off (kein automatsicher Zeilenumbruch). 6.3.8 LabeledButtonTextField Die Klasse LabeledButtonTextField stellt ein Textfeld mit einem verkn¨pften Button dar. u Bei einem sog. Drei-Punkte-Button handelt es sich um ein normales Textfeld, das mit einem nebenstehenden Button um eine Funktion erweitert werden kann. Anwendung findet eine solche Komponente u.a. zur Auswahl von Konten. Das Feld zeigt die aktuelle Auswahl, mit einem Klick auf den Button wird ein Dialog ge¨ffnet, in dem eine neue Auswahl getroffen o werden kann. Ein weiteres Beispiel f¨r die Verwendung eines Drei-Punkte-Buttons ist die u Darstellung von Mail-Adressen. In das Textfeld kann eine Adresse eingegeben werden, an die auf Knopfdruck eine Nachricht geschickt wird. Die Klasse leitet von LabeledTextField ab und f¨gt folgende Eigenschaften hinzu: u public 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 a es 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 u Frame die Ausgabe erfolgen soll. Voreinstellung ist, dass die aufgerufenen Seiten im aktuellen Frame erscheinen. M¨glich w¨re allerdings auch, Ausgaben in einem neuen Fenster oder o a in 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. o 6.3.9 LabeledCheckBox Die Klasse LabeledCheckBox dient zur Ausgabe eines beschrifteten Kontrolk¨stchens. Die a Klasse definiert eine Eigenschaft public void setValue (boolean value) Hiermit wird angegeben, ob die Check-Box selektiert werden soll oder nicht. 6.3.10 LabeledRadioButton Die Klasse LabeledRadioButtons erzeugt genau wie LabeledCheckBox Auswahllisten, bei denen jedoch keine Mehrfachauswahl m¨glich ist. Radio-Buttons sind eine Gruppe von be- o schrifteten Kn¨pfen, von denen der Anwender immer nur einen ausw¨hlen kann. Die Klasse o a wurde von LabeledCheckBox abgeleitet und erweitert diese um eine weitere Eigenschaft.
  • 135.
    6.3 Das Packet com.varial.gui 130 public void setGroup (String group) Die Angabe group weißt den Radio-Button einer Gruppe zu. Alle Buttons, die der selben Gruppe angeh¨ren, schließen sich in der Auswahl gegenseitig aus. o 6.3.11 LabeledComboBox Die Klasse LabeledComboBox erzeugt eine beschriftete Combo-Box. Aus einer Liste von Abbildung 38: LabeledComboBox Werten kann jeweils einer ausgew¨hlt werden. Hierzu besitzt die Klasse zwei Eigenschaften. a public void setValues (String[] values) public void setSelectedIndex (int selectedIndex) Die Eigenschaft values definiert die Liste mit Auswahlm¨glichkeiten. Mit selectedIndex o wird angegeben, welcher Eintrag vorselektiert werden soll. 6.3.12 LabeledEditableComboBox Die Klasse LabeledEditableComboBox stellt eine editierbare Combo-Box dar. Im Gegensatz zu der Klasse LabeledComboBox (6.3.11) kann hier nicht nur ein Wert aus einer Liste gew¨hlt a werden, sondern der Benutzer kann zus¨tzlich eigene Werte eingeben. Die Klasse leitet von a LabeledComboBox ab und definiert zus¨tzlich einen weiteren Parameter. a public void setValue (String value) Die Eigenschaft value gibt den Wert an, der ausgew¨hlt bzw. eingegeben wurde. Durch a die Vererbung besitzt die Klasse weiterhin das Attribute values. Der Unterschied zwischen value und values besteht darin, dass values die Auswahlliste definiert, w¨hrend value nur a den jeweils aktuellen Wert angibt. 6.3.13 LabeledListBox Die 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 a m¨glich, die Auswahl eines Eintrags zu verhindern. In diesem Fall dient die Komponente o lediglich zur Anzeige von Elementen. Außerdem k¨nnen Auswahllisten um zus¨tzliche Funk- o a tionen, wie bespielsweise das Hinzuf¨gen oder Entfernen von Elementen erweitert werden. u
  • 136.
    6.3 Das Packet com.varial.gui 131 Die Klasse wurde von LabeledComboBox (6.3.11) abgeleitet. Die Erweiterung besteht darin, dass im Gegensatz zu einer Combo-Box mehrere Listenelemente sichtbar sind. Die Klasse besitzt 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- o ser Eigenschaft gibt an, wieviele Elemente gleichzeitig sichtbar sind. Bei einem Wert von 1 entspricht die Auswahlliste einer Combo-Box. Mit multiple kann angegeben werden, ob eine Mehrfachauswahl m¨glich ist. Steht diese o Eigenschaft auf true, k¨nnen mehrere Eintr¨ge gleichzeitig selektiert werden. Bei false ist o a lediglich die Auswahl eines Elements m¨glich. o Um anzugeben, welche Listeneintr¨ge bereits selektiert sein sollen, wird selectedIndexes a gesetzt. Als Wert wird eine Array von int-Werten erwartet, die die Indizes der angew¨hlten a Eintr¨gen angeben. a Mit der Eigenschaft buttons k¨nnen der Auswahlliste weitere Funktionen zugewiesen wer- o ¨ den. Ubergeben wird eine Instanz der Klasse LabeledListBoxButtons (6.3.14), die Buttons mit weiteren Funktionalit¨ten implementiert. a Als 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 u Tatsache, 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 zur Darstellung von Werten benutzt wird. Eine Auswahl ist nicht erw¨nscht. Stattdessen k¨nnen u o weitere Elemente mit den entsprechenden Buttons hinzugef¨gt bzw. wieder entfernt wer- u den. Da eine Auswahl hier nicht gew¨nscht ist, w¨rden beim Absenden des Formulars keine u u Werte ubertragen. F¨r das verarbeitende Servlet entst¨nde der Eindruck, dass die Liste leer ¨ u a sei. Um dies zu verhindern, wird die keylist-Eigenschaft gesetzt. Die Klasse erzeugt dann automatisch 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 u Listeneintr¨ge w¨re beispielsweise die ID des Business Objektes. a a 6.3.14 LabeledListBoxButtons Mit der Klasse LabeledListBoxButtons k¨nnen einer List-Box (6.3.13) weitere Funktio- o nen zugewiesen werden. Manchmal is es sinnvoll, einer Auswahlliste zus¨tzliche Funktiona- a lit¨t zu verleihen. Ein Bespiel hierf¨r w¨ren Funktionen zum Hinzuf¨gen bzw. zum Ent- a u a u fernen von Elementen der Liste. Da HTML keine PopUp-Men¨s unterst¨tzt, werden sol- u u che zus¨tzlichen Funktionen bei VWE-Web in Form von Icons angezeigt. Mit der Klasse a
  • 137.
    6.3 Das Packet com.varial.gui 132 LabeledListBoxButtons k¨nnen solche Icons implementiert werden. Sie werden im Anschluss o der 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 u aus der Liste und das Anfordern weiterer Einzelheiten zu einem ausgew¨hlten Element. F¨r a u diese 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. o Tabelle 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 LabeledListBoxButtons mit oder ohne den Parameter tooltip aufgerufen werden. Wird dieser Parameter ubergeben, ¨ werden die ubergebenen Texte als Hinweistext bei den Icons angezeigt. ¨ 6.3.15 LabeledGrid Die Klasse LabeledGrid stellt eine beschriftete Tabelle dar. Tabellen sind eine zentrale GUI- Komponente in VWE. Mit ihr werden Daten strukturiert dargestellt. Außerdem kann der Benutzer Zelleninhalte ver¨ndern. In HTML sind zwar Tabellendarstellungen m¨glich, eine a o Komponente mit editierbaren Zellen gibt es hingegen nicht. Deshalb wurde selbst eine solche Komponente entworfen. Sie befindet sich in der Klasse GridBean (6.3.16). Die Handhabung von 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 einer Beschriftung 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 o geregelt, die die H¨he und Breite der Tabelle angeben. Mit showMenu kann definiert wer- o den, ob die Tabelle eine Men¨zeile mit zus¨tzlichen Funktionen erhalten soll. Als weitere u a Eigenschaft kann mit headerAlign die Ausrichtung der Beschriftung ge¨ndert werden. Stan- a dardm¨ssig wird die Beschriftung der Tabelle links neben ihr angezeigt. Alternativ kann die a Eingschaft auf auch top“ gesetzt werden, so dass die Beschriftung oberhalb erscheint. ”
  • 139.
    6.3 Das Packet com.varial.gui 134 Genau wie bei der Klasse LabeledListBox (6.3.13) werden Funktionalit¨ten in Form von a Icons unterhalb der Tabelle angezeigt. Um Icons einzuf¨gen, dient die Methode addEntry(). u public 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 u Bildes an, description liefert die Beschreibung der Aktion, die als Tooltip erscheinen soll und mit action wird der Aktion ein Name gegeben. Dieser Namen wird bei Klick auf den Button ubertragen. Das Servlet kann mit catchActionEvent() darauf reagieren. R¨ckgabewert ist ¨ u der Index des neuen Symbols in der Men¨leiste. u Trennsymbole zwischen den Icons lassen sich mit addSeparator() einf¨gen: u public 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- u blenden 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 u bzw. versteckt. Um Icons ein- bzw. auszublenden dienen die Methoden turnIconOn() und turnIconOff(). public void turnIconOn (int iconindex) public void turnIconOff (int iconindex) Die Klasse bietet weiterhin die M¨glichkeit, fest definierte Zust¨nde anzunehmen. o a public void toInfoView() public void toListView() Bei dem Aufruf von toListView() nimmt das Tabellen-Men¨ das f¨r Listenansicht typi- u u sche Aussehen an. Das Hinzuf¨gen und Entfernen von Zeilen wird ausgeblendet, alle anderen u Symbbole bleiben stehen. Bei der zweiten Methode wird das Men¨ in eine Info-Ansicht ver- u setzt. Auch hier werden die Aktionen f¨r das Hinz¨gen und Entfernen deaktiviert. u u
  • 140.
    6.3 Das Packet com.varial.gui 135 6.3.16 GridBean Die Klasse GridBean ist f¨r die Darstellung einer editierbaren Tabelle zust¨ndig. Die Be- u a handlung von Aktionen sowie die Formatierung der Tabelle wird wie bereits beschrieben von der 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 ¨ u als einzige Aufgabe der GridBean, neue Datens¨tze zu den bestehenden Daten hinzuzuf¨gen a u bzw. diese zu l¨schen. Um die Tabelle mit Inhalt zu f¨llen dient die Methode addRow(). o u public 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 ersten Position des Arrays befindet sich der Wert f¨r die linkeste Spalte, die ¨ußerste rechte Spal- u a te wird mit dem letzten Wert gef¨llt. Da als Typ ein Object m¨glich ist, k¨nnen beliebige u o o Typen ubergeben werden. So ist es m¨glich, Strings, Integer, Vectoren f¨r Combo-Boxen ¨ o u oder 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 Array mit Strings als Parameter mit angegeben werden. Dieser kann Verweise aufnehmen, zu denen gesprungen wird, wenn der Benutzer einen Tabelleneintrag anklickt. So k¨nnen beispielsweise o Detailansichten zu Eintr¨gen definiert werden. Die Verweise, mit denen der Anwender von ei- a ner normalen Listendarstellung zur Detaildarstellung navigieren kann, m¨ssen ubrigens nicht u ¨ expliziet angegeben werden. Wird der Tabelle ein VListState (6.1.7) zugewiesen und wird der addRow()-Methode ein BO bekannt gemacht, werden die Tabellenzeilen automatisch mit Links zu Detailansicht versehen. Weitere Aktionen, wie das Hinzuf¨gen einer neuen, d.h. leeren Zeile und das entfernen von u vorhandenen Werten behandelt die Klasse bzw. der entsprechende State selbstst¨ndig, so a dass die addRow()-Methode in der Regel die einzige Methode sein wird, die aufgerufen wird.
  • 141.
    6.3 Das Packet com.varial.gui 136 6.3.17 DivGridBean Die 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 Einsatz als Callback (5.5) m¨glich. Dem Vorteil einer schnellen Darstellung von großen Tabellen steht o der 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 a ner GridBean optimal an die jeweiligen Eintr¨ge angepasst werden. Die Klasse DivGridBean a kommt 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 o transparent. Unterschiede in der Benutzung gibt es keine. Der Entwickler muss lediglich im in 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 ¨ a eigenen Funktionen. 6.3.18 GraphBean Die 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 a der Klasse VChartServlet erzeugt. Der GraphBean muss lediglich eine Instanz dieser Klasse ubergeben werden. ¨ public void setServlet (VChartServlet servlet) 6.3.19 ImageBean Mit Hilfe dieser Klasse k¨nnen Bilder dargestellt werden. Der ImageBean muss mit der Me- o thode setUrl() die Adresse der Bilddatei gesetzt werden. public void setUrl (String url) 6.3.20 TabSheetBean Die Klasse TabSheetBean stellt eine Tabsheet dar. Bei einer Tabsheet handelt es sich um eine Komponente, die oft auch als Reiter oder Register bezeichnet wird. Die Darstellung ist angelehnt an eine Karteikartenregister. Durch Anklicken der Karteikarten¨berschriften wird u der entsprechende Inhalt angezeigt. Eine solche grafische Komponente findet sich in einer Vielzahl von Desktop-Anwendungen, aud Web-Seiten ist sie hingegen seltener zu finden, da HTML keine entsprechende Komponente zur Verf¨gung stellt. Eine Tabsheet musste somit u selbst 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 Reihen aufgeteilt. Die Reihe mit der jeweils ausgew¨hlten Registerkarte befindet sich hierbei immer a unten. 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 ausblenden lassen. Ein praktisches Beispiel findet sich in der Finanzbuchf¨hrung bei den Debitoren- und u Kreditoren-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- a sterkarten mehr. Bei der Kreditorenverwaltung wird dort, wo die Debitorenverwaltung die entsprechenen 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 u ber¨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 u einfach ausgeblendet. Die Registerkarte f¨r Bankverbindung erh¨lt genau wie in der Debi- u a torenverwaltung den Index 3. Da nun bei Wechsel der Karte nicht die Bezeichnung (diese ist ja abh¨ngig von der aktuellen Sprache), sondern der Index an das Servlet geliefert wird, a kann das Servlet den Index 3 eindeutig der Bankverbindung zuordnen. W¨rde bei Kreditoren u anstelle von null nichts ubergeben, w¨re die Ausgabe der TabSheetBean zwar identisch, das ¨ a Servlet m¨sste aber die Bankverbindungsdaten einmal bei dem Index 2 und das andere mal u beim Index 3 liefern. Ein gemeinsame Bearbeitung von mehreren Use-Cases durch ein Servlet w¨re nicht m¨glich. a o 6.3.21 MenuBarBean Die MenuBarBean erzeugt eine Men¨leiste und stellt diese dar. Die Men¨leiste setzt sich aus u u drei Teilen zusammen: Icons vor der Combo-Box, die Combo-Box selbst und Icons hinter der Combo-Box. Symbole links neben der Combobox sind in der Regel fest vorgegeben. Hier k¨nnen keine neuen Symbole hinzugef¨gt oder bestehende entfernt werden. Die Combobox o u selbst beinhaltet standardm¨ssig eine Firmenauswahl, kann aber auch ge¨ndert werden. Icons, a a die rechts neben der Combobox stehen, sind spezifisch f¨r den jeweiligen Use-Case, sie werden u also expliziet hinzugef¨gt. Dazu bietet die Klasse die Methode addEntry. u public 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- a tionale 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 o Zusammenhang einige n¨tzliche Methoden wie getMenuAction() etc. Wird keine Aktion an- u gegeben, 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 u addSeparator() aufgerufen werden. public int addSeparartor() Alle diese Methoden liefern eine Zahl zur¨ck. Sie zeigt an, welchen Index das eingef¨gte u u Icon in der Men¨leiste einnimmt. Mit diesem Index k¨nnen die Symbole sp¨ter angesprochen u o a werden. Sie k¨nnen ein- und ausgeblendet werden und aktiviert bzw. deaktiviert werden. o public 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, u hideIcon() blendet Symbole aus, showIcon() sorgt daf¨r, dass sie wieder angezeigt wer- u den. 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 139 In der Listenansicht sollte die Men¨leiste mit Aufruf von toListView() in die passende u Ansicht 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, u L¨schen und Speichern von Objekten. Diese Ansicht sollte gew¨hlt werden, wenn die Detail- o a Ansicht keine schreibende Zugriffe erm¨glicht, sondern nur Informationen zur Verf¨gung o u stellt. Die Kontenliste im Use-Case NominalLedgerAccountInformation“, die vorhande- ” ne Kontenst¨nde zeigt w¨re ein Beispiel f¨r eine solche Ansicht. a a u Es 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 u des Ladevorgangs angezeigt. Alternativ kann man auch mit der showCallback()-Methode daf¨r sorgen. u Als 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 a nicht 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 a werden. public void setComboBox(MenuBarComponentInterface combobox) ¨ Das Ubergebene Objekt muss das MenuBarComponentInterface (6.3.24) implementieren. 6.3.22 MenuEntryTreeBean Mit der Klasse MenuEntryTreeBean wird der Men¨baum erstellt. Die Daten f¨r die u u Men¨punkte liefert der Server aus der Datenbank. Diese Daten k¨nnen im VWE- u o Administrationsmodus gepflegt werden, d.h. es k¨nnen vorhandene Programmmodule aus- o geblendet oder gel¨scht werden oder es k¨nnen neue Use-Cases aufgenommen werden. Da o o dies 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(). o public String getOutput() 6.3.23 MenuEntry Die Klasse MenuEntry wird ausschließlich von MenuEntryTreeBean (6.3.22) verwendet und ist deshalb außerhalb des Packets nicht zug¨nglich. Sie repr¨sentiert einen einzelnen Men¨- a a u Eintrag mit dessen Eigenschaften. 6.3.24 MenuBarComponentInterface Das Interface MenuBarComponentInterface legt fest, dass alle Objekte, die als Combo-Box in der Men¨leiste erscheinen sollen, die Methode getOutput() implementieren. u
  • 145.
    6.3 Das Packet com.varial.gui 140 public String getOutput( VContext ctx, boolean enable ) 6.3.25 SelectCompanyBean Die Klasse SelectCompanyBean implementiert das Interface MenuBarComponentInterface (6.3.24) und erstellt die Combo-Box zur Firmenauswahl, die in der Men¨leiste erscheint. u 6.3.26 SelectOkCancelButtonBean Mit der Klasse SelectOkCancelButtonBean k¨nnen Buttons f¨r Auswahldialogen erzeugt o u werden. Als Buttom k¨nnen Best¨tigungs- und Abruch-Buttons erstellt werden. Ein Abbruch- o a Button 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 a gung erzeugt, andernfalls nicht. Oft wird die Klasse in Verbindung mit Tabellen und der SelectSearchBean-Klasse (6.3.27) verwendet. Der Auswahldialog zeigt dann eine Tabelle mit einer Reihe von Eintr¨gen. Ein Eintrag wird durch einfaches Anklicken ausgew¨hlt, so a a dass ein OK-Button in diesem Fall nicht notwendig ist. 6.3.27 SelectSearchBean Auch die Klasse SelectSearchBean findet in Auswahldialogen Verwendung. Sie erzeugt ein Textfeld, dessen Eingabe zum Filtern von Tabellen-Inhalten verwendet wird. Der Inhalt der Tabelle 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 a sich rechts neben dem Textfeld ein Icon, mit dem die Tabellenausgabe aktualisiert wird. Der Anwender gibt also zun¨chst das Suchkriterium ein und klickt dann auf das Icon. Die Tabel- a lenansicht wird entsprechend aktuallisiert. Um diesen Vorgang zu automatisieren, befindet sich neben dem Icon ein Check-Box. Ist diese angew¨hlt, f¨hren alle Angaben sofort zur Aus- a u gaben¨nderung. Die Tabelle wird unmittelbar an den Filter angepasst. Da dies bei langsamen a Verbindungen einige Zeit in Anspruch nehmen kann, k¨nnte der Bedienungskonfort der An- o wendung deutlich darunter leiden. Aus diesem Grunde, wurde dem Anwender die M¨glichkeit o gegeben, die automatische Aktuallisierung auszuschalten. 6.3.28 JavaScriptBean Die Klasse JavaScriptBean ist daf¨r zust¨ndig, JavaScript-Code f¨r die HTML-Ausgabe u a u vorzubereiten. Erzeugt ein Servlet, eine GuiBean oder sonstige Klassen JavaScript-Code, so kann dieser Code durch die JavaScriptBean in die JSP-Seite eingebettet werden. Alle auf
  • 146.
    6.3 Das Packet com.varial.gui 141 diese Weise erzeugten JavaScript-Befehle befinden sich dann automatisch im head-Bereich der 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 alle Befehle von allen Browsern unterst¨tzt. Um anzugeben, dass die Ausf¨hrung nur ab einer u u bestimmten 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 u JavaCode-Befehle, die mit der Version INIT“ erzeugt werden, sorgt die JavaScriptBean ” daf¨r, dass sie zu Beginn ausgef¨hrt werden. u u Der ubergebene Code wird von der Klasse (unter Ber¨cksichtigung evtl. spezifizierten Versi- ¨ u onsnummern) in ein passendes script-Element eingebettet und in die JSP-Ausgabe einge- baut. 6.3.29 JavaScriptHelper Mit der Klasse JavaScriptHelper k¨nnen oft wiederkehrende JavaScript-Fragmente erstellt o werden. Die Klasse beitet dazu eine Reihe statischer Funktionen. Ein Bespiel f¨r solche Me- u thoden sind die mailto- und http-Anweisung. public final static String mailto (String fieldname)
  • 147.
    6.3 Das Packet com.varial.gui 142 public 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. o Ein Klick auf den Button ¨ffnet in diesem Fall die Adresse. Um eine solche Funktionalit¨t zu o a erreichen, ist die Verwendung von JavaScript erforderlich. Die beiden Methoden implemen- tieren diesen JavaScriptCode f¨r http- bzw. mailto-Adressen. Sie erwarten als Parameter u den Namen des Feldes, dass die Adresse enth¨lt. Die erzeugte Ausgabe kann dann dem Drei- a Punkte-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 u die http()-Funktion verwendet, um eine Internet-Seite zu ¨ffnen. o Der zweite Anwendung des JavaScriptHelpers liegt darin, Abh¨ngigkeiten zwischen zwei a oder mehreren GUI-Komponenten zu definieren. Beispielsweise k¨nnte eine Check-Box ein o Eingabefeld aktivieren bzw. deaktivieren. Der JavaScriptHelper bietet die M¨glichkeit der o Abh¨ngigkeitsdefinition f¨r Check-Boxen, Radio-Buttons und Combo-Boxen. a u Abh¨ngigkeiten von Check-Boxen werden wie folgt definiert: a public 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 a werden k¨nnen, gibt es sowohl eine Methode namens enableByCheckBox() als auch o disableByCheckBox(). Weil weiterhin eine einzelne Komponente oder eine Reihe von Kom- ponenten gesteuert werden k¨nne, gibt es jede Methode in zweifacher Ausfertigung. o Als Parameter wird zum einen der Name der Check-Box angegeben, die f¨r die Aktivie- u rung/Deaktivierung verantwortlich ist, zum anderen wird das Feld oder die Felder ubergeben, ¨ die aktiviert/deaktiviert werden. Die Ausgabe dieser Funktionen k¨nnen den entsprechenden o Methoden 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 u mit 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. u public 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- a Boxen oder Radio-Buttons keinen boolschen Wert, der angibt, ob die Komponente ausgew¨hlt a ist oder nicht. Vielmehr kann eine Combo-Box eine Reihe von m¨glichen Werten annehmen. o Es muss also zus¨tzlich angegeben werden, wann die Aktivierung/Deaktivierung erfolgen soll. a Hierzu 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 a folgende 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 a be der Zahlen-/Buchstabenfolge soll nur dann m¨glich sein, wenn ein L¨ndercode ausgew¨hlt o a a wurde. Da der erste Eintrag der Combo-Box leer ist, muss gepr¨ft werden, ob ein Eintrag u ungleich dem ersten ausgew¨hlt ist. Erst dann darf das Textfeld aktiviert werden. a GuiHelper.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 u Feld address ECVATRegNr“ f¨r die Eingabe freigegeben. u ”
  • 150.
    6.3 Das Packet com.varial.gui 145 6.3.30 Theme Mit 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 a dem momentan eingestellten Theme geladen werden. Dazu bietet sie zwei Arten von statischen Methoden. 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 u getImg() bezeichnet die URL eines angeforderten Bildes. Je nach Situation, aus der die ¨ Methoden aufgerufen werden, ist entweder die Ubergabe eines VContexts (6.1.10), oder die Angabe eines Servlets und dem passenden Request-Objekts leichter. Die Methoden der Klasse Theme unterst¨tzen beide Vorgehensweisen. Es f¨llt auf, dass ein weiterer u a Parameter namens move angegeben werden muss. In der Regel ist dies der Wert 0, der besagt, dass Theme die richtige Adresse liefert. Durch Umleitung einer Anfrage mittels des sendRedirect()-Befehls der Klasse VServlet (6.1.1) kann es vorkommen, dass der Aufruf der Theme-Funktion von einer anderen Seite, als der angeforderten durchgef¨hrt wird. Wenn u
  • 151.
    6.4 Das Packet com.varial.taglib 146 sich beide Seiten in verschiedenen Verzeichnistiefen befinden, liefert die Klasse Theme ein falsches Ergebnis, das aber mit dem move-Parameter korrigiert werden kann. Positive Zahlen bedeuten, dass die aufgerufene Datei um die entsprechende Anzahl von Verzeichnissen tiefer liegt. 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- u ten 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. u 6.4 Das Packet com.varial.taglib Das Packet enth¨lt benutzerdefinierte Tags, die sich genau wie HTML-Tags in JSP-Seiten a einbetten lassen und dort f¨r die Ausf¨hrung von Java-Code zust¨ndig sind. Eine solche u u a Sammlung von selbsterstellten Tags wird auch als Taglib bezeichnet. 6.4.1 varial.tld Bei der Datei varial.tld handelt es sich um eine sog. Taglib Descriptor, also um die Beschreibung von benutzerdefinierten Tags. Es ist eine XMl-Datei, die dem in der DTD 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. Weiterhin wird definiert, welche Attribute die Tags haben, ob diese optional oder obligatorisch sind und ob bzw. welche Art von Inhalt die Tags haben d¨rfen. u Jedesmal, 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- o sen 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 currencyfield memo 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 buttontextfield combobox 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 editablecombobox grid 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 graph image 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 vspacer tabsheetcontrol 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 tabsheet menubar 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 javascript csslink 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 hiddenfield hiddenextrafield Behandelt durch die Klasse HiddenExtraField (6.4.29). Attribute Bedeutung Default-Wert name Name des Feldes/Parameters obligatorisch Tabelle 25: Attribute des Tags hiddenextrafield translator 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 translator languagestring 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 languagestring 6.4.2 VComponent Die Klasse VComponent ist keinem Tag der Taglib direkt zugeordnet. Vielmehr stellt sie eine abstrakte Oberklasse f¨r eine Vielzahl von anderen Klassen dar. Bei der Betrachtung der u Taglib Descriptor (6.4.1) f¨llt auf, dass viele Elemente die gleichen Attribute besitzen. Weil a diese Attribute entsprechende Setter-Methoden in den verantwortlichen Klassen ben¨tigen, o bietet es sich an, diese in einer gemeinsamen Oberklasse zu implementierung und durch Vererbung 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 einem Objekt zuzuweisen. protected void fillBean (VGuiBean bean) Die Funktionsweise der abgeleiteten Taglib-Klasse soll nun am Beispiel der Klasse VTextField etwas genauer erl¨utert werden. a 6.4.3 VTextField Die Klasse VTextField wird verwendet, wenn das textfield-Tag der Varial Taglib in eine JSP-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 154 werden, die entsprechenden Setter-Methoden aufgerufen. Die Namensgebung der Methoden muss daf¨r den Regeln einer JavaBean folgen, d.h. eine Methode tr¨gt immer den Namen, u a der sich aus set“ und dem großgeschriebenen Attributenamen zusammensetzt. Dementspre- ” chend implementiert die Klasse f¨r das Attribute maxlength die Methode setMaxlength. u public 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 u zum Beispiel id, align oder enable. Klassen der Taglib m¨ssen deshalb nur noch f¨r sie u u spezifische Attribut-Setter implementieren. Nachdem die Attribute gesetzt wurden, wird vom Server die Methode doEndTag() aufgerufen. public int doEndTag() throws JspException In dieser Methode wird die Instanz der Klasse LabeledTextField (6.3.3), die zuvor vom verarbeitenden Servlet mit dem GuiHelper (6.3.1) erzeugt wurde, wieder aus dem Request-Objekt geholt und die restlichen Attribute werden gesetzt. Schließlich wird die getOutput()-Methode des LabeledTextField aufgerufen, die daf¨r sorgt, dass die entspre- u chende HTML-Ausgabe geschrieben wird. Viele Klassen der Taglib verhalten sich genau so wie die Klasse VTextField. Sie sind von VComponent abgeleitet, implementieren spezifische Setter-Methoden und holen in der doEndtag()-Methode die erzeugten GUI-Elemente aus dem Request-Objekt um nach Wertzuweisung 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 entsprechenden Klasse des Packets com.varial.gui. Die Klassen des Packets com.varial.taglib sorgen nur daf¨r, dass die HTML-Tags mit den richtigen GUI-Klassen verkn¨pft werden. Hierdurch u u l¨ßt sich eine Programmierung nach dem bereits beschriebenen MVC-Modell (5.2) erreichen. a 6.4.4 VNumberField Die Klasse VNumberField wird verwendet, wenn das numberfield-Tag der Varial Taglib in eine JSP-Seite eingebettet ist. Die Klasse wurde von VTextField (6.4.3) abgeleitet und definiert keine weiteren Setter-Methoden. Das numberfield-Tag wird durch die Ausgabe der entsprechenden Instanz der Klasse LabeledNumberField (6.3.4) ersetzt. Oberklasse: VTextField (6.4.3) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledNumberField (6.3.4) 6.4.5 VCurrencyField Oberklasse: VNumberField (6.4.4) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledCurrencyField (6.3.5)
  • 160.
    6.4 Das Packet com.varial.taglib 155 6.4.6 VDateField Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledDateField (6.3.6) 6.4.7 VMemo Oberklasse: 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 VButtonTextField Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: a • public void setTarget (String target) Ausgabe der Klasse: LabeledButtonTextField (6.3.8) 6.4.9 VCheckBox Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledCheckBox (6.3.9) 6.4.10 VRadioButton Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledRadioButton (6.3.10) 6.4.11 VComboBox Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledComboBox (6.3.11)
  • 161.
    6.4 Das Packet com.varial.taglib 156 6.4.12 VEditableComboBox Oberklasse: VComboBox (6.4.11) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: LabeledEditableComboBox (6.3.12) 6.4.13 VListBox Oberklasse: VComboBox (6.4.11) Zus¨tzliche Setter-Methoden: a • public void setSize (int size) Ausgabe der Klasse: LabeledListBox (6.3.13) 6.4.14 VGrid Oberklasse: 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 VGraph Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: GraphBean (6.3.18) 6.4.16 VImage Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: ImageBean (6.3.19) 6.4.17 Empty Die Klasse Empty behandelt das Tag empty und gibt leeren Inhalt aus. Die mag auf den ersten Blick verwunderlich erscheinen, eine solche leere Ausgabe hat aber durchaus Sinn. Um die 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 Rasters nicht belegt, sollte in diese Tabellenzelle ein empty-Tag gelegt werden. Dieser erzeugt nicht wirklich leeren, sondern lediglich unsichtbaren Inhalt. Die Ausgabe des Tags bzw. der Klasse sorgt daf¨r, dass die Tabellenstruktur gem¨ß HTML-Standard gef¨llt ist. W¨rde hier einfach u a u u nichts stehen, w¨re das Dokument nicht mehr valide. a
  • 162.
    6.4 Das Packet com.varial.taglib 157 Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: - 6.4.18 Vspacer Die 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- a ponenten zu erzeugen. Dazu kann eine H¨he in Pixel angegeben werden. Zus¨tzlich zu dem o a normalen Abstand wird dann ein weiterer Leerraum erzeugt. So k¨nnen Komponenten auf o der Oberfl¨che optisch von einander getrennt werden. a Oberklasse: VComponent (6.4.2) Zus¨tzliche Setter-Methoden: a • public void setHeight (int height) Ausgabe der Klasse: - 6.4.19 TabSheetControl Oberklasse: BodyTagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: TabSheetBean (6.3.20) 6.4.20 TabSheet Die Klasse TabSheet wird aufgerufen, wenn ein tabsheet-Tag in der JSP-Datei steht. Wie der Taglib Descriptor (6.4.1) zu entnehmen ist, besitzt dieses Tag nur ein Attribute, n¨mlich a das Attribute index. Mit Hilfe des Tags lassen sich Inhalte zusammenfassen, die nur dann angezeigt werden, wenn die Registerkarte mit dem angegebenen Index aktiv ist. So kann die JSP-Seite eine Reihe von Ausgaben definieren, wovon jeweils eine angezeigt wird. Die Klasse Tabsheet sorgt daf¨r, dass die anderen Teile nicht dargestellt werden. Hierzu wird die u Methode doStartTag() so uberladen, dass der Inhalt des Tags nur dann ausgef¨hrt wird, ¨ u wenn 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 MenuBar Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: MenuBarBean (6.3.21) 6.4.22 SelectOkCancel Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: SelectOkCancelButtonBean (6.3.26) 6.4.23 SelectSearch Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe 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 o zuvor mit Hilfe der setHeadLine()-Methode des GuiHelpers (6.3.1) dar. Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: -
  • 164.
    6.4 Das Packet com.varial.taglib 159 6.4.25 LastChange Die Klasse LastChange behandelt das lastchange-Tag und gibt ein kurze Statusmeldung aus, wann das aktuelle Objekte von wem das letzte Mal ge¨ndert wurde. a Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: a • public void setAlign (String align) Ausgabe der Klasse: - 6.4.26 JavaScript Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: JavaScriptBean (6.3.28) 6.4.27 CssLink Die Klasse CssLink ist zust¨ndig f¨r das csslink-Tag. Dieses Tag erzeugt als Ausgabe eine a u Zeile mit HTML-Code, der eine CSS-Datei einbettet. Die Klasse sorgt daf¨r, dass die Datei u gem¨ß des aktuell eingestellten Corporate Designs (4.4.2) eingebunden wird. Dazu wird die a getCss()-Methode der Klasse Theme (6.3.30) verwendet. Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: - 6.4.28 HiddenField Mit dem hiddenfield-Tag und der zugeh¨rigen Klasse HiddenField k¨nnen Parameter in o o versteckten Feldern zwischengespeichert werden. Damit Query-String-Parameter und Attri- bute im Request-Objekt auch bei Absenden eines Formulars ubergeben werden, m¨ssen sie ¨ u selbst Teil des Formulars sein. Das hiddenfield-Tag sorgt daf¨r, dass die Parameter mit u dem als Tag-Attribute angegebenen Namen als versteckte Felder in das Formular integriert werden. Oberklasse: TagSupport Zus¨tzliche Setter-Methoden: a • public void setName (String name) Ausgabe der Klasse: -
  • 165.
    6.4 Das Packet com.varial.taglib 160 6.4.29 HiddenExtraField Die Klasse HiddenExtraField verh¨lt sich ¨hnlich zu der Klasse HiddenField. Allerdings a a werden hier speziell die Werte in versteckten Formularfelder verwaltet, die dem Servlet vom Men¨baum mitgegeben wurden. VWE erlaubt es im Administrations-Modus die Men¨bau- u u me der Programms zu editieren. Hier k¨nnen u.a. auch Parameter f¨r die aufgerufenen o u Programm-Module angegeben werden. Diese Parameter werden dem Servlet bei Start uber- ¨ geben und k¨nnen mit dem hiddenextrafield-Tag gespeichert werden. Eine Anwendung o f¨r einen Men¨-Parameter findet sich beispielsweise in der Verwaltung von Debitoren und u u Kreditoren. 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 u der Parameter TYPE=SUPPLIER bzw. TYPE=CUSTOMER ubergeben. ¨ Oberklasse: HiddenField (6.4.28) Zus¨tzliche Setter-Methoden: keine a Ausgabe der Klasse: - 6.4.30 Translator Sollen 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. Die letzte Angabe wird vom zu ubersetzenden Text angegeben. Die anderen Angaben m¨ssen als ¨ u Tag-Attribute spezifiziert werden. Da die Klasse TagSupport, von der die Klasse ableitet, bereits eine setParent()-Methode besitzt, musste der Parent-Parameter umbenannt werden und heißt nun Owner. Werden mehrere Translator in die Seite integriert, muss diesen das id-Attribute gesetzt werden, damit sie sp¨ter zu unterscheiden sind. a Nach Initialisierung des Translators k¨nnen Texte mit demlanguagestring-Tag (6.4.31) o ubersetzt werden. ¨ Oberklasse: TagSupport Zus¨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 Translator man sich bezieht.
  • 166.
    6.4 Das Packet com.varial.taglib 161 Oberklasse: TagSupport Zus¨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 u vom CORBA-Server erfragen und ausgeben.
  • 167.
    6.4 Das Packet com.varial.taglib 162 Abbildung 39: LabeledComboBox (ausgeklappt)
  • 168.
    7 Beispiel furdie Verwenung der VWE-Web-API ¨ Nachdem im letzen Kapitel die neu entwickelte Klassenbibliothek f¨r die Umsetzung einer u Web-Oberfl¨che f¨r die Varial World Edition vorgestellt wurde, soll nun deren Verwendung a u an einem Anwendungsfall praktisch erkl¨rt werden. Als Programm-Modul soll die W¨hrungs- a a verwaltung 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 a Vorteile von VWE gegen¨ber anderen ERP-Systemen ist die Mehrw¨hrungsf¨higkeit. D.h. u a a Buchungen und andere Transaktionen lassen sich flexibel in verschiedenen, frei definierbaren W¨hrungen durchf¨hren und umrechnen. Hierdurch wird die M¨glichkeit eines internationa- a u o len Einsatzes m¨glich. Die Umsetzung der W¨hrungen-Pflege dient in diesem Kapitel lediglich o a als Beispiel, da sie zum einen im Vergleich zu anderen Programmpunkten nicht besonders umfangreich ist, zum anderen aber f¨r ihren Umfang viele verschiedene GUI-Komponenten u enth¨lt. Der Frage, inwieweit eine solche Funktionalit¨t im Internet-Umfeld uberhaupt Sinn a a ¨ macht, soll deshalb hier nicht nachgegangen werden. 7.1 Vorbereitung 7.1.1 Die IDL-Beschreibung Am 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 a entsprechende Methoden f¨r die Bearbeitung der BOs zur Verf¨gung stellt. Die Beschreibung u u der 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 a Diese Angaben werden in einer entsprechenden IDL-Datei festgehalten. Da VWE den Use-Case bereits f¨r die Desktop-Version definiert, existiert bereits eine IDL-Beschreibung u f¨r W¨hrungen. Sie befindet sich im Verzeichnis source/corba/framework/Currency.idl. u a Dort 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 u das Abfragen aller Einheiten und getCurrencyByOid() um eine W¨hrung durch die Angabe a der ObjectID zu finden. Außerdem wird eine Methode ben¨tigt, mit der eine Liste aller ISO- o Codes abgefragt werden kann. Diese Funktionalit¨t bietet findSwiftcodes. Das folgende a Listing 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_IDL 7.1.2 Die Server-Funktion Der n¨chste Schritt zur Umsetzung der Anwendung ist die Implementierung des IDL- a Interfaces als Server-Funktion. Dadurch, dass VWE bereits die W¨hrungsverwaltung an- a bietet, kann auf die vorhanden Server-Methoden zugegriffen werden. Der CORBA-Server ist hier also schon vorhanden. 7.1.3 Die Client-BOs Als n¨chstes m¨ssen die IDL-Strukturen in Java-Klassen abgebildet werden, damit die Serv- a u lets auf die Daten zugreifen k¨nnen. Diese Klassen werden auch als Business-Objekte (5.4) o bezeichnet. Es handelt sich hierbei um JavaBeans, die den Namen der Struct, allerdings mit der 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- u dern, wurde ein Perl-Skript namens WebBOBuilder geschrieben. Es befindet sich im Verzeich- nis source/web/templates und erwartet als Kommandozeilen-Parameter den Namen der IDL und die Bezeichnung der Struktur, aus der die Klasse generiert werden soll. Der Aufruf lautet demzufolge: perl WebBoBuilder.pl framework/Currency.idl CurrencyStruct perl WebBoBuilder.pl framework/Currency.idl EmuDataStruct perl WebBoBuilder.pl framework/Currency.idl SwiftcodeStruct Das Perl-Skript erzeugt automatisch eine Java-Datei im Verzeichnis source/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 a untergebracht werden. Mehr dazu folgt sp¨ter. a Die erzeugte Java-Datei l¨ßt sich nun schon fast vollst¨ndig und l¨ßt sich fehlerfrei kom- a a a pilieren. Bei komplexeren Strukturen ist unter Umst¨nden eine kleine manuelle Korrektur a
  • 173.
    7.1 Vorbereitung 168 notwendig. Jedenfalls hat das Perl-Skript dem Entwickler bereits eine Menge Arbeit abgenommen. 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 o eines BOs werden von den commit() bzw. delete() Methoden der Klasse ubernommen. ¨ Sie werden bereits vom Perl-Skript generiert. Weitere Methoden werden meist als statische Methoden wie folgt hinzugef¨gt. u public 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 a mitgegeben bekommt, damit die Zugriffsberechtigung uberpr¨ft werden kann. Mit der au- ¨ u tomatisch generierten Funktion getServant() wird zun¨cht ein Servant geholt. Nun kann a die passende Methode aus der IDL (hier getCurrencies()) mit diesem Servant aufgerufen werden. Die vom Perl-Skript geschriebenen Hilfsfunktion toBoArray() sorgt daf¨r, dass die u IDL-Sequenz in eine Array mit CurrencyBOs umgewandelt wird. Alle Ausnahmen werden pauschal 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 a ableitet, gefangen und behandelt. Sollte anstelle mehrere BOs nur ein BO zur¨ckgegeben werden, kann der Konstrukter der u Klasse 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-Server zugegriffen werden. F¨r das Servlet und alle Klassen, die das BO verwenden, erscheint das u Objekt lokal. Die Verteilung der Anwendung gestalltet sich folglich v¨llig transparent. o 7.1.4 Die Enumerations Die IDL beschreibt weiterhin eine Aufz¨hlung (Enumeration). Diese kann ebenfalls mit einem a Perl-Skript in eine Java-Klasse exportiert werden. Hierzu muss das Skript WebEnumBuilder aufgerufen werden. perl WebEnumBuilder.pl framework/Currency.idl RoundingEnum Ergebnis ist eine Java-Datei mit dem Namen RoundingHelper.java im selben Verzeichnis wie 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 u Translator-Objektes (6.2.1) angepasst werden, zum anderen muss in der init()-Methode die 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 u aus 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 o Servlets umgesetzt werden. 7.2 Listen-Ansicht 7.2.1 Das ListServlet Die W¨hrungen-Verwaltung unterteilt sich wie die meisten Anwendung der VWE in eine a Listen- und eine Detail-Ansicht. Der Anwender bekommt zu Beginn als erstes eine Listen¨ber- u sicht geboten, die die BOs mit den wichtigsten Attributen auff¨hrt. Die Frage, welche Daten u die Listen-Ansicht zur Verf¨gung stellen soll, wird bereits vom vorhandenen C++-Client be- u antwortet. Es sind Code, Name, ISO-Code, W¨hrungseinheit, Untereinheit, Dezimalstellen, a Rundung 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 die Klasse 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- u setzung zust¨ndig ist, als konstante Klassenvariabel. Die Angabe f¨r die Parameter lassen a u sich 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 ¨ u GET-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 a GuiHelper (6.3.1) eine statische Methode addGrid() bereit. Sie erwartet als Parameter den VContext und eine sog. State-Klasse. Eine State-Klasse, oder kurz State genannt, formatiert die Tabelle und behandelt Benutzereingaben in Tabellenzellen. Oberklasse aller States ist VState (6.1.6). Ein solcher State wird im n¨chsten Schritt entworfen. F¨r das ListServlet ist a u es zun¨chst nur wichtig zu wissen, dass ein solcher State existiert. Er wird der GuiHelper- a Methode 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 Sprache erscheint, wird sie mit dem Translator-Objekt erstellt. GuiHelper.setHeadLine( ctx, translator.getCaption( ctx, "vcurrencyform" ) );
  • 176.
    7.2 Listen-Ansicht 171 Als n¨chstes muss noch die Men¨leiste angepasst werden. Listenansichten erlauben als a u Men¨-Aktion lediglich das Anlegen eines neuen Objektes. Alle anderen Icons sind akti- u viert. Die Klasse MenuBarBean (6.3.21 besitzt zur Herstellung dieses Layouts die Methode toListView(). MenuBarBean menu = new MenuBarBean(ctx); menu.toListView(); Die Verarbeitung ist nun abgeschlossen. Zum Schluß muss nun nur noch die Kontrolle an eine JSP-Seite abgegeben werden, die die Angaben darstellt. Diese Vorgehensweise entspricht dem unter 5.2 angesprochenen MVC-Modell. 7.2.2 Der ListState Wie 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 o die Formatierung ubernommen werden. ¨ States f¨r Listenansicht sollten von der Klasse VListServlet (6.1.2) ableiten. u public class CurrencyListGridState extends VListState a u ¨ Auch hier sollte zun¨chst ein Translator-Objekt angelegt werden, das f¨r die Ubersetzung zust¨ndig ist. Außerdem ist es ratsam, alle Spaltennamen als int-Konstanten zu definieren. a Hierdurch 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 u sehen 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 u writeData(), 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 a werd mit der statischen Methode des BOs alle Objekte vom CORBA-Server erfragt. In einer Schleife werden die Objekte durchlaufen und f¨r jedes Objekt eine neue Zeile an die Tabelle u angehangen. Hierzu dient die Methode addRow() der GridBean, die als Parameter die Liste der Spaltenwerte besitzt. Diese Spaltenwerte, also der Code, Name, Rundung etc, wird mit den Getter-Methoden des BOs abgefragt. Dementsprechend sieht die Funktion wie folgt aus.
  • 177.
    7.2 Listen-Ansicht 172 public 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 a ver angefordert wurden, mit der Methode registerBos() beim VContext angemeldet. Dies ¨ erm¨glicht es, eine Statusmeldung mit den Daten der letzen Anderungen anzuzeigen, wenn o der 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 a was anderes, wie beispielsweise ein Ordner im TaskReminder-Use-Case sein. W¨hrungen sind a unabh¨ngig von einem Parent-Objekt. Deshalb wird hier einfach der Leerstring angegeben. a Als zweites f¨llt auf, dass das Ergebnis der getDecimalplaces()-Funktion in einen Short- a Konstruktor gepackt wurde. Der Grund daf¨r ist der, dass die addRow()-Methode einen Array u von Objects erwartet. Da der R¨ckgabewert der Getter-Funktion vom Typ short ist, der u als 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 u Als drittes und letztes soll noch auf den Wert f¨r den Rundungsmodus eingegangen werden. u Hier zeigt sich die Verwendung der in der Vorbereitungsphase erzeugten Helper-Klasse. Die Funktion getString() des RoundingHelpers sorgt daf¨r, dass ein RoundingEnum-Objekt als u String in der aktuellen Sprache angezeigt wird. Bevor die Bearbeitung der State-Klasse entg¨ltig abgeschlossen werden kann, m¨ssen u u noch die Formatierungsangaben gemacht werden. Weil die Listenansicht keine M¨glichkeit o
  • 178.
    7.2 Listen-Ansicht 173 bietet, Daten einzugeben bzw. diese zu ver¨ndern, m¨ssen in VListState-Klassen in der Regel a u nur wenig Formatierungsangaben gemacht werden. Hier m¨ssen nur Spalten¨berschriften u u gesetzt werden und evtl. die Art der Zelleninhalte angegeben werden. Letzteres geschieht mit 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 u W¨hrungsliste soll jedoch die Angabe f¨r die Dezimalstellen als Zahl und somit rechtsb¨ndig a u u angezeigt werden. Die Methode getEditor() muss folglich angeben, dass es sich bei Werte dieser 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 u den. 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. a Nun sind alle Java-Klassen f¨r die Listen-Ansicht implementiert worden. Was fehlt ist die u Darstellung. Diese wird mit einer JSP-Seite realisiert, an die das ListServlet wie oben gezeigt die Kontrolle ubergibt. ¨ 7.2.3 Die JSP-Listen-Seite Die 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 174 Klassen implementiert, kann ein Designer sich mit dem Design der Ausgabe besch¨ftigen. a Die Bearbeitung geschiet hier parallel und vollkommen unabh¨ngig voneinander. Dabei ha- a ben JSP-Seiten unter normalen Umst¨nden immer einen sehr ¨hnlichen Aufbau. Es bietet a a sich 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¨ru die Programm-Teile entsprechende Unterverzeichnisse. So sollte die W¨hrungs-Seite unter a framework/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 positionieren Dies 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 von Java-Klassen der Taglib (6.4) behandelt. Deren Ausgabe erscheint dann anstelle der Tags. So k¨nnen die Daten, die von dem Servlet erzeugt werden, in eine JSP-Seite eingebettet werden. o 7.2.4 Zusammenfassung Nach den oben beschriebenen Schritten ist die Listenansicht komplett. Der Ablauf ist dabei immer identisch. Man erzeugt zuerst aus der Use-Case-Beschreibung die IDL und implementiert den Server. Sehr oft sind diese Schritte bereits vollzogen. Die Perl-Skripte WebBoBuilder und WebEnumBuilder bilden Structs und Enumerations in Java-Klassen, die Servlets verwenden k¨nnen. Das Servlet leitet von VListServlet ab, erzeugt mit o dem GuiHelper eine Tabelle, der eine VListState-Klasse ubergeben wird. Diese f¨llt und ¨ u formatiert 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 u identisch. 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 u um das Laden abzubrechen. Der State muss die Methode isCallback() so uberladen, ¨
  • 181.
    7.3 Detail-Ansicht 176 dass sie true zur¨ckgibt und das F¨llen der Tabelle in die Methode putDataRows() ver- u u schieben. F¨r ein Beispiel sei auf die Klasse PersonalAccountListGridState im Packet u com.varial.accounting.servlet verwiesen. 7.3 Detail-Ansicht 7.3.1 Das DetailServlet Nachdem der Anwender ein BO aus der Listenansicht ausgew¨hlt hat, werden ihm in der a Detail-Ansicht weitere Informationen zur Verf¨gung gestellt. Hier befinden sich dann auch u die Objekt-Attribute, die in der Listen-Ansicht nicht angezeigt wurden. Da die W¨hrungen- a Verwaltung im Verh¨ltnis zu anderen Programm-Modulen nur wenige Daten anzeigt, verwen- a det VWE hier keine Tabsheet um die Daten zu strukturieren. Dies macht zwar durchaus Sinn, im Rahmen der Beispielumsetzung sollen aber Registerkarten verwendet werden, um einen m¨glichst breiten Funktionsumfang der VWE-Web-API zu demonstrieren. Deshalb werden o die 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 VDetailServlet Als n¨chster Schritt ist auch beim DetailServlet die Angabe eines Translators notwendig, a um Bildschirmtexte zu ubersetzen. Ein Blick in Sophia oder die Datenbank verr¨t die Anga- ¨ a ben currency“ und vcurrencydetailframe1“ als Parameter. Weiterhin ist auch in dieser ” ” Klasse die Einf¨hrung von int-Konstanten hilfreich. Die drei Tabsheet-Register werden als u Konstanten definiert, so dass ein benannter Zugriff anstelle des nichtssagenden Index m¨glich o sein 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 bearbeitet werden. Hierzu erzeugt man eine neue MenuBarBean und ruft deren Methode hideIcon() mit dem Parameter MenuBarBean.COMBOBOX auf. Dadurch wird die Men¨leiste erstellt und u die 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-Angabe zu 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- a den. Hierzu bietet jede VDetailServlet-Klasse die Funktion fillBO(), auf die sp¨ter genauer a eingegangen wird. An dieser Stelle ist es ausreichend zu wissen, dass diese Funktion immer den aktuellen Stand des BOs liefert. Der R¨ckgabewert ist jedoch immer vom Typ Object. u Ein 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 a den m¨ssen nur noch die GUI-Elemente mit dem GuiHelper erstellt werden. Den Anfang u macht 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 der Methode 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 u sich auf der aktiven Karte befinden, ist es uberfl¨ssig, alle Komponenten zu erzeugen. Eine ¨ u bessere Performance wird dadurch erreicht, dass lediglich die Felder im Servlet erzeugt und gef¨llt werden, die sp¨ter auch angezeigt werden. Aus diesem Grunde wird die Erzeugung u a der Felder in drei Bl¨cke einer switch-Anweisung unterteilt, die jeweils nur dann ausgef¨hrt o u werden, wenn die jeweilige Karte ausgew¨hlt wurde. a
  • 183.
    7.3 Detail-Ansicht 178 switch (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; } // switch Dadurch, dass zu Beginn Konstanten f¨r die Tabsheet-Register definiert wurden, k¨nnen u o hier die Namen der Karten verwendet werden, was die Lesbarkeit und die Wartung des Codes deutlich verbessert. Im ersten Register wird zun¨chste ein Textfeld f¨r die Eingabe a u der Code-Bezeichnung erstellt. Hierf¨r wird die Methode addTextField() des GuiHelpers u aufgerufen. Als Parameter erwartet diese den VContext, den Translator, den Namen, den das Feld bekommen soll, die Beschriftungsbezeichnung, mit derren Hilfe der Translator die Feldbeschriftung ubersetzt und nat¨rlich den Wert, den das Feld anzeigen soll. In diesem Fall ¨ u ist es der Code der W¨hrung, der mit der Funktion getCode() abgefragt wird. Folglich lautet a der Aufruf: // Code GuiHelper.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 a k¨nnen analog dazu erstellt werden. o // Name GuiHelper.addTextField( ctx, translator, "details__namelabel", "namelabellabel", mBo.getDescription() ); // Unit GuiHelper.addTextField( ctx, translator,
  • 184.
    7.3 Detail-Ansicht 179 "details__unitlabel", "unitlabellabel", mBo.getUnitname() ); // Subunit GuiHelper.addTextField( ctx, translator, "details__subunitlabel", "subunitlabellabel", mBo.getSubunitname() ); // Import Code GuiHelper.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 o kann entweder frei eingegeben werden oder der Benutzer w¨hlt die passende Bezeichnung aus a einer Liste vorgefertigter ISO-Codes aus. Eine solche Funktionalit¨t stellt der Drei-Punkte- a Button repr¨sentiert durch die Klasse LabeledButtonTextField (6.3.8) zur Verf¨gung. Die a u GuiHelper-Funktion addButtonField() erzeugt die Komponente. Als zus¨tzlichen Parame- a ter erwartet die Methode die URL einer Seite bzw. eines Servlets, das den Auswahldialog darstellt. 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 a StringBuffers 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 180 Query-String-Parameter der aktuelle ISO-Code ubergeben. Da das Zusammenf¨gen zwei- ¨ u er String-Objekte intern relativ viel Speicher und dadurch auch viel Rechenzeit ben¨tigt, o wird ein StringBuffer verwendet, der diese Aufgabe schneller erledigt. Die Funktion setDirectEdit() sorgt daf¨r, dass auch freie Eingaben in das Feld m¨glich sind. Ohne u o diesen Aufruf k¨nnten Werte f¨r das Feld ausschließlich durch die Auswahl vordefinierter o u Angaben ge¨ndert werden. Da die addButtonField()-Methode wie jede add()-Methode des a GuiHelpers das erzeugte Objekt zur¨ckliefert, kann die Methode direkt mit der dem Funk- u tionsaufruf verbunden werden. Bei den Feldern f¨r die Angabe der Dezimalstellen und des Rundungsverfahrens handelt es u sich um Combo-Boxen. Sie werden durch den GuiHelper und dessen addComboBox()-Methode erzeugt. Diese Methode erwartet neben einer Liste von Eintr¨gen f¨r die Combo-Box den In- a u dex des aktuell ausgew¨hlten Eintrags. Die Erstellung der Combo-Box f¨r die Rundungsart a u ist recht einfach. Gl¨cklicherweise stellt der RoundingHelper, der zuvor von dem Perl-Skript u erzeugt wurde, alle n¨tigen Methoden zur Verf¨gung. Die getStrings()-Methode liefert alle o u Eintr¨ge f¨r die Combo-Box, mit indexOfEnum() kann der Index eines Eintrags abgefragt a u werden. Als Befehl zum Erzeugen der Combo-Box ergibt sich damit: // Rounding Mode GuiHelper.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 u Enumeration definiert. Vielmehr beschreibt sie zwei Konstanten MIN DECIMAL PLACES und MAX DECIMAL PLACES. F¨r das Servlet ist dadurch noch ein wenig Java-Code erforderlich. u int 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 181 Diese Zeilen erzeugen einen String-Array, der die Eintr¨ge f¨r die Dezimalstellen-Auswahl a u beinhaltet. 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 a aktuellen 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 u G¨ltigkeitsdatums. Hierf¨r wird die addDateField()-Methode des GuiHelpers verwendet, u u die ein Feld f¨r eine Datumseingabe, ein sog. DateField (6.3.6) erstellt. Die Verwendung u entspricht der eines normalen Textfeldes. // Use Until GuiHelper.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, u die Angaben zur Verwendung im Rahmen der Europ¨ischen W¨hrungsunion enth¨lt. Dort a a a befindet sich zuerst eine Check-Box, die angibt, ob es sich bei der W¨hrung um den Euro han- a delt oder nicht. Zur Erstellung einer solchen Check-Box kann die addCheckBox()-Methode des GuiHelpers verwendet werden. Wie jede add()-Methode der Klasse liefert sie als R¨ck- u gabewert die erzeugte Komponente. In den meisten F¨llen wird diese R¨ckgabe ignoriert, a u in diesem Fall kann sie aber dazu genutzt werden, weitere Eigenschaften der Check-Box zu setzen. Da die Eigenschaft nicht vom Benutzer gesetzt werden kann, ist dieses Feld nicht editierbar. Deshalb wird die Eigenschaft enable auf false gesetzt. Es entsteht folgender Aufruf. // Is Euro GuiHelper.addCheckBox( ctx, translator, "emu__iseurolabel", "iseurolabel", mBo.isTheEuro() ).setEnable(false);
  • 187.
    7.3 Detail-Ansicht 182 Die zweite Check-Box f¨r die Angabe, ob es sich um eine W¨hrung der EWU handelt, kann u a genauso implementiert werden. Allerdings werden hier Abh¨ngigkeiten von Feldern definiert. a Eine Eingabe in die Felder f¨r das Startdatum der G¨ltigkeit und den Umrechnungskurs zum u u Euro ist nur dann sinnvoll, wenn diese Check-Box aktiviert ist. Folglich muss beim Erzeugen der Check-Box angegeben werden, dass die anderen Felder nur im Falle einer Aktivierung zur Verf¨gung stehen. Hierzu dient die Klasse JavaScriptHelper (6.3.29), die f¨r ein solches Sze- u u nario 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 u der enableByCheckBox()-Funktion kann wiederum der GuiHelper-Methode als zus¨tzlichera Parameter ubergeben werden. Zusammen ergibt sich der folgende Funktionsaufruf. ¨ // EMU Currency GuiHelper.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 Currency GuiHelper.addDateField( ctx, translator, "emu__dateemucurrencylabel", "dateemucurrencylabel", mBo.getisEmuCurrencyUnion().getDateEmuCurrency() ); // EMU Rate GuiHelper.addNumberField( ctx, translator, "emu__emuratelabel", "emuratelabel", mBo.getisEmuCurrencyUnion().getEmuRate() );
  • 188.
    7.3 Detail-Ansicht 183 Somit w¨re auch der zweite Tabsheet-Reiter vollst¨ndig. Der letzte Reiter besteht nur aus a a einem Feld. Es handelt sich hierbei um ein mehrzeiliges Textfeld, das zur Angabe von diversen Notizen gedacht ist. Um ein mehrzeiliges Textfeld zu erzeugen, sollte die addTextArea()- Funktion der GuiHelper-Klasse verwendet werden. Die Handhabung entspricht exakt der eines 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 ¨ a Beschriftung ausschalten. Eine Feldbezeichnung ist hier nicht notwendig, weil das Tabsheet- ¨ Register keine weitern Felder enth¨lt. Somit bildet bereits die Register-Uberschrift eine Be- a zeichnung f¨r das Eingabefeld. u Nachdem nun alle GUI-Elemente erzeugt wurden, kann auch hier die Verarbeitung an eine JSP-Seite weitergegeben werden. Genau wir bei der VListServlet-Klasse dient hierzu der Aufruf von forwardToJsp(). forwardToJsp( ctx, "/framework/currency/CurrencyDetail.jsp", menu ); Nachdem die Oberfl¨che erzeugt wurde, sollen nun noch die Methoden getBO() und fillBO() a der Klasse angesprochen werden. Beide Methoden sind in der Oberklasse VDetailServlet als abstrakt gekennzeichnet. Das bedeutet, dass alle abgeleiteten Klassen diese Methoden implementieren m¨ssen. Die Methoden dienen dazu, das jeweils aktuelle BO zu erfragen. u fillBO() 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 nicht in der Datenbank gespeichert wurde. Damit BOs auf eine solche Weise tempor¨r zwischen- a gespeichert werden k¨nnen, ohne dass ein Speichern in der Datenbank notwendig ist, wurde o die Klasse TempData (6.1.15) entworfen. Mit ihr k¨nnen BOs in der Session gespeichert und o aus dieser geladen werden. Genau diesen Mechanismus stellt getBO() bereit. In dieser Methode wird das BO aus dem TempData-Speicher geladen. Wird dort ein BO gefunden, wird es zur¨ckgegeben. Sollte kein BO gefunden werden, gibt es zwei weitere u M¨glichkeiten. Erstens kann es sein, dass das BO gerade vom Benutzer neu angelegt wurde. o In diesem Fall wird eine neue Instanz des BOs zur¨ckgegeben. Zweitens k¨nnte die Anfra- u o ge die erste sein. Folglich wurde noch kein BO in den TempData-Speicher geschrieben. Die getBO()-Methode muss dann mit der Server-Funktion das BO mit der ObjectID erfragen. ¨ Diese Uberlegungen f¨hren zu folgender Implementierung: u protected 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- a Speicher 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 a das 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 a Tabsheet-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; } // switch Das BO wird auf den neusten Stand gebracht, indem zuerst die Formularwerte mit einer der getAttribute()-Methoden des VContexts abgefragt werden und diese dann an die Setter- Methoden des BOs ubergeben werden. ¨ // Code mBo.setCode( ctx.getStringAttribute(PARAMETER, "details__codelabel") );
  • 190.
    7.3 Detail-Ansicht 185 Hier 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, u Haupt-, Untereinheit und Importcode gesetzt. Auch der Wert des LabeledButtonTextFields wird so gesetzt. // Code // SWIFT mBo.setSwift( ctx.getStringAttribute(PARAMETER, "details__swiftlabel") ); Bei der Eingabe der G¨ltigkeitsdauer wurde ein Datumsfeld verwendet. Solche Parameter u sollten mit getDateAttribute() abgefragt werdebm da dieser Methode den R¨ckgabewert u bereits in ein passendes Format f¨r den Serveraufruf formatiert. u // Use Until mBo.setStopDate( ctx.getDateAttribute(PARAMETER, "details__useuntillabel") ); Als letztes fehlen die beiden Combo-Boxen. Ihr Wert kann mit getIntAttribute() abgefragt werden. Man erh¨lt den Index des selektierten Eintrags. Auch f¨r die Umwandlung des Index a u in ein Enum-Objekt bietet der automatisch erzeugte RoundingHelper eine passende Funktion getIdl(). // Rounding mBo.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 u MIN DECIMAL PLACES addiert werden muss. // DecimalPlaces mBo.setDecimalplaces( (short)( ctx.getShortAttribute(PARAMETER, "details__decimalplaceslabel") + MIN_DECIMAL_PLACES.value ) ); Beim zweiten Tabsheet-Register ist zu beachten, dass die IDL-Struktur hier eine Union enth¨lt. Unions erm¨glichen es, in verschiedenen Situationen unterschiedliche Datentypen zu a o verwenden. In diesem Fall bedeutet das konkret, dass die Klasse CurrencyBO eine Instanz der
  • 191.
    7.3 Detail-Ansicht 186 Klasse EmuDataBO enthalten kann oder nicht. Ist die Check-Box f¨r die EWU aktiviert, enth¨lt u a das W¨hrungs-BO auch ein EmuDataBO, andernfalls nicht. Die Attribute des EmuDataBOs wer- a den durch die jeweiligen Setter-Methoden an die Benutzereingaben angepasst. // EMU Currency if (!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 bei den Textfeldern des ersten Registers. // Notes mBo.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 der fillBO()-Funktion zur¨ckgeliefert werden. u // Notes TempData.storeBO(ctx, mBo); return mBo;
  • 192.
    7.3 Detail-Ansicht 187 7.3.2 Die JSP-Detail-Seite Genau 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- o zugriff 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 (Index in der Navigationsreihenfolge), oidparent (ObjectID des Parent-Objekts) und enablesave (Angabe, ob der Speicher-Button aktiviert ist). Durch die Verwendung des hiddenfield-Tags der Varial-Taglib wird garantiert, dass die Parameterwerte w¨hrend der Verarbeitung nicht a verloren 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 der Oberfl¨che ver¨ndert, wird von ihnen die JavaScript-Methode enableSave() aufgerufen, die a a den 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 u werden. 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 Tabelle angeordnet. 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 dem tabsheetcontrol-Tag umrandet. Jedes einzelne Register befindet sich wiederum in einem tabsheet-Tag, das daf¨r sorgt, dass der Inhalt nur dann angezeigt wird, wenn die jeweilige u Register-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 Zusammenfassung Nach 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 dem GuiHelper passende Elemente, die als Wert die Ergebnisse der Getter-Methoden erhalten. Anschließend wird die Bearbeitung an eine JSP-Seite zwecks Visualisierung abgegeben. Ein DetailServlet definiert ferner die Methoden getBO() und fillBO(). W¨hrend getBO() nur a das 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 u Setter-Methoden des BOs die Query-String-Parameter ubergeben. ¨ 7.4 Auswahl-Dialog Einige Use-Cases beinhalten diverse Auswahl-Dialoge. Im Beispiel ist dies die Auswahl des ISO-Codes aus einer Liste vordefinierter Angaben. 7.4.1 Das SelectServlet Servlets, 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 191 Um 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 beispielsweise ein 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 u erfolgen. Ein Klick auf das Reload-Icon aktuallisiert die Tabelle. Durch Aktivierung der ne- benstehenden Check-Box erfolgt die Aktuallisierung automatisch nach jedem eingegebenen Zeichen. // Headline GuiHelper.setHeadLine(ctx, translator.getCaption(ctx, "vsearchswiftform")); // Search GuiHelper.setSearch(ctx, translator.getCaption(ctx, "vsearchswiftform")); // Grid GuiHelper.addGrid ( ctx, new SelectIsoCodeGridState() ); // Forward to JSP forwardToJsp( ctx, "/framework/currency/SelectIsoCode.jsp" ); 7.4.2 Der SelectState Durch die Verwendung einer Tabelle auf der Auswahlseite muss eine passende State- Klasse entworfen werden. Sie tr¨gt den Namen SelectIsoCodeGridState und wird von a VSelectState (6.1.9) abgeleitet. Sie beinhaltet einige bekannte Elemente. So wird auch hier ein 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 192 In der Methode wird zun¨chst der Query-String-Parameter search gelesen, der angibt, a welche Eingabe bereits vom Benutzer get¨tigt wurde. Der Tabelleninhalt soll ja entsprechend a angepasst 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 Accounts SwiftcodeBO[] swifts = SwiftcodeBO.findSwiftcodes( ctx, code ); Nun wird die Tabelle durch Aufruf der addRow()-Methode in einer Schleife genau wie bei der Listen-Ansicht gef¨llt. u // Fill grid grid.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 a Query-String-Parameter gesetzt wird. Es ist der jeweilige ISO-Code, der als selectedCode ubergeben wird. Diese Angabe dient dazu, dass das SelectServlet erf¨hrt, welcher Eintrag der ¨ a Liste ausgew¨hlt wurde. Normalerweise liefert jede Zeile in einem VSelectGrid die ObjectID a des jeweiligen Eintrags. Das SelectServlet kann dar¨ber das passende Objekt finden. Da der u CORBA-Server aber in der IDL aber keine Methode bereit stellt, mit der ein SwiftcodeBO
  • 198.
    7.4 Auswahl-Dialog 193 bzw. ein SwiftcodeStruct¨ber die ObjectID erfragt werden kann, muss statdessen die Code- u Angabe verwendet werden. Wie gewohnt definiert auch diese State-Klasse die Tabellen¨berschriften. u public 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 u des 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 Aktionsbezeichnung an das Select-Servlet ubertragen. Das Servlet weiß dann, welche Aktion ausgef¨hrt wurde. ¨ u Bei 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-Seite Die JSP-Seite unterscheidet sich nicht viel von der Listen-Ansicht. Jedoch wird zus¨tzlich a das Suchfeld durch das selectsearch-Tag eingebunden. Außerdem m¨ssen genau wie bei u der JSP-Seite f¨r die Detaildarstellung einige Parameter mit versteckten Formularfeldern u zwischengespeichert werden, damit die entsprechenden Werte nicht w¨hrend der Verarbeitung a verloren 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 195 7.4.4 Zusammenfassung Auswahldialoge bestehen zumeist aus einem Servlet, das von der Klasse VSelectServlet abgeleitet wird, und einer State-Klasse, einer Unterklasse von 6.1.9. Der Aufbau ist fast identisch mit der Listenansicht, jedoch kann zus¨tzlich ein Suchfeld erstellt werden, das den a Inhalt der Tabelle filtert. Jede Auswahl hat eine eindeutige Aktionsbezeichnung, durch die die Auswahl vom DetailServlet erkannt wird. 7.5 Abschluss Die VWE-Web-GUI erm¨glicht den Entwurf grafischer Benutzeroberfl¨chen f¨r die Browser- o a u Darstellung. 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 u Web implementiert werden. Die Umsetzung der W¨hrungsverwaltung war beispielsweise a in knapp zwei Stunden m¨glich. Dadurch, dass die API die Feinheiten von CORBA und o das typische Request-/Response-Modell mit all seinen T¨cken vor dem Entwickler ver- u bergen, ist eine Entwicklung auf einer recht hohen Abstraktionsebene m¨glich. Bevor der o Use-Case endg¨ltig abgschlossen ist, muss er jetzt nur noch in der Men¨struktur ver- u u linkt werden. Dazu ist VWE im Administrationsmodus zu starten. Dort k¨nnen berech- o tigte User die Men¨darstellung von VWE ver¨ndern. Nach Auswahl des Web-Men¨s kann u a u die W¨hrungen-Pflege als neuer Men¨punkt aufgenommen werden. Neben einer Bezeich- a u nung wird das Packet (com.varial.framework.servlet.currency) und der Servlet-Name ¨ (CurrencyListServlet) angegeben. Nachdem die Anderungen gespeichert wurden, befindet sich die W¨hrungen-Pflege im Web-Men¨. Um eine h¨here Performance zu erreichen, werden a u o Men¨daten jedoch im Server gecacht. In der Regel ¨ndert sich die Men¨struktur nur sehr u a u selten oder uberhaupt nicht. Infolgedessen ist die Zwischenspeicherung nicht weiter schlimm. ¨ Sollten neue Punkte ins Web-Men¨ aufgenommen werden. Muss der Web-Server neu gestar- u tet werden, bevor die neuen Programmmodule angezeigt werden. Der komplette Source-Code kann im Anhang noch einmal zusammengefasst betrachtet wer- den.
  • 201.
    8 Aufbau undBedienung der Web-Oberflache ¨ 196
  • 202.
    9 Zusammenfassung undAusblicke Im Rahmen der Diplomarbeit wurde eine Klassenbibliothek entwickelt, mit der das ERP- System Varial World Edition um ein Web-Interface erweitert werden kann. Es wurden Techniken und Konzepte diskutiert und an Hand ausgew¨hlter Beispiele eine Realisierung a demonstriert. Die Diplomarbeit zeigt zum einen, dass eine Web-Anbindung nicht nur sinnvoll ist, sondern dass sie auch mit dem hier entworfenen System umsetzbar ist. Zum anderen zeigte sich jedoch auch deutlich, dass der momentane Stand der Technik f¨r solche Anwendungen noch u nicht als ausgereift bezeichnet werden kann. Zwar bietet CORBA eine optimale Infrastruktur f¨r verteilte Anwendungen, in der problemlos ein Servlet den Platz eines Client einnehmen u kann, jedoch liegen die Schwachstellen f¨r die Entwicklung von webbasierten Anwendungen u deutlich im Bereicht HTTP und HTML. Da das Servlet lediglich eine HTML-Seite erzeugen kann, die dann vom Web-Server an der Browser geschickt wird, ist es ihm nicht m¨glich, unmittelbar auf die Verarbeitung der o Eingaben zu reagieren. Mit HTTP werden Aktionen des Web-Servers ausschließlich auf Client-Anfrage hin ber¨cksichtigt. Somit fehlt der erzeugten HTML-Seite teilweise die n¨tige u o Programmlogik, um auf Oberfl¨chenereignisse und Benutzeraktionen passend zu reagieren. a JavaScript stellt auf Grund seines eher rudiment¨ren Charakters keine wirkliche Alternative a zur m¨chtigen Java-API dar. a Weiterhin hat sich gezeigt, dass sich die Browser unterschiedlicher Hersteller zum Teil so stark unterscheiden, dass eine allgemein g¨ltige und auf allen Systemen lauff¨hige u a Internet-Applikation sehr schwer und nur mit vielen Umwegen zu realisieren sind. Vor allem in der Handhabung von DOM (Document Object Modell) unterscheiden sich die einzelnen Browser sehr stark. Einige Varianten unterst¨tzten das Modell erst gar nicht. u Eine weitere H¨rde, die auf dem Weg zur Realisierung eines Web-Interfaces genommen u werden musste, war die Tatsache, dass einige allgemein gebr¨uchliche grafische Ober- a fl¨chenelemement von HTML nicht angeboten werden. So gibt es beispielsweise keine a editierbare Combo-Box, so dass eine entsprechende Komponente selbst aus den vorhandenen M¨glichkeiten entwickelt werden musste. o Zusammenfassend l¨ßt sich sagen, dass eine Realisierung eines webbasierten ERP-Systems a trotz der noch nicht ausgereiften Technik, erm¨glicht wurde. In Zukunft werden die entspre- o chenden Web-Technologien sicherlich entsprechend erweitert, so dass Internet-Applikation den gewohnten Desktop-Anwendungen in nichts nachstehen. Eventuell werden die Grenzen zwischen diesen beiden Arten von Software bald sogar ganz verwischen, so dass zuk¨nftig u kein Unterschied zwischen Online- und Offline-Applikation mehr bestehen wird. Leider konnten nicht alle Ideen, die zu Beginn im Vorfeld entworfen wurden, umgesetzt werden, da sie den Umfang der Arbeit gespregt h¨tten. Einige Vision werden vorraussichtlich a im Anschluss an die Arbeit bei Varial in Angriff genommen werden. 197
  • 203.
    198 Erklarung ¨ 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 a habe. Gleichzeitig versichere ich, daß diese Arbeit in keiner Weise, gleich oder ¨hnlich, weder a ver¨ffentlicht noch einer anderen Pr¨fungsbeh¨rde vorgelegt habe. o u o Siegen, den 28. August 2002.
  • 204.
    199 A Anhang Tabellenverzeichnis 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 200 A.1 Abbildungsverzeichnis Abbildungsverzeichnis 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 201 A.2 Glossar Applets Ein in Java geschriebenes Programm, das uber das Internet ubertragen und im ¨ ¨ Browser ausgef¨hrt wird. u BO Business-Objekt BOA 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. u Byte-Code Java-Programme werden in sog. Byte-Code kompiliert. Dieser Byte-Code ist plattformunabh¨ngig und kann mit einer JVM ausgef¨hrt werden, a u C++ 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. o CORBA 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. o Design Pattern Entwurfsmuster. Designvorschl¨ge f¨r den Entwurf objektorientierter Softwa- a u resysteme, die vordefinierte L¨sungen f¨r konkrete Programmierprobleme darstellen. o u Digital 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. o DTD Document Type Definition. Schemadefinitionssprache, die den Aufbau einer XML- Datei festlegt. Embedded-Systeme
  • 207.
    A.2 Glossar 202 ERP Enterprise Resource Planning. Software, die ein Unternehmen bei der Abwicklung von Gesch¨ftsprozessen unterst¨tzt. a u GUI Graphical User Interface. Grafische Benutzeroberfl¨che. a HTML Hypertext Text Markup Language. Sprache, die Hypertext-Dokumente beschriebt. ¨ HTTP Hypertext Transfer Protocol. Ubertragungsprotokoll f¨r HTML-Seiten. u IDL 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. o IIS Internet Information Server. Web-Server von Microsoft. Java Moderne objektorientierte Programmiersprache von der Firma Sun Microsystems JDBC 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 u Load 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. u OMG 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. u POA 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 203 Regular 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. a Session-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 u Tag Auszeihnungsbefehl, der ein Element in HTML bzw. XML markiert. Taglib Sammlung von zusammenh¨ngenden Tags zu einer Bibliothek. a TCP/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. o URL 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 AG VBScript Eine von Microsoft entwicklete Skriptsprachem, die sich sehr stark an Visual Basic anlehnt. H¨ufig verwendet f¨r die Programmierung von ASP-Seietn. a u W3C 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. u Web-Browser Browser World-Wide-Web Internet XML 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.