Untitled - Pageballs

Werbung
Fachhochschule Köln
University of Applied Sciences Cologne
Campus Gummersbach
Institut für Informatik
Diplomarbeit
zur Erlangung des Diplomgrades
Diplom-Informatiker (FH)
in der Fachrichtung Allgemeine Informatik
Erstprüfer:
Prof. Dr. Frank Victor
Zweitprüfer:
Prof. Dr. Erich Ehses
vorgelegt am:
21. Juni 2004
von cad.:
Pero Djordjic
aus:
Musäusstraße 12
51067 Köln
Tel.-Nr:
Tel.: (0221) 9990348
E-Mail:
[email protected]
Matr.-Nr:
1101519716
Inhaltsverzeichnis
Abbildungsverzeichnis
v
Tabellenverzeichnis
vi
Glossar
vii
1 Einführung
1.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Ziel der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1
3
I
4
Grundlagen
2 Webanwendungen
2.1 Basistechnologien . . . . . . . . . . . . . . . .
2.1.1 Webserver . . . . . . . . . . . . . . . .
2.1.2 Hypertext Transfer Protocol . . . . . .
2.2 Webanwendungen . . . . . . . . . . . . . . . .
2.2.1 Definition von Webanwendungen . . .
2.2.2 Abgrenzung zu Webdiensten . . . . . .
2.3 Webservererweiterungen . . . . . . . . . . . .
2.3.1 Common Gateway Interface . . . . . .
2.3.2 Webserver APIs . . . . . . . . . . . . .
2.3.3 Server Pages und Servlets . . . . . . .
2.3.4 Probleme von Webservererweiterungen
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
5
5
6
6
7
8
8
8
9
10
3 Model 2 - die Lösung?
3.1 Eine einfache Architektur . . . . . . .
3.2 Model View Controler Entwurfsmuster
3.2.1 Definition von Entwurfsmustern
3.2.2 Model View Controler . . . . .
3.3 Model 2 Architekturen . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
15
15
15
18
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Architekturerweiterung für Unternehmensanwendungen
21
4.1 Grundlagen Unternehmensanwendungen . . . . . . . . . . . . 22
4.1.1 Business Objects . . . . . . . . . . . . . . . . . . . . . 22
ii
4.2
4.3
4.4
4.5
4.1.2 Verteilte Objekte . . . . . . . . .
4.1.3 Verzeichnisdienste . . . . . . . . .
4.1.4 Transaktionen . . . . . . . . . . .
4.1.5 Partitionierung von Clustern . . .
Plattform J2EE . . . . . . . . . . . . . .
Laufzeitumgebung und Middleware . . .
Implementation von Geschäftslogik . . .
4.4.1 Aufbau und Arbeitsweise . . . . .
4.4.2 Unterschiedliche Bean Typen . .
4.4.3 RAD durch implizite Middleware
4.4.4 Datenbankunabhängigkeit . . . .
4.4.5 Performanceoptimierung . . . . .
Front-End Technologien in J2EE . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Integration von Frameworks und Technologien
5.1 Struts Framework . . . . . . . . . . . . . . . . .
5.1.1 Wieso Struts? . . . . . . . . . . . . . . .
5.1.2 Arbeitsweise und Bestandteile . . . . . .
5.1.3 Actions für den Navigationsfluss . . . . .
5.1.4 Formularverarbeitung und Validierung .
5.1.5 Lokalisierung . . . . . . . . . . . . . . .
5.1.6 Übergabe von Objekten an Views . . . .
5.2 Views mit Tag Libraries und HTML . . . . . .
5.3 Erweiterung von Views mit Tiles . . . . . . . .
5.4 Struts mit EJB Model . . . . . . . . . . . . . .
5.4.1 JNDI Lookups in Actions . . . . . . . .
5.4.2 Übergabe von Entity Beans an Views . .
II
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
22
23
25
26
27
31
35
36
42
46
53
54
55
.
.
.
.
.
.
.
.
.
.
.
.
56
56
56
56
60
62
64
65
65
66
67
68
68
Eine Beispiel-Anwendung
6 Einführung
6.1 Kontoführung als Beispiel . . . . . . . . . . . . .
6.2 Session Façade zur Optimierung des EJB Models
6.3 Objekt-Relationales Mapping und EJB Entwurf .
6.4 Navigationsfluss und Eingabeverarbeitung . . . .
6.5 Views . . . . . . . . . . . . . . . . . . . . . . . .
69
.
.
.
.
.
70
70
71
73
77
79
7 Implementierung
7.1 Integrierte Entwicklungsumgebung . . . . . . . . . . . . . . .
7.2 Attributorientierte Programmierung . . . . . . . . . . . . . . .
7.3 Performancetest . . . . . . . . . . . . . . . . . . . . . . . . . .
80
80
80
84
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
III
Schlussbetrachtung und Ausblick
8 Ausblick
8.1 MVC in Webanwendungen . .
8.1.1 JavaServer Faces . . .
8.1.2 Integration mit Struts
8.2 Entwicklungsumgebungen . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
88
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
89
89
89
91
92
9 Schlussbetrachtung
93
IV
96
V
Literaturverzeichnis
Erklärung
103
Abbildungsverzeichnis
3.1
3.2
3.3
Model 1 Architekturen . . . . . . . . . . . . . . . . . . . . . . 13
Model und Views . . . . . . . . . . . . . . . . . . . . . . . . . 16
Model 2 Architektur . . . . . . . . . . . . . . . . . . . . . . . 18
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
4.10
Model 2 Architektur . . . . . . . . .
Model 2 Unternehmensanwendungen
Verteilte Objekte . . . . . . . . . . .
JNDI Namespaces . . . . . . . . . . .
3-Tier und 4-Tier Architektur . . . .
Java 2, Enterprise Edition . . . . . .
Enterprise JavaBeans Typen . . . . .
Enterprise JavaBeans Interfaces . . .
Initiierung und Methodenaufruf . . .
CMP 2.0 . . . . . . . . . . . . . . . .
5.1
5.2
5.3
Struts Controller . . . . . . . . . . . . . . . . . . . . . . . . . 57
Struts Controller UML Klassendiagramm . . . . . . . . . . . . 59
Struts Controller UML Sequenzdiagramm . . . . . . . . . . . 60
6.1
6.2
6.3
6.4
6.5
6.6
6.7
6.8
6.9
Überweisung mit Entity Beans . . . . . . . . . . . . .
Vergleich Zugriff mit und ohne Session Façade . . . .
Überweisung mit Session Façade . . . . . . . . . . . .
Relationales Mapping von m:n Objektbeziehungen . .
Objektorientierter Entwurf für die Beispielanwendung
Relationales Mapping für die Beispielanwendung . . .
Bean Implementation für das Beispiel . . . . . . . . .
Struts Entwurf . . . . . . . . . . . . . . . . . . . . .
Tiles Layout und graphischer Entwurf . . . . . . . . .
7.1
Durchschnittliche Verarbeitung - JMeter Load Test . . . . . . 87
8.1
8.2
MVC in J2EE Webanwendung . . . . . . . . . . . . . . . . . . 91
Abstraktionen - Struts mit JavaServer Faces . . . . . . . . . . 91
9.1
Schichten der vorgestellten Architektur . . . . . . . . . . . . . 93
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
21
21
23
25
27
30
37
39
40
47
72
73
73
76
76
77
77
78
79
Tabellenverzeichnis
4.1 Application Server Marktübersicht 1 . . . .
4.2 Application Server Marktübersicht 2 . . . .
4.3 Web Container Marktübersicht . . . . . . .
4.4 Effekte von Transaktionsattributen bei CMT
vi
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
33
34
35
51
Glossar
Abstraktion
Abstraktion ist eine Vorgehensweise, bei der
unter einem bestimmten Gesichtspunkt die wesentlichen Merkmale eines Gegenstandes oder
Begriffes herausgesondert werden.
Abstrakte Klasse
Von einer abstrakten Klasse werden niemals
Objektexemplare erzeugt; sie ist bewußt unvollständig und bildet somit die Basis für weitere Unterklassen, die Exemplare haben können.
In C++ werden diese Klassen virtuelle Klasse
genannt.
Abstrakte Methode
Eine Methode, für die nur eine Signatur, jedoch keine Anweisungsfolge definiert ist, d.h.
die Operation ist definiert, aber noch nicht implementiert. Sie wird in einer abgeleiteten Klasse implementiert. In C++ werden diese Methoden virtuelle Methoden genannt.
Aggregation
Eine Aggregation ist eine Sonderform der Assoziation, bei der die beteiligten Klassen keine gleichwertige Beziehung führen, sondern eine Ganzes-Teile-Hierarchie darstellen. Eine Aggregation beschreibt, wie sich etwas Ganzes aus
seinen Teilen zusammensetzt.
Akteur
Ein Akteur ist eine außerhalb des Systems liegende Klasse, die an der in einem Anwendungsfall beschriebenen Interaktion mit dem System
beteiligt ist. Akteure nehmen in der Interaktion
gewöhnlich eine definierte Rolle ein.
API
Abkürzung für Application Programming Interface. API ist eine dokumentierte SoftwareSchnittstelle, mit deren Hilfe eine Software
die Funktionen einer anderen Software nutzen
kann.
vii
Architektur
Eine Architektur ist die Spezifikation grundlegender Eigenschaften und Möglichkeiten einer
Lösung, die im Verlauf der Weiterentwicklung
nur schwierig rückgängig zu machen ist.
Argument
Konkreter Wert eines Parameters.
Assoziation
Eine Assoziation beschreibt eine Relation zwischen Klassen, d.h. die gemeinsame Semantik
und Struktur einer Menge von Objektbeziehungen.
Attribut
Eine benannte Eigenschaft eines Typs. Ein Attribut ist ein Datenelement, das in jedem Objekt einer Klasse gleichermassen enthalten ist
und von jedem Objekt mit einem individuellen Wert repräsentiert wird. Im Gegensatz zu
Objekten haben Attribute außerhalb des Objektes, von dem sie Teil sind, keine eigene Identität. Attribute sind vollständig unter der Kontrolle der Objekte, von denen sie Teil sind.
Back-End
Anwendungen, die im Hintergrund laufen und
die vom Benutzer über das Front-End eingegebenen Daten verarbeiten und dann das Ergebnis an das Front-End schicken.
Front-End
Bereich einer Anwendung der Benutzereingaben aufnimmt und diese an das Back-End zur
Verarbeitung weitergibt. Nach der Verarbeitung stellt das Front-End das Ergebnis der Verarbeitung dar.
Bibliothek
Eine Sammlung von Klassen.
Business Object
Ein Business Object repräsentiert einen Gegenstand, ein Konzept, einen Ort oder eine Person
aus dem realen Geschäftsleben in einem fachlichen geringen Detaillierungsgrad, d.h. einen
fachlich elementaren Begriff (Vertrag, Rechnung etc.). Für die praktische Umsetzung sind
Business Objects auf rein fachlich motivierte
Eigenschaften reduzierte Aggregationen fundamentaler Fachobjekte, zu denen alles weitere
delegiert wird. Sie definieren typischerweise vor
allem Schnittstellen und sind eine Art Fassade.
Client
In Bezug auf Enterprise JavaBeans können Clients Servlets, JSP Tag Libraries, Anwendungen, Applets, CORBA Clients oder andere Enterprise JavaBeans sein.
Collection
Eine Collection ist ein Objekt, welches eine
Menge anderer Objekte referenzieren und die
Operationen bereitstellen, um auf diese Objekte zuzugreifen.
Content
Content (engl. Inhalt) ist Information in strukturierter, schwach strukturierter und unstrukturierter Form, die in elektronischen Systemen
zur Nutzung bereitgestellt wird.
Cookie
Eine vom Webclient erzeugte Datei, welche Daten speichert, die ein Webserver, häufig vom
Benutzer unbemerkt, an einen Webclient gesendet hat.
Debugger
Meist ein Tool in einer IDE, welches dabei hilft
Fehler zu lokalisieren.
Delegation
Delegation ist ein Mechanismus, bei dem ein
Objekt eine Nachricht nicht (vollständig) selbst
interpretiert, sondern an ein anderes Objekt
weiterleitet.
Design
Mit Design werden alle Aktivitäten im Rahmen
des Softwareentwicklungsprozesses bezeichnet,
mit denen ein Modell logisch und physisch
strukturiert wird und die dazu dienen zu
beschreiben, wie das System Anforderungen
erfüllt.
Domain
Ein einprägsamerer Name, über den das Domain Name Systems (DNS) eine logische Verbindung zu einer IP-Adressen herstellt.
DLL
DLL ist die Abkürzung für Dynamic Link Library. Eine DLL enthält Programmroutinen,
die erst bei Bedarf geladen werden.
Entwurfsmuster
Entwurfsmuster sind generalisierte und
bewährte Lösungsansätze zu wiederkehrenden
Entwurfsproblemen. Sie sind keine fertig
kodierten Lösungen, sie beschreiben lediglich
den Lösungsweg bzw. die Lösungsidee.
Ereignis
Ein Geschehen, das in einem gegebenen Kontext eine Bedeutung hat und sich räumlich und
zeitlich lokalisieren läßt.
Event
siehe Ereignis
Exception
Eine Exception ist ein Ereignis, welches
während der Ausführung eines Programmes
auftritt und den normalen Programmablauf
unterbricht.
Fail-Over
Sind mehrere Server zu einem Cluster gekoppelt, kann, wenn ein Server ausfällt, ein anderer
dessen Funktion übernehmen.
Firewall
System zum Schutz gegen unerlaubte Zugriffe
auf ein Netzwerk.
Formular
Eine Eingabemaske in HTML.
Framework
siehe Rahmenwerk
Geschäftsprozess
Ein Geschäftsprozess ist eine Zusammenfassung von fachlich verwandten Geschäftsanwendungsfällen. Dadurch bildet ein Geschäftsprozess gewöhnlich eine Zusammenfassung von organisatorisch evtl. verteilten, fachlich jedoch
zusammenhängenden Aktivitäten, die notwendig sind, um einen Geschäftsvorfall, beispielsweise einen konkreten Antrag, ergebnisorientiert zu bearbeiten. Die Aktivitäten eines
Geschäftsprozesses stehen gewöhnlich in zeitlicher und logischer Abhängigkeit zueinander.
GUI
Graphical User Interface, Grafische Benutzeroberfläche.
Handler
Ein Begriff aus der ereignisgetriebenen Programmierung: eine Funktion, die ein Ereignis
im allgemeinen Sinne verarbeitet.
Hidden Input Field
Ein Eingabefeld eines HTML Formulars, bei
dem das Attribut Type auf den Wert hidden
gesetzt ist. Dadurch ist das Eingabefeld zwar
vorhanden aber nicht sichtbar für den Benutzer.
Hilfsklassen
Hilfsklassen sind Klassen, in denen globale Variablen und Funktionen definiert sind,
die jedoch inhaltlich nicht unmittelbar zusammenhängen. Hilfsklassen werden als Ablage für
Variablen und Funktionen verwendet, die vom
eigentlichen System gebraucht werden.
HTML
Abkürzung für Hypertext Markup Language,
Standardisierte Seitenbeschreibungssprache für
WWW-Seiten im Internet bzw. Intranet. Sie
definiert sowohl die Gestaltung, den Inhalt und
die Grafik der Seite als auch die Links.
Hyperlinks
Verbindungen zu eigenen oder fremden HTML
Seiten.
IDE
Integrated Development Environment. Eine
”integrierte Entwicklungsumgebung”, welche
aus Editor, Compiler, Linker, Debugger und
anderen Tools besteht.
Instanz
In der Praxis können Instanz, Objekt und Exemplar synonym betrachtet werden.
Instantiierung
Instantiierung ist das Erzeugen einer Instanz
aus einer Klasse.
Integration
Das Zusammenwachsen oder Zusammenfügen
mehrerer Teile zu einem Ganzen. Dies können
Softwarebestandteile oder ganze Anwendungen
sein.
Interface
In Java eine Sammlung von Methoden und
Konstanten ähnlich einer Klasse, welche von einer Klasse implementiert werden kann.
Interoperabilität
Beschreibt die Fähigkeit von Systemen, die mit
Hilfe unterschiedlicher Protokolle zusammenarbeiten können.
IP-Adresse
Eine IP-Adresse besteht aus einem Zahlencode von vier Zahlen, jeweils zwischen 0 bis
255, die durch Punkte getrennt werden (z.B.
192.148.0.195). Damit ist jeder Internetrechner
eindeutig adressierbar.
Iteration
Die wiederholte Ausführung eines oder mehrerer Befehle.
JDBC
JDBC ist ein Java API und bietet eine plattformunabhängige Kommunikationschnittstelle zu
Datenbanken und anderen permanenten Speichern.
JOIN Statement
Eine Anweisung in SQL über mehrere Tabellen.
Kardinalität
Anzahl der Elemente.
Klasse
Eine Klasse ist die Definition der Attribute,
Operationen und der Semantik für eine Menge
von Objekten. Alle Objekte einer Klasse entsprechen dieser Definition.
Klassendiagramm
Ein Klassendiagramm zeigt eine Menge statischer Modellelemente, vor allem Klassen und
ihre Beziehungen.
Komponente
Eine Komponente ist ein ausführbares Softwaremodul mit eigener Identität und wohldefinierten Schnittstellen (Sourcecode, Binärcode, DLL oder ausführbares Programm). Häufig
auch gleichbedeutend mit Bestandteil.
Komposistion
Eine Komposition ist eine strenge Form der Aggregation, bei der die Teile vom Ganzen existenzabhängig sind.
Konkrete Klasse
Eine Klasse, die Objekte instantiieren kann.
Kontext
Eine bestimmte begrenzte Situation.
Lebenszyklus
Der Lebenszyklus beschreibt das Leben eines
Objektes zur Laufzeit. Ein Objekt wird in
der Regel erzeugt, verwendet und schließlich
zerstört. Es können auch andere Zustände bestehen, wie etwa ein aktiver oder passiver Zustand.
Library
siehe Bibliothek
Links
siehe Hyperlinks
Listing
Die Abbildung eines Source Codes in einem Dokument.
Lock
Sperren von Daten oder Datein vor dem Zugriff
durch andere Benutzer, Prozesse oder Transaktionen.
Look and Feel
Mit Look and Feel bezeichnet man das Erscheinungsbild und die Handhabung einer Software.
Map
Eine Implementation einer Java Collection.
Map repräsentiert eine Menge von ObjektPaaren, wobei jeweils ein Objekt einen einzigartigen Schlüssel zum Zugriff auf das dazugehörige andere Objekt darstellt.
Markup
Auszeichnungssprache. Beispiele für Markups
sind SGML (Standard Generalized Markup
Language), HTML (Hypertext Markup Language) und MathML. In Markup-Dokumenten
wird der Inhalt durch Markup-Elemente strukturiert, die zum Beispiel den Textsatz bestimmen.
Member Variable
Eine in einer Klasse deklarierte Variable.
Methode
In Java werden Operationen Methoden genannt. In UML wird eine Methode als Implementierung einer Operation definiert. Für die
Praxis ist es unkritisch, Methode und Operation synonym zu verwenden.
Methodenkopf
Der Methodenkopf (auch Signatur) setzt sich
zusammen aus dem Namen der Methode, seiner Parameterliste und der Angabe eines eventuellen Rückgabetyps.
Methodenrumpf
Programmcode innerhalb einer Methode.
Message
siehe Nachricht
Middleware
Integrationsplattform für die Koppelung von
heterogenen Einzelsystemen.
Nachricht
Nachrichten sind ein Mechanismus, mit dem
Objekte untereinander kommunizieren können.
Eine Nachricht überbringt einem Objekt die Information darüber, welche Aktivität von ihm
erwartet wird, d.h. eine Nachricht fordert ein
Objekt zur Ausführung einer Operation auf.
Eine Nachricht besteht aus einem Namen, einer
Liste von Argumenten und geht an einen oder
mehrere Empfänger. Der Sender einer Nachricht erhält ggf. ein Antwort-Objekt zurück.
Durch Polymorphismus kann eine Nachricht
zum Aufruf einer von mehreren gleichlautenden Operationen führen.
Nebenläufigkeit
Zwei oder mehr Aktiviäten werden zeitgleich
parallel ausgeführt.
Object
siehe Objekt
Objekt
Ein Objekt ist eine konkret vorhandene und
agierende Einheit mit eigener Identität und definierten Grenzen, das Zustand und Verhalten
kapselt. Der Zustand wird repräsentiert durch
die Attribute und Beziehungen, das Verhalten durch Operationen bzw. Methoden. Jedes
Objekt ist Exemplar (Synonym: Instanz) einer Klasse. Das definierte Verhalten gilt für alle Objekte einer Klasse gleichermassen, ebenso
die Struktur ihrer Attribute. Die Werte der Attribute sind jedoch individuell für jedes Objekt.
Jedes Objekt hat eine eigene, von seinen Attributen u.a. unabhängige, nicht veränderbare
Identität.
Objektbeziehung
Eine konkrete Beziehung zwischen zwei Objekten, d.h. die Instanz einer Assoziation. Ein Objekt hat eine Beziehung zu einem anderen Objekt, wenn es eine Referenz darauf besitzt. Implementiert werden diese Referenzen gewöhnlich durch Attribute, was für die Modellierung
jedoch unerheblich ist.
OO
Abkürzung für Objektorientierung.
Open Source
Software, die sowohl als Quelltext als auch in
ausführbarer Form inspiziert, verändert und
auch verändert unter gleicher Lizenz weitergegeben werden darf. Häufig ist die Nutzung kostenlos.
Operation
Operationen sind Dienstleistungen, die von einem Objekt mit einer Nachricht angefordert
werden können, um ein bestimmtes Verhalten
zu bewirken. Sie werden implementiert durch
Methoden. In der Praxis werden Operation und
Methode häufig synonym verwendet.
Parameter
Ein Parameter ist die Spezifikation einer Variablen, die Operationen, Nachrichten oder Ereignissen mitgegeben, von diesen verändert oder
zurückgegeben wird. Ein Parameter kann aus
einem Namen, einem Typ (einer Klasse) und
einer Übergaberichtung bestehen. Über URL
können auch Parameter an Resourcen wie Servlets übergeben werden.
Parsing
Der Vorgang einer syntaktischen Analyse.
PDF
Portable Document Format - Proprietäres Dokumentformat der Firma Adobe - Kann mit
dem kostenlosen Adobe Acrobat Reader gelesen werden. Dieser kann innerhalb von Webclients ausgeführt werden.
Persistente Objekte
Persistente Objekte (persistent: lat. ”anhaltend”) sind solche, deren Lebensdauer über die
Laufzeit einer Programmsitzung hinausreicht.
Die Objekte werden hierzu auf permanenten
Speichermedien (z.B. Datenbanken) gehalten.
Persistenz
Persistenz ist die Eigenschaft von Daten oder
Objekten, über die Laufzeit eines Programms
hinaus in ihrer Identität, ihrem Zustand und
ihrer Beschreibung zu existieren.
Plug-In
Hilfsprogramm, welches zu einem Hauptprogramm hinzugefügt werden kann.
Polymorphismus
Polymorphismus (Vielgestaltigkeit) heißt, daß
gleichlautende Nachrichten an kompatible Objekte unterschiedlicher Klassen ein unterschiedliches Verhalten bewirken können. Beim dynamischen Polymorphismus wird eine Nachricht nicht zur Compilierzeit, sondern erst
beim Empfang zur Programmlaufzeit einer
konkreten Operation zugeordnet. Voraussetzung hierfür ist das dynamische Binden.
Protokoll
Definierte Vereinbarung über die Art und Weise des Informationsaustauschs zwischen zwei
Systemen.
Rahmenwerk
Ein Rahmenwerk ist eine Menge kooperierender Klassen, die unter Vorgabe eines Ablaufes
eine generische Lösung für eine Reihe ähnlicher
Aufgabenstellungen bereitstellen.
Referentielle
grität
Inte- Regel, die die Integrität von Objektbeziehungen beschreibt, vor allem für den Fall, daß eines
der beteiligten Objekte oder die Objektverbindung selbst gelöscht werden sollen.
Rekursion
Eine Methode ruft sich wiederholt selbst auf
um ein zusammengesetztes Ergebnis aus den
Rückgabewerten zu liefern. Dieses Verfahren ist
häufig effektiver als eine Iteration.
Relationship
Beziehung
Roll-Back
Rückabwicklung
Sequenzdiagramm
Ein Sequenzdiagramm zeigt eine Menge von Interaktionen zwischen einer Menge ausgewählter Objekte in einer bestimmten begrenzten
Situation (Kontext) unter Betonung der zeitlichen Abfolge. Sequenzdiagramme können in
generischer Form existieren (Beschreibung aller möglichen Szenarien) oder in Instanzform
(Beschreibung genau eines speziellen Szenarios).
Server
Server ist vom englischen ”to serve” (dienen,
jemanden versorgen) abgeleitet: Ein zentraler
Rechner in einem Netzwerk, der den Arbeitsstationen/Clients Daten, Speicher und Ressourcen zur Verfügung stellt.
Session
Sitzung. Mit einer Session bezeichnet man eine
identifizierbare Clientverbindung.
Schnittstelle
Schnittstellen beschreiben einen ausgewählten
Teil des extern sichtbaren Verhaltens von Modellelementen (hauptsächlich von Klassen und
Komponenten).
Shut-Down
Beenden aller laufenden Programme (Herunterfahren) eines Computersystems, meist verbunden mit Ausschalten der Stromversorgung.
Signatur
siehe Methodenkopf
Skalierbarkeit
Möglichkeit, die Anzahl der Anwender oder der
Kapazitäten einer Softwarelösung zu erhöhen,
ohne die Anwendungssoftware oder das System
wesentlich zu verändern.
Skript
Programme oder Teile davon, die von einem anderen Programm interpretiert werden.
Skripting
Programmierung von Skripten.
SOAP
Simple Object Access Protocol - XMLSpezifikation zum Objektaustausch - definiert,
wie Transaktionen über das Internet und XML
getätigt sowie dynamische Web Services über
verteilte Netzwerke genutzt werden können.
Sockel
siehe Socket
Socket
Eine IP-Adresse zusammen mit einem Port
nennt sich Socket. Beispiel: 127.0.0.1:80 beschreibt den www-http- Port (80) des lokalen
Rechners mit der feststehenden IP 127.0.0.1
Standard Input
Standard Kanal eines Betriebssystems für Eingaben.
Standard Output
Standard Kanal eines Betriebssystems für Ausgaben.
Stream
Eine Folge (Strom) von Daten.
Subklasse
siehe Unterklasse
Submit
Das Absenden eines HTML Formulars.
Superinterface
Ein übergeordnetes Interface eines Interfaces.
Superklasse
Eine Superklasse ist eine Verallgemeinerung
ausgewählter Eigenschaften ihrer Unterklassen.
Szenario
Ein Szenario ist eine spezifische Folge von Aktionen. Beispielsweise ein konkreter Ablaufpfad
in einem Anwendungsfall (sozusagen eine Instanz des Anwendungsfalls).
Tag
Markierung innerhalb von Text. Beispielsweise eine Formatierungsanweisung in HTML oder
ein Element in XML.
Tier
Schicht
Tool
Ein Programm, das eine bestimmte Arbeit erleichtert.
Transaktion
Eine Transaktion bezeichnet die Abwicklung eines Geschäftes in der realen Welt. In der Informatik ist eine Transaktion ein Verarbeitungsschritt, der ein abgeschlossenes Teilergebnis erzeugt; oft werden im Interesse der Datensicherheit Veränderungen erst bei einer vollständig
durchgeführten Transaktion dauerhaft gespeichert.
Typkonformität
Andere Elemente sind typkonform, wenn sie
über die durch den Typen definierten Eigenschaften verfügen.
UML
UML ist die Abkürzung für Unified Modeling
Language. Die Sprache wurde als internationaler Standard zur Beschreibung von Software
entwickelt.
Unterklasse
Eine Unterklasse ist die Spezialisierung einer
Oberklasse und erbt alle Eigenschaften der
Oberklasse.
URI
Universal Resource Identifier. Ein Oberbegriff
für URL und URN, der allerdings fast immer
einen URL bezeichnet, da URN kaum in Gebrauch sind.
URL
Universal Resource Locator - eine URL ist eine
allgemeingültige Adresse einer Resource (zum
Beispiel einer Datei) im Internet. Diese eindeutige Adresse besteht aus der Bezeichnung des
Protokolls (z.b. http://), aus dem Namen des
Servers auf dem die Resource zu finden ist (z.b.
localhost), aus dem Namen des Dienstes der die
Resource zur Verfügung stellt, aus dem eigentlichen Namen der Resource. Weiter können noch
Parameter für die Resource angegeben werden.
URL Rewriting
Anstatt eines Cookies können Identifikationsnummern einer Session als URL Parameter bei
Requests mitgeführt werden.
Validierung
Die Überprüfung auf Inkonsistenzen oder Fehler. Häufig eine Überprüfung von Benutzereingaben.
Vector
Eine Implementation einer Java Collection. Ein
Vector repräsentiert eine lineare Liste von Elementen beliebiger Typen, auch unterschiedlicher Typen.
Vererbung
Vererbung ist ein Programmiersprachenkonzept für die Umsetzung einer Relation zwischen
einer Ober- und einer Unterklasse, wodurch
Unterklassen die Eigenschaften ihrer Oberklassen mitbenutzen können.
Verzeichnisdienst
Directory Service - Eine nach dem ITU (International Telecommunications Union)-Standard
X.500 hierarchisch (baumförmig) aufgebaute
Datenbank, in der von einem geeigneten Client
aus Informationen abgerufen werden können.
Webclient
Internet-Client, Webbrowser wie beispielsweise
der Microsoft Internet Explorer oder Netscape.
Wiederverwendbarkeit Eine Eigenschaft, welche beschreibt in welchem
Umfang Programmteile einer Software in einer anderen Software erneut verwendet werden
können.
Workflow
Ein Workflow ist die computergestützte
Automatisierung und Unterstützung eines
Geschäftsprozesses oder eines Teils davon.
XML
Extensible Markup Language (XML) ist ein
einfaches und sehr flexibles Textformat.
Zustand
Ein Zustand ist eine Abstraktion der möglichen
Attributwerte eines Objektes. Ein Zustand
gehört zu genau einer Klasse und stellt eine Abstraktion bzw. Zusammenfassung einer Menge von möglichen Attributwerten dar, die die
Objekte dieser Klasse einnehmen können. In
der UML ist ein Zustand eine Bedingung bzw.
Situation im Leben eines Objektes, während
der eine bestimmte Bedingung erfüllt ist, Aktivitäten ausgeführt werden oder auf ein Ereignis
gewartet wird.
xix
Einführung
Einleitung
Kapitel 1
Einführung
1.1
Einleitung
Das Internet hat sich unter anderem zu einem weltumspannenden Marktplatz für den Einkauf und Verkauf von Gütern und Dienstleistungen jeder
Art entwickelt. Viele Unternehmen haben auf diesen Vertriebs- und Informationskanal gesetzt und entdecken weitere Einsatzmöglichkeiten der Internet
Technologien bei der Optimierung ihrer Arbeits- und Geschäftsprozesse (vgl.
[Bullinger, 2000]. Webanwendungen, Anwendungen, die über das Internet angeboten werden, gelten bereits seit einiger Zeit als attraktive Möglichkeit, um
traditionelle lokale Client-Server Lösungen zu ersetzen. So schreibt Sarsam
in dem vor kurzem in der COMPUTERWOCHE erschienen Artikel ”ThinClient-Hersteller bündeln ihre Kräfte”:
”Dem sogenannten Server-Based-Computing, also der Verlagerung der Anwendungen auf einen zentralen Server, bestätigen auch die einschlägigen
Marktforschungsinstitute klare Kosten- und Sicherheitsvorteile gegenüber dem
PC. Ein Grund ist, dass Administration und Pflege der Applikationen von
einer Stelle aus übernommen werden können. Die Kostenvorteile gegenüber
PCs werden auf 22 Prozent (Gartner) bis 57 Prozent (Zona Research) geschätzt.
Auch der wachsenden Frage nach Sicherheit für Unternehmensdaten kommt
die zentrale Steuerung und Kontrolle entgegen.” [Sarsam, 2004]
Beim Server-Based-Computing wird die Geschäftslogik von lokalen Servern
auf zentrale Webserver im Internet verlagert. Gängige und frei erhältliche
Webclients nutzen parametrisierte Aufrufe über das Hypertext Transfer Protokoll (HTTP) für die Kommunikation mit dem Webserver, der Anwendungsplattform. Die Ausführung geschäftskritischer Geschäftslogik erfordert dort
hohe Skalierbarkeit, Ausfallsicherheit und eine intelligente Kommunikation
mit Datenbanken und integrierten Anwendungen. (vgl. [Schick, 1999])
1
Einführung
Einleitung
Zu den Herausforderungen bei der Entwicklung von Webanwendungen schreibt
Neil Ford in seinem aktuell erschienenen Buch ”Art of Java Web Development”:
”Developers coming from more traditional application development (for example, client/server applications) discover that building web applications is
fundamentally different in many ways. Even if you are fluent in Java, the architecture and design of web applications doesn’t necessarily come naturally.
Just as the switch from console applications to event-driven applications required a major shift in thinking, the switch from event-driven applications
to the stateless world of web development requires a paradigm shift as well.
Even an understanding of the basic infrastructure of web applications won’t
immediately reveal the most effective architecture and design. Many decisions
made early in the design and development process have unforeseen repercussions later in the process. Because of the oft-quoted and well-documented
cost of architectural and design changes late in the application lifecycle, it
behooves you to get it right from the outset.” [Ford, 2004]
Die Ursachen für spätere Änderungen an der Architektur und dem Design
einer Anwendung erläutert Depke. Gleichzeitig stellt er ein noch größeres
Problem fest:
”Objektorientierte Programmierung und objektorientierte Modellierung haben sich zum Ziel gesetzt, die modulare Strukturierung eines Systems mittels Klassen und Objekten zu unterstützen und somit die Verständlichkeit
und die Wartbarkeit zu erhöhen. Mittlerweile ist es jedoch allgemein anerkannt, dass OO hinter diesen Zielen zurück geblieben ist. In der Praxis sind
objektorientierte Entwurfsmodelle groß und monolithisch, weil die vorhandenen Sprachmittel in objektorientierten Modellierungssprachen wie Interfaces,
Klassen und Pakete den Entwickler dazu zwingen, Entwurfsentscheidungen
zu treffen, die nachteilige Konsequenzen haben. [...] Entwürfe sind selten
wiederverwendbar und schwer zu warten. Ein noch größeres Manko stellt in
größeren Projekten die Schwierigkeit dar, mit mehreren Entwicklern parallel
am Entwurf zu arbeiten, da die Verantwortung nicht entsprechend den Anforderungen für isolierte Entwurfsteile vergeben werden kann. Als Konsequenz
dieser Beobachtungen wurden in den letzten Jahren einige Anstrengungen
unternommen, sowohl den Entwurf als auch den Code hinsichtlich verschiedener Anforderungen zu trennen (Separation of Concerns).” [Depke, 2001]
2
Einführung
Ziel der Arbeit
Wenn die Verantwortungen entsprechend den Anforderungen für Entwurfsteile einer Webanwendungen vergeben werden können, können Entwicklungsteams optimal eingeteilt werden. So schreibt Husted:
”Die meisten Projektmanager bevorzugen die Aufteilung von Entwicklerteams in spezialisierte Gruppen. Sie wünschen, dass HTML Designer an
der Darstellung arbeiten, während Java Entwickler die Geschäftslogik programmieren. [...] Die heutigen Webanwendungen sind kritische Komponenten
für die Umsetzung von unternehmerischen Zielen. Wie immer müssen Entwicklerteams Anwendungen in Rekordzeiten entwickeln, die Anwendungen
müssen aber stabil und langlebig sein.” [Husted, 2003]
1.2
Ziel der Arbeit
Das Ziel der Arbeit ist es, eine Multi-Tier Architektur für Webanwendungen
in Java vorzustellen, welche aus isolierten Entwurfsteilen besteht, Schichten
oder Tiers genannt, um den Entwurf und den Programmcode hinsichtlich
verschiedener Anforderungen zu trennen (Separation of Concerns).
Die Architektur und die verwendeten Technologien sollen gleichzeitig für den
Einsatz als zentrale Anwendung für das Server-Based-Computing zur Abbildung von geschäftskritischer Geschäftslogik geeignet, und somit skalierbar,
ausfallsicher und in die Datenverarbeitungslandschaft eines Unternehmens
integrierbar sein. Die theoretischen Grundlagen für die Entwicklung einer
derartigen Webanwendungen werden im ersten Teil der Arbeit besprochen.
Der zweite Teil der Arbeit besteht aus einem Implementationsbeispiel, dass
die Leichtigkeit und Zügigkeit der Entwicklung demonstrieren soll. Möglichkeiten der Generierung von Programmcode und der ausgiebige Einsatz von
bestehender Software (Middleware und Frameworks), die eine zügige und
einfache Entwicklung ermöglichen, aber auch einen grundlegenden und erprobten Entwurf für eine Webanwendung vorgeben, werden vorgestellt und
eingesetzt.
3
Teil I
Grundlagen
4
Webanwendungen
Basistechnologien
Kapitel 2
Webanwendungen
2.1
2.1.1
Basistechnologien
Webserver
Eine Definition für den Begriff Webserver lautet :
”Ein Rechner, der unter einer eindeutigen Domain- beziehungsweise IP-Adresse
die Webseiten eines Anbieters zum Abruf über das Internet bereithält. Eine
Software, die über Internetprotokolle mit Clients und anderen Servern kommunizieren kann.” [Zschau, 2002]
Eine andere Definition lautet :
”Ein Rechner im Internet, von dem HTML-Dokumente und Grafiken abgerufen werden können. Als Webserver wird manchmal auch die Software bezeichnet, die auf diesem Rechner die Aufgabe übernimmt, die angeforderten
Dokumente an die Benutzer zu übertragen.” [Hoffmann, 2000]
2.1.2
Hypertext Transfer Protocol
Das Hypertext Transfer Protocol (HTTP) definiert, wie Daten zwischen einem Webclient und einer Anwendung auf einem Webserver übertragen und
dekodiert werden. Ein Webclient sendet über HTTP eine Anfrage (Request)
an einen Webserver und dieser sendet eine entsprechende Antwort (Response)
an den Webclient zurück (vgl. [W3C-HTTP, 2004]). HTTP zeichnet sich in
besonderer Weise darin aus, dass es zustandslos ist. Dem Webserver ist weder
die Identität des Webclients bekannt, noch ist ihm bekannt, ob überhaupt
weiterhin eine Verbindung zum Webclient nach einem Response besteht. Diese Eigenschaft ermöglicht es, dass viele Requests in kürzester Zeit verarbeitet
werden können, hat aber zur Folge, dass persistente Verbindungen zwischen
Webclient und Webserver, die eine eindeutige Identifikation erfordern, nur
mit Hilfe von Cookies oder URL Rewritings machbar sind. Beide Verfah5
Webanwendungen
Webanwendungen
ren generieren eine Identifikationsnummer, welche bei dem ersten Request
generiert und an einen Webclient ”geheftet” wird. Ein Response liefert immer statischen Inhalt an den Webclient. Der Inhalt besteht aus Text, der
üblicherweise mit HTML (vgl. [W3C-HTML, 2004]) formatiert ist, welcher
vom Webclient mehr oder weniger standardisiert dargestellt werden kann.
Dynamischer Inhalt wird auf dem Webserver generiert und als statischer Inhalt versendet (vgl. [Husted, 2003]), so dass sämtliche Aufgaben auf dem
Webserver durchgeführt werden. Lediglich die Darstellung wird dem Webclient überlassen. Die Eigenschaften des HTTP beeinflussen die Entwicklung
und den Entwurf von Anwendungen für das Internet in dem Maße, dass sich
deren Aufbau grundlegend vom Aufbau traditioneller Anwendungen unterscheidet (vgl. [Ford, 2004]).
2.2
2.2.1
Webanwendungen
Definition von Webanwendungen
Für den Begriff Webanwendung (engl. web application) existieren Definitionen, die jedoch je nach Sichtweise variieren:
”The Web has evolved from a network-based hypermedia distributed information system offering static information to a marketplace for selling and
buying goods and services. Sophisticated web applications are required to
enable this marketplace.” [Mahmoud, 2002]
”The fundamental purpose of all web applications is to facilitate the completion of one or more tasks. [...] The point remains, however, that if a web
property establishes a one-to-one relationship with its users and allows those
users to edit, manipulate, and permanently store data, then it possess certain capabilities and complexities that distinguish it from traditional contentcentric websites.” [Baxley, 2004]
”A web application is a dynamic extension of a Webserver.” [Bodoff, 2004]
Webanwendungen unterscheiden sich klar von Webseiten darin, dass sie dem
Benutzer spezifische Funktionen außerhalb der reinen Darstellung von Information anbieten. Sammlung, Aufbereitung und Haltung von Daten gehören
genauso dazu wie die Interaktion mit dem Benutzer, welche die Benutzung
der Webanwendung ermöglicht und erleichtern soll. Wichtig ist weiterhin
die Darstellung von Information, jedoch mit Möglichkeiten der Reduzierung
durch individuelle Auswahl des Benutzers und einer vielfältigeren dynamischen Darstellung. Häufig werden mit Hilfe von Webanwendungen Geschäftsvorgänge zwischen Unternehmen (B2B) oder vom Unternehmen zum End-
6
Webanwendungen
Webanwendungen
kunden (B2C) abgebildet.
Für Webanwendungen existieren bereits vielfältige Einsätze. So können Mitarbeiter eines Einzelhändlers Waren über eine Webanwendung bestellen und
über eine eigene Webanwendung an Ihre Kunden weiterverkaufen. Mit Hilfe
von drei Funktionen, wie etwa einem Katalog, einem Warenkorb und einem
Abrechnungssystem (Kasse), könnte ein Bestellvorgang abgebildet werden.
Ein Bestellvorgang wäre ein Beispiel für einen Geschäftsprozess (business
process). Mit Geschäftsprozessen bezeichnet man generell Vorgänge innerhalb einer Webanwendung, die Einstiegs- und Endpunkte haben, eine oder
mehrere Funktionen ausführen und zu einem gewünschten Resultat führen
können. Eine Webanwendung könnte als ein unterstützendes System für den
Berater einer Bank eingesetzt werden, um ihn bei verschiedenen Aufgaben
während einer Beratung des Kunden behilflich zu sein. So könnte ein Prozess dem Berater dabei helfen, für den Kunden ein Girokonto anzulegen, ein
anderer würde ihm Fragen zu einer Baufinanzierung vorschlagen, die er gemeinsam mit dem Kunden beantwortet. Als Resultat würde eine individuell
auf den Kunden zugeschnittene Broschüre, beispielsweise als ausdruckbares
PDF, anhand der Antworten zusammengestellt werden.
Webanwendungen sind dynamische Erweiterungen von Webservern (vgl. [Bodoff, 2004]). Sie erweitern den Funktionsumfang eines Webservers, der nur
Information darstellen kann. Unter Webservererweiterungen versteht man allerdings aus einer technischeren Perspektive Sprachen, Umgebungen, Modelle
und Mechanismen, die es überhaupt erst ermöglichen, Webanwendungen zu
entwickeln. Die bekanntesten Webservererweiterungen sind CGI, Serlvets und
Server Pages, wie JavaServer Pages (JSP), Active Server Pages (ASP) und
PHP (vgl. [Husted, 2003]). Webservererweiterungen werden im Kapitel 2.3
vorgestellt.
2.2.2
Abgrenzung zu Webdiensten
”Unter Webdiensten versteht man Dienste, die eine Anwendung einer anderen Anwendung über das World Wide Web anbietet. Clients dieser Dienste
können diese zusammensetzen und eine Anwendung für Endbenutzer bilden,
um Geschäftsprozesse abzubilden, oder neue Webdienste anzubieten.” [Bodoff, 2004]
In einem typischen Szenario für Webdienste sendet eine Unternehmensanwendung einen Request an einen Dienst, welcher über eine URL mit HTTP
angesprochen wird und das SOAP Protokoll verwendet. Der Dienst empfängt
den Request, verarbeitet ihn und sendet einen Response zurück. Ein Beispiel für einen Webdienst ist eine Anwendung für Aktienkurse, bei der der
Request nach dem aktuellen Kurs einer Aktie fragt und der Response aus
einem aktuellen Aktienkurs besteht. Dabei handelt es sich um die einfachs7
Webanwendungen
Webservererweiterungen
te Form eines Webdienstes, denn der Response kann unmittelbar gesendet
werden. Ein anderes Beispiel für einen Dienst ist die Berechnung einer effizienten Route für die Lieferung von Waren. In diesem Fall wird ein Request
mit gewünschten Zielen an einen Dienst gesendet, der die kostengünstigste
Route berechnen soll. Die Zeit, die der Dienst benötigt um den Response
zu liefern, hängt möglicherweise von der Komplexität der Streckenführung
ab, so dass der Response wahrscheinlich nicht unmittelbar gesendet werden
kann. Anbieter und Konsument von Webdiensten ist typischerweise ein Unternehmen, welches Webdienste überwiegend für Business-to-Business (B2B)
Transaktionen nutzt. Ein Unternehmen kann ein Anbieter von Webdiensten
und gleichzeitig ein Konsument von anderen Webdiensten sein. Webdienste
bieten im Gegensatz zu Webanwendungen keine Interaktionsmöglichkeiten
für einen Benutzer. Die Systeme arbeiten autonom und indirekt. (vgl. [Bodoff, 2004])
2.3
Webservererweiterungen
2.3.1
Common Gateway Interface
Das Common Gateway Interface (CGI), das, wie der Webserver selbst, vom
U.S. National Centre for Supercomputing Applications (NCSA) entwickelt
wurde, ist ein Standard für den Zugriff von Webservern auf andere Anwendungen, die sich auf demselben Rechner befinden. Mit CGI ist die Generierung von dynamischen Inhalt ermöglicht worden, der anschließend an
einen Webclient gesendet wird. Ein CGI Skript definiert den Programmablauf
und kann in gängigen Computersprachen geschrieben sein. Es kann Funktionen des Betriebssystems, darunter Umgebungsvariablen, Standard Input und
Standard Output, verwenden. Allerdings sind komplexere Programmfunktionen häufig sehr aufwendig in der Implementation. Die Performance eines CGI
Programms ist niedrig und die direkte Anbindung an das Betriebssystem
stellt ein hohes Risiko für Angriffe von Außerhalb dar. Die Performanceprobleme ergeben sich hauptsächlich durch das Fehlen von Nebenläufigkeit. (vgl.
[NCSA, 2004])
2.3.2
Webserver APIs
Webanwendungen können auch mit Hilfe von Webserver APIs entwickelt werden. Dazu wird zunächst ein ladbares Modul programmiert (eine DLL unter
Windows, ein Shared Object in Unix). Der Webserver lädt dieses Modul und
führt es bei einem Request aus. Über eine Konfigurationsdatei wird innerhalb
der Webservers festgelegt, welche Module geladen werden und welcher Request von welchem Modul verarbeitet wird. Die Module werden üblicherweise in C oder C++ geschrieben. Bekannte Webserver APIs sind das Netscape
Server Application Programming Interface (NSAPI) für den Netscape Enterprise Server oder das Internet Information Server Application Programming
8
Webanwendungen
Webservererweiterungen
Interface (ISAPI) von Microsoft.
Die Ausführungsgeschwindigkeit von Webserver API Modulen ist für einfache
Webanwendungen unübertroffen schnell, da ein Aufruf eines Moduls einem
Funktionsaufruf des Betriebssystems gleicht. Anders als bei einem CGI findet
der Aufruf innerhalb eines Prozesses statt (Nebenläufigkeit), welcher bereits
läuft (der Prozess des Webservers). Zustände können gespeichert werden und
der Entwickler ist in der Lage, redundante Verarbeitungen zu vermeiden. (vgl.
[Shachor, 2001])
Webserver APIs haben sich dennoch nicht durchsetzen können. Die Gründe
dafür sind (vgl. [Shachor, 2001]) :
1. Jeder Server besitzt ein eigenes API und somit existiert kein Standard,
der einmal erlernt und auf verschiedenen System verwendet werden
kann.
2. Die Erweiterungen müssen in einer Low-Level Sprache wie C oder C++
geschrieben werden, was eine Entwicklung nur mit High-Level Kenntnissen ermöglicht.
3. Fehler in den Erweiterungen können den gesamten Webserver zum Absturz bringen. Daher ist ein enormer Aufwand für Tests notwendig.
2.3.3
Server Pages und Servlets
Eine Alternative zu Webserver APIs und CGIs sind Server Pages. Die bekanntesten Server Pages sind Microsoft Active Server Pages (ASP), JavaServer
Pages (JSP) von Sun Microsystems Inc. und eine Open Source Variante mit
dem Namen PHP. Server Pages erreichen nicht die Performance von Webserver APIs, doch übertreffen sie bei weitem die des CGI (vgl. [Husted, 2003]).
Bei Requests müssen nicht immerwährend neue Prozesse initialisiert werden. Da jedoch bei jedem Request die Skripte interpretiert werden müssen,
sind Server Pages Lösungen in der Regel zwar performanter als auf CGIbasierende Lösungen, aber im Nachteil gegenüber denen, die Webserver APIs
verwenden. Dies wird in Kauf genommen, denn das vorrangige Ziel von Server
Pages ist die Steigerung der Produktivität (vgl. [Husted, 2003]). Sie erfordern
zum einen nicht zwingend High-Level Kenntnisse über eine höhere Sprache,
zum anderen wird die Entwicklung dadurch vereinfacht, dass Programmlogik in Dateien mit Markup, meist HTML, eingefügt werden kann, was aus
der Sicht vieler Entwickler von traditionellen Webseiten als eine natürlichere
Vorgehensweise empfunden wird. Weiter wird die Entwicklung dadurch vereinfacht, dass, neben der grundlegenden Syntax für das Skripting von Programmlogik, Objekte für den Zugriff auf Datenbanken oder das Versenden
von E-Mails angeboten werden. Die Programmlogik kann, abhängig von der
eingesetzten Server Pages Technologie, in Sprachen wie Java, Perl, VBScript
9
Webanwendungen
Webservererweiterungen
und JavaScript geschrieben sein. Zur Laufzeit interpretiert der Webserver
diese Skripte, fügt die Resultate in den Darstellungscode ein und sendet das
Ergebnis an den Webclient. Ein ASP Beispiel zeigt die Kombination von
HTML und VBScript:
<% @Language = "VBScript" %>
<HTML>
<BODY>
<% If Request.ServerVariables("SERVER_NAME") = "localhost" then %>
Sie haben den Server auf Ihrem Rechner angefragt.
<% else %>
Sie haben den Server <%= Request.ServerVariables("SERVER_NAME")
angefragt %>
<% end if %>
</BODY>
</HTML>
Programme auf dem Webserver, die Java Server Pages zur Laufzeit ausführen,
werden Web Container genannt. Eine frühere Webservererweiterung von Sun
Microsystems sind Java Servlets. Servlets sind Klassen in Java, die alle von
der Klasse javax.servlet.GenericServlet aus dem Servlet API abgeleitet
werden müssen. Dem Entwickler stehen auf diese Weise vordefinierte Methoden zur Implementation einer Requestverarbeitung mit zwei zentralen Objekten zur Verfügung: request und response. Mit diesen Objekten können alle
Informationen des Requests abgefragt und dazu der entsprechende Response programmiert werden. Dabei wird der Markup zur Darstellung innerhalb
der Programmlogik ausgegeben. Diese Vorgehensweise erinnert an die Entwicklung mit CGI oder Webserver APIs. Die hinter den Java Server Pages
stehende Technologie sind Java Servlets. Eine JavaServer Page wird bei einem Request zunächst von einem Web Container in ein Servlet umgewandelt,
welches anschließend kompiliert und ausgeführt wird. (vgl. [Sun-JSP, 2004]).
2.3.4
Probleme von Webservererweiterungen
In dem Buch ”JSP Tag Libraries” geht Shachor auf die grundsätzlichen Probleme von Webservererweiterungen ein :
”Eine der größten Herausforderungen bei der Entwicklung von Webanwendungen ist die saubere Trennung von Darstellung und Geschäftslogik. Alle
bekannten Webservererweiterungen, sei es CGI, Webserver APIs, Servlets
oder Server Pages unterstützen von Haus aus keine Trennung. ” [Shachor,
2001]
Webanwendungen lassen sich zunächst in zwei Schichten mit unterschiedlichen Aufgaben und Anforderungen aufteilen :
10
Webanwendungen
Webservererweiterungen
1. Geschäftslogik-Schicht - Der Bereich einer Webanwendung, welcher geschäftsbezogene Erfordernisse löst, beispielsweise eine Überweisung eines Betrages auf ein Konto oder das Anlegen eines neuen Kunden. Diese
Schicht erfordert Programmcode einer höheren Sprache und fällt somit in den Aufgabenbereich eines Programmierers.
2. Darstellungsschicht - Resultate aus der Ausführung der Geschäftslogik
werden entgegengenommen und für den Benutzer dargestellt. Die Darstellung erfordert dafür vorgesehene Technologien und Entwickler (Graphikdesigner und HTML Programmierer), die diese einsetzen können.
Eine Interaktion zwischen Geschäftslogik und Darstellung ist notwendig, da
die Resultate der Geschäftslogik dargestellt werden müssen. Ein Extrem für
die Interaktion ist die eng gekoppelte Implementation der Darstellung wie
auch der Geschäftslogik in denselben Dateien, ohne eine Trennung. Das andere Extrem ist die Implementation der Darstellung innerhalb eines separaten
Anwendungsbestandteils (Modul), gänzlich unabhängig vom Modul mit der
Geschäftslogik, mit Ausnahme von wohldefinierten Kommunikationsschnittstellen. Dieser Aufbau trennt die Darstellung von der Geschäftslogik. Wieso
diese Trennung entscheidend wichtig ist, erklärt Shachor :
”In vielen Fällen sind die Entwickler der Darstellung und die der Geschäftslogik verschiedene Personen mit unterschiedlichen Kenntnissen oder Kenntnisschwerpunkten. Üblicherweise sind die Entwickler der Darstellung HTML
Programmierer oder Graphikdesigner, die nicht notwendigerweise ausreichend
qualifizierte Programmierer sind. Ihre Hauptaufgabe besteht darin, gute Navigationen und attraktive Webseiten zu entwickeln. Die Hauptaufgabe der
Programmierer der Geschäftslogik ist, eine stabile und skalierbare Anwendung zu programmieren, die die Darstellungsschicht mit Daten versorgt. Diese beiden Gruppen von Entwicklern unterscheiden sich bei den Tools, die sie
einsetzen, ihrem Training, ihrem Wissen und ihrer Erfahrung. Die Aufgabe,
eine Benutzeroberfläche einer Webanwendung zu verändern, gestaltet sich
äußert schwierig, wenn sie aus Programmcode besteht, der die Darstellung
von der Geschäftslogik nicht trennt.” [Shachor, 2001]
Abhängig von der gestellten Aufgabe können CGI oder Server Pages Dateien aus mehreren hundert oder tausend Zeilen HTML, CSS, JavaScript, Java
und SQL Code bestehen.
”Keine Trennung impliziert Herausforderungen bei der Pflege, da Programmierkenntnisse in höheren Sprachen als auch Kenntnisse für Darstellungstechnologien erforderlich sind. Auf jede Veränderung an der Darstellung folgt
eine Überprüfung, ob die Skripte mit Programmcode nicht beschädigt worden sind. Diese Überprüfung ist notwendig, weil die Darstellung mit Skripten
überhäuft ist, die nur der Programmierer der Geschäftslogik versteht. Dies
zwingt den Entwickler der Darstellung aus Sorge, dass keine Geschäftslogik
11
Webanwendungen
Webservererweiterungen
in Mitleidenschaft gezogen wird, sich wie auf Eierschalen durch den Code zu
bewegen. Dieses Arrangement verursacht häufig, dass beide Entwickler ein
und dieselbe Datei ändern müssen, und somit mit der mühsamen Aufgabe
konfrontiert sind, Besitzrechte für Dateien zu verwalten. Dieses Szenario kann
die Entwicklung und die Pflege von Webanwendungen zu einem kostenintensiven Unterfangen werden lassen und die Vorteile, die eine Entwicklung von
Webanwendungen mit Server Pages hinsichtlich der Produktivitätssteigerung
mit sich bringt, werden dadurch erheblich vermindert.” [Shachor, 2001]
Die Trennung von Code für die Darstellung vom Programmcode in einer
höheren Sprache ist ein erster Schritt zur Trennung von Entwurfsteilen einer Anwendung hinsichtlich verschiedener Anforderungen. Die Bezeichnung
sämtlichen Programmcodes innerhalb einer Webanwendung, der nicht der
Darstellung dient, als Geschäftslogik der Anwendung, wie sie Shachor vornimmt, ist relativ grob. So spricht Cavaness in dem Buch ”Programming
Jakarta Struts” von ”Real Business Logic” und meint damit Programmcode, der nur direkte geschäftsbezogene Operationen implementiert, wie etwa die Berechnung eines Brutto Preises oder die Generierung einer Kontonummer. So sind etwa die darstellungsunterstützende Programmlogik, die
Überprüfung von Benutzereingaben (Validierung) und die dauerhafte (permanente) Speicherung von Daten in Datenbanken (Persistenzlogik), nicht
Bestandteil der Geschäftslogik (vgl. ([Cavaness, 2002])). Die von Shachor
bemängelte Übersichtlichkeit bei JavaServer Pages und anderen Webservererweiterungen findet ihre Fortsetzung innerhalb des Programmcodes, wenn
Validierung, Persistenzlogik, Geschäftslogik und andere mögliche Bestandteile nicht getrennt werden. Der Entwurf einer Multi-Tier Webanwendung, bei
der der gesamte Programmcode hinsichtlich verschiedener Anforderungen geteilt ist, wird durch Webservererweiterungen nicht unmittelbar unterstützt.
Somit ist deren Einsatz für aufwendige und umfangreiche Projekte mit mehreren Entwicklern problematisch.
12
Model 2 - die Lösung?
Eine einfache Architektur
Kapitel 3
Model 2 - die Lösung?
3.1
Eine einfache Architektur
Die einfachste Architektur einer Webanwendung mit JavaServer Pages besteht aus JSP Dateien, welche gleichzeitig für die Verarbeitung der Requests
als auch für die Darstellung der Responses verantwortlich sind. Bei der Verarbeitung eines Requests werden in der Regel Daten manipuliert, die sich
entweder persistent in einem permanenten Speicher oder in einem nichtpersistenten Objekt befinden. Diese Vorgehensweise ist auch bei anderen
Server Pages üblich. Bei der Entwicklung in Java werden für die nichtpersistenten Objekte JavaBeans eingesetzt. Abbildung 3.1 zeigt den grundlegenden Aufbau dieser Architektur :
Abbildung 3.1: Model 1 Architekturen
JavaBeans und Enterprise JavaBeans haben kaum Gemeinsamkeiten. Enterprise JavaBeans werden im folgenden Kapitel behandelt. Roman erklärt was
JavaBeans sind:
13
Model 2 - die Lösung?
Eine einfache Architektur
”JavaBeans are completely different from Enterprise JavaBeans. In a nutshell, JavaBeans are Java classes that have get/set methods on them. They
are reusable Java components with properties, events, and methods (similar
to Microsoft’s ActiveX controls) that can be easily wired together to create
(often visual) Java applications. JavaBeans are much smaller than Enterprise JavaBeans. You can use JavaBeans to assemble larger components or to
build entire applications. JavaBeans, however, are development components
and are not deployable components. You typically do not deploy a JavaBean;
rather, JavaBeans help you construct larger software that is deployable. And
because they cannot be deployed, JavaBeans do not need to live in a runtime environment. Since JavaBeans are just Java classes, they do not need an
application server to instantiate them, to destroy them, and to provide other
services to them. The application itself is made up of JavaBeans.” [Roman,
1999]
Für die persistenten Daten werden Datenbanken eingesetzt, die über Hilfsklassen und dem JDBC API (vgl. [Sun-JDBC, 2004]) erzeugt, gelesen, verändert
und gelöscht werden. Diese einfache Architektur wird in der Literatur häufig
Model 1 Architektur genannt :
”The literature on Web-tier technology in the J2EE platform frequently uses
the terms ”Model 1” and ”Model 2” without explanation. This terminology
stems from early drafts of the JSP specification, which described two basic
usage patterns for JSP pages. While the terms have disappeared from the
specification document, they remain in common use. Model 1 and Model 2
simply refer to the absence or presence (respectively) of a controller servlet
that dispatches requests from the client tier and selects views.” [Sun-DEA,
2004]
Eine Model 1 Webanwendung besteht aus mehreren JSP Dateien, JavaBeans
und Hilfsklassen, die zur Ausführung in die Umgebung eines Web Containers
kopiert werden. Dieser Vorgang wird Deployment genannt.
”A JSP container is a system-level entity that provides life-cycle management and runtime support for JSP pages and servlet components. Requests
sent to a JSP page are delivered by the JSP container to the appropriate
JSP page implementation object. The term web container is synonymous
with JSP container. A web component is either a servlet or a JSP page. The
servlet element in a web.xml deployment descriptor is used to describe both
types of web components. JSP page components are defined implicitly in the
deployment descriptor through the use of an implicit .jsp extension mapping,
or explicitly through the use of a jsp-group element.” [Roth, 2003]
Für komplexere Anwendungen eignet sich Model 1 nicht. Die unüberlegte
Anwendung dieser Architektur führt zu einer enormen Anzahl von unüber14
Model 2 - die Lösung?
MVC Entwurfsmuster
sichtlichen Skriplets und Java Code innerhalb der JSP Seiten (vgl. [Seshadri,
1999]). Diese Architektur ist üblich bei Webanwendungen und funktioniert
ausreichend gut, solange die Anforderungen nicht die Möglichkeiten eines
Web Containers überschreiten.
Cavaness schreibt über das Design von Web Containern :
”Die Prioritäten beim Design eines Web Containers sind für die Bereiche
der Sicherkeit, Skalierbarkeit und Transaktionen nicht hoch gesetzt, wie es
bei anderen Typen von Containern der Fall ist, ... wie etwa bei Application
Servern” [Cavaness, 2002]
3.2
3.2.1
Model View Controler Entwurfsmuster
Definition von Entwurfsmustern
”Ein Entwurfsmuster (design pattern) beschreibt abstrakt eine Lösung eines
bestimmten Problems in der Informatik, welches häufig in verschiedenster
Form auftritt, aber dem Lösungsmuster des Entwurfsmusters folgend, gelöst
werden kann. Model View Controller (MVC) ist ein Entwurfsmuster für die
Darstellung von Benutzeroberflächen und die Verarbeitung der Benutzereingaben.” [Go4, 1994]
Die Darstellung von Benutzeroberflächen und die Verarbeitung der Benutzereingaben sind zentrale Aufgaben jeder Webanwendung. Die folgende Beschreibung des Model View Controler Entwurfsmusters zeigt grundlegende
Überlegungen, um eine geeignete Lösung für die Trennung von Darstellung
und Logik zu finden.
3.2.2
Model View Controler
MVC ist von Glenn E. Krasner und Stephen T. Pope im Jahre 1988 für
Smalltalk-80 Benutzeroberflächen entwickelt worden. Im Buch ”Design Patterns - Elements of Reusable Object-Oriented Software” von Gamma, Helm,
Johnson, Vlissides - bekannt unter dem Synonym ”Gang of Four”, wird MVC
wie folgt beschrieben:
”MVC besteht aus drei Objekttypen: Das Model Objekt ist das Anwendungsobjekt, der View die Bildschirmdarstellung, und der Controller definiert die
Reaktion der Benutzeroberfläche auf die Aktionen des Benutzers. Vor MVC
tendierten Entwurfsmuster von Benutzeroberflächen dazu, die Aufgaben dieser Objekte nicht klar zu trennen. Das Ziel von MVC ist Flexibilität und
Wiederverwendbarkeit.” [Go4, 1994]
15
Model 2 - die Lösung?
MVC Entwurfsmuster
Ein Anwendungobjekt (application object) ist ein Objekt mit Zuständen,
welches optional Funktionen bietet.
”MVC entkoppelt Views und Models indem es ein Anmelden/Benachtigigen
Protokoll (subscribe/notify protocol) zwischen diesen Objekttypen errichtet.
Ein View muss sicherstellen, dass seine Anzeige den Zustand des Models wiedergibt. Immer wenn sich die Daten des Models ändern, benachrichtigt das
Model die von ihm abhängigen Views. Im Gegenzug bekommt jedes View die
Möglichkeit sich auf den aktuellen Stand zu aktualisieren. Diese Verbindung
ermöglicht es, mehrere Views an ein Model zu binden, um unterschiedliche
Darstellungen der Daten anzuzeigen. Es ist auch möglich, neue Views für ein
Model zu entwickeln, ohne dass das Model verändert werden müßte.” [Go4,
1994]
Abbildung 3.2 zeigt ein Model und drei Views (der Controller wurde zur Vereinfachung weggelassen). Das Model enthält einige Daten, die Views stellen
diese Daten dar. Die Views sind eine Tabelle, ein Balken- und ein Kreisdiagramm, und zeigen diese Daten in unterschiedlicher Art und Weise an. Das
Model kommuniziert mit seinen Views, sobald seine Werte sich ändern, und
die Views kommunizieren mit dem Model, um auf dessen Daten zuzugreifen.
Abbildung 3.2: Model und Views
”Im Grunde genommen zeigt dieses Beispiel einen Entwurf, der Views vom
Model entkoppelt. Aber das Design enthält ein Entwurfsmuster für ein generelleres Problem: Die Entkoppelung von Objekten in der Form, dass Änderungen an einem Objekt eine beliebige Anzahl anderer Objekte beeinflussen,
ohne die Notwendigkeit, dass das veränderte Objekt irgendwelche Details der
16
Model 2 - die Lösung?
MVC Entwurfsmuster
anderen Objekte kennt. Die Lösung für dieses Problem wird durch das Entwurfsmuster Observer beschrieben. Eine andere Eigenschaft von MVC ist,
dass Views eingenistet werden können. Zum Beispiel kann eine Reiterleiste
(control panel) mit Buttons als ein komplexes View implementiert werden,
welches eingenistete Button-Views als Komponenten enthält. [...] MVC bietet
eingenistete Views mit Hilfe einer CompositeView Klasse, eine Unterklasse
von View. CompositeView Objekte verhalten sich wie View Objekte; ein
CompositeView kann auf die gleiche Weise wie ein View gehandhabt werden,
nur dass er eingenistete Views beinhaltet und verwaltet. MVC läßt nicht nur
zu, dass CompositeView genauso gehandhabt werden kann wie seine Komponeten, sondern enthält ein weiteres Entwurfsmuster für ein generelleres
Problem, welches immer dann auftritt, wenn Objekte gruppiert werden und
diese Gruppe wie ein einzelnes Objekt behandelt wird. Dieses generellere
Design wird durch das Entwurfsmuster Composite beschrieben. Es läßt die
Erstellung einer Klassenhierarchie zu, in der einige Unterklassen primitive
Objekte (z.B.: Buttons) definieren, und anderen Klassen Composite Objekte
(CompositeView) definieren, welche aus den primitiven komplexere Objekte
bilden. MVC läßt auch zu, die Art und Weise zu verändern, wie ein View
auf Benutzereingaben reagiert, ohne seine visuelle Präsentation zu ändern.
So könnte zum Beispiel die Art und Weise verändert werden, wie ein View
auf die Tastatur reagiert, oder dass ein Pop-up Menü verwendet wird anstatt
Kommandotasten. MVC kapselt den Reaktionsmechanismus in ein Controller Objekt. Es existiert eine Klassenhierarchie der Controller, die es einfach
macht, einen neuen Controller als Variation eines bestehenden zu erzeugen.
Ein View verwendet eine Instanz einer Controller Unterklasse, um eine einzige Reaktionsstrategie zu implementieren; um eine ganz andere Strategie zu
implementieren, muss einfach die Instanz mit einer anderen Art von Controller ersetzt werden. Es ist sogar möglich einen Controller eines Views während
der Laufzeit zu wechseln, um die Art und Weise zu ändern, wie ein View auf
Benutzereingaben reagiert. Zum Beispiel kann ein View deaktiviert werden,
damit er keine Benutzereingaben akzeptiert, indem man ihm einen Controller
zuweist, der Benutzereingaben ignoriert. Die Beziehung zwischen View und
Controller ist ein Beispiel des Strategy Entwurfsmusters. Ein Strategy ist ein
Objekt, welches einen Algorithmus darstellt. Das Objekt ist nützlich für den
Fall, dass man einen Algorithmus entweder statisch oder dynamisch austauschen möchte, oder dass man viele Varianten des Algorithmus hat, oder wenn
dieser Algorithmus komplexe Datenstrukturen hat, die man kapseln möchte.
[...] Die Hauptbeziehungen in MVC sind durch die Entwurfsmuster Observer,
Composite und Strategy gegeben.” [Go4, 1994]
Bei einer HTTP Verbindung zwischen einem Webclient und einer Webanwendung kann eine Kommunikation nur von einem Client ausgehen, indem
von diesem ein Requests an die Webanwendung gesendet wird (vgl. Kapitel
2.1.2). Diese Eigenschaft verhindert die Umsetzung des Observer Entwurfsmusters, welches voraussetzen würde, dass von beiden Seiten eine Kommu17
Model 2 - die Lösung?
Model 2 Architekturen
nikation ausgehen kann, damit der Client automatisch Modifikationen der
Model-Zustände erkennt. Eine Trennung von Darstellung- und Programmcode in Webanwendungen bedeutet unter anderem, dass in den verschiedenen
Schichten nicht dieselbe Programmiersprache eingesetzt wird (vgl. Kapitel
2.3.4). Die Verwendung von HTML und verwandten Technologien für die
Gestaltung von Benutzeroberflächen hat zur Folge, dass in dieser Schicht
keine Programmlogik vorhanden ist, und auch keine Composite Objekte zur
Verfügung stehen. Daher ist die Umsetzung des Composite und Strategy
Entwurfsmusters in Webanwendungen nicht unmittelbar möglich.
3.3
Model 2 Architekturen
In der frühen Veröffentlichung der JavaServer Pages Spezifikation (Version
0.92) hat Sun Microsystems den Begriff Model 2 für eine Architektur von
Webanwendungen eingeführt, die sowohl JavaServer Pages als auch Servlets
einsetzt. Dieser Begriff wurde aus der endgültigen Fassung der Spezifikation
entfernt, wird jedoch in der Literatur und von Entwickler für folgende in
Abbildung 3.3 gezeigte Architektur weiter verwendet:
Abbildung 3.3: Model 2 Architektur
Ein Client sendet keine Requests direkt an eine JavaServer Page sondern
an ein Controller Servlet. Dieses führt eine Vorverarbeitung des Requests
aus, welche verschiedene, für Webanwendungen häufig erforderliche, Aufgaben erfüllen kann:
• Authentifizierung der Verbindung/des Requests
• Autorisierung für bestimmte Bereiche der Webanwendung
• Lokalisierung der Darstellung
18
Model 2 - die Lösung?
Model 2 Architekturen
• Implementation von einem Workflow Regelsystem (Steuerung des Navigationsflusses)
• Validierung der Benutzereingaben
• andere Vorverarbeitungen
Diese Vorverarbeitungen eines Requests vom Controller sind nicht Bestandteil der Geschäftslogik einer Webanwendung. Die Geschäftslogik befindet sich
getrennt davon im Model. Sowohl Model als auch Controller verwenden die
Programmiersprache Java, sind aber isolierte Schichten, die unterschiedliche
Aufgaben erfüllen. Die Darstellung in einer Model 2 Architektur übernehmen die JSP Dateien (Views), welche lediglich aus HTML und XML Tags
bestehen. Sie bilden die dritte isolierte Schicht.
Model 2 setzt ”Separation of Concerns” um. Es teilt eine Webanwendung in
drei Schichten hinsichtlich verschiedener Anforderungen; in Model-, View-,
und Controllerschicht. Die Schichten ermöglichen eine einfachere gleichzeitige
Entwicklung an der Webanwendung durch Entwickler mit unterschiedlichen
Kenntnisschwerpunkten. (vgl. [Husted, 2003])
Die Controller-Schicht besteht aus dem Controller Servlet und einer Vielzahl
von Funktionsklassen, die, je nach Bedarf, einem bestimmten Schema entsprechen können. Eine Funktionsklassen könnte beispielsweise ein Produkt
in einen Warenkorb ablegen, eine andere die Gültigkeit einer Kreditkarte
überprüfen. Das Schema der Funktionsklassen könnte wie folgt aussehen:
Zunächst wird die Benutzereingabe validiert, anschließend wird Geschäftslogik aus der Model-Schicht aufgerufen, und schließlich wird die Kontrolle an
einen View übergeben (Steuerung des Navigationsflusses), der das Ergebnis
des Requests und der ausgeführten Geschäftslogik, den Response, darstellt.
Die Views sollen frei von Java Programmcode sein, müssen aber dynamische Ergebnisse in Form von Objekten, welche vom Controller übergeben
werden, lesen und darstellen. Diese Objekte werden vom Controller in eine
Umgebung, die der Web Container zur Speicherung zur Laufzeit anbietet,
abgelegt. Der Zugriff auf diese Objekte erfolgt innerhalb von Views mit Hilfe von Custom Tag Libraries. Custom Tag Libraries ermöglichen es, dass
Programmierer Funktionalitäten in Klassen kapseln und gleichzeitig HTML
Entwicklern die Möglichkeit geben, über parametrisierte Custom Tags, diese Funktionalitäten aus HTML Seiten aufzurufen. Custom Tags sind XML
Tags und setzen sich aus Elementen und Attributen zusammen, welche strukturierte Informationen beinhalten (vgl. [W3C-XML, 2004]). In diesem Fall
werden die Informationen zur Identifizierung von Objekten, dem Aufrufen
von Methoden der Funktionsklassen und der Übergabe von Parametern an
die Methoden genutzt. Mit Hilfe von Tag Handlern, die der Programmierer ebenfalls programmiert, wird aus den Custom Tags bei der Verarbeitung
19
Model 2 - die Lösung?
Model 2 Architekturen
eines Requests Java Code zum Aufruf der Funktionsklassen generiert. Die
Entwicklung von Custom Tag Libraries wird im Buch ”JSP Tag Libraries”
von Shachor ausführlich beschrieben. (vgl. [Shachor, 2001])
Die Model-Schicht implementiert neben der Geschäftslogik auch die Persistenzlogik zur dauerhaften Speicherung von Daten. Auch hier ist es üblich,
JDBC für die Kommunikation mit einer Datenbank einzusetzen.
Der Entwurf einer Model 2 Webanwendung entscheidet nicht über deren Einsatzmöglichkeiten, sie dient lediglich der Aufteilung in isolierte Schichten
hinsichtlich verschiedener Anforderungen. Zur gleichzeitigen Erfüllung hoher
Anforderungen an die Skalierbarkeit, Ausfallsicherheit und Integrationsfähigkeit einer Webanwendung, müssen weitere Technologien eingesetzt und Model 2 erweitert werden. Auch eine Trennung von Geschäfts- und Persistenzlogik ist wünschenswert, da für beide verschiedene Anforderungen gelten. Die
Persistenzlogik erfordert andere Technologien und anderen Formen der Modellierung (selten objektorientiert). Daher sind auch andere Kenntnisse vom
Entwickler gefordert.
20
Architekturerweiterung
Model 2 Architekturen
Kapitel 4
Architekturerweiterung für
Unternehmensanwendungen
Model 2 schlägt die Verwendung von JavaBeans in der Model-Schicht zur Implementation der Geschäftslogik vor. JavaBeans sind einfachste Java Klassen
und können als Model viele Anforderungen, die Unternehmen an ihre Anwendungen stellen, nicht erfüllen. Daher ist es notwendig die Geschäftslogik
auf eine andere, leistungsfähigere technologische Basis zu stellen. Abbildung
4.1 zeigt die im Kapitel 3 vorgestellte Model 2 Architektur, Abbildung 4.2
eine erweiterte Architektur, die im folgenden Kapitel beschrieben wird :
Abbildung 4.1: Model 2 Architektur
Abbildung 4.2: Model 2 Unternehmensanwendungen
21
Architekturerweiterung
Grundlagen Unternehmensanwendungen
Für die Erweiterung der Model 2 Architektur hinsichtlich derer Einsatzfähigkeit für Unternehmensanwendungen ist eine Vielzahl von Konzepten und
Technologien notwendig, die im Folgenden vorgestellt werden.
4.1
4.1.1
Grundlagen Unternehmensanwendungen
Business Objects
”Business Objects sind logische Objekte, die gekapselt Funktionen und Informationen von DV-Systemen repräsentieren. Ein Business Object ist eine
Abstraktion eines in der realen Geschäftswelt vorkommenden Objekts im Anwendungssystem, dem Informationsobjekt. [...] Die Business Objects sind gehaltvolle Schnittstellenobjekte, die bestehende Anwendungen system- und anwendungsneutral kapseln und notwendige Informationen zur Verfügung stellen.” [Bullinger, 2000]
4.1.2
Verteilte Objekte
Ein verteiltes Objekt (distributed object) kann von einem entfernten System
(remote system) aufgerufen werden. Ein Client, der ein verteiltes Objekt aufruft, kann sich innerhalb desselben Laufzeitprozesses, außerhalb davon auf
demselben Rechner oder irgendwo anders in einem Netzwerk befinden.
Prinzipiell funktionieren Aufrufe von verteilten Objekten wie folgt:
1. Der Client ruft das Client-seitige Proxy Objekt (Vertreterobjekt) auf,
welches die Netzwerkkommunikation maskiert. Der Client muss daher
keine Sockel, Nachrichtenparameter und andere Details kennen und
bearbeiten.
2. Das Client-seitige Proxy Objekt ruft über das Netzwerk ein Serverseitiges Proxy Objekt auf, welches die Netzwerkkommunikation gegenüber dem verteilten Objekt maskiert.
3. Das Server-seitige Proxy Objekt delegiert den Aufruf an das verteilte
Objekt und das verteilte Objekt beginnt mit seiner Arbeit. Nach Beendigung gibt es die Kontrolle wieder zurück an das Server-seitige Proxy
Objekt, dieses gibt sie zurück an das Client-seitige Proxy Objekt und
dieses wiederum an den Client.
Abbildung 4.3 zeigt den Aufruf eines verteilten Objekts:
22
Architekturerweiterung
Grundlagen Unternehmensanwendungen
Abbildung 4.3: Verteilte Objekte
Hervorzuheben ist, dass sowohl das Client-seitige Proxy Objekt als auch das
verteilte Objekt dasselbe Remote Interface implementieren. Das bedeutet,
dass die Signaturen der Methoden des verteilten Objektes vom Client-seitigen
Proxy Objekt gekloned werden. Dadurch glaubt ein Client, der das Clientseitige Proxy Objekt anspricht, dass er direkt das verteilte Objekt aufruft;
in Wirklichkeit ruft er allerdings nur ein leeres Client-seitige Proxy Objekt
auf, dass versteht, wie ein Aufruf über ein Netzwerk weitergegeben wird.
Verteilte Objekte können mit verschiedenen Technologien realisiert werden.
Die bekanntesten sind CORBA von OMG, DCOM von Microsoft und RMIIIOP von Sun Microsystem.
4.1.3
Verzeichnisdienste
”Ein Verzeichnisdienst (directory service) ist eine verbundene Zusammenstellung von Verzeichnisobjekten. Ein Verzeichnisdienst ist ein Dienst der
Operationen zum Erstellen, Hinzufügen, Entfernen und Ändern von Attributen, die mit Objekten assoziiert sind, bietet. Auf diesen Dienst wird über
sein eigenes Interface zugegriffen. Viele Beispiele für Verzeichnisdienste sind
möglich. Der Novell Directory Service (NDS) ist ein Verzeichnisdienst von
23
Architekturerweiterung
Grundlagen Unternehmensanwendungen
Novell, welcher Informationen über Netzwerkdienste, wie Dateien- und Druckdienste, bietet. Network Information Service (NIS) ist ein Verzeichnisdienst
im Solaris Betriebssystem zum Speichern von systembezogenen Informationen über Rechner, Netzwerk, Drucker und Benutzer. Verzeichnisdienste für
Mehrzweckinformationen, wie etwa der SunOne Directory Server, basieren
auf dem Internet-Standard LDAP (Lightweight Directory Access Protocol).”
[Lee, 2004]
Zusätzlich zur Verwendung von Verzeichnisdiensten auf traditionelle Weise,
können Java Anwendungen sie zum Speichern und Abrufen von Java Objekten verwenden. So könnte beispielsweise ein Java Client ein Druckerobjekt
über einen Verzeichnisdienst finden und dem Objekt Daten zum Drucken
senden. Zu diesem Zweck kann das JNDI API verwendet werden :
”Das Java Naming and Directory Interface (JNDI) ist ein API, das Java Anwendungen Namens- und Verzeichnisdienst-Funktionen bietet. Es ist
unabhängig von spezifischen Verzeichnisdiensten. Dadurch kann auf allgemeiner Weise auf eine Vielfalt von Verzeichnissen [...] zugegriffen werden.
Das javax.naming Paket definiert ein Kontextinterface, welches das Kerninterface für das Heraussuchen, Binding/Unbinding, Umbenennen, Erschaffen
und Zerstören von Unterkontexten ist. Die allgemein verwendete Operation
ist lookup(). Dieser Operation wird ein Name übergeben und sie gibt das Objekt zurück, welches an den Namen gebunden ist.” [Lee, 2004]
Ein Objekt eines Druckers mit dem Namen ”Laserdrucker2” könnte wie folgt
abgerufen werden :
Printer printer = (Printer)ctx.lookup("Laserdrucker2");
printer.print(report);
Abbildung 4.4 zeigt den möglichen Aufbau eines Verzeichnisdienstes, welcher
ein Kontextinterface für verschiedene LDAP unterstützende Systeme anbietet :
24
Architekturerweiterung
Grundlagen Unternehmensanwendungen
Abbildung 4.4: JNDI Namespaces
4.1.4
Transaktionen
Unter einer Transaktion versteht man eine Serie von Operationen an permanenten Daten, die nacheinander ausgeführt werden und in einem bestimmten Zusammenhang stehen: Wenn eine Operation aus einer Serie nicht erfolgreich durchgeführt werden konnte, wird keine Operation aus der Serie
durchgeführt (Atomität). Eine Transaktion beginnt mit der ersten Operation (begin). Wenn diese erfolgreich durchgeführt werden konnte, wird die
nächste ausgeführt. Wenn eine Operation nicht erfolgreich durchgeführt wer25
Architekturerweiterung
Grundlagen Unternehmensanwendungen
den konnte, wird die Transaktion abgebrochen (abort. Ein Roll-Back von
Operationen gibt es allerdings nicht. Üblicherweise wird eine Transaktion
realisiert, indem die Operationen auf Kopien von Daten ausgeführt werden. Erst nachdem alle Operationen erfolgreich durchgeführt worden sind,
werden ihre Änderungen permanent gespeichert (commit). Weitere Eigenschaften von Transaktionen sind Konsistenz, Isolation und Dauerhaftigkeit.
Transaktionen stellen sicher, dass manipulierte Daten nach der Beendigung
der Transaktion konsistent sind. Für die Konsistenz müssen Regeln bestehen
wie : ”Eine Person kann kein negatives Alter haben”. Isolation bedeutet, dass mehrere Transaktionen gleichzeitig auf denselben Daten arbeiten,
sie aber nicht voneinander wissen (Nebenläufigkeit). Dieser Eindruck wird
durch Low-Level Synchronisations-Protokolle und Datenkopien erreicht. Isolation wird für folgende Szenarien benötigt (nach Isolationslevel sortiert):
• Dirty Reads: ein anderer Client ließt Daten, die von einem Client
verändert, aber noch nicht dauerhaft gespeichert worden sind (read
uncommited )
• Unrepeatable Reads: Ein Client kann nur dauerhaft gespeicherte Daten
lesen (read committed ) und ließt diese. Bei einem erneuten Lesen bemerkt er, dass die Daten in der Zwischenzeit von einem anderen Client
verändert worden sind.
• Phantom Reads: Ein Client erhält die Garantie, einmal gelesene Daten
bei einem erneuten Einlesen während einer Transaktion in ursprünglicher Form wiederzufinden (repeatable read ), doch bemerkt er, dass die
ihm bekannten Daten zwar identisch sind, aber ein neuer Datensatz von
einem anderen Client angelegt worden ist. Wenn auch dies verhindert
wird, ist der maximale Isolationslevel (serializable) erreicht.
Für den Fall, dass es zu einem Systemausfall bei einem Commit kommt, werden zusätzlich alle Aktionen protokolliert, damit bei der Wiederinbetriebnahme Änderungen rückgängig gemacht werden können. Diese Eigenschaft
wird Dauerhaftigkeit genannt.
4.1.5
Partitionierung von Clustern
Ein Cluster ist ein lockerer Verbund von Servern, die eine vereinheitlichte und
einfache Darstellung ihrer Dienste bieten, und miteinander kommunizieren
können. Ein Cluster dient der Erhöhung der Verfügbarkeit und Zuverlässigkeit eines Systems. Die zwei üblichen Vorgehensweisen bei der Partitionierung
sind die 3-Tier und die 4-Tier Partitionierung (Abbildung 4.5).
26
Architekturerweiterung
Plattform J2EE
Abbildung 4.5: 3-Tier und 4-Tier Architektur
Es gibt viele Argumente, um sich für die eine oder die andere Partitionierung zu entscheiden; die wichtigsten Argumente sind die folgenden drei (vgl.
[Roman, 1999]):
• Statische Daten. Der separate Webserver bei der 4-Tier Partitionierung
kann statische Webseiten schneller liefern.
• Sicherheit. Die 4-Tier Partitionierung erlaubt den Einsatz einer Firewall zwischen Webserver und Application Server
• Erweiterungen. Die 3-Tier Partitionierung läßt sich einfacher um einen
weiteren Server in der Middle-Tier erweitern.
Welche Partitionierung die nützlichere ist, hängt von der Anwendung und
der verwendeten Plattform ab und muss im Einzelfall abgestimmt werden.
4.2
Plattform J2EE
Im Zusammenhang mit der Entwicklung von Anwendungen für Unternehmen werden häufig Technologien wie Java 2 Enterprise Edition (J2EE) oder
27
Architekturerweiterung
Plattform J2EE
auch Microsoft .NET genannt. Beides sind Plattformen für die Entwicklung
und den Betrieb von datenverarbeitenden Systemen (DV-Systeme) in Unternehmen. Im Folgenden werden die Grundlagen für die Entwicklung einer
Geschäftslogik auf der J2EE Plattform besprochen, die im zweiten Teil der
Diplomarbeit als Model Tier zur Anwendung kommen :
”Die Java 2 Plattform - Enterprise Edition ist ein hochentwickeltes Paket
von APIs für Unternehmen, welche das Schreiben von robusten, skalierbaren, Multi-User-fähigen und sicheren Anwendungen ermöglicht. Der Umfang
von J2EE ist riesig und birgt eine Vielzahl von Konzepten.” [Roman, 1999]
Ein grundlegendes Konzept ist das ”Distributed Enterprise Computing”:
”[...] J2EE ermöglicht mehrschichtige Anwendungen [...] J2EE ist grundlegend verteilt und die verschiedenen Teile einer Anwendung können auf verschiedenen Rechnern ausgeführt werden.” [Mahmoud, 2002]
Mit J2EE sind nicht nur verteilte Java Anwendungen möglich. Bestehende
Systeme in einer DV-Landschaft eines Unternehmens können integriert werden, auch wenn diese auf gänzlich anderen Technologien basieren. Ermöglicht
wird dies durch CORBA :
”CORBA ist ein Akronym für Common Object Request Broker Architekture,
eine offene, von Herstellern unabhängige Architektur und Infrastruktur, welche von Computer-Anwendungen verwendet wird, um über ein Netzwerk zusammen zu arbeiten. Mit der Verwendung des standardisierten Protokolls
IIOP kann ein auf CORBA basierendes Programm von irgendeinem Hersteller, auf irgendeinem Computer mit irgendeinem Betriebssystem, in irgendeiner Programmiersprache und irgendeinem Netzwerk mit einem auf CORBA basierenden Program vom selben oder von einem anderen Hersteller, auf
irgendeinem Computer mit irgendeinem Betriebssystem, in irgendeiner Programmiersprache und innerhalb irgendeines Netzwerkes, zusammenarbeiten.”
[OMG-CORBA, 2004]
J2EE unterstützt zwei CORBA-entsprechende und -fähige Technologien: JavaIDL und RMI-IIOP.
”JavaIDL ermöglicht Java Anwendungen, mit jedem CORBA-fähigen DVSystemen zusammen zu arbeiten. RMI-IIOP Technologie kombiniert die einfache Programmierbarkeit des Java Remote Method Invocation APIs (RMI)
mit dem CORBA Internet-ORB-Protokoll (IIOP) für eine einfachere Integrationen von Java Anwendungen mit bestehenden Systemen.” [Sun-J2EE,
2004]
Neben der CORBA Schnittstelle zur Interoperalibität mit anderen techno28
Architekturerweiterung
Plattform J2EE
logiefremden Anwendungen bietet J2EE APIs, welche implementationsunabhängige Abstraktionen von allgemein verwendeten Technologien in DVLandschaften sind. So schreibt Monson-Haefel :
”Das JDBC API bietet ein herstellerunabhängiges Java Interface für den Zugriff auf relationale SQL Datenbanken. Diese Abstraktion war so erfolgreich,
dass es schwierig geworden ist, einen Hersteller von relationalen Datenbanken
zu finden, der kein JDBC unterstützt. Die Auswahl an Java Abstraktionen
für Unternehmenstechnologien sind beträchtlich erweitert worden, indem beispielsweise JNDI (Java Naming and Directory Interface) für die Abstraktion
von Verzeichnisdiensten, JTA (Java Transaction API) als Abstraktion für
den Zugriff auf Transaktionsmanager, JMS (Java Messaging Server) als Abstraktion für den Zugriff auf verschiedene nachrichtenorientierte Middleware
Produkte und mehr entwickelt wurden.” [Monson-Haefel, 2001]
Die zentralen APIs von J2EE (Spezifikation 1.3) sind (vgl. [Shirah, 2003]):
• Enterprise JavaBeans Technologie 2.0 (EJB)
• Java Database Connectivity API 2.0 (JDBC)
• Java Servlet Technologie 2.3 (Servlets)
• JavaServer Pages Technologie 1.2 (JSP)
• Java Message Service 1.0 (JMS)
• Java Naming and Directory Interface 1.2 (JNDI)
• Java Transaction API 1.0 (JTA)
• Java Mail API 1.2 (JavaMail)
• JavaBeans Activation Framework 1.0 (JAF)
• Java API for XML Processing 1.1 (JAXP)
• J2EE Connector Architecture 1.0 (JCA)
• Java Authentication and Authorization Service 1.0 (JAAS)
Abbildung 4.6 zeigt die zentralen Bestandteile der J2EE Plattform (vgl. [SunJ2EE, 2004]):
29
Architekturerweiterung
Laufzeitumgebung und Middleware
Abbildung 4.6: Java 2, Enterprise Edition
J2EE Anwendungen haben eine auf Komponenten basierende Architektur:
”Die J2EE Spezifikation 1.3 (http://java.sun.com/j2ee/) [...] verwendet einen
auf Komponenten basierenden Ansatz, um ein mehrschichtiges, verteiltes und
transaktionales Modell für Unternehmensanwendungen zu ermöglichen.” [Shirah, 2003]
”Die auf Komponenten basierende Architektur von J2EE vereinfacht die Entwicklung von Unternehmensanwendungen, da die Geschäftslogik in wiederverwendbaren Komponenten organisiert ist, und darunterliegende Dienste
von J2EE, in Form eines Containern für jeden Komponenten-Typ, bereitgestellt werden. Ein Container kann als Interface zwischen der Komponente und den Low-Level Funktionalitäten, die die Komponenten unterstützen,
gesehen werden. Daher muss eine Komponente, bevor sie ausgeführt werden kann, als J2EE Dienst konfiguriert sein und in ihrem Container zur
Verfügung stehen.” [Mahmoud, 2002]
Dienste für die wiederverwendbaren Komponenten, den Enterprise JavaBeans, stellen Application Server bereit. Sie sind die Laufzeitumgebung der
Enterprise JavaBeans und bieten für verschiedene Zwecke Middleware an,
die für Low-Level Funktionalitäten genutzt werden kann.
30
Architekturerweiterung
4.3
Laufzeitumgebung und Middleware
Laufzeitumgebung und Middleware
Die Programmierung der Geschäftslogik mit Business Objects ist die zentrale Aufgabe des J2EE Entwicklers. Low-Level Funktionalitäten überläßt
er der Middleware des Application Servers. Es existieren zwei grundsätzliche Arten von Middleware: Explizite Middleware wird vom Entwickler durch
den Einsatz von APIs angesprochen, implizite wird durch Deklaration definiert, wird daher auch deklarative Middleware genannt. Application Servern
bieten zu diesem Zweck XML Konfigurationsdateien an, welche Deployment
Descriptoren genannt werden. Sie bestimmen welche Middleware für ein Business Object eingesetzt wird. Die Einbeziehung von impliziter Middleware in
die Entwicklung einer J2EE Anwendung reduziert in erheblichem Umfang
den Programmieraufwand für leistungsfähige und skalierbare Unternehmensanwendungen, auch im Vergleich zur expliziten Middleware (vgl. [Roman,
1999])
Application Server bieten Middleware für viele Zwecke an (vgl. [Roman,
1999]):
• Interoperabilität. Die Kommunikation zwischen Rechnern innerhalb eines Netzwerks in der Form, dass Operationen auf anderen Rechnern
ausgeführt und Ergebnisse zurück gereicht werden können (siehe CORBA und RMI-IIOP in Kapitel 4.2).
• Back-End Integrationsfähigkeit. Nutzung von Datenbanken und anderen Informationsträgern als Contentlieferanten und zur persistenten
Speicherung von Daten.
• Ausfallsicherheit durch Fail-Over. Übernahme von Aufgaben durch redundante Systeme im Falle eines Ausfalls eines Servers oder Netzwerks
(siehe redundanten Webserver und Application Server in 3-Tier Partitionierung - Kapitel 4.1.5). Nicht persistente Daten werden auf redundanten Rechnern dupliziert, so dass zustandsbehaftete Clientverbindungen unbeeinflußt bleiben.
• Sichere Transaktionen. Möglichkeit der Generierung von Transaktionslogik (Ausführung folgt in diesem Kapitel).
• Softwareupdates zur Laufzeit und saubere Shutdowns. Im laufenden
Betrieb können Updates ausgeführt werden, so dass keine Dienste unterbrochen werden müssen. Wenn dennoch ein Shutdown durchgeführt
wird, wird die Beendigung der laufenden Clientverbindungen automatisch abgewartet.
• Protokollierung und Monitoring. Log Dateien und Tools zur Überwachung und zur Lokalisierung von Fehlern.
31
Architekturerweiterung
Laufzeitumgebung und Middleware
• Multi-Threading. Der Application Server ist in der Lage, eine große
Zahl von Clientverbindungen zeitgleich und performant zu bedienen.
• Lastenverteilung. Übergabe von neuen Anfragen an den am wenigsten
belasteten Server innerhalb einer Cluster Partitionierung (siehe Kapitel
4.1.5)
• Management von Lebenszyklen und Resource Pooling. Automatische,
lastenorientierte Erschaffung, Zerstörung, Passivierung und Aktivierung von Business Objects zur Optimierung der Performance (Ausführung
folgt).
• Möglichkeit zur Nachrichten-basierten Verarbeitung von Anfragen (Ausführung
folgt).
• Datenbankunabhängigkeit, performanceoptimierter Zugriff auf Datenbanken und generierbare Persistenzlogik (Ausführung folgt).
J2EE Application Server können von zahlreichen Herstellern bezogen werden
(vgl. [TSS-Matrix, 2004]):
32
Architekturerweiterung
Laufzeitumgebung und Middleware
Hersteller
Ausführung
Release
EJB
J2EE
Cert
Preis in Dollar
Apple WebObjects
v5.1
Jan 2002
1.1
keine
699 je Server
ATG Dynamo
v6.1
Sep 2003
2.0
1.3
15000 je CPU
BEA Weblogic
Workgroup 8.1
Feb 2003
2.0
1.3
4000
Server 8.1 Advantage
Feb 2003
2.0
1.3
10000
Server 8.1 Premium
Feb 2003
2.0
1.3
17000
Server 8.1 64 bit Preview
Feb 2003
2.0
keine
Freie Evaluation
Borland Enterprise Server
Appserver Edition v5.2
Jan 2003
2.0
1.3
12000 je CPU
Desiderata Enterprise Blazik
v1.2
Mai 2002
1.1
keine
495 je Server, 1995 je
Unternehmen
Fujitsu Siemens Computers BeanTransactions
v3.0
Feb 2003
2.0
keine
siehe Hersteller
Fujitsu Software Corp. Interstage
Web-J v5.0
Jul 2002
2.0
1.3
siehe Hersteller
Standard v5.0
Jul 2003
2.0
1.3
siehe Hersteller
Enterprise v5.0
Jul 2003
2.0
1.3
siehe Hersteller
Enterprise v1.5
Feb 2001
1.1
keine
199
Lite v1.5
Feb 2001
1.1
keine
99
Application Server v5.5 Windows
Application Server v5.5 HPUX, Solaris, AIX
Mai 2003
2.0
1.3
1.2 Mio Yen
Mai 2003
2.0
1.3
1.2 Mio Yen
Enterprise 5.0
Mär 2003
2.0
1.3
25000 je CPU
Websphere v5
Nov 2002
2.0
1.3
8000 je CPU
Websphere Network Deployment v5
Websphere Application Server v5 for z/OS
Nov 2002
2.0
1.3
12000 je CPU
Apr 2003
2.0
1.3
Preis nach Millionen
Service Einheiten
v1.0
Jul 2000
1.1
keine
10000 je Server
J2EE Technology v6.0
Dez 2002
2.0
1.3
1495 je Rechner, 5000
je CPU
Standard v6.0
Dez 2002
2.0
1.3
5000 je Rechner 10000,
je CPU
Enterprise v6.0
Dez 2002
2.0
1.3
10000
je
Rechner,
20000 je CPU
Ironflare Orion
v2.0
Mar 2003
2.0
1.3
1500 Server, frei für
nicht
kommerzielle
Nutzer
JBoss
v3.2
Apr 2003
2.0
keine
Frei / Open Source
LGPL
Macromedia JRun Server
Developer License v4
Mai 2002
2.0
1.3
Frei
Full License v4
Mai 2002
2.0
1.3
899 je CPU
Developer 4.0
Sep 2002
2.0
1.3
495 je Rechner
Professional 4.0
Sep 2002
2.0
1.3
5000 je CPU
Enterprise 4.0
Sep 2002
2.0
1.3
10000 je CPU
ObjectWeb JOnAS
v3.3.1
Okt 2003
2.0
1.3
Frei / Open Source
OpenConnect OC://WebConnect
Enterprise Integration Server
v1.5
Jul 2000
1.1
keine
Frei
HHPN XLiRAD
Hitachi Cosminexus
IBM Websphere
Interactive
EAS
Business
Solutions
IONA Orbix ASP 6.0
Novell exteNd
Tabelle 4.1: Application Server Marktübersicht 1
33
Architekturerweiterung
Laufzeitumgebung und Middleware
Hersteller
Ausführung
Release
EJB
J2EE
Cert
Preis in Dollar
Oracle Application Server 10g (includes Toplink)
Java Edition v9.0.4
Dez 2003
2.0
1.3
5000 je CPU
Standard Edition v9.0.4
Dez 2003
2.0
1.3
10000 je CPU
Enterprise Edition v 9.0.4
Dez 2003
2.0
1.3
20000 je CPU
OC4J Standalone v10.0.3 Developer Preview Release with
J2EE 1.4 Support
Sep 2003
2.1
keine
Frei
Persistence Power Tier for J2EE
v7.0
Aug 2001
1.1
1.2
25000 je CPU
Pramati
Server
Standard Edition v3.5
Aug 2003
2.0
1.3
2500 je CPU
Enterprise Edition v3.5
Aug 2003
2.0
1.3
5000 je CPU
SAP AG Web Application Server
v6.3
Apr 2002
2.0
1.3
Auf Anfrage
Secant ModelMethods
ModelMethods
Server v3.5
Jun 2000
1.1
keine
5500 je Rechner
Sun Microsystems Sun Java System Application Server
Platform Edition 7.0
Okt 2002
2.0
1.3
Frei
Technologies
Pramati
Enterprise
Standard Edition 7.0
Okt 2002
2.0
1.3
2000 je CPU
Enterprise Edition 7.0
Okt 2002
2.0
1.3
10000 je CPU
Developer 4.1.2
Sep 2002
2.0
1.3
Frei
Small Bus v4.1.2
Sep 2002
2.0
1.3
2995 je Server
Advanced v4.1.2
Sep 2002
2.0
1.3
7500 je CPU
Enterprise v4.1.2
Sep 2002
2.0
1.3
20000 je CPU
Developer v4.0
Jan 2003
2.0
1.3
Auf Anfrage
Enterprise v4.0
Jan 2003
2.0
1.3
Auf Anfrage
TradeCity Cybersoft Rexip Appserver
Enterprise v2.5
Mär 2003
2.0
keine
3888 je CPU
Trifork
Server
Non-Commercial v3.3
Jun 2003
2.0
1.3
Frei
Web v3.3
Jun 2003
2.0
1.3
999 je Dual CPU
Linux Deployment v3.2.0
Jun 2003
2.0
1.3
895 je Server
Pro v3.3.0 Dual CPU
Jun 2003
2.0
1.3
2500 je Dual CPU
Enterprise v3.2.0 Dual CPU
Jun 2003
2.0
1.3
10000 je Dual CPU
Sybase EAServer
TmaxSoft JEUS
Enterprise
Application
Tabelle 4.2: Application Server Marktübersicht 2
34
Architekturerweiterung
Geschäftslogik
Die Mehrzahl der Application Server bieten neben einem EJB Container auch
einen Web Container, oder lassen eine Integration eines Web Containers zu.
Die bekanntesten Web Container sind (vgl. [TSS-Matrix, 2004]):
Hersteller
Ausführung
Release
Preis in Dollar
Apache Tomcat
v4.1
Dez 2001
Frei
BEA Weblogic
Express 8.1 Basic
Feb 2003
495
Express 8.1 Premium
Feb 2003
3000
Borland Enterprise Server
Webserver v5.2
Jan 2003
399 je Server
Caucho Resin
Core 2.1
Jun 2003
500 je Server, Frei
für nicht kommerziellen Einsatz
Gefion Software LiteWebServer
v3.0
Jan 2003
Frei
IBM Websphere
Express 5.0
Okt 2002
1778
je
CPU,
Entwickler
Developer v4.2
Okt 2002
Frei
DeBugger v4.1
Nov 2001
Frei
Deployment v4.2
Okt 2002
695 je CPU
5.1
Sep 2003
Frei
Developer v2.5
Mär 2003
Frei
Standard v2.5
Mär 2003
650 je CPU
New Atlanta
ServletExec
Communications
Together Teamlösungen EDVDienstleistungen
GmbH.
in
cooperation
with
ObjectWeb
Enhydra Server
TradeCity Cybersoft Rexip Appserver
25
Tabelle 4.3: Web Container Marktübersicht
4.4
Implementation von Geschäftslogik
Enterprise JavaBeans sind Business Objects in einer J2EE Umgebung. Üblicherweise werden mehrere Enterprise JavaBeans programmiert, um ein Problem der realen Geschäftswelt abzubilden und zu lösen. Die J2EE Umgebung
bietet neben dieser Architektur APIs und Middleware, um komplexe, leistungsfähige und verteile Unternehmensanwendungen in einfacher und zügiger
Weise zu entwickeln. Die Value Proposition (Werteangebot) von Enterprise
JavaBeans ist die zügige Entwicklung von Anwendungen (”Rapid Application
Development” - Kurzform: RAD). Die resultierenden Anwendungen können
in EJB Containern verschiedener Hersteller ohne Veränderungen am Programcode ausgeführt werden.
”Ein Application Server macht aus einem EJB ein verteiltes Objekt und er
verwaltet Dienste wie Transaktionen, Persistenz, Nebenläufigkeit und Sicher35
Architekturerweiterung
Geschäftslogik
heit. Zusätzlich zu der Programmierung der Geschäftslogik, definiert der Entwickler Laufzeitattribute. [...] Das transaktionale Verhalten, die Nebenläufigkeit und die Sicherheit wählt der Entwickler aus einer Liste aus.” [MonsonHaefel, 2001]
Die Enterprise JavaBeans Spezifikation Version 2.0 definiert drei Typen von
Enterprise JavaBeans:
• Session Beans dienen der Modellierung von Geschäftsprozessen. Sie sind
Aktionen und werden deswegen häufig auch ”Verben” genannt. Beispiele sind DatenbankVerbindungsBean, ZaehlerBean, ERPAufrufBean.
• Entity Beans dienen der Modellierung von Geschäftsdaten. Sie sind
Behälter, welche Daten halten und speichern. Sie werden auch ”Subjekte” und ”Objekte” genannt. Beispiele sind BestellungBean, KundenBean,
KreditKartenBean, AktienBean.
• Message-Driven Beans sind wie Session Beans Aktionen. Sie unterscheiden sich darin, dass sie nur über Nachrichten (Messages) aufgerufen werden können. Beispiel sind ReceiveAktienHandelMessage,
ReceiveAuthorisationMessage, ReceiveGeschäftsProzessMessage.
4.4.1
Aufbau und Arbeitsweise
Ein Enterprise JavaBean setzt sich aus mehreren Klassen, Interfaces, Objekten und Dateien zusammen, die verschiedene Aufgaben erfüllen. Die zentrale Klasse eines Enterprise JavaBeans ist die Enterprise Bean Klasse, welche eine einfache Java Klasse ist, die ein vordefiniertes Interface implementiert, die gesamte Geschäftslogik enthält und einige Regeln beachtet, damit
sie innerhalb eines EJB Containers ausgeführt werden kann. Das Objekt
dieser Klasse wird Bean oder Bean Instanz genannt. Die Programmierung
der Bean Klasse ist die eigentliche Aufgabe bei der Entwicklung mit Enterprise JavaBeans. Die EJB Spezifikation definiert drei standardisierte Interfaces mit Methoden, welche vom EJB Container zur Verwaltung der Beans benötigt werden. Das zugrundeliegende serialisierbare Superinterface ist
javax.ejb.EnterpriseBean, von dem die drei folgenden Interfaces abgeleitet sind (siehe auch Abbildung 4.7):
• javax.ejb.SessionBean
• javax.ejb.EntityBean
• und javax.ejb.MessageDrivenBean
36
Architekturerweiterung
Geschäftslogik
Abbildung 4.7: Enterprise JavaBeans Typen
Die Interfaces bieten Methoden, mit denen der EJB Container die Bean Instanzen über Ereignisse in ihren Lebenszyklen benachrichtigt. Diese Methoden werden EJB Methoden genannt:
Session Beans
• setSessionContext()
• ejbCreate(...)
• ejbRemove()
• ejbActivate()
• ejbPassivate()
Entity Beans
• setEntityContext()
• unsetEntityContext()
• ejbCreate(...)
• ejbPostCreate(...)
• ejbRemove()
• ejbActivate()
37
Architekturerweiterung
Geschäftslogik
• ejbPassivate()
• ejbLoad()
• ejbStore()
Message-Driven Beans
• setMessageDrivenContext(MessageDrivenContext)
• onMessage(Message)
• ejbCreate(...)
• ejbRemove()
Die Aufgabe der Kontext-setzenden Methoden ist, dem Bean ein Objekt mit
den Informationen seines Umfelds zu übergeben. Häufig wird der übergebene
Kontext einer Member Variablen zugewiesen, damit darauf in anderen Methoden zugegriffen werden kann (this.ctx = ctx;). Mit unsetEntityContext()
wird diese Member Variable auf null zurückgesetzt (nur bei Entity Beans
notwendig). ejbCreate(...) überprüft die Parameter und erzeugt eine neue
Instanz. Nach der Erzeugung wird ejbPostCreate(...) ausgeführt. In dieser
Methode können Transaktionen oder beispielsweise eine Übergabe des neuen
EJB Objektes an andere Beans (nur Entity Beans) implementiert werden.
ejbRemove() gibt das Bean zur Zerstörung frei. ejbActivate() aktiviert
ein Bean aus dem Pool. Hier können beispielsweise Socket-Verbindungen für
spezielle Clients wieder aktiviert werden. ejbPassivate() hat die gegenteilige Aufgabe. Message-Driven Beans werden anders aktiviert bzw. deaktiviert
und besitzen dafür die Methode onMessage(Message). Für Entity Beans
existieren noch zwei besondere Methoden: ejbLoad() lädt die Daten aus dem
permanenten Speicher in die Member Variablen und ejbStore() schreibt die
Member Variablen zurück.
Damit das entwickelte Bean in der verteilten Umgebung arbeiten kann, braucht
es einige Hilfsobjekte. Grundlegende Interfaces zur Erstellung der Hilfsobjekte stehen zur Verfügung, werden jedoch nicht direkt zur Implementation der
Klassen verwendet. Der Entwickler hat die Aufgabe davon spezifischere Interfaces zu programmieren, aus denen dann der EJB Container Klassen für
die Hilfsobjekte generiert. Abbildung 4.8 zeigt die grundlegenden Interfaces,
sowie die vom Entwickler zu programmierenden Interfaces in grau und die
daraus resultierenden Objekte. Die Klassen der Objekte sind in Abbildung
4.8 zur Vereinfachung weggelassen.
38
Architekturerweiterung
Geschäftslogik
Abbildung 4.8: Enterprise JavaBeans Interfaces
Ein Bean benötigt entweder EJB Object und Home Object oder EJB Local
Object und Local Home Object, kann aber auch alle vier Objekte verwenden. Der Programmieraufwand ist häufig sehr gering, doch notwendig, um
dem EJB Container wichtige Informationen zu geben, die er zur Generierung der Klassen und schließlich zur Erschaffung der Hilfsobjekte benötigt.
Weitere Informationen, beispielsweise zum Laufzeitverhalten oder zur Persistenzform, werden in Deployment Descriptoren vom Entwickler angegeben.
Im Folgenden werden die Hilfsobjekte, ihre Aufgaben und die Entwicklungsschritte aufgezeigt.
EJB Object Wie im vorangegangenen Abschnitt 4.1.2 erwähnt, wird ein
Server-seitiges Proxy Objekt, welches die Netzwerkkommunikation maskiert,
benötigt, um ein verteiltes Objekt zu realisieren. Eine Bean Instanz verwendet als Server-seitiges Proxy Objekt ein EJB Objekt. Ein Client spricht
niemals ein Bean direkt an, sondern arbeitet mit dem EJB Objekt, welches
nur den Anschein erweckt, selbst das Bean zu sein. Das geschieht, indem
der Entwickler die Methoden des Beans im Remote Interface dupliziert, indem er nur die Methodenköpfe der zuvor entwickelten Bean Methoden in das
Remote Inferface schreibt. Die Implementation der Methoden befinden sich
weiterhin im Bean. Anzumerken ist hier, dass jeder Methodenkopf eine RemoteException (java.rmi.RemoteException) anmelden muss, damit Fehler
bei der Netzwerkkommunikation aufgefangen werden können. Der Application Server generiert weitere Methoden, die er für den Einsatz der impliziten
Middleware benötigt, und erstellt später das EJB Objekt. Ein Teil dieser
Methoden sorgt für die verteilte Kommunikation.
Home Object Die Aufgabe der Zuteilung einer Referenz und der Erschaffung von EJB Objects übernimmt das Home Object, welches auch Factory
39
Architekturerweiterung
Geschäftslogik
genannt wird. Der Client spricht demzufolge zunächst ein Home Object an,
welches ihm dann ein EJB Object zuweist. Diese Vorgehensweise hat den
Vorteil, dass das Home Object bestimmen kann, wo das EJB Object existieren wird, ohne dass dem Client der Ort bekannt sein muss. Das ermöglicht
Funktionen wie Load Balancing, Monitoring und mehr. Die Aufgaben des
Home Objects sind:
• Erschaffung von EJB Objects
• Auffinden von EJB Objects (nur bei Entity Beans)
• Entfernen von EJB Objects
Das Home Interface gibt dem Entwickler die Möglichkeit, festzulegen, welche
Parameter notwendig sind, damit ein Home Object ein EJB Object seiner
Bean Instanz erstellen und finden kann, indem er die Methodenköpfe der Bean Klasse im Home Interface dupliziert und sie als Methoden deklariert, die
eine RemoteException (java.rmi.RemoteException) werfen können. Anschließend ist der EJB Container in der Lage, daraus eine Klasse für ein
Home Object zu generieren. Abbildung 4.9 zeigt die Art und Weise, wie die
Bestandteile eines Beans zusammenarbeiten:
Abbildung 4.9: Initiierung und Methodenaufruf
Ein EJB Container erzeugt im optimalen Fall nur ein Home Object als Factory, ein EJB Object zur Maskierung der verteilten Umgebung und mehrere
Bean Instanzen. Die verschiedenen Implementationen der EJB Container unterscheiden sich in ihrer Arbeitsweise im Hintergrund. So gibt es auch den
Fall, dass für m Bean Instanzen n EJB Objects (m:n-Beziehung) existieren.
40
Architekturerweiterung
Geschäftslogik
Da einmal entwickelte Enterprise JavaBeans auf allen EJB Container ausgeführt werden können, ist dies für die Entwicklung nicht relevant.
Clients finden Home Objects über einen Verzeichnisdienst. Zu diesem Zwecke wird das JNDI API (Java Naming and Directory Interface) verwendet
(Kapitel 4.1.3). Ein nicht triviales Modell von verschiedenen EJB Objekten,
die eine Geschäftslogik abbilden, enthält Beans, die andere Beans aufrufen.
Das Auffinden eines anderen Beans über sein Home Objekt erfolgt über einen
JNDI Lookup:
// Default JNDI Kontext abrufen
Context ctx = new InitialContext();
// Home Interface eines Beans finden
Object result = ctx.lookup("java:comp/env/ejb/BeispielHome");
// Typ-Konvertierung
BeispielHome home = (BeispielHome)
javax.rmi.PortableRemoteObject.narrow(result, Beispiel.Home.class);
// Bean erschaffen über EJB Methode
Beispiel beispiel = home.create(...);
EJB Local Object und Local Home Object Enterprise JavaBeans
werden nicht nur extern von Clients aufgerufen, sondern rufen sich auch
gegenseitig auf. Für diese Fälle gibt es die Möglichkeit, sowohl ein lokales
EJB Object als auch ein lokales Home Object anzulegen. Dies wird nicht
erzwungen, jedoch ermöglichen lokale Interfaces bei der internen Kommunikation Performancegewinne, denn die verteilte Kommunikation über ein
Netzwerk erfordert viele Akteure und Arbeitsschritte, die bei der internen
Kommunikation nicht notwendig sind. Für gewisse Probleme existieren Entwurfsmuster, die definieren welche Beans lokal arbeiten können und welche
fähig sein müssen, verteilt zu arbeiten. Weiterführende Informationen über
Entwurfsmuster in Enterprise JavaBeans gibt das Buch ”EJB Design Patterns: Advanced Patterns, Processes, and Idioms” [Marinescu, 2002]. Ein
Entwurfsmuster ist das Session Façade Pattern, welches in Kapitel 6 dieser
Arbeit umgesetzt wird.
Für den Entwickler sind die Unterschiede im Vergleich zu den Remote ProxyObjekten geringfügig. Er muss auch hier die Business Methods des Beans
duplizieren, nur mit dem Unterschied, dass die Methodenköpfe diesmal ohne
RemoteException (java.rmi.RemoteException) deklariert werden.
Deployment Descriptoren Ein Deployment Descriptor ist eine XML Datei, mit derer Hilfe der Entwickler den EJB Container informiert, welche implizite Middleware für ein bestimmtes Bean eingesetzt werden soll. So können
Optionen für die Verwaltung, den Lebenszyklus, die Transkationen und die
Persitenz spezifiziert werden. Für ein Session Bean könnte ein Deployment
Descriptor wie folgt aussehen:
41
Architekturerweiterung
Geschäftslogik
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar >
<description>Beispiel Deployment Descriptor</description>
<display-name></display-name>
<enterprise-beans>
<!-- Session Beans -->
<session>
<description>Produziert eine Rechnung</description>
<ejb-name>BillProducer</ejb-name>
<home>beispiel.BillProducerHome</home>
<remote>beispiel.BillProducer</remote>
<local-home>beispiel.BillProducerLocalHome</local-home>
<local>beispiel.BillProducerLocal</local>
<ejb-class>beispiel.BillProducerBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<!-- weitere Session, Entity oder Message Beans -->
</enterprise-beans>
</ejb-jar>
4.4.2
Unterschiedliche Bean Typen
Session Beans haben ihren Namen aufgrund ihrer kurzen Lebensdauer
erhalten, die etwa die Länge einer Clientverbindung, einer Sitzung (session)
beträgt. Sie sind die wahren Akteure in einer EJB Anwendung und müssen
daher in besonderem Maße Ressourcen schonen. Aus diesem Grund gibt es
zwei Arten von Session Beans: Statefull und Stateless Session Beans. Statefull Session Beans können Daten über mehrere Anfragen eines Clients hinweg speichern. Clients sind in diesem Fall Anwendungen oder andere Beans,
die ein Session Bean aufrufen. Stateless Session Beans hingegen müssen alle
benötigten Dialogdaten (clientverbindungsspezifische Daten) bei Ihrem Aufruf in Form von Parametern vom Client erhalten. Nach der Ausführung einer
einzigen Anfrage werden sie bereits vom EJB Container freigegeben. Sie sind
daher zustandslos. Andere, nicht clientverbindungsspezifische Daten, die von
allen Clients gleichermaßen verwendet werden, wie beispielsweise eine Adresse oder ein konstanter Wert für eine Umrechnung, können als private nichtstatische Variablen eingesetzt werden. Stateless Session Beans sind in der
Regel die Leichtgewichte im Hinblick auf die Ressourcennutzung. Durch ihre
Zustandslosigkeit sind alle Instanzen absolut identisch, was bedeutet, dass
ein EJB Container eine einzige Instanz nacheinander für alle Clientanfragen
nutzen kann. Eine Gefahr birgt jedoch die Eigenschaft, dass alle Dialogdaten
übergeben werden müssen. Wenn diese aus extrem großen Objekten bestehen, kann ein Stateless Session Bean durchaus mehr Ressourcen in Anspruch
42
Architekturerweiterung
Geschäftslogik
nehmen als ein Statefull Session Bean. Ein Ausweg ist unter Umständen
ein externer Verzeichnisdienst, über den indirekt die Dialogdaten in Form
von einem oder mehreren Objekten übergeben werden. Für eine performante
Lösung sollten nach Möglichkeit unbedingt Stateless Session Beans eingesetzt
werden.
Der EJB Container versucht natürlich auch die Ressourcennutzung von Statefull Session Beans zu optimieren. Mit Hilfe eines ”Least Recently Used” Algorithmus ermittelt er Instanzen von Statefull Session Beans, die kurzzeitig aus dem Speicher entfernt werden (Passivierung), und bei Bedarf wieder geladen werden können (Aktivierung). Das Ablegen von Daten aus dem
Speicher auf einen permanenten Speicher wird Swapping genannt. Das Verfahren, Objekte zu passivieren und wieder bei Bedarf zu aktivieren, wird
Pooling genannt. Bei längeren Konversationen mit einem Client, wie bei der
Verarbeitung von Benutzereingaben, die von mehreren aufeinanderfolgenden
Instanzen von Statefull Session Beans durchgeführt werden können, kann es
bei einem Ausfall des Systems zu einem Zustandsverlust kommen. Daher
sollten längere Konversationen möglichst vermieden werden oder es sollten
zumindest Checkpoints eingerichtet werden, in denen die Daten zur Wiederaufnahme einer Konversation durch Objektserialisierung zwischengespeichert
werden. Zur Zwischenspeicherung und Wiederherstellung der Objekte können
Handles, langlebige Proxies, welche persistente Referenzen für EJB Objects
sind, eingesetzt werden. Entwurfsmuster sind häufig sehr hilfreich, um eine
gute Lösung zu finden, aber letztlich kann nur ein Performancetest über die
Qualität entscheiden. Session Beans können auch dazu verwendet werden,
Daten persistent zu speichern, indem CRUD Methoden (Create, Read, Update, Delete) geschrieben werden, die direkt über JDBC einen permanenten
Speicher ansprechen. Als Alternative dazu bietet J2EE Entity Beans als eine eigene Schicht an, die ausschließlich für persistente Daten zuständig ist.
Der Einsatz von Entity Beans ermöglicht die Trennung von Geschäfts- und
Persistenzlogik.
Entity Beans sind Datenobjekte für die Modellierung von Geschäftslogik. Ihre Hauptaufgabe besteht darin, ihre Zustände dauerhaft zu speichern,
indem sie diese mit einem Datensatz oder einem Objekt innerhalb eines permanenten Speichers mit Hilfe von CRUD Methoden synchronisieren. Für die
permanente Speicherung von Objekten existieren mehrere Möglichkeiten :
Java Objekt Serialisierung ist ein Verfahren, dass ein Java Objekt in einen
Stream umwandelt und diesen in eine Datei speichert. Wenn das Objekt wieder benötigt wird, kann der Stream wieder zu einem Objekt dekodiert werden.
Die Objekt Serialisierung hat das Problem, dass Abfragen wie beispielsweise
’’Zeig mir alle Objekte, die den Wert X > 10 haben’’ nicht unmittelbar performant durchzuführen sind, da sämtliche Objekte in den Speicher
geladen und nacheinander geprüft werden müssen.
43
Architekturerweiterung
Geschäftslogik
Ein anderes Verfahren ist das Objekt-Relationale Mapping. Hierbei werden Daten eines Java Objektes in einer relationalen Datenbank abgebildet.
Die Abbildung von Objekten auf relationale Tabellen ist nicht unmittelbar möglich, so dass eine Konvertierung und Rückkonvertierung erfolgen
muss. Im optimalen Fall repräsentiert eine Zeile einer relationalen Tabelle
alle Zustände eines Java Objekts. Der Vorteil des Objekt-Relationalen Mappings ist, dass riesige Datenmengen performant durchsucht werden können.
Das Mapping kann von Hand geschehen oder es können dafür Produkte wie
TOPLink von WebGain oder JavaBlend von Sun Microsystems eingesetzt
werden. In Kapitel 6 werden Verfahren für das manuelle Mapping gezeigt.
Die dritte Möglichkeit ist der Einsatz von Objektdatenbanken, welche die
direkte Speicherung von Java Objekten mit Hilfe eines mitgelieferten APIs
erlauben. Anfragen werden über die Object Query Language OQL definiert.
Objektdatenbanken unterstützen Relationen unter den Objekten, was zu performanten Ergebnissen bei Abfragen über mehrere Objekte führt. ObjectStore, Versant und POET sind Hersteller von Objektdatenbanken. Objektdatenbanken scheinen zunächst die beste Alternative zu sein. Dazu schreibt
Roman:
”Objektdatenbanken sind vorhersagbar performant und skalierbar. Sie bieten
starke Integrität und Sicherheit und sind somit ein exzellenter Speicher für
komplexe persistente Objekte. Bestimmte Anwendungen, wie geospatial oder
CAD/CAM, funktionieren sehr gut mit Objektdatenbanken im Gegensatz zu
relationalen Datenbanken. Andere Anwendungen lassen sich einfach auf relationale Datenbanken mappen, wie etwa die meisten Geschäftsanwendungen.
Für schlichte hochvolumige Geschäftstransaktionen skalieren relationale Datenbanken besser.” [Roman, 1999]
Der EJB Container verwendet im Fall von Entity Beans, wie bei Statefull
Session Beans, Swapping für das Pooling. Bei Statefull Session Beans werden
die Objekte immer serialisiert. Bei Entity Beans kommt jedoch ihr permanenter Speicher zum Einsatz, der im Fall von Datenbanken in der Regel bessere
Zugriffszeiten bietet.
Für Methoden, die auf Datenbanken zugreifen, müssen Transaktionen verwendet werden. Ein Entity Bean enthält Methoden, die sich in mehrere Gruppen unterteilen lassen:
• EJB Methoden und CRUD Methoden
• set und get Methoden
• Finder Methoden
44
Architekturerweiterung
Geschäftslogik
• Home Methoden
Finder Methoden suchen Entity Beans über ihre Daten. Auch wenn die Beans
nicht aktiv sind, kann eine Finder Methode aufgerufen werden. Wenn die
Suche erfolgreich ist, erzeugt der EJB Container Instanzen von Entity Beans,
deren Daten der Suchanfrage entsprechen. Beispiele für mögliche Methoden
sind:
• public KontoLocal ejbFindByPrimaryKey(KontoPK key)
• public Collection ejbFindAllKunden()
• public Collection ejbFindMostRecentBestellungen(Date date)
Alle Methoden müssen mit dem Prefix ejbFind beginnen. Alle anderen Abfragen werden in Home Methoden (Prefix ejbHome) durchgeführt, wie etwa
die Summe über einen Wert über mehrere Entity Beans oder die Anzahl von
Werten in einem Entity Bean, was bei relationalen Tabellen der Anzahl der
Spalten entsprechen würde.
Message-Driven Beans ermöglichen eine asynchrone Kommunikation zwischen Clients und Servern, wobei sowohl Clients als auch Server Session Beans
sind. Asynchrone Kommunikation bedeutet, dass ein oder mehrere Clients
(Producer) Nachrichten an ein oder mehrere Server (Consumer) versenden
können. Ein Message-Driven Bean arbeitet als Mittelsmann zwischen Producern und Consumern. Ein Producer kann eine Nachricht zu ein oder mehreren
Consumern versenden und braucht nicht auf die Antwort der Consumer zu
warten. Wenn der Consumer die Anfrage bearbeitet hat, kann er optional
dem Producer über eine Nachricht antworten. Diese Form der Kommunikation wird asynchron genannt, weil der Consumer die Nachricht ”irgendwann”
bearbeitet. Das bedeutet, dass zum einen der Zeitpunkt der Verarbeitung
wahrscheinlich zeitnah aber nicht zeitgleich sein wird, zum anderen, dass die
Reihenfolge der Verarbeitung nicht unbedingt der Reihenfolge folgt, in der
die Nachrichten versendet worden sind. Message-Driven Beans sind daher
ungebundene Objekte, die keine Remote oder Local Interfaces zur verteilten
Kommunikation haben. Die besitzen nur eine Methode (onMessage()), die
keinen Rückgabewert liefert. Ihre Aufgabe ist es, die Nachricht zu identifizieren und sie an die entsprechenden Consumer weiterzugeben. Meistens besteht
sie daher aus einer Folge von IF Anweisungen. Die Nachrichten, die versendet
werden, sind JMS Nachrichten (Java Message Service 1.0). Die Verwendung
von Message-Driven Beans ermöglicht: (vgl. [Roman, 1999]):
• Performancegewinne, da Clients nicht auf Server warten müssen.
• Mehr Zuverlässigkeit. Im Gegensatz zur verteilten Kommunikation muss
der Server nicht aktiv sein; die Nachricht wartet auf ihn.
45
Architekturerweiterung
Geschäftslogik
• Flexiblere Kommunikation. Im Gegensatz zur verteilten Kommunikation können mehrere Clients mehrere Server ansprechen.
Message-Driven Beans können nicht eingesetzt werden, wenn eine sortierte
Serie von Anweisungen an einen Server gesendet werden soll und eine Verarbeitung in derselben Reihenfolge notwendig ist. Zudem werden MessageDriven Beans vom EJB Container nach der ersten Initialisierung immer aktiv
gehalten. Es erfolgt in der Regel kein Pooling, was aber kein schwerwiegendes
Problem ist, da Message-Driven Beans nicht viele Ressourcen in Anspruch
nehmen.
4.4.3
RAD durch implizite Middleware
RAD steht für Rapid Application Development. Die EJB Spezifikation hat
zum Ziel, die Entwicklung von leistungsfähigen Anwendungen in kürzester
Zeit zu ermöglichen. Persistenz, Transaktionen und Nachrichtenverarbeitung
können durch Deklarationen bestimmt werden, damit der entsprechende Programmcode vom EJB Container generiert werden kann. Die Möglichkeit einer
manuellen Programmierung besteht, sogar die Möglichkeit einer Kombination von Deklaration und Programmierung. Die Programmierung sollte allerdings nur dann eingesetzt werden, wenn ein Problem durch Deklaration nicht
lösbar sein sollte. (vgl. [Roman, 1999])
Persistenz von Entity Beans Die CRUD Methoden für die Synchronisation mit dem permanenten Speicher, die Membervariablen mit entsprechenden set und get Methoden und die Finder Methoden zur Lokalisierung können vom EJB Container generiert werden. Dieses Verfahren wird
Container-Managed-Persistence (CMP) genannt. Mit CMP reduziert sich
die Aufwand für die Entwicklung eines Entity Beans auf das Schreiben der
Geschäftslogik und die Bereitstellung eines Deployment Descriptors. Die Geschäftslogik in Entity Beans ist in der Regel nicht umfangreich. Sie beschränkt sich
auf die Bereitstellung von Daten in Form von Home Methoden und auf kleinere Operationen, wie beispielsweise die Umrechnung von Werten. Der EJB
Container verwendet eine Subklasse der Bean Klasse, um die oben genannten Methoden zu generieren. Der Vorteil ist die Trennung von Geschäfts- und
Persistenzlogik, die die Geschäftslogik unabhängig vom eingesetzten permanenten Speicher macht (Abbildung 4.10).
46
Architekturerweiterung
Geschäftslogik
Abbildung 4.10: CMP 2.0
Die vom Entwickler zu implementierenden Home Methoden in der Bean Klasse sollten daher auch keine Persistenzlogik enthalten. Aus diesem Grund bietet CMP eine weitere Gruppe von Methoden, die Select Methoden genannt
werden. Diese werden ebenfalls im Deployment Descriptor deklariert und
vom EJB Container generiert. Im Deployment Descriptor werden Anfragen
an den permanenten Speicher in Form von SELECT Anweisungen in der Sprache QL (Query Language) eingesetzt, die SQL sehr ähnlich ist. Eine Bean
Instanz kennt ihre Daten bereits seit der Erschaffung. Der Sinn der Select Methoden ist daher, Informationen über andere in einer relationalen Beziehung
stehende Entity Beans abzurufen. In Home Methoden sollten deswegen zur
Beibehaltung der Trennung von Geschäfts- und Persistenzlogik ausschließlich
die Select Methoden für das Heranziehen von Daten und die set und get
Methoden zum Zugriff auf die eigenen Werte verwendet werden. Damit diese
Methoden wie auch alle anderen vom EJB Container generierten Methoden
bei der Programmierung der Geschäftslogik in der Bean Klasse zur Verfügung
stehen, müssen abstrakte Methodenköpfe deklariert werden. Wenn kein CMP
eingesetzt wird, muss die Persistenzlogik programmiert werden. Dieses Verfahren wird Bean-Managed-Persistence (BMP) genannt. Dazu müssen APIs
wie etwa JDBC für die CRUD Methoden verwendet werden. Zudem ist die
Implementation der set und get Methoden, sowie das Aufführen der Member Variablen notwendig. Die folgenden zwei Listings zeigen die Unterschiede
bezüglich der set und get Methoden und der Member Variablen bei der Implementation einer Entity Beans Klasse, die eine einfache, in Entity Beans
einsetzbare, Business Methode enthält (die Berechunung eines Verkaufspreises). Sämtliche abgeleitete Methoden, und somit auch die manuell zu programmierenden JDBC Aufrufe im BMP Beispiel, wurden zur Vereinfachung
47
Architekturerweiterung
Geschäftslogik
weggelassen:
/*
Beispiel für ein Bean-Managed Persistent Entitiy Bean
*/
public class ArtikelBean implements EntityBean {
/*
Member Variablen
*/
public
public
public
public
public
String artikelNummer;
String artikelBezeichnung;
int verpackungsStueckzahl;
double verpackungsNettoPreis;
double umsatzSteuersatz;
// Primärschlüssel
// ... weitere Member Variablen ...
/*
set und get Methoden
*/
public int getVerpackungsNettoPreis () {
return this.verpackungsNettoPreis ;
}
public void setVerpackungsNettoPreis (String verpackungsNettoPreis ) {
this.verpackungsNettoPreis = verpackungsNettoPreis ;
}
// ... weitere set und get Methoden für alle Member Variablen ...
/*
Business Logik
Teilt den Verpackungspreis durch die Anzahl der Artikel in einer Verpackung und
addiert den prozentuallen Steuersatz. Beispiel 10.00 / 5 * 1.16 = 2,32
*/
public double berechneBruttoEinzelPreis() {
return this.getVerpackungsNettoPreis()
/ this.getVerpackungsStueckzahl() * (1 + this.getUmsatzSteuersatz());
}
// ... weitere Business Methoden
/*
... abgeleitetet EntityBean Methoden ...
*/
}
In CMP ohne Persistenzlogik wie folgt:
/*
Beispiel für ein Container-Managed Persistent Entitiy Bean
*/
public abstract class ArtikelBean implements EntityBean {
/*
Abstrakte Klasse.
Keine Member Variablen.
*/
/*
Abstrakte set und get Methoden
48
Architekturerweiterung
Geschäftslogik
*/
public abstract String getArtikelBezeichnung() {
}
public abstract void setArtikelBezeichnung(String artikelBezeichnung) {
}
// ... weitere set und get Methoden ...
/*
Business Logik wie bei BMP Entity Bean
*/
public double berechneBruttoEinzelPreis() {
return this.getVerpackungsNettoPreis()
/ this.getVerpackungsStueckzahl() * (1 + this.getUmsatzSteuersatz());
}
// ... weitere Business Methoden
/*
... abgeleitetet EntityBean Methoden ...
*/
}
Der Deployment Descriptor, der zur Generierung der Subklasse in CMP
benötigt wird, sieht wie folgt aus:
...
<cmp-version>2.0</cmp-version>
<abstract-schema-name>ArtikelBean</abstract-schema-name>
<cmp-field>
<field-name>artikelNummer</field-name>
</cmp-field>
<cmp-field>
<field-name>artikelBezeichnung</field-name>
</cmp-field>
<cmp-field>
<field-name>verpackungsStueckzahl</field-name>
</cmp-field>
<cmp-field>
<field-name>verpackungsNettoPreis</field-name>
</cmp-field>
<cmp-field>
<field-name>umsatzSteuersatz</field-name>
</cmp-field>
<primkey-field>artikelNummer</primkey-field>
...
Aufgrund der höheren Abstraktion ist die Nutzung von CMP sicherlich etwas
gewöhnungsbedürftig. Dabei stellt nicht das Programmieren der Geschäftslogik mit abstrakten Methoden in der Bean Klasse das Hauptproblem dar
sondern die Konfiguration des Deployment Descriptors. Ein auf XML basierender Deployment Descriptor hat einen weitgehenden Vorteil: Die Möglichkeiten der Setzung von Attributen, die ein CMP Entity Bean konfigurieren,
49
Architekturerweiterung
Geschäftslogik
sind endlich. Diese Eigenschaft ermöglicht es IDEs leichter die Anforderungen
an ein Entity Bean vom Entwickler abzufragen und den entsprechenden Deployment Descriptor zu generieren. Der Programmieraufwand für Datenobjekte, die keine zusätzliche Geschäftslogik enthalten, ist somit gleich null. Der
Entwickler muss entscheiden, ob er Geschäftslogik in Entity Beans einsetzt.
Für den Fall, dass beispielsweise unterschiedliche Session Beans eine Methode für die Berechnung eines Bruttopreises eines Verkaufsartikels benötigen,
die Daten jedoch nur in Nettopreisen persistent gespeichert werden, ist die
Implementation dieser Methode im Entity Bean sinnvoll, um Redundanzen
im Programmcode zu vermeiden.
Transaktionen Die Implementation von Transaktionen ist auch mit Hilfe
eines APIs wie dem Java Transaction API (JTA)
(http://java.sun.com/products/jta/;
siehe auch http://java.sun.com/products/jts/) häufig komplex und zeitaufwendig. Dennoch ist der Einsatz in vielen Fällen notwendig, im besonderen bei verteilten Anwendungen. Netzwerk- und Rechnerausfälle können fatale Auswirkungen auf die Konsistenz der Daten haben, unbemerkte Fehler
können sich fortpflanzen und gesamte Datenbestände unbrauchbar machen.
Auch Multiuserfähigkeit setzt Transaktionen voraus, falls diese Operationen auf den gleichen Datensätzen gleichzeitig ausführen möchten. ContainerManaged Transactions (CMT) ist wie CMP implizite deklarative Middleware
und Bestandteil jedes EJB 2.0-kompatiblen Application Servers. Um CMT
einzusetzen, muss im Deployment Descriptor der Name des Beans, der Name
der Methode, die Parameter der Methode und ein Transaktionsattribut (Tabelle 4.4) angegeben werden, welches die Art der Transaktion bestimmt. Die
Implementation der Klassen, die über JTA die begin-, abort- und commitAnweisungen herausgeben, übernimmt der EJB Container. Das Transaktionsattribut bestimmt das Verhalten einer Transaktion gegenüber vorangegangenen, noch aktiven Transaktionen. Wenn beispielsweise eine Transaktion die Belegung eines Sitzplatzes in einem Flugzeug ist und eine andere die
Abbuchung des Flugpreises von der Kreditkarte des Passagiers, dann sind
diese beiden Transaktionen voneinander abhängig. In diesem Fall muss sich
die zweite Transaktion der ersten anschließen, sich mit ihr in einer Transaktion vereinigen (Transaktionsattribut = Supports), und somit Atomität
gewährleisten.
Für die Konsistenz der Daten muss der EJB Entwickler bei der Programmierung der Geschäftslogik Sorge tragen. Der Grund ist einfach: Die Regeln
für die Konsistenz sind lösungsspezifisch und eine Programmiersprache wie
Java ist das beste Mittel zur Spezifikation von Regeln. Die EJB Spezifikation definiert keine deklarative Isolation von Transaktionen. Der Grund
ist, dass sich die Hersteller von Application Servern dagegen gewehrt haben, da viele die Meinung vertreten haben, dass die Implementation dieser
Middleware zu schwierig wäre (vgl. [Monson-Haefel, 1999]). Andere wieder50
Architekturerweiterung
Geschäftslogik
Transaktionsattribut
vorangegangene Transaktion existiert
Transaktionsverhalten
Required
nein
neue beginnen
ja
anschließen
nein
neue beginnen
ja
neue beginnen
nein
keine beginnen
ja
anschließen
nein
Fehler melden
ja
anschließen
nein
keine beginnen
ja
keine beginnen
nein
keine beginnen
ja
Fehler melden
RequiresNew
Supports
Mandatory
NotSupported
Never
Tabelle 4.4: Effekte von Transaktionsattributen bei CMT
um bieten auch vom Container bereitgestellte Isolation von Transaktionen.
Zu diesem Zweck werden, wie auch in anderen Fällen, die nicht von der EJB
Spezifikation abgedeckt sind, Container-spezifische Deployment Descriptoren angeboten. Die Nutzung dieser macht die entwickelte Anwendung vom
Application Server abhängig. Eine weitere Alternative ist die Nutzung von
Isolationsmechanismen in Datenbanken wie beispielsweise Oracle. Der Nachteil ist dann natürlich die Abhängigkeit von einer spezifischen Datenbank.
Wenn die Äbhängigkeit von einem Application Server oder einer Datenbank
ein Problem darstellt, kommt man nicht um eine Implementation von Isolation mit Hilfe des Java Transaction APIs herum. Es existieren dabei zwei
mögliche Strategien: Die Strategie der optimistischen und der pessimistischen
Nebenläufigkeitskontrolle.
Die optimistische Nebenläufigkeitskontrolle basiert auf der Annahme, dass
Dirty Reads, Unrepeatable Reads und Phantom Reads in der Praxis selten
vorkommen. Basierend auf dieser Annahme werden Inkonsistenzen unmittel51
Architekturerweiterung
Geschäftslogik
bar bemerkt, aber nicht von vornherein verhindert. Für den Fall, dass es zu
einer Inkonsistenz kommt, wird eine Reaktionsstrategie implementiert. Die
Datensätze werden zwischen dem Einlesen und dem Update auf Gleichheit
kontrolliert. Wenn dies nicht der Fall sein sollte, wird die gesamte Transaktion rückgängig gemacht (abort). Während einer Transaktion kommuniziert eine Anwendung in der Regel mehrere Male mit der Datenbank. Locks
auf die Daten erfolgen nur dann, wenn auch wirklich eine Kommunikation
zur Datenbank stattfindet. Die Implementation wird durch den Einsatz von
javax.ejb.SessionSynchronization als zusätzliches optionales Interface
für ein Bean vereinfacht. Über die Methoden des Interfaces benachrichtigt
der EJB Container Beans, falls eine Transaktion nicht erfolgreich war. Es
bleibt jedoch der Programmieraufwand die Reaktion auf die Benachrichtigung bereitzustellen. Die optimistische Nebenläufigkeitskontrolle ist die performantere Möglichkeit und sollte für größere Anwendungen in Betracht gezogen werden (vgl. [Roman, 1999]). Die Performance richtet sich nach dem
Isolationslevel, der eingesetzt wird (Read Commited, Repeatable Read oder
Serializable).
Die pessimistische Nebenläufigkeitskontrolle eignet sich für kleinere Anwendungen. Hierbei werden die Daten vom Beginn der Transaktion bis zur Beendigung gelockt. Die Implementation ist trivial und verhindert Dirty Reads
und Unrepeatable Reads. Um Phantom Reads zu verhindern, müßte die gesamte Tabelle gesperrt werden. Der Nachteil liegt selbstverständlich darin,
dass andere Beans in dem Fall mit ihrem Zugriff auf die Daten warten müssen.
Für eine zügige Entwicklung empfiehlt sich die Vorgehensweise, zunächst
die pessimistische Nebenläufigkeitskontrolle einzusetzen und bei Performanceproblemen zu entscheiden, ob die optimistische Nebenläufigkeitskontrolle
nachträglich implementiert wird, da, wie bereits erwähnt, die Implementation der pessimistischen Nebenläufigkeitskontrolle trivial ist. Mit Hilfe von
Monitoring-Tools, die häufig Bestandteil von Application Servern sind, können
”Flaschenhälse” lokalisiert werden. Unter Umständen kann auch eine Performanceverbesserung an anderer Stelle, wie beispielsweise durch Clustering,
erreicht werden, um der Notwendigkeit die Implementation von optimistischer Nebenläufigkeitskontrolle zu umgehen. (vgl. [Roman, 1999])
Die letzte Transaktionseigenschaft ist die Dauerhaftigkeit, die garantiert, dass
eine Veränderung durch einen Commit permanent gespeichert wird. Bei nur
einem permanenten Speicher ist die Implementation trivial, denn bei der
Dauerhaftigkeit steht nicht die Rückmeldung eines permanenten Speichers
über die korrekte Durchführung eines Datenupdates im Mittelpunkt, sondern ob ein Commit überhaupt den permanenten Speicher erreicht. Dies kann
erst zu einem Problem beim Einsatz von mehreren, mitunter verschiedenen,
permanenten Speichern werden und die Verwendung eines Zwei-Phasen Commits erfordern. Die erste Phase sendet ein Before Commit Statement an alle
52
Architekturerweiterung
Geschäftslogik
beteiligten Ressourcen und bietet den Ressourcen die letzte Möglichkeit eine
Transaktion durch einen Abort zu verhindern. Wenn alle Ressourcen zustimmen, wird die Transaktion unwiderruflich durchgeführt. Die Commits werden
ausgeführt und gleichzeitig in einem Journal protokolliert. Falls durch einen
Systemausfall zu diesem Zeitpunkt eine Ressource nicht erfolgreich das Commit absetzen konnte, besteht die Möglichkeit, über das Journal das nicht
ausgeführte Commit im Rahmen einer Wiederinbetriebnahme wiederzuholen. Dauerhaftigkeit wird durch den Einsatz von dafür vorgesehener Software
oder mit eigenen Implementationen erreicht, häufig mit wenig oder gar keinen Auswirkung auf den Programmcode der Beans.
Unter RAD Gesichtspunkten ist der Einsatz von CMT für die Atomität von
Operationen, die Implementation von Logik für die Konsistenz von Daten
innerhalb der Geschäftslogik, der Einsatz von pessimistischer Nebenläufigkeitskontrolle bei Anwendungen kleineren und mittleren Umfangs, sowie der
Einsatz von Tools, die die Dauerhaftigkeit von persistenten Veränderungen
garantieren, sinnvoll. Falls die Abhängigkeit von Application Servern und
Datenbanken keine Rolle spielt, können deren Transaktionsmechanismen eingesetzt werden.
Objektbeziehungen Die Vorteile des Einsatzes von CMP für die Persistenzlogik gelten auch für die Abbildung von Relationen zwischen Objekten.
Sämtliche aus dem Entwurf von relationalen Datenbanken bekannten Beziehungen können durch Einträge im Deployment Descriptor angegeben werden.
So können Kardinalität, Richtung, Aggregation, Komposition sowie rekursive
und zirkuläre Beziehungen deklariert werden. Für die referentielle Integrität,
dass Beziehungen zulässig sind, und das kaskadierte Löschen von Daten (Entfernen von Kompositionen) sorgt der EJB Container. Wenn ein Objekt in den
Speicher geladen wird und es in Beziehungen zu anderen Objekten steht,
werden diese standardmäßig ebenfalls in den Speicher geladen. Dies kann zu
extrem großen Graphen von Objekten führen und viel Speicherplatz einnehmen. Aus diesem Grund besitzen EJB Container die Möglichkeit des Lazy
Loadings. Dabei werden die Objekte erst dann geladen, wenn auch eine Anfrage ausgeführt wird und sie daran beteiligt sind. Application Server stellen
häufig ein Flag zur Verfügung, mit dem Lazy Loading aktiviert werden kann.
Objektbeziehungen über CMP lassen sich umfassend abbilden, die Abfragen
sind performant und CMP benötigt keinen zusätzlichen Programcode (vgl.
[Roman, 1999]).
4.4.4
Datenbankunabhängigkeit
Der Einsatz von QL als Sprache für Datenbankabfragen bei CMP Entity
Beans hat den Vorteil, dass der Programmcode frei von SQL Statements
ist und somit auch keine Abhängigkeit zu einem SQL Dialekt besteht. Der
Application Server muss allerdings die Datenbank unterstützen. Viele Appli53
Architekturerweiterung
Geschäftslogik
cation Server unterstützen bis zu zwanzig und mehr relationale Datenbanken
verschiedener Hersteller.
4.4.5
Performanceoptimierung
Objektbeziehungen brauchen trotz Lazy Loading viel Speicher. Generell sollten Rechner, auf denen Application Server laufen, mit dem maximal vom Motherboard unterstützten Speicher ausgestattet werden. Dadurch wird auch
Pooling seltener, was sich erheblich auf die Gesamtperformance auswirkt.
Eine gute Gesamtperformance kann zur Folge haben, dass pessimistische Nebenläufigkeitskontrolle für Transaktionen ausreichend ist. Somit wird zwar
ein weniger performantes Verfahren verwendet, welches aber keine Implementation von Reaktionsmechanismen erfordert und somit erheblich zügiger
zu entwickeln ist. Aber nicht nur durch den Einsatz von viel Speicherplatz
kann die Performance optimiert werden. So können zwar Datenbankzugriffe
direkt aus Session Beans über JDBC erfolgen, so dass keine Entity Beans
eingesetzt werden, aber neben dem Nachteil, dass es dabei keine Trennung
zwischen Geschäfts- und Persistenzlogik gibt, können Session Beans nicht
gecached werden (vgl. [Roman, 1999]). Entity Beans werden von vornherein vom EJB Container gecached, vorausgesetzt, dass ausreichend Speicher
vorhanden ist. Das Caching sorgt dafür, dass weniger zeitaufwendige Erzeugungen von neuen Beans durchgeführt werden müssen. Die Verwendung von
Entity Beans wirkt sich daher günstig auf die Gesamtperformance aus und
isoliert die Persistenzlogik. Wie bereits erwähnt, ist der Einsatz von CMP gegenüber BMP bei Entity Beans unter RAD Gesichtspunkten zu empfehlen.
CMP ist auch vorteilhafter im Bezug auf die Performance. Denn ein BMP
Entity Bean benötigt zwei SQL Statements, um geladen zu werden. Das erste wird für die Finder Methode und das zweite in ejbLoad() benötigt. Eine
Anfrage, die als Resultat n Entitiy Beans in Form eines Collection Objektes liefert, braucht daher n + 1 Statements bei BMP. EJB Container haben
bei CMP Entity Beans die Möglichkeit, bei Anfragen dieser Art ein einziges
(1) großes Statement aus den QL Anweisungen im Deployment Descriptor
zu generieren. Besonders bei Cluster Partitionierungen, bei denen über ein
Netzwerk auf die Datenbank zugegriffen wird, wirkt sich die Zusammenfassung von Statements sehr positiv auf die Performance aus. Desweiteren hat
auch der relationale Entwurf einer Datenbank Einfluß auf die Menge der erforderlichen Datenbankzugriffe bei einer Abfrage. So hat die Normalisierung
von relationalen Tabellen zum Ziel, Datenredundanz zu vermeiden. Obwohl
dabei 1:1 Beziehungen häufig sinnvoll sind, erfordern diese mehr Datenbankzugriffe, da eine Normalisierung in der Regel die Zahl der Tabellen erhöht.
Daher kann eine weniger normalisierte Tabellenstruktur günstiger für die
Performance sein. Zu empfehlen ist dennoch eine Normalisierung, doch wenn
es möglich ist, sollten 1:1 Beziehungen vermieden werden.
Falls eine Anwendung zu irgendeinem Zeitpunkt von Seiten der Benutzer ein
54
Architekturerweiterung
Front-End Technologien
Maß an Anfragen erreicht hat, das dazu führt, dass die Performance einbricht, weil der Server kaum Caching aber dafür viel Pooling betreibt, dann
muss eine Strategie für das Hinzufügen eines weiteren Rechners existieren.
Application Server bieten dafür unterstützende Software und Konfigurationsmöglichkeiten, so dass keine weitere Programmierung notwendig ist um
einen weiteren Server in einem Cluster zu integrieren. Da Enterprise JavaBeans netzwerkfähige, verteilte Objekte sind, können Anwendungteile problemlos innerhalb mehrerer Application Servern betrieben werden. Besonders die
3-Tier Partitionierung eignet sich für eine zügige Erweiterung um einen weiteren Application Server, da bereits mindestens zwei parallel arbeiten. Die
Lastenverteilung erfolgt automatisch (Load Balancing). Dennoch sollte auf
den Application Servern ein Limit gesetzt werden, indem der Thread-Pool
oder der Bean-Instanzen-Pool begrenzt wird. Dies geschieht über Konfigurationsdateien. Dabei sollte durch Monitoring ermittelt werden, welches Limit
klein genug ist, um das Pooling von Beans zu verhindern. (vgl. [Roman,
1999])
4.5
Front-End Technologien in J2EE
Servlets und JavaServer Pages sind auch Bestandteil der J2EE Plattform
und sind für die Erstellung von Front-Ends über das Web vorgesehen. Aus
Sicht von Entwicklern von Webanwendungen kann die J2EE Plattform zur
Implementation von verteilter, in Schichten nach Anforderungen geteilter,
skalierbarer Geschäfts- und Persistenzlogik für Webanwendungen verwendet
werden, wie in der in Abbildung 4.2 gezeigter und in diesem Kapitel vorgestellter Art und Weise. Die Verwendung von CMP und CMT reduzieren
dabei den Programmieraufwand erheblich. Eine weitere Möglichkeit des Rapid Application Developments wird in Kapitel 7 vorgestellt. Zunächst bleibt
jedoch die Frage offen, wie Controller und Views implementiert werden, und
wie diese mit dem EJB Model zusammenarbeiten können.
55
Frameworks
Frameworks
Kapitel 5
Integration von Frameworks
und Technologien
5.1
5.1.1
Struts Framework
Wieso Struts?
Husted schreibt über das Buch ”Sun’s Core J2EE Patterns” von Deepak
Alur, John Crupi und Dan Malks:
”The Book Sun’s Core J2EE Patterns is ostensibly about J2EE patterns,
since they are patterns the book’s advice can be applied to any compatible
technology. The Core patterns work well with any Java web application, regardless of whether EJBs are used on the backend. The key point about the
J2EE patterns is that they stress building applications in tiers, with strong
abstractions, layering, and clean separation between the presentation, business, and integration tiers. Struts is designed to provide that same separation,
and is a good fit with the overall focus of the book. In fact, Core J2EE Patterns uses Struts as the example implementation for the Synchronizer Token
pattern in the book’s refactoring section.” [Husted, 2003]
Der Kern des Struts Frameworks, welches auf Standardtechnologien wie Servlets, JavaBeans und XML basiert, ist eine flexible Controller-Schicht. Struts
ermöglicht die Entwicklung von Webanwendungen mit einer Model 2 Architektur. (vgl. [Jakarta-Struts, 2004])
5.1.2
Arbeitsweise und Bestandteile
Die Laufzeitumgebung für eine mit dem Struts Framework erstellten Webanwendung ist ein JavaServer Pages Web Container. Der Apache Tomcat
Server ist ein geeigneter Web Container und kann integriert innerhalb eines J2EE Application Servers, wie etwa mit dem JBoss Application Server,
arbeiten. Eine Integration dieser Art ermöglicht den Aufbau einer 3-Tier
56
Frameworks
Frameworks
Cluster Partitionierung (siehe Kapitel 4). Das Struts Framework besteht aus
mehreren APIs und XML Konfigurationsdateien, die sowohl zur Entwicklung als auch zur Laufzeit Bestandteil der zur erstellenden Webanwendung
sein müssen. Das Rückgrat des Struts Frameworks ist der Struts Controller, welcher auch ActionServlet genannt wird. Er wird durch die Ableitung
der Klasse org.apache.struts.action.ActionServlet implementiert und
delegiert die Kontrolle jedes Requests an den Web Container zu einer vom
Entwickler der Webanwendung zu definierenden Action Klasse. Die Action
Klassen werden von der Klasse org.apache.struts.action.Action abgeleitet. Die zentrale Methode jeder Action Klasse ist die execute() Methode.
Ein bereits implementierter Standard Controller liegt dem Struts Framework
bei.
Nachdem die execute() Methode einer Action Klasse ausgeführt worden
ist, gibt diese einen Schlüssel in Form eines Strings an den Controller zurück.
Diesen verwendet der Controller, um einen View auszuwählen, der das Resultat der Verarbeitung aus dem Action Objekt darstellt. Abbildung 5.1 zeigt
diesen Verarbeitungsvorgang :
Abbildung 5.1: Struts Controller
Seit der Version 1.1 wurde die Verarbeitungslogik aus der Klasse ActionServlet
in die Klasse RequestProcessor ausgelagert. Auf die Enwicklung einer Webanwendung mit Struts hat dies jedoch keine Auswirkung (vgl. [JakartaStruts, 2004]). Damit auch mehrere verschiedene Controller innerhalb einer
Webanwendung eingesetzt werden können, bietet Struts eine ActionMapping
Klasse an. Hier kann ein URI definiert werden, der bestimmt, welcher Controller bei einem bestimmten Request angesprochen werden soll. Es ist üblich
57
Frameworks
Frameworks
dafür eine einheitliche Endung zu verwenden. .do könnte eine Endung für
ein ActionMapping sein. Die URL www.beispiel.de/zeigeWetterDaten.do
würde dazu führen, dass dieser Request an den Controller delegiert wird, der
an den Pfad .do angebunden ist, und dass dieser den Request an seine Action
zeigeWetterDaten delegiert. Diese und weitere Festlegungen von Seiten des
Entwicklers werden in einer Datei mit dem Namen struts-config.xml definiert. Mit Hilfe dieser Datei wird bei einer beginnenden Session der Controller
initialisiert. Diese Vorgehensweise wird Pluggable Initialization genannt. Eine struts-config.xml Datei könnte beispielhaft wie folgt definiert sein:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean
name="neuesKontoForm"
type="pero.diplom.kontofuehrung.web.forms.NeuesKontoForm"/>
</form-beans>
<global-forwards>
<forward name="zeigeKonten" path="/zeigeKonten.do"/>
</global-forwards>
<action-mappings>
<action
path="/zeigeKonten"
type="pero.diplom.kontofuehrung.web.actions.ZeigeKontenAction"
unknown="false"
validate="true">
<forward
name="success"
path="/pages/zeigeKonten.jsp"
redirect="false"/>
</action>
<action
path="/neuesKonto"
type="org.apache.struts.actions.ForwardAction"
parameter="/pages/neuesKonto.jsp" />
</action-mappings>
<message-resources parameter="resources.application"/>
</struts-config>
Ein weiterer wichtiger Bestandteil des Struts Frameworks sind ActionForms.
ActionForms dienen der Verarbeitung von Benutzereingaben, die zuvor in
HTML Formularen eingegeben worden sind. ActionForms werden von der
Klasse ActionForm abgeleitet. Sie unterscheiden sich zunächst kaum von
einem einfachen JavaBean mit Member Variablen und set und get Methoden, haben allerdings ableitbare Methoden wie validate(), um Eingaben zu prüfen. Diese müssen in der struts-config.xml Datei angemeldet
58
Frameworks
Frameworks
werden. Es können auch ActionForms allein durch eine Deklaration in der
struts-config.xml Datei erzeugt werden. Der Controller generiert eine entsprechende, von der DynaActionForm Klasse abgeleitete, Klasse bei seiner
Initialisierung. DynaActionForms sind daher sehr praktisch, jedoch weniger performant als ActionForms, da sie Reflektion einsetzen (vgl. [Shenoy,
2004]). Reflektion ist ein Verfahren, dass nur die Sprache Java bietet. Reflektion ermöglicht, dass Java Klassen sich selbst zur Laufzeit untersuchen
und verändern. So kann eine Java Klasse die Namen ihre Member Variablen abrufen und ausgeben. (vgl. [McCluskey, 1998]) Die Verwendung von
ActionForms wird daher empfohlen. Abbildung 5.2 zeigt eine Übersicht der
Bestandteile des Struts Frameworks als UML Klassendiagramm:
Abbildung 5.2: Struts Controller UML Klassendiagramm
Abbildung 5.3 zeigt die Arbeitweise von Struts als UML Sequenzdiagramm:
59
Frameworks
Frameworks
Abbildung 5.3: Struts Controller UML Sequenzdiagramm
5.1.3
Actions für den Navigationsfluss
Actions können als Adapter zwischen Web-Schicht und Geschäftslogik gesehen werden. Sie nehmen Eingaben aus der Web-Schicht auf und übergeben
sie verändert oder unverändert an die Geschäftslogik weiter. Da Actions Java
Klassen sind, sind dem Entwickler keine Grenzen gesetzt selbst in Actions
Geschäftslogik abzubilden. Um Code hinsichtlich verschiedener Anforderungen zu isolieren, sollten Actions jedoch lediglich folgende Aufgaben erfüllen
(vlg. [Husted, 2003]):
• Validierung von Vorbedingungen und Regeln
• Aufruf von Geschäftslogik
• Erkennen von Verarbeitungsfehlern
• Übergabe der Kontrolle an einen geeigneten View
Diese Vorgehensweise hat weitreichende Vorteile (vgl. [Husted, 2003]):
• Bei Arbeiten an den Action Klassen kann die Geschäftslogik, die unter
Umständen auch bei anderen System eingesetzt wird, nicht ungewollt
beschädigt werden.
60
Frameworks
Frameworks
• Kürzere Programmcodes ermöglichen eine bessere Übersichtlichkeit.
• Die separate Geschäftslogik kann auch für andere Front-End Technologien eingesetzt werden.
• Die separate Geschäftslogik kann auch in anderen Action Klassen verwendet werden.
Innerhalb von Actions können weitere vordefinierte Objekte eingesetzt werden, um Fehlermeldungen zu erzeugen und zu registrieren (ActionErrors und
ActionError). Diese können innerhalb eines View herangezogen und ausgegeben werden. MessageResources ähneln ActionErrors, sind aber für Nachrichten an den Benutzer gedacht, die keine Fehlermeldungen sind.
Actions können die Kontrolle direkt an ein View übergeben; es können aber
auch ActionForwards eingesetzt werden. ActionForwards werden ebenfalls in
der struts-config.xml Datei angelegt. Sie haben einen frei wählbaren Namen und einen Pfad. Der Pfad ist eine URI zu einem View, wie beispielsweise
zu einer JSP Datei (pages/views/anzeige.jsp). Die Action Klassen übergeben die Kontrolle an ein ActionForward, indem sie diesen über seinen Namen
referenzieren. Der ActionForward übergibt anschließend die Kontrolle an das
View. Da besonders bei größeren Anwendungen häufig auf dieselben Views
verwiesen wird, hat die Verwendung von ActionForwards den Vorteil, dass
eine mögliche Änderung des Pfades nur einmal zentral in der ActionForward
Deklaration notwendig ist. ActionForwards werden auch als Platzhalter für
noch nicht geschriebene Actions genutzt. Für spezielle Fälle existieren weitere
Action Typen (vgl. [Husted, 2003]):
• IncludeAction
• BaseAction
• DispatchAction
• LookupDispatchAction
• SwitchAction
• SuccessAction
• ReplayAction
• ParameterAction
• FindForwardAction
• BaseHelperAction
• ProcessAction
61
Frameworks
Frameworks
• AttributeExistsAction
• RemoveAttributeAction
Die Verwendung der zusätzlichen Action Typen ist nicht zwingend notwendig. Sie helfen jedoch den Programmcode zu reduzieren und die Anwendung
stabiler zu machen (vgl. [Husted, 2003]). Dies soll ein einfaches Beispiel demonstrieren :
Eine Aufgabe besteht darin, dass dem Benutzer über ein HTML Formular
ermöglicht wird, einen Datensatz mit allen CRUD Methoden zu manipulieren. Die Aufgabe wird durch mehrere Actions gelöst. Ein Hidden Input Feld
im HTML Formular ist gesetzt und dessen Wert (Value) entscheidet nach einem Submit innerhalb der ersten Action Klasse, welche der CRUD-Methoden
beziehungsweise welche folgende Action aufgerufen wird. Umgesetzt wird dies
mit if und else Anweisungen in der execute() Methode der ersten Action
Klasse. Für alle CRUD Methoden werden somit fünf Action Klassen benötigt.
Eine andere Lösung verwendet DispatchAction. DispatchAction nutzt zum
einen automatisch das Hidden Input Feld als Schlüssel, zum anderen Reflektion um fragile if- und else- Abfragen zu ersetzen. Zudem können bei
einer DispatchAction mehrere Methoden definiert werden, so dass alle CRUD
Methoden in einer einzigen DispatchAction vereinigt werden können.
5.1.4
Formularverarbeitung und Validierung
HTML Formulare bestehen aus mehreren verschiedenartigen Feldern, die
vom Benutzer Eingabe, Auswahl oder Setzung fordern. Jedes Formular besitzt eine Resource als Ziel in Form einer URI und kann an dieses Ziel abgesendet werden (Submit). Das Resultat eines Submits ist zum einen die Anzeige der als Ziel definierten Ressource, welche eine HTML Seite, ein Servlet
oder Ähnliches sein kann, und zum anderen eine Umwandlung der HTML
Felder in URL Parameter. Diese Parameter können von der Ressource, beispielsweise durch Parsing bei CGI, gelesen und verarbeitet und somit alle
Informationen aus den Feldern des Formular abgegriffen werden. JavaServer
Pages bieten nach einem Submit das Objekt (request) an, über welches,
mit dem Namensbezeichnern der Felder als Schlüssel, die Werte aus den
Parametern abgefragt werden können. Empfehlenswert ist die Nutzung von
JavaBeans zum Mapping des gesamten Formulars auf ein Objekt. Dadurch
repräsentiert ein JavaBean ein Formular und erleichtert den späteren Zugriff
auf die Daten.
ActionForms in Struts sind Objekte zum Mapping von Formularen. Neben
dem reinen Mapping bieten ActionForms die Möglichkeit der Validierung der
Benutzereingaben. Dazu kann die Methode validate() abgeleitet und in einer Implementation die Member Variablen auf Richtigkeit geprüft werden.
62
Frameworks
Frameworks
ActionForms werden an Actions gebunden, damit im Falle einer erfolgreichen Validierung die Kontrolle an die entsprechende Action weitergegeben
werden kann. In der Action Klasse besteht nun die erneute Möglichkeit der
Validierung. Der Grund dafür ist, dass Benutzereingaben häufig auf unterschiedliche Weise validiert werden müssen. So empfiehlt es sich, innerhalb
eines ActionForms zu überprüfen, ob beispielsweise überhaupt eine Eingabe
erfolgt ist, oder ob ausschließlich Ziffern in ein Feld, dass eine Telefonnummer abfragt, eingegeben wurden. In der Action dagegen muss die Eingabe
gegen die Geschäftslogik validiert werden, wie etwa, ob eine Überweisung den
Kontostand eines Konto überschreitet und somit nicht ausführbar ist.
Grundsätzlich sollte dem Benutzer bei einer nicht erfolgreichen Validierung
die Möglichkeit gegeben werden, seine Eingaben zu korrigieren, und sinnvollerweise sollten die bereits gemachten Eingaben für den Benutzer nicht verloren gehen. Das vorherige Ausfüllen der Formulare mit bereits erhaltenen
Benutzereingaben wird Repopulating genannt und erfolgt bei der Nutzung
von ActionForms automatisch.
ActionForms ermöglichen durch die Validierungsmechanismen und das automatische Mapping eine rasche und stabile Verarbeitung von Benutzereingaben, die sicherlich zu den am häufigsten erforderlichen Aufgaben bei der
Entwicklung von Webanwendungen gehört. (vgl. [Husted, 2003])
Als Ersatz für die programmierte Validierung in ActionForm Klassen bietet
Struts ein Validation Plugin. Dabei werden zentral in einer weiteren XML
Konfigurationsdatei (validation.xml) Regeln zur Prüfung von Eingabefeldern definiert. Die Regeln können die Notwendigkeit einer Eingabe, die Typkonformität, die Entsprechung auf einen vom Entwickler angegeben regulären
Ausdruck und mehr überprüfen. (vgl. [Jakarta-Struts, 2004])
Ein Plugin in Struts wird deklariert und initialisiert wie alle anderen Komponenten. Es besteht auch die Möglichkeit zur Entwicklung von eigenen Plugins.
Ein häufig genutztes Plugin für Struts ist Tiles. Tiles bedeutet ”Kacheln” und
beschreibt die Aufteilung von Views in fest definierte Bereiche, wie es schon
zu den Anfängen der Programmierung von HTML Webseiten mit Server
Side Includes möglich war. Diese Vorgehensweise erspart redundanten Darstellungscode. JavaServer Pages bieten JSP Includes, die in Form von XML
Tags innerhalb von JSP Seiten eingesetzt werden und untergeordnete Resourcen wie HTML Seiten und JSP Dateien einbinden. Das Tiles Framework
ist eine erweiterte Form von JSP Includes. Ein Layout definiert die generelle
Aufteilung in Templates. Der Vorteil von Tiles gegenüber JSP Includes ist,
dass Tiles die Pfade zu den Resourcen, genau wie ActionForms in Struts,
kapselt. Struts kann über die Namen der Tiles die definierten Darstellungsbereiche (Tiles) ansprechen. Zudem wird die Übergabe von Parametern und
Objekten an in die einzelnen Unterbereiche (Subviews) automatisch bei der
63
Frameworks
Frameworks
Verarbeitung generiert. Bei komplexeren Anwendungen sind häufig sehr viele
Übergaben notwending, daher reduziert diese Eigenschaft den Programmcode und erhöht dadurch die Übersichtlichkeit. Struts Anwendungen können
auch JSP Includes verwenden. Aus den oben genannten Gründen ist der
Einsatz von Tiles jedoch praktikabler. (vgl. [Jakarta-Struts, 2004])
5.1.5
Lokalisierung
Das zentrale Objekt jeder Java Anwendung für die Internationalisierung
ist das Locale Objekt (java.util.Locale). Das Local Objekt enthält immer eine Kombination einer Landessprache, eines Landes und einer Variante (Locale(String language, String country, String variant)). Die
Sprachen und Länder sind durch die ISO Standards ISO-3166 und ISO-639
definiert (vgl. [Sun-Locale, 2004]). Die Definition zur Variante lautet wie
folgt:
”The variant argument is a vendor or browser-specific code. For example,
use WIN for Windows, MAC for Macintosh, and POSIX for POSIX. Where
there are two variants, separate them with an underscore, and put the most
important one first. For example, a Traditional Spanish collation might construct a locale with parameters for language, country and variant as: ”es”,
”ES”, ”Traditional WIN”.” [Sun-J2SE, 2004]
In der Regel wird das Locale Objekt an eine Methode übergeben, die Ausgaben dem Locale Objekt entsprechend formatiert. Das Locale Objekt dient
also nur als Identifikator und ist unveränderbar. Wenn eine andere Landessprache für die Ausgabe einer Anwendung verwendet werden soll, muss daher
das bestehende Objekt durch ein neues ersetzt werden. Struts ermittelt automatisch anhand des Webclients zum Beginn einer Session ein Locale Object,
welches dann später ausgetauscht werden kann, um die Ausgabe in einer anderen Landessprache auszugeben.
Damit nicht innerhalb des Programmcodes der Anwendung die Ausgaben
in den jeweiligen Landessprachen enthalten sind, werden ResourceBundles
eingesetzt. Die Java ResourceBundle Klasse (java.util.ResourceBundle)
ermöglicht es, dass sämtliche Texte zur Beschreibung von Elementen der Benutzeroberfläche und Nachrichten an den Benutzer separat in Text-Dateien
angelegt werden. Die Text-Dateien werden auch Property-Dateien genannt.
Für jede Landessprache, die die Anwendung unterstützen soll, wird eine
Property-Datei angelegt. Die Property-Dateien bestehen aus Schlüsseln und
Texten, separiert mit einem Gleichheitszeichen, die alle dieselben Schlüssel
aber lokalisierte Texte in der jeweiligen Landessprache enthalten. Dadurch
können innerhalb des Programmcodes die Schlüssel als Platzhalter verwendet
werden. Struts verwendet die Schlüssel bei der Verarbeitung eines Requests,
um sie mit dem entsprechendem lokalisierten Text aus den Property-Dateien
64
Frameworks
Frameworks
zu ersetzen. Die Standard-Property-Datei application.properties wird in
der struts-config.xml Datei angemeldet. Diese sollte auch verwendet werden, wenn die Anwendung zunächst nur eine Landessprache unterstützen
soll. Der Grund ist, dass zum einen Texte innerhalb von Programmcode
schwierig aufzufinden sind, zum anderen kann durch das Hinzufügen einer
weiteren Property-Datei die Ausgabe der Anwendung in weiteren Sprachen
einfach realisiert werden. Weitere lokalisierte Property-Dateien werden mit
einem Postfix versehen, die eine Sprache identifizieren. Beispiele dafür sind
application de DE.properties für Deutsch oder application fr FR.properties
für Französisch. (vgl.[Jakarta-Struts, 2004]
5.1.6
Übergabe von Objekten an Views
Um Resultate von Operationen darzustellen, werden Objekte, hauptsächlich
JavaBeans, in Scope Objekten zwischengespeichert. Scope Objekte bietet
jeder JavaServer Pages Web Container an. Sie sind Maps und lassen es daher
zu, dass Objekte von unterschiedlichen Klassen mit Hilfe von Schlüsseln in
dasselbe Scope Objekt abgelegt werden können. Referenzen der abgelegten
Objekte können über den entsprechenden Schlüssel in Views erstellt werden.
Damit kein Java Programmcode innerhalb des Views benötigt wird, bietet
Struts eine Bean Tag Library an. Das Beispiel zeigt die Ausgabe eines Vectors
mit einer Iteration über mehrere Konto Javabeans:
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<logic:iterate id="konto" name="konten">
<bean:write name="konto" property="kontonummer"/>
<bean:write name="konto" property="kontostand"/>
</logic:iterate>
Für die Iteration über den Vector wurde die Struts Logic Tag Library verwendet. Iterationen können auf diese Weise auf alle von der Collection Klasse abgeleiteten Klassen durchgeführt werden. Die drei Scope Objekte sind
application, session und request. Sie unterscheiden sich hauptsächlich
durch ihre unterschiedliche Lebensdauer voneinander.
5.2
Views mit Tag Libraries und HTML
Für Views können unterschiedliche Technologien eingesetzt werden. XML/XSLT
kann zur Darstellung eingesetzt werden, aber auch Frameworks wie Velocity,
eine Template Engine vom Jakarta Project. Einen gravierenden Unterschied
macht der Einsatz dieser Technologien bezüglich der Model 2 Architektur
und Multi-Tier Webanwendungen für Unternehmen nicht. Beide realisieren
auch nicht das Composite oder das Strategy Entwurfsmuster (siehe Kapitel
65
Frameworks
Frameworks
2). Eine weitere, bereits erwähnte, Möglichkeit ist der Einsatz von JavaServer
Pages mit HTML und Tags Libraries. Ein View, das HTML und Tag Libs
verwendet, besteht somit ausschließlich aus Markup wie folgendes Beispiel
zeigt:
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<html:form
action="neuesKontoSpeichern"
name="neuesKontoForm"
type="pero.diplom.kontofuehrung.web.forms.NeuesKontoForm">
<table border="0">
<tr>
<td>
<bean:message key="app.ersteinzahlung" />:
</td>
<td>
<html:text property="kontoStand" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
<html:submit />
</td>
</tr>
</table>
</html:form>
Die gezeigte JSP Datei ist durch den Controller von der Verwaltung des Navigationsflusses, der Verarbeitung von Formularen, dem Aufruf von Geschäftslogik und dergleichen entlastet. Tags Libraries, die nicht zu Struts gehören,
wie beispielsweise die Java Standard Tag Library (JSTL), können ebenfalls
verwendet werden. (vgl. [Jakarta-Struts, 2004])
5.3
Erweiterung von Views mit Tiles
Tags, die das Tiles Framework verwendet, können eingesetzt werden, um
Redundanzen in Views zu reduzieren. Das folgende Beispiel zeigt das anhand
eines Templates. Zuvor wurde ein Tiles Layout mit drei Templates ( head,
menu und body) angelegt.
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-tiles" prefix="tiles" %>
<tiles:insert page="/pages/common/layouts/layout.jsp" flush="true">
<tiles:put name="header" value="/pages/common/tiles/header.jsp" />
<tiles:put name="menu" value="/pages/common/tiles/menu.jsp" />
<tiles:put name="body" type="string">
<html:form
action="neuesKontoSpeichern"
name="neuesKontoForm"
type="pero.diplom.kontofuehrung.web.forms.NeuesKontoForm">
<table border="0">
66
Frameworks
Frameworks
<tr>
<td>
<bean:message key="app.ersteinzahlung" />:
</td>
<td>
<html:text property="kontoStand" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
<html:submit />
</td>
</tr>
</table>
</html:form>
</tiles:put>
</tiles:insert>
Die ersten beiden tiles:put Tags fügen immer wieder verwendete Templates
dem View hinzu. Diese beiden Templates sind selbst auch Views (header.jsp
und menu.jsp). Der hier gezeigte View definiert sich selbst als body-Template
des Layouts. Das entsprechende Tiles Layout legt die Positionen der Templates innerhalb einer HTML Seite fest:
<%@ taglib uri="/tags/struts-tiles" prefix="tiles" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<html>
<head>
<title><bean:message key="app.title" /></title>
<html:base/>
<link rel="STYLESHEET" type="text/css"
href="<html:rewrite page=’/assets/styles/kfmain.css’/>">
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td colspan="3" background="<html:rewrite page=’/images/mastbackground.jpg’/>">
<tiles:insert attribute="header"/>
</td>
</tr>
<tr>
<td valign="top"><tiles:insert attribute="menu"/></td>
<td><html:img page="/images/t1.gif" width="20" height="1"/></td>
<td width="100%" height="100%" valign="top"><br/><br/><tiles:insert attribute="body"/></td>
</tr>
</table>
</body>
</html>
5.4
Struts mit EJB Model
Struts ist kein Framework für Geschäftslogik oder den Datenzugriff und spielt
somit keine Rolle bei der Implementation der Model-Schicht einer Model 2
67
Frameworks
Frameworks
Webanwendung (vgl. [Husted, 2003]). Eine auf Enterprise JavaBeans basierende J2EE Anwendung bietet jeder Anwendung die Möglichkeit, ihre verteilte Geschäftslogik über die JNDI oder CORBA Schnittstelle anzusprechen
(Kapitel 4.4.1). Somit kann auch eine Struts Webanwendung Enterprise JavaBeans ansprechen und die dort abgebildete Geschäftslogik für ihre Zwecke
einsetzen.
5.4.1
JNDI Lookups in Actions
Um auf ein auf Enterprise Java Beans basierendes Model zuzugreifen, werden,
wie in Kapitel 4.1.3 beschrieben, JNDI Lookups verwendet. Da Actions für
das Aufrufen von Geschäftslogik verantwortlich sind, werden Lookups in der
im folgenden Beispiel gezeigter und ähnlicher Form innerhalb der execute()
Methode in Actions durchgeführt:
Properties props = System.getProperties();
Context ctx = new InitialContext(props);
Object obj = ctx.lookup("ejb/beispiel/KontoVerwalter");
KontoVerwalterHome home = (KontoVerwalterHome)
PortableRemoteObject.narrow(obj, KontoVerwalterHome.class);
Kontoverwalter kontoverwalter = home.create();
In dem Beispiel wird ein Remote Session Bean mit dem Namen Kontoverwalter angesprochen. Nun können Methoden des Beans aufgerufen werden.
5.4.2
Übergabe von Entity Beans an Views
Die Struts Tag Library zur Ausgabe von JavaBeans kann, auf gleiche Art und
Weise wie bei JavaBeans, Member Variablen von EJB Entity Beans ausgeben
(vgl. [Jakarta-Struts, 2004]). So ist die Übergabe von Entity Beans an Views
möglich, um Resultate von Operationen aus der Geschäftslogik darzustellen.
Tags der Struts Bean Tag Library beginnen mit dem Prefix <bean: und
wurden zuvor in der Beispielen verwendet.
68
Teil II
Eine Beispiel-Anwendung
69
Einführung Beispiel
Einführung
Kapitel 6
Einführung
6.1
Kontoführung als Beispiel
Eine an die Kontoführung für Privatkunden einer Bank angelehnte Beispielanwendung soll die im ersten Teil der Arbeit vorgestellte mehrschichtige
Architektur für Webanwendungen unter Verwendung des Struts Frameworks
und der J2EE Plattform in der Praxis zeigen. Dazu wurde eine Anwendung
entworfen, die nur einige mögliche, kurze und in der realen Welt in der Form
nicht vorkommende Geschäftsprozesse abbildet. Die vorrangigsten Ziele sind
die Trennung von Code hinsichtlich verschiedener Anforderungen und die
Verwendung von Enterprise Technologien. Es werden Methoden der Codegenerierung, ein Entwurfsmuster für performante Kommunikation in der verteilten Umgebung und Objekt-Relationales-Mapping für die persistente Speicherung von Daten vorgestellt.
Die Anwendung setzt sich aus folgenden Geschäftsprozessen zusammen:
1. Kontoeröffnung. Eine Kontonummer wird generiert und der Benutzer
gibt einen Betrag als Ersteinzahlung ein. Anschließend wird ein neues
Konto erschaffen.
2. Kontenansicht. Alle Konten werden angezeigt. Dargestellt werden
zunächst die Kontonummer und der Kontostand. Wird ein Konto ausgewählt, werden Detailinformationen des Kontos angezeigt. Diese bestehen aus einer Auflistung der Kontobewegungen.
3. Interne Überweisung. Der Benutzer hat die Möglichkeit, Beträge
von einem Konto auf ein anderes zu verschieben. Eine Überschreitung
des Kontostandes wird nicht zugelassen.
4. Externe Überweisung. Der Benutzer kann ein Formular für einen
fiktiven externen Überweisungsauftrag ausfüllen. Der Betrag wird von
einem Konto abgezogen. Eine Überschreitung des Kontostandes wird
auch hier nicht zugelassen.
70
Einführung Beispiel
Einführung
5. Kontoauflösung. Konten können gelöscht werden, wenn kein Betrag
mehr auf dem Konto vorhanden ist. Falls ein Betrag vorhanden sein
sollte und noch ein weitere Konto existiert, kann die Auflösung durch
eine interne Überweisung des Restbetrages erfolgen. Ist kein anderes
Konto vorhanden, wird eine Auflösung nicht gestattet.
Die Anwendung soll die Verwendung von Struts mit den beiden Plugins Tiles und Validator zeigen. Zur Darstellung werden Tag Libraries und HTML
verwendet. Sowohl Views als auch Controller befinden sich innerhalb eines
Web Containers. Das Model der Anwendung besteht aus verteilten Business
Objects (Enterprise Java Beans), die sich zur Laufzeit innerhalb eines Application Servers befinden. Der Geschäftsprozess ”Interne Überweisung” soll neben grundlegenden technischen Eigenschaften und Möglichkeiten dieser Architektur die Funktionen des Struts Messagings zeigen. Der Geschäftsprozess
”Externe Überweisung” zeigt die Verwendung von ActionForms mit einer Validierung. ”Kontoauflösung” zeigt die Möglichkeiten der Navigationsflusskontrolle. ”Kontoeröffnung” und ”Kontenansicht” dienen lediglich zur Erstellung
von neuen Konto Objekten und geben dem Benutzer die Möglichkeit seine
vorangegangener Aktionen nachzuvollziehen (Auflistung der Kontobewegungen).
6.2
Session Façade zur Optimierung des EJB
Models
Ein abgebildeter Geschäftsprozess erfordert die Ausführung von Geschäftslogik, so dass in der Regel auf mehrere Session und Entity Beans zugegriffen
werden muss. Bei einer verteilten Anwendung stellt die dadurch erforderliche Zahl von Aufrufen über das Netzwerk ein Problem dar. Wie in Kapitel
4 beschrieben, ist der Remote Zugriff auf ein verteiltes Objekt ein komplexer Prozess, der mehrere Akteure erfordert, und somit verglichen mit einem
lokalen Zugriff sehr zeitintensiv. Ein vereinfachtes Beispiel kann das verdeutlichen:
Ein Benutzer authentifiziert sich bei einem Kontoführungssystem und überweist von einem Konto einen Betrag auf ein anderes Konto. Zunächst wird
über ein Login (Primärschlüssel für Benutzer) der Benutzereintrag gesucht.
Anschließend wird das Passwort überprüft, dann die Konten gefunden und
schließlich der Betrag vom ersten Konto abgezogen und dem anderen Konto
gutgeschrieben. Abbildung 6.1 zeigt das entsprechende Sequenzdiagram :
71
Einführung Beispiel
Einführung
Abbildung 6.1: Überweisung mit Entity Beans
Dieses Szenario erfordert sechs Aufrufe über das Netzwerk. Für den performancekritischen Einsatz wäre diese Konstruktion nicht geeignet. Zudem
erfordert jeder Zugriff auf ein Entity Bean eine eigene Transaktion. Das Entwurfsmuster Session Façade bietet eine Möglichkeit, die Kommunikation zu
reduzieren :
”The Session Façade abstracts the underlying business object interactions
and provides a service layer that exposes only the required interfaces. Thus,
it hides from the client’s view the complex interactions between the participants. The Session Façade manages the interactions between the business
data and business service objects that participate in the workflow, and it
encapsulates the business logic associated with the requirements. Thus, the
session bean (representing the Session Façade) manages the relationships between business objects. The session bean also manages the life cycle of these
participants by creating, locating (looking up), modifying, and deleting them
as required by the workflow.” [Sun-CJ2EEP, 2004]
Bei der Session Façade wird eine Schicht von Session Beans, auf die über
ein Netzwerk zugegriffen werden kann, eingesetzt. Ein Zugriff auf die Entity
Beans erfolgt nur über Methoden dieser Session Beans. Das Resultat sind
zum einen seltenere Zugriffe über das Netzwerk, zum anderen eröffnet sich
die Möglichkeit, einen Geschäftsprozess in einer einzigen Transaktion zusammenzufassen. Abbildung 6.2 zeigt die reduzierte Kommunikation über das
Netzwerk, die durch den Einsatz einer Session Façade entsteht:
72
Einführung Beispiel
Einführung
Abbildung 6.2: Vergleich Zugriff mit und ohne Session Façade
Die Überweisung aus dem vorangegangenen Beispiel kann mit einer Session
Façade durch lediglich einen Aufruf über das Netzwerk erfolgen (Abbildung
6.3):
Abbildung 6.3: Überweisung mit Session Façade
6.3
Objekt-Relationales Mapping und EJB Entwurf
In Kapitel 4 wurde Objekt-Relationales Mapping erwähnt, um Entity Beans
persistent in einer relationalen Datenbank zu speichern. CMP erlaubt zwar
die automatische Generierung von Persistenzlogik, der Entwurf der Datenbank bleibt jedoch weiterhin dem Entwickler überlassen. Das im Folgenden
vorgestellte Verfahren ”Objekt-Relationales Mapping” beschreibt die Umwandlung eines objektorientierten Entwurfs in ein Entity-Relationship Modell.
73
Einführung Beispiel
Einführung
Für jede Entity Bean Klasse wird zunächst eine Tabelle angelegt. Die Reihen einer Tabelle repräsentieren ein Entity Bean, die Spalten die Member
Variablen des Entity Beans (vgl. Kapitel 4). Die beim objektorientierten Entwurf übliche Vererbung kann auf drei Arten abgebildet werden (vgl. [Ambler,
2000]):
1. Die Verwendung einer Tabelle für eine gesamte Klassenhierarchie
2. Die Verwendung einer Tabelle für jede konkrete Klasse
3. Die Verwendung einer Tabelle für jede Klasse
Bei der Verwendung einer Tabelle für eine gesamte Klassenhierarchie, wird
für jede in der Klassenhierarchie vorkommende Member Variable eine Spalte
belegt, und eine zusätzliche Spalte angelegt, welche identifiziert zu welcher
Klasse eine Reihe gehört. Die Vorteile dieser Methode sind ihre Einfachheit,
die Unterstützung von Polymorphismus und dass alle Daten in einer Tabelle aufzufinden sind. Sie verwendet jedoch viel ungenutzten Speicherplatz,
aufgrund der ungenutzten Felder, Änderungen müssen mit Vorsicht durchgeführt werden, weil diese leicht andere Objekte unbeabsichtigt beeinflussen
können (starkes Coupling), und es können keine Objekte, die die Eigenschaften mehrerer Klassen aus der Klassenhierarchie vereinigen, erzeugt werden,
da keine identischen Primärschlüssel zulässig sind. (vgl. [Ambler, 2000])
Bei der Möglichkeit des Objekt-Relationalen Mappings, bei der die konkreten
Klassen, auf mehrere Tabellen verteilt, abgebildet werden, wird für jede Member Variablen der übergeordneten abstrakten Klassen eine Spalten belegt. Die
Identifizierung der Klasse über eine zusätzliche Spalte entfällt. Dieses Verfahren ermöglicht, wenn auch unter schwierigen Bedingungen, die sich aus
dem Fehlen der abstrakten Klassen ergeben, die Vereinigung der Eigenschaften mehrerer Klassen. Problematisch ist dabei das redundante Vorkommen
von Member Variablen, die von abstrakten Klassen geerbt wurden. Änderungen an den abstrakten Klassen sind aufwendiger als bei der Verwendung
einer Tabelle für die gesamte Klassenhierarchie, da sie in mehreren Tabellen
angeglichen werden müssen. Die Tabellen sind jedoch übersichtlich und die
Implementation kaum schwieriger als bei dem Mapping aller Klassen auf eine
Tabelle. (vgl. [Ambler, 2000])
Das dritte Verfahren entspricht am meisten der objektorientieren Modellierung. Für jede Klasse wird eine Tabelle angelegt. Änderungen an Superklassen sind leicht durchzuführen, Polymorphismus ist möglich und es können auf
einfache Weise Eigenschaften mehrerer Klassen vereinigt werden. Die größere Zahl an Tabellen ist unter Umständen schwieriger zu überschauen, aber
viel schwerwiegender sind die Probleme beim Zugriff auf die Daten. Selbst
einfache Datenbankabfragen erfordern komplexe JOIN Statements und sind
somit bei der Durchführung zeitaufwendiger. (vgl. [Ambler, 2000])
74
Einführung Beispiel
Einführung
Alle drei Verfahren haben Stärken und Schwächen, folgende Matrix zeigt eine
Übersicht (vgl. [Ambler, 2000]):
Methode 1
Methode 2
Methode 3
Übersichtlichkeit
gut
befriedigend
ungenügend
Implementation
einfach
mittel
schwierig
Datenzugriff
einfach
einfach
mittel/schwierig
Coupling
sehr stark
stark
schwach
Performance
gut
gut
befriedigend
Polymorphismus
befriedigend
ungenügend
gut
Die vier Arten von Objektbeziehungen sind Vererbung, Assoziation, Aggregation und Komposition. Die Beziehungen Assoziation, Aggregation und Komposition werden mit Datenbankrelationen abgebildet, Vererbungsbeziehungen mit einem der oben beschriebenen Verfahren zum Mapping von Objekten.
Aggregation und Komposition machen beim Objekt-Relationalen Mapping
keinen Unterschied. Assoziation und Aggregation/Komposition unterscheiden sich lediglich darin, dass in der Regel bei einer Aggregation/Komposition
das Einlesen aller in dieser Beziehung stehender Objekte gewünscht ist. Dasselbe gilt auch für das Speichern und Löschen (kaskdadierendes Löschen). Auf
diesen Unterschied muss im Fall der Entity Beans bei der Implementation von
ejbFind() Methoden, bzw. deren Konfiguration bei CMP, geachtet werden.
Bei dem Entwurf der Datenbank werden alle Beziehungen gleich behandelt
und die Relationen mit Hilfe von Fremdschlüsseln umgesetzt. So wird bei einer unidirektionalen 1:1 Beziehung zwischen zwei Klassen ein Fremdschlüssel
in der Tabelle angelegt, die die Klasse repräsentiert, die Kenntnis über die
andere Klasse hat. Beim relationalen Entwurf ist dies die Tabelle von der aus
der Pfeil ausgeht. Bei bidirektionalen Beziehungen werden in beide Tabellen
Fremdschlüssel eingesetzt. Ähnlich wird bei 1:n Beziehungen verfahren, nur
dass dort der Fremdschlüssel immer in die Tabelle eingesetzt wird, aus der n
Elemente in Beziehung stehen. Für eine m:n Beziehung muss eine zusätzliche,
assoziative Tabelle angelegt werden, die die Primärschlüssel beider in m:n Beziehung stehender Tabellen als eigenen Primärschlüssel enthält (Singular, da
zwei als Primärschlüssel gekennzeichnete Attribute einen Primärschlüssel für
die Tabelle bilden). Wenn der erste Teil des Primärschlüssels aus der Tabelle
A stammt und der zweite aus der Tabelle B, dann muss eine 1:n Beziehung
zwischen Tabelle A und assoziativer Tabelle sowie eine m:1 Beziehung zwischen assoziativer Tabelle und Tabelle B angelegt werden (siehe Abbildung
6.4). (vgl. [Ambler, 2000])
75
Einführung Beispiel
Einführung
Abbildung 6.4: Relationales Mapping von m:n Objektbeziehungen
Für die Beispielanwendung wurde zunächst folgender objektorientierter Entwurf (Abbildung 6.5) entwickelt:
Abbildung 6.5: Objektorientierter Entwurf für die Beispielanwendung
Zur Auflösung der Vererbungsbeziehung (Klassenhierarchie unter der Superklasse Überweisung) wurde eine Tabelle verwendet. Abbildung 6.6 zeigt den
relationalen Datenbankentwurf:
76
Einführung Beispiel
Einführung
Abbildung 6.6: Relationales Mapping für die Beispielanwendung
Kombiniert mit der Implementation des Session Façade Entwurfmusters (Kommunikation erfolgt nur über Session Bean - siehe Kapitel 6.2), wurde das
folgende in Abbildung 6.7 gezeigte Enterprise JavaBeans Modell umgesetzt:
Abbildung 6.7: Bean Implementation für das Beispiel
6.4
Navigationsfluss und Eingabeverarbeitung
Der Teil der Webanwendung, der mit Struts realisiert wird, kann mit Hilfe
einer Graphik, welche an Petri Netze (vgl. [Aarhus, 2004]) angelehnt ist, modelliert werden. In Petri Netzen repräsentieren Kreise Aktionen und Quadrate
Zustände. Alternierend werden Aktionen und Zustände miteinander verbunden und stellen auf diese Art und Weise einen Use-Case (Anwendungsfall)
dar. In Abbildung 6.8 werden Struts Actions durch Kreise und Views durch
Quadrate repräsentiert. Actions können sich allerdings gegenseitig aufrufen,
um eine schrittweise Verarbeitung eines Requests zu ermöglichen (vgl. Kapitel 5.1.3). Views können auf Views folgen, wenn sie durch einen traditionellen
HTTP Link verbunden werden. Benutzerinteraktionen gehen von einem dargestellten View aus und verursachen die Ausführung einer Action. Ein View
kann ein Formular enthalten, dessen Verarbeitung durch ein ActionForm erfolgt und an eine Action weitergegeben wird. ActionForms sind durch Recht77
Einführung Beispiel
Einführung
ecke zwischen View und Action dargestellt. Wenn ein View Daten aus dem
Model anzeigen soll, beispielsweise die Aufstellung aller persönlichen Konten,
dann muss vorher eine Action die Daten aus dem Model abrufen (vgl. Kapitel 5.1.6). Der erste Request führt die mit dem großen Pfeil gekennzeichnete
Action ZeigeKontenAction aus. Alle am äußersten linken Rand stehenden
Objekte sind über ein Menü jederzeit für den Benutzer ausführbar, d.h. immer wenn ein View dargestellt wird. Das Menü ist ein Template eines Tiles
Layouts (siehe Kapitel 5.3).
Abbildung 6.8: Struts Entwurf
Der Geschäftsprozess ”Kontenansicht” zeigt ein einfaches Aufeinanderfolgen
von Actions auf Views. ”Kontoeröffnung” beginnt mit einem View, führt
dann eine Action aus, die dann die Kontrolle wieder zurück an eine Action ZeigeKontenAction gibt, auf die wieder ein View folgt. ”Interne Über78
Einführung Beispiel
Einführung
weisung” zeigt einen Geschäftsprozess mit einem Formular. ”Externe Überweisung” sammelt hingegen Benutzereingaben mit zwei Formularen. ”Kontoauflösung” zeigt die Verzweigung von einem View auf zwei Actions, sowie
die Verzweigung von einer Action auf zwei mögliche Views.
6.5
Views
Views werden graphisch entworfen. HTML Programmierer können aus den
graphischen Entwürfen die notwendigen Views mit Hilfe von HTML und Tag
Librariers erstellen. Abbildung 6.9 zeigt den für das Beispiel verwendeten
graphischen Entwurf und die geplante Aufteilung in Tiles.
Abbildung 6.9: Tiles Layout und graphischer Entwurf
79
Implementierung
Implementation
Kapitel 7
Implementierung
7.1
Integrierte Entwicklungsumgebung
Für die Bearbeitung von Java Sourcen, HTML und XML wurde die Eclipse
3.0 IDE (http://www.eclipse.org/) verwendet. Als Laufzeitumgebung wurde
der J2EE Application Server JBoss 3.2 (http://www.jboss.org/) mit integriertem Apache Tomcat 4.1 Web Container (http://jakarta.apache.org/tomcat/)
eingesetzt. Das automatische Deployment und die Steuerung der Laufzeitumgebungen wurde über das JBoss-IDE Plugin für Eclipse durchgeführt. Das
Plugin verwendet Apache Ant (http://ant.apache.org/) als Build Tool. Weiter wurde für die UML Modellierung ArgoUML (http://argouml.tigris.org/),
für Tests HTTPUnit (http://httpunit.sourceforge.net/) und JMeter
(http://jakarta.apache.org/jmeter/) und verschiedene Tools aus der J2EE
Distribution (http://java.sun.com/j2ee/) genutzt. Im Folgenden wird die Verwendung von XDoclet (http://xdoclet.sourceforge.net/) zur attributorientierten Programmierung beschrieben. Sämtliche aufgeführte Software ist kostenlos über das Internet beziehbar.
7.2
Attributorientierte Programmierung
Programmiert wurde das Beispiel unter anderem mit Hilfe von XDoclet, einer Software, die attributorientierte Programmierung erlaubt. Dabei werden
innerhalb von Kommentarblöcken in Java Klassen für spezielle Aufgaben
vordefinierte Attribute mit Werten belegt, mit deren Hilfe XDoclet Code generieren kann. XDoclet unterstützt viele verschiedene Technologien. Eingesetzt wurde es hier für die Generierung von Konfigurationsdateien für Struts
und von Hilfklassen für die verteilte Kommunikation von Enterprise JavaBeans sowie für Konfigurationsdateien (Deployment Descriptoren) für die
J2EE Umgebung. Bei Enterprise Java Beans reduziert sich der Aufwand der
Programmierung lediglich auf die Implementation der Bean Klassen. Sämtliche andere Interfaces werden zunächst mit XDoclet automatisch erstellt und
vorbereitet, so dass der Application Server beim Deployment daraus entspre80
Implementierung
Implementation
chende Klassen generieren kann. Aus einigen hundert Zeilen Programmcode
entstehen durch diesen Vorgang mehrere tausend Zeilen Programmcode und
einige hundert Zeilen Konfigurationsdeklarationen, die eine skalierbare und
verteilte Anwendung mit Enterprise JavaBeans ermöglichen. Lediglich die
Geschäftslogik muss vom Entwickler selbst programmiert werden. Folgender
Programmcode zeigt die in der KontoBean Klasse eingesetzten XDoclet Attribute:
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
@ejb.bean description="Konto CMP Bean"
type="CMP"
cmp-version = "2.x"
name="Konto"
schema="Konto"
local-jndi-name="KontoLocalHome"
view-type="local"
primkey-field="id"
@ejb.persistence table-name = "konto"
@ejb.finder signature = "java.util.Collection findAll()"
result-type-mapping = "Local"
method-intf = "LocalHome"
query = "SELECT OBJECT(o) FROM Konto o"
@ejb.transaction type = "RequiresNew"
Den Java Programmcode des Session Beans KontoVerwalterBean zeigt das
folgende Listing (Kommentare entfernt):
package pero.diplom.beispiel.kontofuehrung.ejb;
import java.rmi.RemoteException;
import java.util.Collection;
import
import
import
import
import
import
javax.ejb.CreateException;
javax.ejb.DuplicateKeyException;
javax.ejb.EJBException;
javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.InitialContext;
import
import
import
import
pero.diplom.beispiel.kontofuehrung.interfaces.KontoLocal;
pero.diplom.beispiel.kontofuehrung.interfaces.KontoLocalHome;
pero.diplom.beispiel.kontofuehrung.interfaces.UeberweisungLocal;
pero.diplom.beispiel.kontofuehrung.interfaces.UeberweisungLocalHome;
public class KontoVerwalterBean implements SessionBean {
public double getKontoStand(String id) throws Exception {
InitialContext ctx = new InitialContext();
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
KontoLocal konto = home.findByPrimaryKey(id);
return konto.getKontoStand();
}
public Collection getAllKonten() throws Exception {
InitialContext ctx = new InitialContext();
81
Implementierung
Implementation
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
return home.findAll();
}
public Collection getAusgehendeUeberweisungenIntern(String kontonummer) throws Exception {
InitialContext ctx = new InitialContext();
UeberweisungLocalHome home = (UeberweisungLocalHome)
ctx.lookup(UeberweisungLocalHome.JNDI_NAME);
return home.findByQuellkontonummerIntern(kontonummer);
}
public Collection getAusgehendeUeberweisungenExtern(String kontonummer) throws Exception {
InitialContext ctx = new InitialContext();
UeberweisungLocalHome home = (UeberweisungLocalHome)
ctx.lookup(UeberweisungLocalHome.JNDI_NAME);
return home.findByQuellkontonummerExtern(kontonummer);
}
public Collection getEingehendeUeberweisungen(String kontonummer) throws Exception {
InitialContext ctx = new InitialContext();
UeberweisungLocalHome home = (UeberweisungLocalHome)
ctx.lookup(UeberweisungLocalHome.JNDI_NAME);
return home.findByZielkontonummer(kontonummer);
}
public String createKonto(double kontostand) throws Exception {
InitialContext ctx = new InitialContext();
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
KontoLocal konto = null;
try {
konto = home.create(kontostand);
} catch (DuplicateKeyException dke) {
return this.createKonto(kontostand);
}
return konto.getId();
}
public String createUeberweisung(String quellkontonummer, double betrag,
String empfaenger, String verwendungszweck, String verwendungszweck2,
String zielbankname, String zielbankleitzahl, String zielkontonummer,
String interneueberweisung) throws Exception {
InitialContext ctx = new InitialContext();
UeberweisungLocalHome home = (UeberweisungLocalHome)
ctx.lookup(UeberweisungLocalHome.JNDI_NAME);
UeberweisungLocal ueberweisung = null;
try {
ueberweisung = home.create(quellkontonummer, betrag, empfaenger,
verwendungszweck, verwendungszweck2, zielbankname, zielbankleitzahl,
zielkontonummer, interneueberweisung);
} catch (DuplicateKeyException dke) {
}
return ueberweisung.getId();
}
public String createUeberweisung(String quellkontonummer, double betrag,
String zielkontonummer, String interneueberweisung) throws Exception {
82
Implementierung
Implementation
InitialContext ctx = new InitialContext();
UeberweisungLocalHome home = (UeberweisungLocalHome)
ctx.lookup(UeberweisungLocalHome.JNDI_NAME);
UeberweisungLocal ueberweisung = null;
try {
ueberweisung = home.create(quellkontonummer, betrag,
"", "", "", "", "", zielkontonummer, interneueberweisung);
} catch (DuplicateKeyException dke) {
}
return ueberweisung.getId();
}
public void deleteKonto(String id) throws Exception {
InitialContext ctx = new InitialContext();
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
home.remove(id);
}
public double ueberweiseBetrag(String quellkontonummer, String zielkontonummer,
double betrag) throws Exception {
InitialContext ctx = new InitialContext();
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
KontoLocal quellkonto = home.findByPrimaryKey(quellkontonummer);
KontoLocal zielkonto = home.findByPrimaryKey(zielkontonummer);
if (quellkonto.getKontoStand() < betrag) {
betrag = quellkonto.getKontoStand();
}
quellkonto.setKontoStand(quellkonto.getKontoStand() - betrag);
zielkonto.setKontoStand(zielkonto.getKontoStand() + betrag);
this.createUeberweisung(quellkontonummer, betrag, zielkontonummer, "true");
return betrag;
}
public double zahleBetragEin(String id, double einzahlung) throws Exception {
InitialContext ctx = new InitialContext();
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
KontoLocal konto = home.findByPrimaryKey(id);
konto.setKontoStand(konto.getKontoStand() + einzahlung);
return konto.getKontoStand();
}
public double ueberweiseExtern(String quellkontonummer, double zahlung,
String verwendungszweck, String verwendungszweck2, String empfaenger,
String zielbankname, String zielbankleitzahl, String zielkontonummer) throws Exception {
InitialContext ctx = new InitialContext();
KontoLocalHome home = (KontoLocalHome) ctx.lookup(KontoLocalHome.JNDI_NAME);
KontoLocal konto = home.findByPrimaryKey(quellkontonummer);
konto.setKontoStand(konto.getKontoStand() - zahlung);
this.createUeberweisung(quellkontonummer, zahlung, empfaenger, verwendungszweck,
verwendungszweck2, zielbankname, zielbankleitzahl, zielkontonummer, "");
return konto.getKontoStand();
}
83
Implementierung
Implementation
public void ejbCreate() throws CreateException {
}
public KontoVerwalterBean() {
super();
}
public void ejbActivate() throws EJBException, RemoteException {
}
public void ejbPassivate() throws EJBException, RemoteException {
}
public void ejbRemove() throws EJBException, RemoteException {}
public void setSessionContext(SessionContext arg0)
throws EJBException, RemoteException {
}
}
Das KontoVerwalterBean ist beinhaltet die gesamte Geschäftslogik. Die beiden Entity Beans KontoBean und UeberweisungBean enthalten neben abstrakten set und get Methoden sowie leeren EJB Methodenrümpfen fast
keinen Programmcode und werden daher hier nicht abgebildet.
KontoVerwalterBean besteht zu einem großen Teil aus JNDI Lookups und
nur einigen Zeilen Code, welche die Geschäftslogik ausmachen. Die Persistenzlogik wird von den Entity Beans übernommen, deren Programmcode jedoch wird generiert. Lediglich die zuvor gezeigten XDoclet Attribute müssen
angegeben werden. Da QL und pessimitische Nebenläufigkeitskontrolle eingesetzt wird, ist diese Anwendung zudem datenbankunabhängig.
7.3
Performancetest
Der Geschäftsprozess ”Interne Überweisung” der Beispielanwendung beginnt
mit der Action ZeigeKontenAuswahlAction. Innerhalb der Action wird über
die Hilfsklasse KontoVerwalterUtil ein JNDI Lookup auf das Home Objekt der KontoVerwalterBean Session Beans, die Session Façade Objekte,
durchgeführt. Über die Methode getAllKonten() der Session Beans wird
durch ein weiteres JNDI Lookup das Home Objekt der KontoBean Entity
Beans gefunden und durch die findAll() Methode der Entity Beans eine
Collection aller KontoBeans abgerufen. Die Action speichert diese in das
Session Scope Objekt des Web Containers und übergibt die Kontrolle an
den View ueberweiseBetrag.jsp, welcher mittels Struts Tag Libraries ein
Formular mit Auswahlfeldern für ein Quellkonto und ein Zielkonto, sowie
ein Text Feld für die Eingabe eines Betrages für eine interne Überweisung
darstellt. Die Auswahlfelder werden mit den Daten aus dem im Session Scope gespeicherten Entity Beans, deren Kontonummern, vorbelegt. Durch das
Versenden des Formulars wird die Methode validate() des ActionForms
UeberweisungForm ausgeführt. Hier werden durch vier Abfragen folgende
Überprüfungen durchgeführt:
1. Ist eine Eingabe erfolgt?
84
Implementierung
Implementation
2. Sind Quellkonto und Zielkonto verschieden?
3. Kann die Eingabe in ein Double umgewandelt werden?
4. Ist der Überweisungsbetrag größer 0 EUR?
Wenn eine der Überprüfungen negativ ausfällt, wird das Formular mit entsprechender Meldung zur Nachbesserung der Eingabe angezeigt. Im positiven Falle wird die Action UeberweiseBetragAction ausgeführt. In dieser Action wird, wie in der vorherigen Action, erneut das Session Bean
KontoVerwalterBean angesprochen und anschließend dessen Methode
ueberweiseBetrag aufgerufen. Hier werden über ejbfind Methoden die beiden Konten (Entity Beans) aufgefunden und der eingegebene Betrag in einer Transaktion vom Quellkonto subtrahiert und auf das Zielkonto addiert.
Anschließend wird ein neues UeberweisungBean Entity Bean erzeugt. Die
Action erzeugt eine Nachricht, eine positive Bestätigung für eine erfolgreiche
Überweisung an den Benutzer und übergibt die Kontrolle nicht an ein View
sondern an die zuerst genannte Action ZeigeKontenAuswahlAction. Diese
wird erneut ausgeführt, die Daten der Konten abfragt und zur Darstellung
bereitgestellt und die Kontrolle an das View ueberweiseBetrag.jsp übergeben. Das View stellt zusätzlich die Nachricht über die erfolgreiche Überweisung dar.
Der gerade beschriebene Geschäftsprozess ”Interne Überweisung” besteht
aus einer Vielzahl von Verarbeitungen und Schritten, welche viele Verfahren, Entwurfsmuster und zentrale Bestandteile der vorgestellten Architektur
verwenden :
• Remote Kommunikation auf das Session Bean der Session Façade
• Interne Kommunikation der verteilten Objekte
• Create, Read und Update der CRUD-Methoden
• findAll() und findByPrimaryKey() Methoden
• Container Managed Transaktions (CMT)
• Persistente Speicherung durch Container Managed Persistence (CMP)
in eine relationale Datenbank
• Struts Actions
• Struts ActionForms mit Valdierung
• ActionForwards
• Struts Tag Libraries
• Struts Messaging
85
Implementierung
Implementation
• Ausgabe aller Texte über das ResourceBundle der Lokalisierungsfunktion
Aus diesem Grund wurde dieser Prozess für einen Performancetest mit Apache JMeter (vgl. [JMeter, 2004]) ausgewählt.
”Apache JMeter may be used to test performance both on static and dynamic resources. It can be used to simulate a heavy load on a server, network
or object to test its strength or to analyze overall performance under different load types. You can use it to make a graphical analysis of performance
or to test your server/script/object behavior under heavy concurrent load.”
[JMeter, 2004]
Der Geschäftsprozess ”Interne Überweisung” wurde so entworfen, dass seine
gesamte Verarbeitung durch einen einzigen HTTP Request ausgelöst werden
kann. Eine URL mit Parametern simuliert einen Submit des Überweisungsformulars. Dieser Request löst die zuvor beschriebene Verarbeitung, die interne
Überweisung, aus. Als Response wird das View mit dem Überweisungsformular inklusive der Meldung über die erfolgreich durchgeführte Überweisung
dargestellt. Mit Hilfe von JMeter wurde die Ausführung von 640 Requests pro
Minute simuliert und die Webanwendung wurde 15 Minuten damit belastet.
Bei jedem Request wurde ein Betrag in Höhe von einem Euro überwiesen. Somit wurden während des Tests insgesamt 9600 Euro transferiert. Zu berücksichtigen ist allerdings, dass dieser Test bei laufender Entwicklungsumgebung
inklusive Debugger, dem Application Server, dem Web Container, der Datenbank (MySQL - InnoDB) und JMeter auf einem Rechner mit Windows
XP, einer AMD 2000+ CPU und lediglich 512 MB RAM durchgeführt wurde.
Der Anwendungen standen nur 70 MB freies RAM zur Verfügung. Da sich
sämtliche beteiligte Dienste und Software auf demselben Rechner befanden,
existierte keine Verzögerung durch die Übertragung über HTTP. Dieser Test
ist aus diesen Gründen nicht repräsentativ für eine reale Umgebung und dient
lediglich der Demonstration einer relativ zügigen Verarbeitung eines komplexeren Requests. Der Rechner war durch die gering vorhandenen Ressourcen
nicht in der Lage, mehr als 640 Requests pro Minute zu simulieren. Abbildung 7.1 zeigt den Verlauf des Tests, die Kurve zeigt die durchschnittliche
Verarbeitungsdauer eines Requests zum jeweiligen Zeitpunkt:
86
Implementierung
Implementation
Abbildung 7.1: Durchschnittliche Verarbeitung - JMeter Load Test
Der Tests ergab, dass die durchschnittliche Dauer vom Absenden der Requests bis zum Response 367 Millisekunden betrug. Der Median der Messung
lag bei 359 Millisekunden. Die längste Verarbeitung dauerte 657, die kürzeste 94 Millisekunden. Die Reaktionszeiten wären für eine Webanwendungen
ausreichend schnell, wenn keine zeitkritischen Reaktionszeiten für spezielle
Zwecke erforderlich sind.
87
Teil III
Schlussbetrachtung und
Ausblick
88
Kapitel 8
Ausblick
8.1
8.1.1
MVC in Webanwendungen
JavaServer Faces
Model 2 verwendet die Begriffe Model, View und Controller des MVC Entwurfsmusters, welches seine Anwendung in vielen heutigen GUI Systemen
gefunden hat. Eine Umsetzung der grundlegenden Idee von MVC ist Model 2 nicht, denn MVC bezieht sich rein auf die Architektur einer Benutzeroberfläche. So ist mit Model in MVC nicht etwa die Geschäftslogik einer
Anwendung gemeint, wie es in Model 2 der Fall ist, sondern ein Speicher
für Zustände der Komponenten einer Benutzeroberfläche. In einigen Artikeln wird anstatt Model 2 der Begriff MVC 2 verwendet. Diese Bezeichnung
macht aus den oben genannten Gründen wenig Sinn.
Die in den vorangegangenen Kapiteln vorgestellte Umsetzung einer Model
2 Webanwendung verwendet HTML Kontrollelemente zur Gestaltung der
Benutzeroberfläche. Die Möglichkeiten zur Gestaltung sind in HTML sehr
begrenzt. Dies liegt zum einen an der geringen Anzahl von verschiedenen
Kontrollelementen, zum anderen daran, dass sich deren Eigenschaften und
Reaktionsmechanismen kaum verändern lassen. Die Flexibilität einer Benutzeroberfläche, wie sie im MVC Entwurfsmuster beschrieben wird, ist bei traditionellen Anwendungen heutzutage üblich. Bei Webanwendungen müssen
Entwickler mit einem Minimum an Möglichkeiten auskommen. Hier setzt eine neue Technologie mit dem Namen JavaServer Faces von Sun Microsystems
an. Das Ziel von JavaServer Faces ist die weitgehende Umsetzung des MVC
Entwurfsmusters für Webanwendungen.
Zur Zeit existiert eine Beta Version der Spezifikation zu JavaServer Faces
(JSF), welches zum Ziel hat, Composite und Strategy und somit auch Benutzeroberflächen mit Zuständen für Webanwendungen zu ermöglichen. Zu
diesem Zweck wird zum Beginn einer Session durch JSF ein Graph von Objekten, der die Zustände einer Benutzeroberfläche abbildet, erzeugt. Dieser
89
Ausblick
Schlussbetrachtung
Graph von Objekten wird in der Spezifikation ebenfalls mit dem Begriff Model und die Klassen der Objekte mit UI Components bezeichnet. Beispiele
für UI Components sind UIInput, UIOutput, UIPanel, UISelectBoolean,
UISelectItem, UISelectMany und UISelectOne. Das JSF Framework bietet
bereits einige an, dem Entwickler steht es jedoch frei, eigene UI Components
zu programmieren. UI Components können geschachtelt werden, komplexe
UI Components können aus primitiven bestehen, und somit ist das in MVC
beschriebene Composite Entwurfsmusters erfüllt.
UI Components benötigen zur Darstellung sogenannte Renderer. Renderer
legen für jede der UI Components die Art und Weise fest, wie diese dargestellt werden. Den UI Components können unterschiedliche Renderer zugewiesen werden. Ein Renderer kann die Darstellung einer UI Component
für Webclients variieren, sie in HTML oder XML/XSLT ausgeben, aber
auch zur Darstellung über ein anderes Medium verwendet werden. Die Klasse UIComponent speichert einen Baum von UI Components und generiert
Events auf Aktionen, die auf der Client Seite auftreten. Für diese Events
können Handler programmiert werden, die entsprechenden Anwendungscode
aufrufen und Veränderungen an der Darstellung vornehmen. Damit sind die
im Strategy Entwurfsmuster beschriebenen Reaktionsmechanismen gekapselt. Neben Zustandsmanagement und Eventhandling bietet JSF Typkonvertierung, Validierung, Navigationsflusskontrolle und die Möglichkeit der
Lokalisierung.
Zur Zeit existiert ein Framework der JSF Spezifikation im Beta Stadium,
dass noch nicht für den Einsatz in der Praxis geeignet ist. Erste einsetzbare
JSF Frameworks werden nach Aussage von Sun Ende Juni 2004 erwartet.
(vgl. [Makda, 2004])
Neben der Flexibilität bei der Gestaltung und der Entwicklung von Benutzeroberflächen mit JavaServer Faces, werden weitere nach Anforderungen
isolierte Anwendungsschichten eingeführt. Die Zustände der Benutzeroberfläche werden im JSF Model, die Reaktionsmechanismen im JSF Controller
und die Darstellung in JSF Views gekapselt. Die Kapselung reduziert den
Aufwand bei Anpassungen und erhöht die Wiederverwendbarkeit vom Programmcode. So kann beispielsweise durch den Austausch des Renderers die
Benutzeroberfläche an das Corporate Design eines Unternehmens angepasst
werden, wobei ohne JSF der gesamte Model 2 View von Änderungen betroffen wäre. JavaServer Faces setzen somit das Prinzip der Isolierung von
Entwurfsteilen einer Anwendungen nach Anforderungen fort.
Abbildung 7.2 zeigt eine Architektur für Webanwendungen, die JSF, Struts
und EJB einsetzt:
90
Ausblick
Schlussbetrachtung
Abbildung 8.1: MVC in J2EE Webanwendung
8.1.2
Integration mit Struts
In einigen Bereichen sind sich Struts und JSF ähnlich. So bieten beide Formularverarbeitung, Validierung und Lokalisierung. Abbildung 7.3 zeigt die
Mechanismen und Verfahren der beiden Frameworks sortiert nach Abstraktionsstärken:
Abbildung 8.2: Abstraktionen - Struts mit JavaServer Faces
Das Jakarta Project hat eine Bibliothek zur Integration von Struts und JSF
zur entgültigen JSF Spezifikation angekündigt. Zur Zeit existieren nur experimentelle Ansätze. Daher wurde in der Beispielanwendung von der Integration von JSF abgesehen. Die Vorgehensweise wird in etwa so sein, dass ein
Struts-Faces-Processor von der Struts Controller Klasse abgeleitet wird, die
bei einem JSF Request die Verarbeitung über einen JSF Event an die JSF
Components und an die Struts Actions weitergibt. Bei direkten Requests an
Struts (non-JSF Request) wird der Kontrolle an die Elternklasse, den Struts
Controller, weitergegeben. Die Integrationsbibliothek wird auch eine Klasse
zur gemeinsamen Formularverarbeitung anbieten. (vgl. [Jakarta-StrutsFaces,
2003] und [Shenoy, 2003])
91
Ausblick
8.2
Schlussbetrachtung
Entwicklungsumgebungen
Für die Entwicklung von Webanwendungen, die auf Struts, JavaServer Faces,
Enterprise JavaBeans und weiteren Technologien beruhen, werden laufend
neue Entwicklungsumgebungen angekündigt, die zum einen weitere Möglichkeiten des RAD versprechen und zum anderen die Komplexität einzelner
Bereiche hinter einfach zu handhabenden GUI Elementen verbergen (vgl.
[JamesHolmes, 2004]). Die ausgiebige Verwendung von Deployment Descriptoren, der Einsatz von standarisierter Middleware und die saubere Trennung
von Entwurfsteilen einer Webanwendungen vereinfachen die Entwicklung von
leistungsfähigen Entwicklungsumgebungen (vgl. [Husted, 2003]).
92
Schlussbetrachtung
Schlussbetrachtung
Kapitel 9
Schlussbetrachtung
Durch den verstärken Einsatz des Server-Based-Computings zur Abbildung
unternehmenskritischer Geschäftsprozesse im Internet werden Webanwendungen umfangreicher und komplexer. Für die Entwicklung werden daher
größere Entwicklerteams benötigt und somit werden die Möglichkeiten sowohl der gleichzeitigen parallelen Entwicklung als auch der Reduzierung von
Komplexität, die Technologien und Architekturen durch Abstraktionen bieten, immer wichtiger.
Die vorgestellte Architektur isoliert Entwurfsteile hinsichtlich verschiedener
Anforderungen, damit spezialisierte Entwickler zur Lösung der unterschiedlichen Anforderungen in den jeweiligen Entwurfsteilen eingesetzt werden können.
Dies gestaltet die Entwicklung effektiver, da zum einen die Komplexität für
den einzelnen Entwickler reduziert wird und er die Möglichkeit erhält, seine
Kenntnisse in den für diese Schicht relevanten Technologien zu vertiefen.
Abbildung 8.1 zeigt die Entwurfsteile und deren Kommunikationsschnittstellen:
Abbildung 9.1: Schichten der vorgestellten Architektur
93
Schlussbetrachtung
Schlussbetrachtung
Isolierte Entwurfsteile werden zudem in eigenen Dateien und Klassen entwickelt. Dadurch wird zwar die Anzahl der Dateien und Klassen insgesamt
größer, die Dateien und Klassen selbst sind aber weniger umfangreich und
dadurch übersichtlicher.
Dem Problem der Notwendigkeit von frühen Entwurfsentscheidungen bei der
objektorientierten Entwicklung, die zu nachteiligen Konsequenzen im späteren Verlauf der Entwicklung führen können, wirkt der Einsatz von Frameworks und Technologien wie Enterprise JavaBeans entgegen. Diese nehmen
den Entwicklern viele grundlegenden Entwurfsentscheidungen von vornherein
ab. Zusätzlich empfiehlt sich für die Entwicklung der Geschäftslogik der Einsatz von EJB Entwurfsmustern. Die vorgegebenen Entwürfe sind von erfahrenen Software-Architekten entwickelt und vielfach in der Praxis erprobt worden. Dies vereinfacht nicht nur den Entwicklungsprozess und verhindert frühe
Fehlentscheidungen, sondern zwingt gleichzeitig den Entwickler zur Einhaltung bestimmer Regeln. Das führt auch dazu, dass im Laufe der Entwicklung
strukturierter Programmcode entsteht, in dem sich andere Entwickler besser
zurechtfinden können.
Die Verwendung von Middleware und die Möglichkeiten der Codegenerierung
beschleunigen die Entwicklung und reduzieren zudem erheblich den von den
Entwicklern von Hand zu erstellenden Programmcode. Beides reduziert in
der Regel den Debugging-Aufwand. Hervorzuheben ist, dass die Codegenerierung nicht die Flexibilität in der Hinsicht einschränkt, dass bestimmte
Aufgaben nicht abzubilden sind. Das liegt zum einen an den zahlreichen
Konfigurationsmöglichkeiten, zum anderen daran, dass keine extrem hohen
Abstraktionen genutzt werden.
Wenn ein späterer Ausbau einer Webanwendung mit wenigen Funktionen
nicht vorgesehen ist, eignet sich die Model 2 Webanwendung nicht unbedingt. Der Mehraufwand, der durch die Isolierung und die Bereitsstellung
von Kommunikationsschnittstellen bedingt ist, führt sehr wahrscheinlich in
diesem Fall zu längeren Entwicklungszeiten. Dieser Mehraufwand lohnt sich
ebenfalls nicht, wenn sämtliche Entwurfsteile von einem einzelnen Entwickler programmiert werden. Wegen der guten Wiederverwendbarkeit von Entwurfsteilen und Programmcode ist dennoch die Entwicklung einer Model 2
Webanwendung durch einen Entwickler von Vorteil, wenn davon ausgegangen
wird, dass bestimmte Teile der Webanwendung zukünftig in anderen Projekten benötigt werden.
Speziell für Unternehmensanwendung wird eine skalierbare, Multi-User- und
integrations-fähige Laufzeitumgebung benötigt. J2EE bietet einen entsprechenden Industriestandard und gleichzeitig ein leistungsfähiges Modell zur
Implementation von Geschäfts- und Persistenzlogik. Aus diesem Grund empfiehlt sich der Einsatz von Enterprise JavaBeans für die Model-Schicht ei94
Schlussbetrachtung
Schlussbetrachtung
ner Model 2 Webanwendung. Enterprise JavaBeans, aber auch Application
Server, bieten zudem eine Vielzahl von Konzepten und Möglichkeiten zur
Performancesteigerung, auf welche im Rahmen dieser Arbeit nur auf einige
eingegangen werden konnte. Selbst in der Praxis werden sicherlich nicht immer alle Möglichkeit vollends ausgeschöpft. Häufig ist die Erweiterung der
Clustering-fähigen Laufzeitumgebung um einen weiteren Rechner die günstigste und einfachste Alternative um die Leistung eines Systems zu steigern.
Zentral wichtig für die Umsetzung von Multi-User-fähigen Webanwendung
sind sichere Transaktionen und Thread-Sicherheit. Hierbei sind einige Schwachpunkte zu bemerken. CMT bietet noch nicht die Möglichkeit der Codegenerierung bei der optimischen Nebenläufigkeitskontrolle, obwohl diese performanter ist. Daher wurde für das Beispiel auch die pessimitische Nebenläufigkeitkontrolle verwendet. Ein weiterer Schwachpunkt ist, dass Objekte aus der
Geschäftslogik-Schicht über die Scope Objekte des Web Containers übergeben werden. Der Grund ist, dass die Scope Objekte nicht Thread-sicher sind.
Die JavaServer Pages Spezifikation begründet diese Eigenschaft damit, dass
die Scope Objekte für eine Clientverbindung erzeugt werden und somit nicht
von anderen Benutzern verwendet werden. Das Problem dabei sind allerdings nicht die Threads von anderen Benutzern, sondern die eigenen, weil
diese dieselben Scope Objekte verwenden. Wenn viele Requests in sehr kurzen Zeitabständen versendet werden, kann es dazu kommen, dass die Reponses
nicht in der Reihenfolge der Requests eintreffen und sogar Daten überschrieben werden. Dies geschieht allerdings nur bei Requests, die in Abständen
von wenigen Millisekunden hintereinander versendet werden. Durch eine Simulation mit Tools wie JMeter kann dieses Problem bemerkt werden. Durch
das manuelle Versenden von Requests durch Mausklicks war dies allerdings
nicht möglich, da diese nicht ausreichend schnell durchgeführt werden konnten. Dennoch bleibt ein minimales Risiko, besonders bei stark ausgelasteten
Systemen. Aufwendige Implementationen sind derzeit notwendig um auch
hier absolute Thread-Sicherheit zu gewährleisten.
Abschließend ist zu sagen, dass weitere Technologien und neuere Versionen
derzeitige Mängel wahrscheinlich beseitigen und noch mehr Möglichkeiten
bieten werden. Zu erwarten Besonders interessant ist die in Kürze erscheinende JavaServer Faces Spezifikation, welche weitere Isolierungen innerhalb
der View-Schicht verspricht (MVC).
Mit Spannung kann auch die in Kürze von IBM erscheinende Beta-Version
des Websphere Studio Application Developers erwartet werden. Die IDE setzt
primär auf die Entwicklung von Multi-Tier Webanwendungen mit Enterprise
JavaBeans, Struts und JavaServer Faces.
(http://www-306.ibm.com/software/awdtools/studioappdev/)
95
Teil IV
Literaturverzeichnis
96
Literaturverzeichnis
[Aarhus, 2004]
Petri Nets World
CPN Group, University of Aarhus, Dänemark
http://www.daimi.au.dk/PetriNets/
08.04.2004
[Ambler, 2000]
Ambler, Scott W.:
Mapping objects to relational databases
IBM DeverloperWorks
http://www-106.ibm.com/developerworks/webservices/library/ws-mappingto-rdb/
04.04.2004
[Baxley, 2004]
Baxley, Bob:
What is a Web Application?
http://www.boxesandarrows.com/archives/what is a web application.php
14.02.2004
[Bodoff, 2004]
Bodoff, Stephanie :
The Java Web Services Tutorial - Chapter 4 - Web Applications
http://java.sun.com/webservices/docs/1.1/tutorial/doc/
14.02.2004
[Bullinger, 2000]
Bullinger, Hans-Jörg; Schuster, Erwin; Wilhelm, Stephan:
Content Management Systeme
Stuttgart, Fraunhofer Gesellschaft - Institut Arbeitswirtschaft und Organisation (IAO), 2000
[Cavaness, 2002]
Cavaness, Chuck:
Programming Jakarta Struts
Sebastopol, O’Reilly & Associates, Inc., 2002
[Davis, 2001]
Davis, Malcolm:
Struts, an Open Source MVC Implemetation
http://www-106.ibm.com/developerworks/java/library/j-struts/
IBM Developerworks
04.03.2004
97
Literaturverzeichnis
[Depke, 2001]
Depke, Ralph; Mehner, Katharina:
”Separation of Concern” mit Rollen, Subjekten und Aspekten
Fachbereich Mathematik und Informatik, Universität Paderborn
http://www.info.uni-karlsruhe.de/∼pulvermu/workshops/aop2001/beitraege/depke.pdf
30.03.2004
[Ford, 2004]
Ford, Neil:
Art of Java Web Development
Greenwich, Manning Publications Co., 2004
[Go4, 1994]
Gang of Four
Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John:
Design Patterns, Elements of Reusable Object Oriented Software
Boston, Addison-Wesley, 1994
[Hoffmann, 2000]
Hoffmann, Anke; Zilch, Andreas:
Unternehmensstrategie nach dem E-Business-Hype
Bonn, Galileo Press, 2000
[Husted, 2003]
Husted, Ted:
Struts in Action
Greenwich, Manning Publications Co., 2003
[Jakarta-Struts, 2004]
The Apache Jakarta Project - Struts
http://jakarta.apache.org/struts/
02.04.2004
[Jakarta-StrutsFaces, 2003]
The Apache Jakarta Project - Struts Faces
http://jakarta.apache.org/struts/proposals/struts-faces.html
02.04.2004
[JamesHolmes, 2004]
JamesHolmes.com
http://www.jamesholmes.com/
14.04.2004
98
Literaturverzeichnis
[JMeter, 2004]
Apache JMeter
http://jakarta.apache.org/jmeter/
03.04.2004
[Lee, 2004]
Lee, Rosanna:
The JNDI Tutorial - Building Directory-Enabled Java Applications
http://java.sun.com/products/jndi/tutorial/
21.02.2004
[Mahmoud, 2002]
Mahmoud, Qusay H.:
Developing Enterprise Applications using Java
http://www.iceis.org/iceis2002/Tutorials.htm
4th International Conference On Enteprise Information Systems
14.01.2004
[Makda, 2004]
Makda, Mohammad Afaque :
JSF Called a Misunderstood Standard
http://devmobile.net/hurricane/news/ViewNewsItem.aspx?NewsId=62
02.04.2004
[Marinescu, 2002]
Marinescu, Floyd:
EJB Design Patterns: Advanced Patterns, Processes, and Idioms
New York, Wiley Computer Publishing, John Wiley & Sons, Inc., 2002
[McCluskey, 1998]
McCluskey, Glen :
Using Java Reflection
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
02.04.2004
[Monson-Haefel, 1999]
Create forward-compatible beans in EJB
http://www.javaworld.com/javaworld/jw-01-2000/jw-01-ssj-ejb2.html
06.04.2004
[Monson-Haefel, 2001]
Monson-Haefel, Richard :
Enterprise JavaBeans, 3rd Edition
Sebastopol, O’Reilly & Associates, Inc., 2001
99
Literaturverzeichnis
[NCSA, 2004]
U.S. National Centre for Supercomputing Applications
The Common Gateway Interface
http://hoohoo.ncsa.uiuc.edu/cgi/intro.html
12.01.2004
[OMG-CORBA, 2004]
Object Management Group, Inc.
r BASICS
CORBA
http://www.omg.org/gettingstarted/corbafaq.htm
01.04.2004
[Roman, 1999]
Roman, Ed :
Mastering Enterprise JavaBeans
New York, Wiley Computer Publishing, John Wiley & Sons, Inc., 1999
[Roth, 2003]
Roth, Mark; Pelegri-Llopart, Eduardo :
JavaServer Pages Specification Version 2.0
Santa Clara, Sun Microsystems, 2003
[Sarsam, 2004]
Sarsam, Riem:
Computerwoche Online
http://www.computerwoche.de/index.cfm?pageid=258&artid=53624&type=detail&category
07.04.2004
[Schick, 1999]
Schick, Karl-Wilhelm :
Java haucht bewährter Middleware neues Leben ein
Computerwoche Nr. 38 vom 24.09.1999, Seite 76-78
http://bs2www.fujitsu-siemens.de/rl/produkte/software/presse/news/cw38 1999.pdf
30.03.2004
[Seshadri, 1999]
Seshadri, Govind:
Exploring the MVC Design Pattern
http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html
12.02.2004
[Shachor, 2001]
Shachor, Gal; Chage, Adam; Rydin, Magnus:
JSP Tag Libraries
Greenwich, Manning Publications Co., 2001
100
Literaturverzeichnis
[Shenoy, 2003]
Shenoy, Srikanth; Mallya, Nithin :
Integrating Struts, Tiles, and JavaServer Faces
http://www-106.ibm.com/developerworks/library/j-integrate/
02.04.2004
[Shenoy, 2004]
Shenoy, Srikanth :
ActionForm or DynaActionForm - Making the choice
http://weblogs.java.net/pub/wlg/964
02.04.2004
[Shirah, 2003]
Shirah, Joe Sam:
Getting started with EJB technology
http://www-106.ibm.com/developerworks/java/edu/j-dw-java-gsejb-i.html
21.02.2004
[Sun-CJ2EEP, 2004]
Core J2EE Patterns - Session Façade
http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html
30.03.2004
[Sun-DEA, 2004]
Designing Enterprise Applications
http://java.sun.com/blueprints/guidelines/designing enterprise applications 2e/webtier/web-tier5.html
31.03.2004
[Sun-J2EE, 2004]
Java 2 Platform, Enterprise Edition (J2EE)
http://java.sun.com/j2ee/
20.02.2004
[Sun-J2SE, 2004]
Java 2 Platform, Standard Edition (J2SE)
http://java.sun.com/j2se/
25.02.2004
[Sun-JDBC, 2004]
Sun Microsystems J2EE JDBC Technology
http://java.sun.com/products/jdbc/
25.01.2004
101
Anhang
[Sun-JSP, 2004]
Sun Microsystems JavaServer Pages
http://java.sun.com/products/jsp/
20.02.2004
[Sun-Locale, 2004]
Java 2 Standard Edition API Documentation - Class Locale
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Locale.html
02.04.2004
[Sun-Servlets, 2004]
Sun Microsystems Java Servlets Technology
http://java.sun.com/products/servlet/
20.02.2004
[TSS-Matrix, 2004]
The Server Side - Application Server Matrix
http://www.theserverside.com/reviews/matrix.tss
02.04.2004
[W3C-HTTP, 2004]
W3C, World Wide Web Consortium Hypertext Transfer Protocol
http://www.w3.org/Protocols/
12.01.2004
[W3C-HTML, 2004]
W3C, World Wide Web Consortium Hypertext Markup Language
http://www.w3.org/MarkUp/
12.01.2004
[W3C-XML, 2004]
Extensible Markup Language (XML)
http://www.w3.org/XML/
15.04.2004
[Walls, 2004]
Walls, Craig; Richards, Norman:
XDoclet in Action
Greenwich, Manning Publications Co., 2004
[Zschau, 2002]
Zschau, Oliver; Traub, Dennis; Zahradka, Rik :
Web Content Management - Aktualisierte und erweiterte Auflage 2002
Bonn, Galileo Press, 2002
102
Teil V
Erklärung
103
Eidesstattliche Erklärung
Erklärung
Ich versichere, die von mir vorgelegte Arbeit selbständig
verfasst zu haben. Alle Stellen, die wörtlich oder sinngemäß
aus veröffentlichten oder nicht veröffentlichten Arbeiten anderer
entnommen sind, habe ich als entnommen kenntlich gemacht.
Sämtliche Quellen und Hilfsmittel, die ich für die Arbeit benutzt
habe, sind angegeben. Die Arbeit hat mit gleichem Inhalt bzw.
in wesentlichen Teilen noch keiner anderen Prüfungsbehörde
vorgelegen.
Ort, Datum
Unterschrift
104
Herunterladen