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