Beruflich Dokumente
Kultur Dokumente
Fakultt Informatik Referent: Prof. Dr. Oliver Braun Korreferent: Prof. Dr. Klaus Chantelau eingereicht von: Nico Pleyer Matr.-Nr. 280408 Marienstrae 3 98693 Martinroda Schmalkalden, den 14.12.2011
Abstract Koop is a proprietary middleware, which was developed as a XML based communication platform twelve years ago. This bachelor thesis decribes that middleware. By now Koop is a bit too old for just refactoring it. These days most of Koops work could be done by standard technologies or frameworks. For that reason this thesis should give an overview of possible options. The assembly of the middleware and the lifecycle during requests will be analysed and decribed in the course of this thesis. The aim is to establish technical requirements for a new approach. In consideration of these technical requirements current technologies will be contemplated and evaluated. Furthermore a concept will be developed for the new approach. This concept is described by the help of a technical prototype.
Zusammenfassung Koop ist eine proprietre Middleware, die vor zwlf Jahren fr eine XML basierte Kommunikation entwickelt wurde. Diese Arbeit beschftigt sich mit der Analyse der Middleware. Viele der Aufgaben von Koop werden heute bereits von Standardtechnologien und Frameworks angeboten. Diese Arbeit gibt einen berblick ber einige der verschiedenen Mglichkeiten, beim erstellen eines neuen Ansatzes. Es wird der Aufbau der Middleware und die Ablufe, whrend einer Anfrage an das System, beschrieben. Ziel ist es, aus der Analyse resultierend, Anforderungen an einen neuen Ansatz der Middleware zu erstellen. Unter Bercksichtigung der Anforderungen werden aktuelle Technologien betrachtet und bewertet. Weiterhin wird ein Konzept fr einen neuen Ansatz erarbeitet und anhand eines technischen Durchstichs beschrieben.
Inhaltsverzeichnis
1 Einleitung 1.1 Die Anwendungen InetP und Koop . . . . . . . . . . . . . . . . . . . 1.2 Aufgabenstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Analyse der Koop-Middleware 2.1 Aufbau des Systems . . . . 2.1.1 Koop-Frontend . . 2.1.2 Koop-Backend . . . 2.2 Ablufe im System . . . . 2.3 nderungsaufwnde . . . . 1 1 2 2 3 3 5 5 6 8 9 9 9 9 9 10 10 10 10 10 10 11 11 11 11 13 13 13 13 14 15 16 17 17
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
3 Spezikation der Anforderungen 3.1 Beschreibung . . . . . . . . . . . . . . . . . 3.2 Anforderungen . . . . . . . . . . . . . . . . 3.2.1 Standardtechnologie . . . . . . . . . 3.2.2 Mandantenfhigkeit . . . . . . . . . . 3.2.3 Performance . . . . . . . . . . . . . . 3.2.4 Wartungsaufwand . . . . . . . . . . . 3.2.5 Sicherheit . . . . . . . . . . . . . . . 3.2.6 Konguration . . . . . . . . . . . . . 3.2.7 Protokoll . . . . . . . . . . . . . . . . 3.2.8 Redaktionierbarkeit . . . . . . . . . . 3.2.9 Seitenaufbau . . . . . . . . . . . . . 3.2.10 Sessionverknpfung . . . . . . . . . . 3.2.11 JavaScript und AJAX Untersttzung 3.3 Bewertung . . . . . . . . . . . . . . . . . . . 4 Aktuelle Technologien 4.1 Technologien . . . . . . . . . . . . . . . . 4.1.1 Apache Struts . . . . . . . . . . . . 4.1.2 Google Web Toolkit . . . . . . . . 4.1.3 JavaServer Faces 2.0 . . . . . . . . 4.1.4 Java Portlets 2.0 . . . . . . . . . . 4.1.5 Java Architecture for XML Binding 4.1.6 Java Servlet . . . . . . . . . . . . . 4.2 Bewertung . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Nico Pleyer
IV
Inhaltsverzeichnis
5 Lsungsanstze 19 5.1 Verteilte Portlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.2 Eigenentwicklung von Tools . . . . . . . . . . . . . . . . . . . . . . . 20 5.3 Proxy-Servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 6 Beschreibung der Lsung 6.1 Voraussetzungen . . . . . . 6.2 Architektur . . . . . . . . . 6.3 Implementierung . . . . . . 6.3.1 Frontendanwendung 6.3.2 Backendanwendung . 7 Zusammenfassung und Ausblick Literaturverzeichnis A Anhang A.1 Quelltext des ProxyServlet . . . . . . A.2 Beispiel einer Transport-XML . . . . A.3 Abbildungen der Backendanwendung A.4 Installation der Anwendungen . . . . Eidesstattliche Erklrung 21 21 22 23 23 35 38 40 42 42 46 47 49 53
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
Nico Pleyer
1 Einleitung
In diesem Kapitel werden die Middleware Koop sowie die Anwendung InetP, im Umfeld dessen diese Arbeit entstand, vorgestellt. Weiterhin wird die Aufgabenstellung der Arbeit erlutert und auf die Motivation, die hinter dem Umbau der Middleware steht, eingegangen.
Abbildung 1.1: Kommunikation zwischen Koop Front- und Backend, Quelle: eigene Darstellung
1
Vgl. [Invc]
Nico Pleyer
Seite 1 von 53
1. Einleitung
Koop war ursprnglich dazu angedacht, unterschiedliche Front- und Backendsysteme verschiedener Versicherungsunternehmen miteinander zu verbinden. Derzeit werden einige unterschiedliche Anwendungen ber Koop miteinander verbunden. Abbildung 1.1 soll den dargestellten Sachverhalt verdeutlichen. Die Kommunikation zwischen den einzelnen Anwendungen, hier als APP dargestellt, erfolgt ausschlielich ber die Koop-Komponenten am jeweiligen Front- und Backendsystem. Durch die Verwendung von Koop ist es beispielsweise mglich, dass APP1 auf seinen eigenen Backendservice zugreift aber auch auf den Service der APP2.
1.2 Aufgabenstellung
Das Thema der Arbeit ist es, die bereits bestehende Middleware Koop zu analysieren sowie die Rahmenbedingungen zur Systemkopplung und den Entwicklungsprozessen zu erfassen. Diese Rahmenbedingungen stellen Funktionen, Leistungen und verschiedene Kriterien des Systems dar. Des Weiteren sollen die Rahmenbedingungen bezglich ihres aktuellen Bedarfs bewertet werden, um daraus Anforderungen an einen neuen Ansatz zu erstellen. Weiterhin sollen aktuelle Technologien und Standards betrachtet und hinsichtlich ihrer Einsetzbarkeit analysiert werden. Mit Hilfe der identizierten Anforderungen und der Bewertung der Technologien soll ein Konzept erarbeitet werden, welches einen neuen Ansatz beschreibt. Auf der Grundlage dieses Konzeptes soll ein Prototyp, in Form eines technischen Durchstichs umgesetzt werden. Mit Hilfe dieser Arbeit soll ein berblick ber aktuelle Webtechnologien geschaen werden, um herauszunden inwieweit es mglich ist, Koop oder einen Koop-hnlichen Ansatz mit Standardtechnologien umzusetzen.
1.3 Motivation
Die Hintergrnde fr den Umbau der Middleware sind sehr vielseitig. Zum einen ist das System bereits relativ alt und greift somit kaum auf aktuelle Standards zurck. Weiterhin sind Arbeitsablufe in der Wartung des Systems komplex und zum Teil sehr aufwndig. Koop ist formular- beziehungsweise seitenbasiert. Das Ziel ist es mehr Interaktivitt, zum Beispiel durch Asynchronous JavaScript and XML (AJAX), zu gewhrleisten und weniger XML-Transformationen durchfhren zu mssen. Zum anderen ist Koop eine Eigenentwicklung und bietet somit einige Vorteile, da es genau auf die bentigten Anforderungen abgestimmt ist. Diese Vorteile gilt es herauszunden und fr einen neuen Ansatz zu bercksichtigen. Die Entwicklung von Features fr die Middleware und die gesamte Anwendung InetP ist sehr komplex und umstndlich. Daher ist eines der Ziele, diese Software so umzugestalten, dass Arbeitsablufe vereinfacht werden. So soll schneller und besser auf Kundenanfragen reagiert werden knnen. Koop wurde bisher wenig weiterentwickelt. Es ist daher nicht ohne weiteres mglich, moderne Konzepte der Softwareentwicklung, aktuelle Webtechnologien oder Standards in der Entwicklung zu nutzen. Aus diesen Grnden wird versucht, einen neuen Ansatz zu formulieren.
Nico Pleyer
Seite 2 von 53
Abbildung 2.1: InetP Systembersicht, Quelle: eigene Darstellung Eine Koop-Anwendung besteht aus Frontend- und Backendsystemen, welche wiederum aus verschiedenen Modulen aufgebaut sind. Diese Systeme werden im Folgenden als Koop-Frontend und Koop-Backend bezeichnet. Die Kommunikation zwischen den Systemen erfolgt ber das Koop-Protokoll, dass inzwischen auf SOAP aufbaut. Fr den Datenaustausch wird ein XML-Format verwendet, welches im weiteren Verlauf Koop-XML genannt wird. ber dieses XML werden Informationen ausgetauscht, die fr den jeweiligen Dienst am Backend bentigt werden. Die Struktur des Koop-XML und somit auch die Informationen die gesendet werden, wird durch einen Satz von Schema-Denitionen festgelegt. Im Anhang bendet sich Listing A.3, welches ein Beispiel fr das Koop-XML einer Begrungsseite, nach dem Einloggen des Nutzers darstellt. Dieses knnte als Antwort des Backends gesendet werden. Die Schema-Denition des Koop-XML enthlt die folgenden Elemente.
Nico Pleyer
Seite 3 von 53
SERVICE - Dieses Element ist ein eindeutiger Identier, fr die am Backend auszufhrende Aktion. Der Wert des Elementes dient ebenfalls dazu die entsprechende XML-Vorlage zu bestimmen. ERROR - Zur bertragung technischer Fehler auf Seiten des Backends kann dieses Element genutzt werden. TRANSFORM_ID - Die Ergebnisdaten des Backends werden in einer passenden HTML-Seite angezeigt. Diese Seite wird per Extensible Stylesheet Language (XSL) und CMS-Templates erzeugt. Um die entsprechende XSL-Datei am Frontend auszuwhlen, wird ein eindeutiger Bezeichner bentigt. Dieser wird ber das Element TRANSFORM_ID bertragen und bereitgestellt. PARAM - Falls bentigt, knnen ber das Element PARAM noch weitere Steuerparameter an das Backend gesendet werden. Hierfr stehen zum Beispiel die folgenden Parameter zur Verfgung: AID, SECURETOKEN, SESSION_ID. CONTENT - Das fachliche XML, also die befllte XML-Vorlage, wird immer ber eine CDATA-Sektion im Element CONTENT bertragen. VU_SESSION_ID - In diesem Element wird die Nutzerabhngige SessionID bertragen. Diese wird beim ersten Request vom Backend erzeugt und an das Frontend gesendet. Bei weiteren Anfragen wird sie immer ber dieses Element mitgesendet. USER_LEVEL - Fr die berprfung von Berechtigungen eines Nutzers wird dessen Anmeldestatus bentigt. Unter anderem sind folgende Userlevel bekannt: 1 - fr nicht angemeldete Nutzer 2 - fr angemeldete Nutzer. Tabelle 2.1: Elemente des Koop-XML, Quelle: Vgl. [Invb, S. 49f.] Wenn aus einem anderen Projekt oder Softwaresystem auf Koop-Backendservices zugegrien werden soll, muss in diesem Projekt eine eigene Koop-Komponente integriert werden. Sobald diese Komponente implementiert ist, knnen die Dienste des Koop-Backends genutzt werden. Abbildung 2.1 soll diesen Zusammenhang verdeutlichen. Derzeit werden die Anwendungen Extranet und Wind ber die KoopMiddleware angebunden. Die Anwendung Extranet ist ein Serviceportal fr Geschfts- und Vertriebspartner von Versicherungsunternehmen. Extranet bindet einige Tarifrechner zur Berechnung von angebotenen Versicherungen, ber Koop an. Wind hingegen ist ein Unwetterwarnservice. Kunden erhalten Informationen zum Wetter fr einen, von ihnen bestimmten, Postleitzahl-Bereich.2 In den folgenden Abschnitten wird der Aufbau der einzelnen Komponenten nher erlutert.
2
Vgl. [Invc]
Nico Pleyer
Seite 4 von 53
2.1.1 Koop-Frontend
Das Koop-Frontend baut auf dem Interceptor-Entwurfsmuster auf. Dieses Muster ermglicht eine einfache Konguration und Erweiterung der Software, ohne grere nderungen am System selbst durchfhren zu mssen. In Abbildung 2.2 wird der Aufbau des Koop-Frontends dargestellt.
Abbildung 2.2: Aufbau des Koop-Frontends, Quelle: eigene Darstellung Das Modul KoopService vermittelt zwischen der Interceptor-Chain und dem CMSModul am Koop-Frontend. Die Interceptor-Chain ist aus mehreren Interceptoren zusammengesetzt. Diese werden nacheinander abgearbeitet. Die Interceptoren ExceptionInterceptor und SessionInterceptor sind fr das Exception- beziehungsweise das Sessionhandling einer Anfrage zustndig. Der Unmarshaller ist fr das Lesen eines Requests verantwortlich, wohingegen der Marshaller ein Response-Objekt schreibt. Der DispatchInterceptor stt die eigentliche Verarbeitung einer Anfrage an. Die Verarbeitung der Requestbeziehungsweise Response-Daten sowie des Koop-XML wird dann durch den TransformInterceptor ausgefhrt. Der letzte Interceptor in der Verarbeitungskette, der Request-Interceptor, leitet die Anfrage an das Modul RequestDelegate weiter. RequestDelegate baut wiederum eine Verbindung ber das Hypertext Transfer Protocol (HTTP) zum geforderten Backendservice auf und verpackt die Anfrage in ein SOAPObjekt. Die Verbindung ber HTTP aufzubauen ist nur eine mgliche Variante. Weitere Mglichkeiten sind der Verbindungsaufbau ber den Java Message Service oder MQSeries. RequestDelegate nimmt weiterhin die Antwortdaten des Backends entgegen und reicht diese in umgekehrter Reihenfolge wieder durch die Interceptor-Chain. Dabei werden die Antwortdaten wieder aufbereitet, geprft und die geforderte Seite, aus XSL- und CMS-Templates aufgebaut.
2.1.2 Koop-Backend
Das Koop-Backend kann in den ProtokollHandler, RequestDispatcher, Datenkonverter und das Command-Framework unterteilt werden. Abbildung 2.3 zeigt den
Nico Pleyer
Seite 5 von 53
Abbildung 2.3: Aufbau des Koop-Backends, Quelle: Vgl. [Inva, S. 22] Aufbau des Koop-Backends. Der ProtokollHandler nimmt Anfragen des Frontends, in Form des Koop-XML entgegen und wertet diese aus. Weiterhin wird aus der Koop-spezischen Anfrage ein Protokollneutraler Request erzeugt, um somit die Verwendung verschiedener Protokolle zu gewhrleisten. Auerdem nimmt er das Response-Objekt des RequestDispatcher entgegen und erzeugt daraus die Koop-XML-Antwort. Die Abarbeitung der Anfrage fhrt der RequestDispatcher aus. Er ermittelt den angeforderten Service, ruft den Datenkonverter auf und stt das Bearbeiten des Kommandos an. Der Datenkonverter wandelt die Daten aus der Koop-XML-Struktur in ein BusinessObjekt um, so dass diese von den entsprechenden Kommandos benutzt werden knnen. Er konvertiert ebenfalls die Antwortdaten in das Koop-XML-Format zurck. Das Command-Framework stellt die Geschftslogik des Systems dar. Jedes Kommando steht fr einen Use Case, der am Frontend angestoen wurde. Diese Aktionen knnen zum Beispiel Tarifberechnungen, Anmeldungen im Kundenbereich oder das Senden allgemeiner Meldungen sein. Die einzelnen Kommandos werden ber einen eindeutigen Identizierer, der ServiceID, bestimmt und erkannt.3
Nico Pleyer
Seite 6 von 53
Fr die Berechnung eines Tarifes sind verschiedene Nutzereingaben erforderlich. Diese werden ber ein Hypertext Markup Language (HTML)-Formular erfasst. Nach dem Absenden der Anfrage, zum Beispiel durch den Klick auf einen BerechnenButton, liest das Koop-Frontend den Request. Dabei wird geprft, welcher Service am Backend ausgefhrt werden soll. Hierfr dient die Datei Service.xml. Sie denert alle vom Backend angebotenen Dienste. Diese sind in Form eines eindeutigen Identizierers, der ServiceID, festgelegt und in den HTML-Formularen, fr jede Aktion hinterlegt. Ist der Service registriert, wird die Anfrage als Koop-XML an das Backend gesendet, andernfalls wird ein technischer Fehler ausgegeben. Sobald das Koop-Backend die Anfrage erhalten hat, wird auch hier der Service ermittelt. Fr diesen wird nun ein Konverter gewhlt, mit dessen Hilfe das Koop-XML in ein JavaObjekt konvertiert wird. Im Anschluss daran wird das Kommando beziehungsweise die Aktion ausgefhrt. Diese gibt eine TransformID zurck. Mit Hilfe der TransformID wird wieder ein Konverter gewhlt, welcher die Ergebnisdaten in das KoopXML-Format konvertiert. Welche Konverter fr die jeweiligen IDs zu whlen sind, wird in der Datei mapping.xml deniert. Das erzeugte Koop-XML wird nun zurck an das Koop-Frontend gesendet. Hier wird die Zielseite, fr die Ausgabe, bestimmt und samt Inhalt angezeigt. Die Seite setzt sich aus dem Koop-XML und einem XSL-Template zusammen, welches ber die TransformID bestimmt wird. Das Mapping einer TransformID zu einem XSL-Template wird in der Datei Transform.xml festgelegt. Abbildung 2.4 stellt diese Ablufe dar.
Abbildung 2.4: Ablauf einer Anfrage, Quelle: eigene Darstellung Whrend einer Anfrage werden ebenfalls Sessiondaten erzeugt und zwischen KoopFrontend und -Backend ausgetauscht. So sind die verschiedenen Systeme immer ber den Status eines Nutzers informiert und knnen eine Session am Frontend mit der am Backend verknpfen. Dieses Verhalten ist notwendig, um zum Beispiel Antwortdaten den jeweiligen Nutzer zuordnen zu knnen. Die erzeugten Daten werden weiterhin fr die Navigationssteuerung genutzt. ber sie wird festgestellt, ob ein Nutzer bestimmte Seiten sehen kann und welche Seite auf eine Anfrage hin angezeigt werden soll.
Nico Pleyer
Seite 7 von 53
2.3 nderungsaufwnde
Die Wartung des Systems besteht zu groen Teilen aus nderungen und Anpassungen an der Nutzeroberche sowie dem Aktivieren und Deaktivieren von Funktionen. Diese Aufgaben knnen sehr fehleranfllig sein. Dienste beziehungsweise Funktionen werden in XML- und Properties-Dateien festgelegt und konguriert. Die Elemente einer anzuzeigenden Seite werden als XSL-Templates deniert und am Frontend mit den entsprechenden Inhalten befllt. Fehleranfllig sind diese Aufgaben deshalb, weil die verschiedenen Kongurationsdateien stark miteinander verbunden sind. Die Anpassungen mssen demnach nicht nur an einer Stelle umgesetzt werden. Das folgende Beispiel soll zeigen, welche Arbeitsschritte notwendig sind um ein neues Element, etwa eine Auswahlliste, in eine Seite einzubetten. Diese Schritte mssen durchgefhrt werden, um die nderungen auf einem Entwicklersystem anzupassen und anschlieend auf einem lokalen Anwendungsserver zu verentlichen. Hinzufgen des Elementes zur XSL-Datei die Schema-Denition des Koop-XML anpassen die Vorlage des Koop-XML anpassen mit Hilfe des Datenkonverters die zu der Vorlage des Koop-XML passenden Java-Klassen neu generieren die generierten Vorlagen an die korrekte Stelle der Projekthierarchie kopieren die XSL-Datei und XML-Vorlage im CMS verentlichen das CMS aktualisieren eventuelle Anpassung des Datenbankmapping, falls das Element einen Datenbankzugri bentigt den Anwendungsserver neustarten
Dieses Beispiel zeigt, wie umfangreich eine relativ simple nderung der Oberche werden kann. Wird der Anwendung neue Funktionalitt hinzugefgt, mssen weiterhin einige der XML-Kongurationsdateien angepasst werden. Diese Arbeitsschritte sind fehleranfllig und gehren zu den Aufgaben, die am hugsten durchgefhrt werden mssen. Aus diesem und einigen weiteren Grnden soll ein Umbau der KoopMiddleware initiiert werden. Hierdurch soll eine bessere Wartbarkeit der gesamten InetP-Anwendung entstehen und Ablufe in der Weiterentwicklung verbessert werden.
Nico Pleyer
Seite 8 von 53
3.1 Beschreibung
Die erstellten Anforderungen beschreiben Funktionen, die der neue Ansatz erfllen sollte. Diese sind allerdings eher Richtlinien und mssen nicht alle zwingend von diesem Ansatz untersttzt werden. Es wre jedoch von Vorteil, die Anforderungen mit einer Wichtung der Stufe drei zu erfllen. Die Anforderungen beruhen auf Funktionen, welche im jetzigen System angeboten und untersttzt werden. Eine Bewertung nach Prioritten erfolgte durch das Entwicklerteam des InetP-Projektes.
3.2 Anforderungen
In den folgenden Unterpunkten werden die identizierten Anforderungen ausfhrlicher betrachtet und dargelegt. Diese Anforderungen wurden whrend der Analyse der Koop-Middleware formuliert.
3.2.1 Standardtechnologie
Bei der Entwicklung des neuen Systems sollte nach Mglichkeit auf Standardtechnologien zurckgegrien werden. Diese knnen Technologien sein, die zum Beispiel in einem Java Specication Request (JSR), durch den Java Community Process beschrieben sind. Auf Standards und Spezikationen anderer anerkannter Organisationen kann ebenfalls zurckgegrien werden.
3.2.2 Mandantenfhigkeit
Das System soll die Mglichkeit bieten, neue Mandanten beziehungsweise KoopKlienten in das System aufzunehmen. Hierbei sollte es mglich sein, die Klienten ohne zu groen Programmier- und Kongurationsaufwand anzubinden.
Nico Pleyer
Seite 9 von 53
3.2.3 Performance
Die Performance des neuen Systems sollte sich nicht verschlechtern. Aus der Verwendung neuer Webtechnologien sollte sich mglichst eine Verbesserung der Arbeitsleistung ergeben. Weiterhin soll der Overhead beim Datenaustausch zwischen Koop-Frontend und -Backend so gering wie mglich gehalten werden.
3.2.4 Wartungsaufwand
Der Wartungsaufwand soll so gering wie mglich gehalten werden. Das heit, dass nderungen am System einen minimalen Aufwand verursachen. Werden neue Module fr das System entwickelt, sollten sich diese ebenso einfach integrieren lassen. Dabei sollten keine groen nderungen am System selbst bentigen werden.
3.2.5 Sicherheit
Das Backend soll aus dem Internet fr den Endkunden nicht direkt erreichbar sein. Weiterhin soll die Mglichkeit bestehen, Nutzer in Gruppen oder Userlevel einteilen zu knnen. Die Navigation am Frontend soll in Abhngigkeit des Userlevel am Backend gesteuert werden knnen. Des Weiteren sollte es einfach mglich sein, die Eingabedaten des Nutzers zu Validieren und zu Plausibilisieren. Auerdem ist eine direkte Untersttzung zur Testintegration und Fehlersuche wnschenswert.
3.2.6 Konguration
Der Kongurationsaufwand sollte so gering wie mglich gehalten werden. Dennoch sollte es mglich sein, in Ablufe beziehungsweise Prozesse einzugreifen, ohne Anpassungen am Code durchfhren zu mssen. Weiterhin sollten die Ablufe einfach zu kongurieren sowie das Datenmapping zur Oberche so einfach wie mglich gehalten werden. nderungen an der Nutzeroberche sollten ebenfalls geringe Aufwnde verursachen.
3.2.7 Protokoll
Das Protokoll fr den Informationsaustausch zwischen Koop-Frontend und -Backend sollte whlbar und nach Mglichkeit austauschbar sein.
3.2.8 Redaktionierbarkeit
Das System sollte die Mglichkeit zur Verfgung stellen, einfache nderungen wie Textanpassungen, ohne ein Deployment am Koop-Frontend durchzufhren. Weiterhin sollte die Mglichkeit geboten werden, die Nutzeroberche durch Templates aufzubauen und zu gestalten. Die Nutzeroberche sollte ein einheitliches und modernes Look & Feel ermglichen.
Nico Pleyer
Seite 10 von 53
3.2.9 Seitenaufbau
Die Seiten sollten nicht bei jedem Request komplett neu aufgebaut werden. Das System sollte die Mglichkeit zur Verfgung stellen, Teile beziehungsweise Fragmente einer Seite einzeln zu laden und zu rendern. Des Weiteren sollte die Navigation ber die Browserfunktionen bercksichtigt werden. Die Seiten sollen, nach Mglichkeit, im Backend deniert und im Frontend, aus den vorhandenen Templates, zusammengebaut werden.
3.2.10 Sessionverknpfung
Die Session im Koop-Frontend soll mit der Session im Backend verbunden werden knnen, so dass diese synchron laufen und zum Beispiel immer ber den aktuellen Status eines Nutzers informiert sind. Weiterhin sollte die Anwendung mglichst nur ber eine Domain erreichbar sein, trotz verschiedener Backendanwendungen.
3.3 Bewertung
Aus Entwicklersicht sind die Punkte zur Mandantenfhigkeit, Redaktionierbarkeit sowie alle Punkte die Kongurations- und Wartungsaufwand betreen am wichtigsten. Durch diese Anforderungen sollen die Prozesse in der Weiterentwicklung und Wartung des Systems vereinfacht werden. Fehleranfllige Arbeitsablufe sollten somit vermieden werden. Aus Sicht der Kunden sind die Punkte zur Sicherheit, Performance, Standardtechnologie und ebenfalls die Punkte zu anfallenden Wartungsaufwand sehr interessant. Weiterhin sind Standardtechnologien bevorzugt, da diese meist einen guten und langfristigen Support bieten. Punkte zum Thema Sicherheit und Performance nehmen aber sicher die hchsten Prioritten ein. Die folgende Tabelle 3.1 bewertet die Anforderungen anhand ihrer Wichtigkeit. Anforderungen mit der Wichtung drei nehmen die hchste Prioritt ein und sollten von der entsprechenden Lsung untersttzt werden. Die Anforderungen mit der Wichtung eins sind nicht zwingend erforderlich.
Nico Pleyer
Seite 11 von 53
Kriterium Mandantenfhigkeit
Konguration
Erluterung Knnen neue Mandanten einfach angebunden werden? Wie hoch ist der Kongurationsaufwand? Wie einfach ist das Datenmapping? Knnen Arbeitsablufe ohne Anpassungen am Code gendert werden? Kann die Session von Front- und Backend verbunden werden? Ist die Anwendung ber eine Domain erreichbar? Wird AJAX von der Technologie untersttzt? Wird ein einheitliches Look & Feel durch Templating ermglicht? Basiert die Technologie auf anerkannten Standards? Wie gut ist die Tooluntersttzung? Wie performant ist die Technologie? Wie aufwndig/komplex ist ein Request? Ist das Backend fr Kunden direkt erreichbar? Ist eine Validierung der Eingabe leicht mglich? Wird die Seite immer komplett neu aufgebaut? Wird die Navigation ber den Browser bercksichtigt? Ist das Protokoll fr Datenaustausch whlbar? Lassen sich einfache nderungen an der Oberche ohne Deployment durchfhren? Ist die Arbeit ohne aktives JavaScript mglich? Wie hoch ist der Aufwand in der Wartung? Gibt es eine direkte Untersttzung fr Tests?
Stufe 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 1 1 1 1 1
Nico Pleyer
Seite 12 von 53
4 Aktuelle Technologien
In diesem Kapitel werden einige Webtechnologien vorgestellt, welche fr einen Lsungsansatz in Betracht gezogen wurden. Die Technologien werden kurz beschrieben und anhand der Anforderungen bewertet. Es wird weiterhin geklrt, weshalb einige der Technologien fr den Lsungsansatz vorgeschlagen beziehungsweise verwendet wurden und andere nicht.
4.1 Technologien
In den folgenden Abschnitten werden die untersuchten Webtechnologien beschrieben und nach den erstellten Anforderungen bewertet.
Nico Pleyer
Seite 13 von 53
4. Aktuelle Technologien
dene Modi bereit. Der Hosted Mode erlaubt es dem Entwickler, den erstellten Java Quelltext zu debuggen. Im Web Mode hingegen, wird die Anwendung in JavaScript und HTML bersetzt und kann zur Ausfhrung auf einem Webserver verentlicht werden. Mit GWT ist es mglich, die Nutzeroberche komplett in Java-Code zu erstellen, hnlich wie das Arbeiten mit Swing7 . Es bietet weiterhin bereits einige Standard Oberchenelemente an und bringt ein integriertes Testframework mit. GWT wurde im Jahr 2006 von Google als Open-Source-Software verentlicht.8 Das GWT-Framework hat den Nachteil, dass es sich schwer in bestehende Webanwendungen integrieren lsst. Durch die bersetzung von Java-Code nach JavaScript, kann die Arbeit mit GWT zum Teil eingeschrnkt werden. Dies ist auf ein weniger umfangreiches Funktionsangebot von JavaScript zurckzufhren. Ein Vorteil von GWT ist, dass bei der Entwicklung der HTML-Seiten nicht mehr auf unterschiedliche Browser Rcksicht genommen werden muss. GWT compiliert den Quellcode browserunabhngig und nimmt dem Entwickler so eine beschwerliche Aufgabe ab. Des Weiteren sind AJAX-Probleme, das Nutzen der Browsernavigation und das Setzen von Lesezeichen, bereits umgesetzt.9 GWT setzt somit bereits einige wichtige Aufgaben der Webentwicklung um.
Nico Pleyer
Seite 14 von 53
4. Aktuelle Technologien
Abbildung 4.1: Aufbau einer Portalseite, Quelle: [LH09] Portlets bieten einen weiteren Standard an, den Web Services for Remote Portlets (WSRP), welcher durch die Organization for the Advancement of Structured Information Standards (OASIS) deniert wurde. Dieser Standard dient zur Kommunikation zwischen Remote Portlets, also verteilten Portlets.13 Das hat den Vorteil, dass die Transportschicht bereits implementiert ist. Die Kommunikation zwischen KoopFrontend und -Backend wrde somit ber einen oziellen Standard erfolgen. Des Weiteren bietet der Portlet-Standard ab der Version 2.0 bereits eine Untersttzung fr AJAX an. Sie bieten vielfltige Mglichkeiten in der Anwendung und lassen sich mit Oberchentechnologien wie JavaServer Pages, JSF, Apache Wicket und weiteren kombinieren. Die Verbindung zwischen Java Portlets 2.0 und JSF 1.2 zum Beispiel, ist durch den JSR-329 in einem eigenen Standard festgehalten.
11 12
Nico Pleyer
Seite 15 von 53
4. Aktuelle Technologien
Diese Technologie hlt allerdings auch einige Nachteile bereit. So ist zum Beispiel die Konguration eines Portlets sehr umstndlich, wenn es darum geht, sie den gestellten Anforderungen entsprechend anzupassen. Es ist zum Beispiel nicht einfach mglich ein Portlet zu erstellen, welches AJAX und den WSRP-Standard untersttzt. Die Konguration kann auerdem fr die unterschiedlichen Portalserver stark variieren. Dies sind aber in der Regel einmalige Aufwnde. Bei der Konguration von Portlets, welche nur AJAX oder nur WSRP untersttzen sollen, gibt es keine greren Schwierigkeiten. Probleme treten erst auf, sobald ein Portlet sehr viele Funktionen untersttzen soll.
Abbildung 4.2: Aufbau einer JAXB-Anwendung, Quelle: [OM03] Der Aufbau einer JAXB-Anwendung gestaltet sich wie folgt. Aus einer vorhandenen Schema-Denition werden Java-Objekte erstellt. Falls diese Objekte bereits existieren, mssen Annotationen hinzugefgt werden, welche die Regeln fr eine XMLAbbildung festlegen. Fr das Schreiben von Java-Objekten in ein XML-Dokument wird der Marshaller bentigt. Er schreibt die Daten des Objektes, laut SchemaDatei in das XML-Dokument. Der Unmarshaller wird fr das Lesen eines XMLDokuments bentigt. Mit Hilfe des Unmarshallers knnen die XML-Dokumente
14
Vgl. [OM03]
Nico Pleyer
Seite 16 von 53
4. Aktuelle Technologien
eingelesen und in das zugehrige Java-Objekt geschrieben werden. Abbildung 4.2 soll diese Zusammenhnge verdeutlichen. Vorteil dieser Programmierschnittstelle ist, dass sich der Entwickler nicht mit der reinen XML-Verarbeitung auskennen muss. Es reicht aus, eine einfache SchemaDenition zu erstellen sowie die Methoden zum Lesen und Schreiben aufzurufen. Die eigentliche Bearbeitung der XML-Dokumente bernimmt die JAXB-Schnittstelle. JAXB kann, in einem neuen Ansatz der Koop-Middleware, den Datenkonverter ersetzen oder verbessern. Weiterhin kann es fr die Aufbereitung der Daten des KoopXML genutzt werden.
4.2 Bewertung
Die beschriebenen Technologien waren Teil der Recherchen, zur Erstellung eines neuen Ansatzes der Koop-Middleware. Diese Technologien erfllen, einzeln betrachtet, allerdings zu wenige der gestellten Anforderungen. Aus diesem Grund el die Entscheidung, mehrere Technologien zu kombinieren. Fr eine nhere Betrachtung wurde etwa eine Kombination aus Java Portlets 2.0 und JavaServer Faces 2.0 untersucht. Die Spezikationen der beiden Standards lsen bereits einige der gestellten Anforderungen und boten somit, zumindest theoretisch,
15
Nico Pleyer
Seite 17 von 53
4. Aktuelle Technologien
eine geeignete Grundlage. Weiterhin wurde die Kombination von Java Servlets sowie JavaServer Face 2.0 untersucht und der technische Durchstich auf dieser aufgebaut. Im weiteren Verlauf der Arbeit werden diese Technologieverknpfungen nher erlutert. Hierbei wird auf Vor- und Nachteile eingegangen und ein mgliches Architekturszenario beschrieben.
Nico Pleyer
Seite 18 von 53
5 Lsungsanstze
Dieses Kapitel beschreibt Lsungsanstze, die whrend der Ausarbeitung nher betrachtet wurden und fr einen technischen Durchstich in Frage kamen. Fr eine mgliche Lsung wurden einige Technologien untersucht und anhand der erstellten Anforderungen bewertet.
16
http://www.jboss.org/gatein
Nico Pleyer
Seite 19 von 53
5. Lsungsanstze
5.3 Proxy-Servlet
Dieser Lsungsansatz baut auf dem Servlet- sowie dem JSF-Standard auf. Er sieht als Frontendanwendung ein Servlet vor, dass die Anfragen an eine Backendanwendung weiterleitet. Das Backendsystem generiert den fertigen HTML-Code und sendet diesen wieder an das Servlet zurck. Am Frontend kann der HTML-Code durch weitere Komponenten bearbeitet und manipuliert werden. Durch diesen Ansatz ist es mglich, relativ einfach, verschiedene Backendanwendungen anzubinden. Das Backend bentigt keine zustzlichen Informationen ber das Frontendsystem und kann somit eine eigenstndige Anwendung sein. Diese Lsung verwendet zwei Apache Tomcat 17 in der Version 6.0.2, welche das Front- beziehungsweise Backend darstellen sollen. Jede Anwendung wird dabei auf einem Applicationserver verteilt. Fr die Verwendung der beiden Applicationserver, auf einem System, muss eine Konguration der Ports erfolgen. Dies wird in den folgenden Kapiteln nher erlutert. Die Entwicklung des Servlets gestaltet sich relativ einfach und durch einige zustzliche Komponenten lsst sich dieses auch an viele der gestellten Anforderungen anpassen. Das bedeutet allerdings, dass eine Reihe von Aufwnden in der Entwicklung anfallen knnen. Aus dem Grund heraus, dass dieser Ansatz viele der Anforderungen erfllt und relativ einfach zu implementieren ist, wurde er fr den technischen Durchstich gewhlt. Im folgenden Kapitel wird dieser Lsungsansatz genauer beschrieben und erklrt.
17
http://tomcat.apache.org/
Nico Pleyer
Seite 20 von 53
6.1 Voraussetzungen
Fr die Umsetzung des technischen Durchstichs kommt am Frontendsystem ein Servlet in Kombination mit dem Apache HttpClient 18 zum Einsatz. Das Backendsystem ist eine einfache JSF 2.0 Anwendung. Die Anwendungen wurden mit Hilfe der Entwicklungsumgebung Eclipse Java EE IDE for Web Developers 19 , in der Indigo SR1 Version erstellt. Die Entwicklungsumgebung wurde um das Maven-Plugin m2eclipse 20 erweitert. Dieses ist ein Build-Tool, mit dem die Anwendungen erstellt und verwaltet werden knnen. Als Applicationserver kommen zwei Apache Tomcat der Version 6.0.2 zum Einsatz. Weiterhin wird die Bibliothek Apache HttpClient in der Version 4.1.2 verwendet, um eine Verbindung zwischen dem Front- und Backendsystem aufzubauen. Die Backendanwendung nutzt die Apache MyFaces 21 Implementierung der JavaServer Faces in der Version 2.1.0. Die Entscheidung el auf den Tomcat, da dieser leicht zu installieren und zu kongurieren ist. Weiterhin ist er sehr performant und auch Firmenintern konnten bereits einige Erfahrungen mit dem Tomcat gesammelt werden. Die beiden Anwendungen wurden zusammen auf einem lokalen Entwicklersystem erstellt und getestet. Aus diesem Grund mssen die Kongurationen der beiden Applicationserver angepasst werden. Beide Applicationserver mssen an unterschiedlichen Ports auf eingehende Anfragen warten. Der Port kann in der Datei server.xml, im conf Verzeichnis des Tomcat, gendert werden. Listing 6.1 zeigt den betreenden Abschnitt dieser Datei. Listing 6.1: Port-Konguration des Tomcat in der server.xml
1 2 3 4 5
< Connector port = " 8080 " protocol = " HTTP /1.1 " connectionTimeout = " 20000 " redirectPort = " 8443 " />
18 19
Nico Pleyer
Seite 21 von 53
Es muss lediglich das port-Attribut bearbeitet werden. Beide Applicationserver mssen auf unterschiedlichen Ports laufen, wie zum Beispiel 8080 und 8081. In Bezug auf die Anforderungen bietet diese Lsung einige Vorteile. Zum einen baut sie auf den Standardtechnologien Servlet und JSF auf und kann leicht durch weitere Technologien erweitert werden. Zum anderen erfllt JSF durch seinen TemplatingMechanismus nicht nur den Punkt der Mandantenfhigkeit, sondern bringt auch eine sehr gute Untersttzung fr AJAX-Anfragen mit. Weiterhin kann der Wartungsaufwand verringert werden, da sich JSF nach dem Prinzip Convention-overConguration kongurieren lsst. Somit knnen einige der Kongurationsdateien entfallen und Einstellungen direkt im Quelltext per Annotation vorgenommen werden. Ein weiterer Vorteil von JSF ist die automatisierte Zustandsverwaltung. Am Backend wird eine eindeutige Nummer generiert, ber die der Nutzer am Frontend erkannt wird. Dies geschieht in der JSF-Implementierung. Der Entwickler muss sich also nicht mit der Implementierung einer Sessionverwaltung am Backendsystem befassen. Es muss lediglich am Frontend eine Mglichkeit geschaen werden, die Sitzung der Backendanwendung wiederzuerkennen. Ein weiterer Vorteil dieser Lsung ist, dass eine Kommunikation ber das HTTPS-Protokoll22 , mit Hilfe des HttpClient, einfach umzusetzen ist. Ein Nachteil ist hingegen, dass das Protokoll, durch die Verwendung des Apache HttpClient, vorerst auf HTTP festgelegt ist. Weiterhin fallen einige Arbeiten an, um beispielsweise ein Content Management System am Frontend einzubinden. Da diese Aufwnde in der Regel nur einmalig sein werden und diese Lsung viele Vorteile aufweist, wurde sie fr den technischen Durchstich gewhlt.
6.2 Architektur
Der technische Durchstich besteht aus zwei Anwendungen, der Frontend- und der Backendanwendung. Ein am Frontend liegendes Servlet wartet auf eingehende Anfragen des Browsers. Dieses Servlet nimmt die Anfragen des Browsers entgegen, bereitet sie auf und sendet sie an die Backendanwendung. Es empfngt die Antwort des Backends und leitet diese an den Browser, zur Prsentation fr den Nutzer, weiter. Mit Hilfe des Servlets ist es auerdem mglich, die Antwort-Daten des Backends, am Frontend zu bearbeiten und zu manipulieren. Abbildung 6.1 zeigt den groben Aufbau des technischen Durchstichs.
Nico Pleyer
Seite 22 von 53
Die Kommunikation zwischen Front- und Backend erfolgt, bedingt durch den Apache HttpClient, ber das HTTP-Protokoll. Der HttpClient ernet in der doGet()- beziehungsweise doPost()-Methode des Servlets, je nach Typ der Anfrage, einen neuen Request. Diesem werden die Parameter und Meta-Daten der ursprnglichen Anfrage bergeben. Anschlieend wird der neu erstellte Request an das Backend weitergereicht. Durch dieses Verhalten wird eine zustzliche Station in den Lebenszyklus der Anfrage eingebaut, an der die Antwort-Daten noch beeinusst werden knnen. Die JSF-Anwendung am Backend soll die Business-Logik des Systems darstellen. Eine Besonderheit dieses Ansatzes ist es, dass sich die Anwendung so verhlt, wie bei einem direkten Zugri auf das Backend. Die Backendanwendung bentigt keine weiteren Informationen ber das Frontend und kann somit eine komplett eigenstndige Anwendung sein. Aus diesem Grund ist es mglich, die Anwendung am Backend einfach auszutauschen. Es muss unter Umstnden lediglich die Konguration des ProxyServlets angepasst werden. Fr das Frontend ist es auerdem gleichgltig, welche Technologie fr die Backendanwendung verwendet wurde. Der technische Durchstich weist derzeit noch einige Nachteile auf. Im momentanen Zustand mssen beispielsweise die Anwendungen am Front- und Backend gleich heien. Dieses Problem wird mit Hilfe der Maven-Konguration umgangen, indem festgelegt wird, dass beide Anwendungen unter dem gleichen Namen erstellt werden. Es ist jedoch auch mglich, dieses Problem durch ein geeignetes Mapping der Uniform Resource Locator (URL), in der Serverkonguration zu handhaben. Das Problem mit Hilfe von Maven zu lsen, war fr den technischen Durchstich erst einmal ausreichend. Spter empehlt es sich jedoch, auf eine geeignete Serverkonguration zurckzugreifen.
6.3 Implementierung
Die folgenden Abschnitte beschreiben die Anwendungen des technischen Durchstichs am Frontend- und Backendsystem. Hierbei wird die technische Seite der Anwendungen anhand von Quelltext-Ausschnitten erlutert.
6.3.1 Frontendanwendung
Die Frontendanwendung wurde mit dem Build-Tool Maven erstellt und verwaltet. Entwickelt wurde sie mit der Entwicklungsumgebung Eclipse Java EE IDE for Web Developers. Abbildung 6.2 zeigt den Aufbau der Anwendung, in einer Standard-Maven-Projektstruktur. Das Verzeichnis src/main/java enthlt dabei den Java-Quellcode. Das Verzeichnis src/main/webapp beinhaltet Kongurationen und zustzliche Ressourcen wie HTML-Seiten und Bilder der Webanwendung. In dem Verzeichnis target wird, nach dem Build-Prozess23 , die fertige Webanwendung abgelegt. Abhngigkeiten des Projektes sowie Einstellung zum Build-Prozess werden in der pom.xml deniert. In der Datei web.xml wird die Konguration der Webapplikation vorgenommen. Weitere Informationen und eine genauere Beschreibung zur
23
Nico Pleyer
Seite 23 von 53
Abbildung 6.2: Projektstruktur der Frontendanwendung, Quelle: eigene Darstellung (erstellt mit Eclipse) Maven-Projektstruktur benden sich auf der Webseite24 des Maven Projektes. Die Frontendanwendung stellt ein Servlet dar, welches die Klasse HttpServlet erweitert. Servlets mssen die Schnittstelle javax.servlet.Servlet implementieren. Das GenericServlet implementiert diese Schnittstelle und stellt somit die Grundlage fr das HttpServlet dar. Dieses erweitert das GenericServlet um einige, fr das HTTPProtokoll, spezische Methoden.25 Durch das Erweitern der Klasse HttpServlet mssen mindestens die beiden Methoden doGet() und doPost() berschrieben werden. Diese Methoden behandeln die GET- bezwiehungsweise POST-Anfragen, die durch den Nutzer, ber den Browser abgesetzt werden. Abbildung 6.3 zeigt das Klassendiagramm der Frontendanwendung. Die Klasse ProxyServlet ist dabei das Servlet, welches die Anfragen des Nutzers entgegen nimmt und an das Backend weiterleitet. ServletHelper ist eine Hilfsklasse26 , die statische Methoden zur Bearbeitung der Request- und ResponseDaten anbietet. Session reprsentiert ein Sitzungsobjekt und enthlt alle ntigen Daten, um die Sitzungen von Front- und Backend miteinander zu verknpfen. Die Klasse SessionHandler ist nach dem Singleton-Muster konzipiert. Dieses sieht vor, dass nur eine Instanz der Klasse erstellt werden kann.27 Die Klasse enthlt eine Li24 25
http://maven.apache.org/ Vgl. [Ull10, Kap. 17.16 Servlets] 26 Stellt Methoden bereit, die aus der eigentlichen Klasse ausgelagert wurden. 27 Vgl. [FFSB05, S. 177]
Nico Pleyer
Seite 24 von 53
ste aller oenen Sitzungen der Anwendung und stellt Methoden bereit, um auf diese zuzugreifen. Trit am Server eine Anfrage des Browsers ein, wird ermittelt, um welchen Typ der Anfrage es sich handelt. In den folgenden Abschnitten werden die Methoden zur Behandlung von GET- beziehungsweise POST-Anfragen nher erlutert.
HTTP GET-Anfragen Im erstellten Durchstich werden GET-Anfragen zum einen bei initialen Aufrufen der Seite angestoen und zum anderen um Ressourcen wie Cascading Style Sheets28 , Java Scripts oder Bilder zu laden. Bei einer GET-Anfrage knnen Daten aus HTMLFormularen, ber die URL, an den Server geschickt werden.29 Beim Eintreen einer Anfrage leitet der HttpClient diese an die Backendanwendung weiter. Hierfr ist es ntig die Request-Parameter und -Header auszulesen und der Anfrage des HttpClient zu bergeben.
28 29
Eine Sprache zum Denieren von Seitenlayouts. Vgl. [Ker11, Kap. 4.6.5 Verschiedene Internet-Anwendungsprotokolle]
Nico Pleyer
Seite 25 von 53
Um die Bearbeitung der Anfragen besser zu berblicken, wurden diese in verschiedene Phasen eingeteilt. Abbildung 6.4 zeigt die einzelnen Phasen, welche sich sowohl im Quelltext der Anwendung als auch im weiteren Verlauf der Arbeit wiedernden.
Abbildung 6.4: Phasen der Bearbeitung einer Anfrage, Quelle: eigene Darstellung Phase - init In diesem Abschnitt wird die Sitzung des Nutzers der aktuellen Anfrage zugeordnet. Ein Session-Objekt enthlt in diesem Fall, die SitzungsID des Frontends und die des Backends. Weiterhin wird der Userlevel des Nutzers der Sitzung zugeordnet. Trit am Frontend eine Anfrage ein, generiert das Servlet eine SessionID. Mit Hilfe dieser ID und des SessionHandlers wird die Liste der oenen Sitzungen durchsucht. Enthlt die Liste bereits eine Sitzung mit der SessionID des Frontends, wird diese aus der Liste gelesen und fr die weitere Bearbeitung der Anfrage verwendet. Fr den Fall, dass die Sitzung noch nicht existiert, wird ein neues Session-Objekt erzeugt. Listing 6.2 zeigt, wie diese Phase umgesetzt ist. Listing 6.2: Initialisieren der Sitzung
1 2 3 4 5 6 7 8
Session current ; if ( sHandler . containsFEId ( req . getSession () . getId () ) ) current = sHandler . getSessionByFEId ( req . getSession () . getId () ) ; else { current = new Session () ; current . setSessionFE ( req . getSession () . getId () ) ; } Das Sessionhandling der Anwendung ist noch sehr unausgereift. Zum Beispiel ist das Aufrumen beendeter Sitzungen, in diesem Beispiel noch nicht umgesetzt. Besonders beachtet werden sollte auerdem das Abstimmen der Timeout-Zeiten der Front- und Backendsitzungen. Fr einen produktiven Einsatz empehlt es sich, aus Grnden der Sicherheit, die Sitzungsverwaltung zu verbessern und zu erweitern. Ein mgliches
Nico Pleyer
Seite 26 von 53
Szenario wre es ebenfalls, dass vorhandene Sessionhandling des derzeitigen KoopAnsatzes an den neuen Ansatz anzupassen. Phase - set requested URL Die nchste Phase besteht darin, ein Objekt des HttpClient und der Http-Methode zu erstellen. Listing 6.3 zeigt das Deklarieren und Initialisieren der Objekte des HttpClient sowie der HTTP GET-Methode. Listing 6.3: Deklaration und Initialisierung des HttpClient
1 2 3 4
HttpClient client = new DefaultHttpClient () ; HttpGet httpget = new HttpGet ( ServletHelper . editUrl ( req ) + ServletHelper . getUrlQuery ( req ) ) ; Dem Objekt der GET-Methode wird im Konstruktor die URL der Backendanwendung bergeben. Mit Hilfe der Methoden editUrl() und getUrlQuery() wird die Zieladresse des Backendsystem erstellt. Beide sind in der Hilfsklasse ServletHelper implementiert. Listing 6.4 und 6.5 bilden diese Methoden ab. Listing 6.4: Methode zum Bearbeiten der Anfrage-URL
1 2 3 4 5 6 7
public static String editUrl ( HttpServletRequest req ) { String url = req . getRequestURL () . toString () . replace ( SRC_URL , DEST_URL ) ; if ( containsSessionId ( req ) ) url = url . substring (0 , url . indexOf ( " ; " ) ) ; return url ; } Die Methode editUrl() ersetzt zuerst den Host der Anfrage-URL, um die Anfrage an das Backendsystem weiterzuleiten. Die Konstante SRC_URL deniert hierbei die URL des ProxyServlets und die Konstante DEST_URL die der Backendanwendung. Weiterhin wird berprft, ob die Anfrage-URL den Parameter jsessionid enthlt. Bei einer initialen Anfrage wird am Backend eine SessionID erzeugt, ber welche der Nutzer, bei weiteren Anfragen, identiziert werden kann. Diese ID wird vom Backend, ber die URL, an das Servlet zurckgesendet. Aus Sicherheitsgrnden wird diese Nummer durch das Servlet aus der URL entfernt und nur noch als Cookie30 ausgetauscht. Listing 6.5: Methode zum Lesen des Query-Strings
1 2 3 4 5 6 7
public static String getUrlQuery ( HttpServletRequest req ) { String qry = req . getQueryString () ; if ( qry == null ) return " " ; else return " ? " + qry ; } Mit Hilfe der Methode getUrlQuery() wird der Query-String aus der Anfrage-URL ausgelesen. ber diese Zeichenkette knnen zustzliche Parameter bertragen wer30
Nico Pleyer
Seite 27 von 53
den. Enthlt die URL keine Parameter, gibt die Methode eine leere Zeichenkette zurck. Andernfalls wird der Query, beginnend mit einem ?, zurckgegeben. Dieses Verfahren kommt nur fr die GET-Methode zum Einsatz, da die Parameter der POST-Methode im HTTP-Body gesendet werden. Phase - set request parameters Nachdem die Zieladresse der Backendanwendung gesetz wurde, werden die RequestParameter und -Header ausgelesen und dem Objekt der GET-Methode bergeben. In Listing 6.6 und 6.7 wird beschrieben welche Schritte hierfr ntig sind. Listing 6.6: Setzen der Request-Parameter in der GET-Methode
1 2 3 4 5
Map < String , String [] > params = req . getParameterMap () ; for ( String key : params . keySet () ) { httpget . getParams () . setParameter ( key , params . get ( key ) [0]) ; } Fr das setzen der Request-Parameter ist es ntig alle Parameter auszulesen und die erhaltene Map31 zu durchlaufen. Hierbei wird jedes Key-Value-Paar der Map an das Objekt der GET-Methode bergeben. Diese Phase ist im technischen Durchstich ebenfalls noch kritisch zu betrachten. Die Anfrage-Parameter werden ungeltert an das Backend durchgereicht, was eine Manipulation von auen ermglicht. Es bietet sich hier an, einen Filter auf der Basis des Chain of Responsibility-Musters32 zu entwickeln. Dieses ermglicht es, den Filter einfach zu erweitern und zu kongurieren. Phase - set request headers Listing 6.7: Setzen der Request-Header in der GET-Methode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Enumeration < String > e = req . getHeaderNames () ; while ( e . hasMoreElements () ) { String name = e . nextElement () ; String value = req . getHeader ( name ) ; if ( " accept " . equalsIgnoreCase ( name ) && value . contains ( " text / html " ) ) { isHtml = true ; } if (! " content - length " . equalsIgnoreCase ( name ) ) { if ( " cookie " . equalsIgnoreCase ( name ) && value . contains ( " JSESSIONID " ) ) { value = " JSESSIONID = " + current . getSessionBE () + " ; Path =/ jsf2 - example " ; } httpget . setHeader ( name , value ) ; } }
31 32
Eine Datenstruktur, in welcher die Daten als Key-Value-Paare angeordnet sind. [FFSB05, S. 616f.]
Nico Pleyer
Seite 28 von 53
Das Setzen der Request-Header gestaltet sich hnlich. Die Header werden in einer Enumeration 33 ausgelesen und durchlaufen. Dabei werden die einzelnen Elemente wieder dem Objekt der GET-Methode bergeben. Whrend der bergabe der Elemente mssen einige Spezialflle beachtet werden. Zum einen wird der Wert des accept-Header geprft. Dieser Header legt fest, von welchem Typ der Inhalt eines Response sein darf. In diesem Fall soll fr Antworten mit einem HTML-Inhalt, die Variable isHtml auf den Wert true gesetzt werden. Der Wert dieser Variable wird spter dazu verwendet, um den Typ der Antwort leichter zu ermitteln. Weiterhin werden die Header auf ihren Namen geprft. Das Element mit dem Namen contentlength wird an dieser Stelle herausgeltert, da dieser spter automatisch gesetzt wird. Wenn der cookie-Header die SessionID enthlt, wird die ID des Frontends mit der des Backends ausgetauscht. Somit wird sichergestellt, dass der Nutzer von der Backendanwendung wiedererkannt wird. Phase - executing request Im Anschluss kann die Anfrage ber den HttpClient abgesetzt werden. Listing 6.8 zeigt wie dies im Quelltext umgesetzt ist. Listing 6.8: Senden eines Request ber die GET-Methode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
ResponseHandler < String > responseHandler = new BasicResponseHandler () ; if ( isHtml ) { HttpResponse response = client . execute ( httpget ) ; responseBody = responseHandler . handleResponse ( response ) ; Session tmp = setSessionData ( req , response ) ; current . setSessionBE ( tmp . getSessionBE () ) ; sHandler . addSession ( current ) ; res = ServletHelper . handleResponseHeader ( current , res , response ) ; } else { responseBody = client . execute ( httpget , responseHandler ) ; } Der ResponseHandler verarbeitet die Antwort des Servers und gibt den Inhalt dieser als String zurck. Die Abfrage prft, von welchem Typ der Inhalt dieser Anfrage ist. Wurde, wie in Listing 6.7 beschrieben, die Variable isHtml auf den Wert true gesetzt, handelt es sich bei der Antwort um ein HTML-Formular. Die Antwort des Backends wird in das Objekt response geschrieben. Dieses wird anschlieend an den ResponseHandler bergeben und in der Methode handleResponse() verarbeitet. Die Methode liest den HTML-Inhalt der Antwort aus und schreibt diesen in die Zeichenkette responseBody. Der nchste Schritt besteht darin, die Sessiondaten der aktuellen Anfrage zu behandeln. Die Methode setSessionData() wird in Listing 6.9 erlutert. Das bearbeitete Session-Objekt wird anschlieend der Liste aller oenen Sitzungen hinzugefgt. Als letztes werden die Header der Backend-Antwort bernommen und
33
Eine Sammlung von Daten, mit dessen Hilfe ber Mengen iteriert werden kann.
Nico Pleyer
Seite 29 von 53
in das Response-Objekt des ProxyServlet geschrieben. Dies geschieht mit Hilfe der Methode handleResponseHeader(), welche in Listing 6.10 beschrieben wird. Erwartet die Anfrage keine HTML-Antwort, wird sie mit Hilfe des ResponseHandler abgesetzt. Der Inhalt wird dabei direkt in die Zeichenkette responseBody geschrieben. Dies ist zum Beispiel der Fall, wenn Bilder oder Style-Sheets geladen werden. Listing 6.9: Methode zum Behandeln der Sessiondaten
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
private Session setSessionData ( HttpServletRequest req , HttpResponse res ) { Session session = new Session () ; String frontId = req . getSession () . getId () ; String backId = null ; String level = null ; if ( res . containsHeader ( " userlevel " ) ) { level = res . getFirstHeader ( " userlevel " ) . getValue () ; } if ( res . containsHeader ( " set - cookie " ) ) { Header [] headers = res . getHeaders ( " set - cookie " ) ; for ( Header h : headers ) { if ( h . getValue () . contains ( " JSESSIONID " ) ) { String value = h . getValue () ; backId = value . substring ( value . indexOf ( " = " ) +1 , value . indexOf ( " ; " ) ) ; } } } if ( backId == null ) backId = sHandler . getBEIdByFEId ( frontId ) ; if ( level == null ) level = sHandler . getUserlevelByFEId ( frontId ) ; session . setSessionFE ( frontId ) ; session . setSessionBE ( backId ) ; session . setUserlevel ( level ) ; return session ; } Die Methode setSessionData() ist fr das Bearbeiten der Sessiondaten zustndig. Sie prft, ob die Antwort des Backends einen Userlevel enthlt. Falls dieser vorhanden ist, wird sein Wert ausgelesen und in der Zeichenkette level gespeichert. Um den Userlevel einem Nutzer zuordnen zu knnen, wird die SessionID bentigt. Diese wird bei initialen Anfragen an das Backend ber den set-cookie-Header gesendet. Aus diesem Header wird die ID herausgelesen und abgespeichert. Wurde der Header nicht gesendet, existiert ein Cookie, welches die ID enthlt. Wenn dieses Cookie besteht, wurde die BackendID bereits dem Session-Objekt hinzugefgt. Aus diesem
Nico Pleyer
Seite 30 von 53
kann dann die SessionID des Backends gelesen werden. Anschlieend werden die Sessiondaten in einem temporren Session-Objekt gespeichert und von der Methode zurckgeben. Die Daten werden nun in die Liste der Sitzungen aufgenommen. Listing 6.10: Methode zum bernehmen der Response-Header
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public static HttpServletResponse handleResponseHeader ( Session aSession , HttpServletResponse res , HttpResponse response ) { Header [] headers = response . getAllHeaders () ; for ( Header h : headers ) { String name = h . getName () ; String value = h . getValue () ; if ( " set - cookie " . equalsIgnoreCase ( name ) && value . contains ( " JSESSIONID " ) ) { value = " JSESSIONID = " + aSession . getSessionFE () + " ; Path =/ jsf2 - example " ;
} res . addHeader ( name , value ) ; } return res ; } Die ausgelagerte Methode handleResponseHeader() bendet sich in der Hilfsklasse ServletHelper. Diese Methode bernimmt die Response-Header des Backends und schreibt sie in das HttpServletResponse-Objekt des ProxyServlets. Hierfr werden die Header in das Array headers ausgelesen. Diese Datenstruktur wird anschlieend durchlaufen und jedes Element dem HttpServletResponse-Objekt hinzugefgt. Wird whrend dem Durchlaufen des Arrays auf den set-cookie-Header getroen, erfolgt wie auch vor dem Senden der Anfrage, ein Mapping der SessionID. In diesem Fall wird allerdings die ID der Backendanwendung, mit der des Frontend ersetzt. Phase - print response Nachdem die Anfrage abgesetzt und die Antwortdaten ausgelesen wurden, mssen diese noch zur Anzeige ausgegeben werden. Hierfr gibt es zwei Methoden, welche in Listing 6.11 und 6.12 beschrieben werden. Listing 6.11: Methode zum Ausgeben von HTML-Antworten
1 2 3 4 5 6 7 8 9 10 11 12
private void manipulateResponse ( Session aSession , HttpServletResponse res , String response ) throws IOException { ServletOutputStream out = res . getOutputStream () ; out . println ( getDeclaration ( response ) ) ; out . println ( " < html xmlns = " + " \" http :// www . w3 . org /1999/ xhtml \" > " ) ; out . println ( getHead ( response ) ) ; out . println ( " < body > " ) ; out . println ( " <h1 > Zustand - " + getState ( aSession . getUserlevel () ) + " </ h1 > " ) ;
Nico Pleyer
Seite 31 von 53
13 14 15 16 17 18
out . println ( getContent ( response ) ) ; out . println ( " </ body > " ) ; out . println ( " </ html > " ) ; out . flush () ; } Die Methode manipulateResponse() wird ausgefhrt, wenn die Antwort des Backends HTML ist. In diesem Fall wird, um die Seite der Backendanwendung herum, eine berschrift mit dem aktuellen Zustand des Nutzers ausgegeben. Dieses Verhalten soll zeigen, dass sich die Anwendung in ein Content Management System integrieren lsst und wie Daten von der Backendanwendung an das ProxyServlet bermittelt werden knnen. Bei den Aktionen login und logout wird, am Backend, der Userlevel in den ResponseHeader geschrieben und an das Frontend gesendet. Hier wird in Abhngigkeit des Userlevels jeweils eine andere berschrift ausgegeben. Die Ausgabe des Userlevels erfolgt durch die Methode getState(). Weiterhin wird die HTML-Seite des Backends in verschiedene Teile zerlegt. Mit Hilfe der Methoden getDeclaration(), getHead() und getContent() werden die einzelnen Teilstcke gelesen und in die Seite des Frontends eingebettet. Listing 6.12: Methode zum Ausgeben von Ressourcen
1 2 3 4 5 6 7 8
private void printResponse ( HttpServletResponse res , String result ) throws IOException { ServletOutputStream out = res . getOutputStream () ; out . println ( result ) ; out . flush () ; } Alle Antworten die kein HTML enthalten, werden ohne Manipulation ausgegeben. Dies knnen Beispielsweise Antworten auf AJAX-Anfragen, Bilder oder andere Ressourcen sein. Der vollstndige Quelltext der GET-Methode bendet sich im Anhang, in Listing A.1. HTTP POST-Anfragen POST-Anfragen wiederum, werden beim Ausfhren von Aktionen, auf einer Seite, angestoen. Diese Aktionen sind zum Beispiel das Klicken auf einen Link oder Button. AJAX-Anfragen werden ebenfalls ber die POST-Methode versendet. Bei einer POST-Anfrage werden Daten aus HTML-Formularen an den Server bertragen, indem sie dem HTTP-Body der Anfrage hinzugefgt werden. In diesem HTTP-Body werden die Nutzdaten gesammelt an das Backend versendet.34 Der Vorteil dieser Methode ist, dass die Nutzdaten nicht ohne weiteres am Bildschirm abgelesen werden knnen.
34
Nico Pleyer
Seite 32 von 53
Phase - init Das Ausfhren der POST-Methode funktioniert im Grunde nach dem gleichen Prinzip, wie das der GET-Methode. Listing 6.2 zeigt das Initialisieren der Session, was fr die POST-Methode ebenso gilt wie, fr die GET-Methode. Es wird auch hier geprft, ob die Session bereits existiert und gegebenenfalls aus der Liste gelesen. Andernfalls wird eine neue Session erzeugt. Phase - set requested URL Auch fr die POST-Methode wird das Objekt des HttpClient sowie das Objekt der HTTP-Methode erstellt. Hier wird allerdings ein Objekt entsprechend der POSTMethode genutzt. Listing 6.13 zeigt das Erstellen dieser Objekte. Listing 6.13: POST Objekt initialisieren und deklarieren
1 2 3
HttpClient client = new DefaultHttpClient () ; HttpPost httppost = new HttpPost ( ServletHelper . editUrl ( req ) ) ; Im Gegensatz zur GET-Methode wird hier der Query-String in der URL vernachlssigt, da die Parameter ausschlielich im Body der HTTP-Anfrage versendet werden. Phase - set request parameters Einen weiteren Unterschied zur GET-Methode stellt das Setzen der Request-Parameter dar. In Listing 6.14 wird gezeigt, wie diese an das Objekt der POST-Methode bergeben werden. Listing 6.14: Setzen der Request-Parameter in der POST-Methode
1 2 3 4 5 6 7 8 9 10 11
List < NameValuePair > nameValuePairs = new ArrayList < NameValuePair >() ; Map < String , String [] > params = req . getParameterMap () ; for ( String key : params . keySet () ) { nameValuePairs . add ( new BasicNameValuePair ( key , params . get ( key ) [0]) ) ; } httppost . setEntity ( new UrlEncodedFormEntity ( nameValuePairs , " UTF -8 " ) ) ; Die Parameter werden auch hier als Map ausgelesen. Beim Durchlaufen der Map, werden die Parameter allerdings in einer Liste zwischengespeichert und anschlieend gesammelt an das Objekt der POST-Methode bergeben. Hier ist in einem produktiven Einsatz ebenfalls ein Filter zu verwenden, ber den geprft wird, welche Parameter an das Backend gesendet werden. Phase - set request headers Whrend dem Setzen der Request-Header wird bei der POST-Methode nicht zwischen HTML-Inhalten und anderen Ressourcen unterschieden. Hier werden AJAXAnfragen von normalen Anfragen getrennt. Wie in Listing 6.15 dargestellt, werden die Header auf ihren Namen geprft. Handelt es sich um einen faces-request mit dem Wert partial/ajax, also einen AJAX-Request, wird die Variable isAjax auf den Wert true gesetzt. Diese Variable wird fr die weitere Bearbeitung der Anfrage ben-
Nico Pleyer
Seite 33 von 53
tigt. Weiterhin erfolgt auch hier ein Mapping der Session des Frontends auf die des Backends. Listing 6.15: Setzen der Request-Header in der POST-Methode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Enumeration < String > e = req . getHeaderNames () ; while ( e . hasMoreElements () ) { String name = e . nextElement () ; String value = req . getHeader ( name ) ; if ( " faces - request " . equalsIgnoreCase ( name ) && " partial / ajax " . equalsIgnoreCase ( value ) ) { isAjax = true ; } if (! " content - length " . equalsIgnoreCase ( name ) ) { if ( " cookie " . equalsIgnoreCase ( name ) && value . contains ( " JSESSIONID " ) ) { value = " JSESSIONID = " + current . getSessionBE () + " ; Path =/ jsf2 - example " ; } httppost . setHeader ( name , value ) ; } } Phase - executing request Das Senden der Anfrage erfolgt hier ohne Abfrage des Inhalts-Typen. Eine POSTAnfrage wird, wie eine Anfrage mit HTML-Inhalt in der doGet()-Methode gesendet, da hier keine Ressourcen angefragt werden. Listing 6.16 zeigt das Senden einer POST-Anfrage. Im Gegensatz zur GET-Anfrage wird hier allerdings nur der Userlevel gesetzt, da sich dieser nur bei POST-Anfragen ndert. Listing 6.16: Senden eines Request ber die POST-Methode
1 2 3 4 5 6 7 8 9 10 11
ResponseHandler < String > responseHandler = new BasicResponseHandler () ; HttpResponse response = client . execute ( httppost ) ; responseBody = responseHandler . handleResponse ( response ) ; Session tmp = setSessionData ( req , response ) ; current . setUserlevel ( tmp . getUserlevel () ) ; sHandler . addSession ( current ) ; res = ServletHelper . handleResponseHeader ( current , res , response ) ; Phase - print response Das Ausgeben der Antwort erfolgt hier in Abhngigkeit des Typs der Anfrage. Handelt es sich um einen AJAX-Request wird die Antwort mit Hilfe der Methode printResponse(), wie in Listing 6.12, ausgegeben. Alle anderen Antworten werden, wie in Listing 6.11 beschrieben, ber die Methode manipulateResponse() angezeigt. Der vollstndige Quelltext der POST-Methode bendet sich im Anhang, in Listing A.2.
Nico Pleyer
Seite 34 von 53
6.3.2 Backendanwendung
Die Backendanwendung ist eine Beispiel-Anwendung, welche die Funktionen des ProxyServlets darstellen und belegen soll. Sie wird aus diesem Grund nicht im Detail beschrieben. Die Anwendung ist ebenfalls ein auf Maven basierendes Projekt und wurde mit der Entwicklungsumgebung Eclipse Java EE IDE for Web Developers entwickelt. Die Struktur des Projektes ist dem der Frontendanwendung hnlich. Hier werden allerdings einige zustzliche Ressourcen bentigt. Diese benden sich hauptschlich im Verzeichnis src/main/webapp. Dessen Unterverzeichnis metainf/includes enthlt dabei vor allem Seitendenitionen und template-Dateien, welche auf den verschiedenen Seiten verwendet werden. Die reinen Seiteninhalte liegen im Verzeichnis pages. Im Verzeichnis resources benden sich zum Beispiel Bilder und Cascading Style Sheets. Abbildung A.1 zeigt die Struktur der gesamten Anwendung. Diese basiert auf JavaServer Faces und wurde mit der Apache MyFaces Implementierung umgesetzt. Sie stellt einige Funktionen einer Nutzerverwaltung zur Verfgung und bietet ebenfalls ein Beispiel fr AJAX-Anfragen. Es ist mglich, sich mit einem Nutzer beziehungsweise Administrator am System anzumelden und je nach Nutzertyp verschiedene Aktionen auszufhren. Als Administrator ist es beispielsweise mglich, seine Nutzerdaten zu ndern oder eine Liste aller vorhanden Nutzer einzusehen. Als einfacher Nutzer ist es jedoch nur mglich, seine eigenen Daten zu ndern. Das Klassendiagramm in Abbildung A.2 zeigt eine bersicht der erstellten Klassen. JSF ist nach dem Model-View-Controller-Prinzip konzipiert, genauer gesagt dem Model2. Dieses ist eine fr Webanwendungen spezialisierte Variante des ModelView-Controller-Prinzips und teilt die Anwendung demnach in die drei Bereiche Model, View und Controller. Die View Komponente stellen hierbei Faclets, also die xhtml-Dateien dar. Sie enthalten den Inhalt der Seiten und bilden somit die Benutzerschnittstelle ab. Die Klasse User enthlt das Datenmodell der Anwendung. In ihr wird festgelegt, welche Attribute ein Nutzer hat und wie diese abgespeichert werden. Die Klasse UserBean fungiert als Verbindung zwischen dem Datenmodell und der View-Komponente. Der Controller wird durch ein Servlet dargestellt, welches durch die JSF-Implementierung bereitgestellt wird.35 Wird auf der Nutzeroberche eine Aktion angestoen, beispielsweise durch das Klicken auf den Login-Button, wird in der Klasse UserBean die Methode login() aufgerufen. Listing 6.17 zeigt die login()-Methode. Listing 6.17: Methode zum Ausfhren der Login-Aktion
1 2 3 4 5 6 7 8 9
public String login () { if ( checkLogin () ) { ExternalContext context = FacesContext . getCurrentInstance () . getExternalContext () ; user . setLevel ( User . LEVEL_ON ) ; context . setResponseHeader ( " Userlevel " , " " + user . getLevel () ) ;
35
[MKM09, S. 5]
Nico Pleyer
Seite 35 von 53
10 11 12 13 14 15 16 17 18 19 20 21 22 23
if ( user . getType () == User . TYPE_USER ) { navigation = Pages . T_NAVI_USER ; return Pages . P_HOME ; } else if ( user . getType () == User . TYPE_ADMIN ) { navigation = Pages . T_NAVI_ADMIN ; users = services . findAll () ; return Pages . A_ADMIN ; } } return Pages . E_LOGIN_FAIL ; } Hier wird ber die Hilfsmethode checkLogin() geprft, ob der Nutzer, mit dem versucht wurde sich einzuloggen, in der Datenbasis existiert. Eine Liste mit allen verfgbaren Nutzern wird beim Start der Anwendung, in der Klasse UserServices, angelegt. Ist der Nutzer vorhanden, wird sein Userlevel gendert und als ResponseHeader gesetzt. So kann der Userlevel am Frontend empfangen werden. Weiterhin wird der Typ des Nutzers geprft. Derzeit gibt es die Typen TYPE_USER und TYPE_ADMIN, um zwischen normalen Nutzern und Administratoren zu unterscheiden. In Abhngigkeit von diesen wird ein entsprechender Verweis auf die Seite zurckgegeben, welche als Antwort auf die login-Aktion angezeigt werden soll. Alle Verweise auf Seiten sind in der Klasse Pages als Konstanten hinterlegt. Um eine Klasse als ManagedBean festzulegen, also als Verbindung zwischen Model und View, muss diese mit der Annotation @ManagedBean(name = BEAN_NAME) und einem entsprechenden Namen fr den Zugri versehen werden. Weiterhin muss ihr ein Scope zugewiesen werden, was ebenfalls mit Hilfe einer Annotation geschehen kann. Dieser legt fest, wie lange ein Objekt der Klasse verfgbar ist. Hier sind die folgenden Optionen mglich. @NoneScoped - Die Managed-Bean wird nicht gespeichert und bei jedem Aufruf neu erstellt. @RequestScoped - Die Managed-Bean lebt fr die Zeitdauer einer HTTP-Anfrage. @ViewScoped - Die Lebensdauer der Managed-Bean ist an die Ansicht geknpft, in der sie verwendet wird. @SessionScoped - Die Managed-Bean lebt fr die Dauer einer Sitzung, in der der Benutzer mit der Anwendung verbunden ist. @ApplicationScoped - Fr die gesamte Lebensdauer der Anwendung ist nur eine fr alle Benutzer gleiche Instanz dieser Managed-Bean vorhanden. Tabelle 6.1: Scopes einer ManagedBean, Quelle: [MKM09, S. 33]
Nico Pleyer
Seite 36 von 53
Die Klasse UserBean verwendet den Session-Scope und ist somit ber die Dauer einer Sitzung verfgbar. Die Klasse UserServices muss dagegen den Application-Scope verwenden, um immer verfgbar zu sein. Hierdurch wird es mglich diese Klasse als eine Art Datenbankersatz zu verwenden und nderungen an den Nutzerdaten zu speichern. Wie bereits erwhnt, soll diese Anwendung lediglich die Funktionalitt der Frontendanwendung demonstrieren und besttigen. Der vollstndige Quelltext der Anwendung liegt allerdings der Arbeit bei.
Nico Pleyer
Seite 37 von 53
Nico Pleyer
Seite 38 von 53
allem das Muster Chain of Responsibility an. Dieses kann dazu eingesetzt werden, den bereits erwhnten Filter, fr das Senden der Anfrage-Parameter, zu entwickeln. Ein weiterer denkbarer Einsatz dieses Musters wre, es hnlich wie das InterceptorMuster in der bestehenden Koop-Middleware zu verwenden. Dies wrde vor allem die Konguration und Erweiterbarkeit der Anwendung verbessern. Eine andere Mglichkeit ist es, den neuen Ansatz in die alte Koop-Middleware zu integrieren und somit die bewhrten Konzepte, zu den genannten Themen anzupassen und zu nutzen. Dabei wren allerdings erhebliche nderungen an der bestehenden Koop-Middleware ntig. Die Arbeitsweise mit dem, im technischen Durchstich verwendeten Ansatz wrde sich dahingehend ndern, dass die Koop-Komponente nur noch am Frontend umgesetzt werden msste. Die Backendanwendungen sind somit eigenstndige Anwendungen und bentigen keine zustzlichen Komponenten.
Nico Pleyer
Seite 39 von 53
Literaturverzeichnis
[Apa] Apache Software Foundation: Apache Struts. http://struts. apache.org/. [Online, Stand 28.10.2011] [FFSB05] Freeman, Eric ; Freeman, Elisabeth ; Sierra, Kathy ; Bates, Bert: Entwurfsmuster von Kopf bis Fu. OReilly, 2005 [Goo] Google Inc.: Google Web Toolkit. http://code.google.com/intl/ de-DE/webtoolkit/overview.html. [Online, Stand 28.10.2011] [Hep08] Hepper, Stefan: Java Portlet Specication 2.0 (Final Release). http://jcp.org/aboutJava/communityprocess/final/jsr286/ index.html. Version: Januar 2008. [Online, Stand 23.11.2011] [Inva] Inverso GmbH: Architektur InetP. internes Dokument [Invb] Inverso GmbH: Entwickler-Leitfaden InetP. internes Dokument [Invc] Inverso GmbH: Projekte. http://www.inverso.de/inverso/ projekte/index.html. [Online, Stand 11.11.2011] [Ker11] Kersken, Sascha: IT-Handbuch fr Fachinformatiker. Galileo Computing, 2011; http://openbook.galileocomputing.de/it_handbuch/. [Online, Stand 17.11.2011] [LH09] Laprun, Chris ; Heute, Thomas: JBoss Portal 2.7.1 - Reference Guide. http://docs.jboss.org/jbportal/v2.7.1/referenceGuide/ html/tutorials.html. Version: Januar 2009. [Online, Stand 23.11.2011] [MKM09] Marinschek, Martin ; Kurz, Michael ; Mllan, Gerald: JavaServer Faces 2.0: Grundlagen und erweiterte Konzepte. dpunkt Verlag, 2009; http://jsfatwork.irian.at/semistatic/introduction.html. [Online, Stand 30.11.2011] [OM03] Ort, Ed ; Mehta, Bhakti: Java Architecture for XML Binding (JAXB). http://www.oracle.com/technetwork/articles/javase/ index-140168.html. Version: Mrz 2003. [Online, Stand 11.11.2011] [Sta] Stahl, Jens: Vorstellung des Google Web Toolkit. http://www.ordix. de/ORDIXNews/1_2007/Java_J2EE/google_web_toolkit_ajax.html. [Online, Stand 11.11.2011]
Nico Pleyer
40
Literaturverzeichnis
[Tho08] Thompson, Rich: WSRP v2.0 Specication. http://docs.oasis-open. org/wsrp/v2/wsrp-2.0-spec-os-01.html. Version: April 2008. [Online, Stand 11.11.2011] [Ull10] Ullenboom, Christian: Java ist auch eine Insel. Galileo Computing, 2010; http://openbook.galileocomputing.de/javainsel/. [Online, Stand 17.11.2011]
Nico Pleyer
41
A Anhang
A.1 Quelltext des ProxyServlet
Listing A.1: doGet()-Methode des ProxyServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
@SuppressWarnings ( " unchecked " ) @Override protected void doGet ( HttpServletRequest req , HttpServletResponse res ) throws ServletException , IOException { HttpClient client = new DefaultHttpClient () ; Session current ; String responseBody = " " ; boolean isHtml = false ; // --- init --if ( sHandler . containsFEId ( req . getSession () . getId () ) ) current = sHandler . getSessionByFEId ( req . getSession () . getId () ) ; else { current = new Session () ; current . setSessionFE ( req . getSession () . getId () ) ; } try { // --- set requested URL --HttpGet httpget = new HttpGet ( ServletHelper . editUrl ( req ) + ServletHelper . getUrlQuery ( req ) ) ; // --- set request parameters --Map < String , String [] > params = req . getParameterMap () ; for ( String key : params . keySet () ) { httpget . getParams () . setParameter ( key , params . get ( key ) [0]) ; } // --- set request headers --Enumeration < String > e = req . getHeaderNames () ; while ( e . hasMoreElements () ) { String name = e . nextElement () ; String value = req . getHeader ( name ) ; if ( " accept " . equalsIgnoreCase ( name ) && value . contains ( " text / html " ) ) {
Nico Pleyer
42
A. Anhang
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
isHtml = true ; } if (! " content - length " . equalsIgnoreCase ( name ) ) { if ( " cookie " . equalsIgnoreCase ( name ) && value . contains ( " JSESSIONID " ) ) { value = " JSESSIONID = " + current . getSessionBE () + " ; Path =/ jsf2 - example " ; } httpget . setHeader ( name , value ) ; } } // --- executing request --ResponseHandler < String > responseHandler = new BasicResponseHandler () ; if ( isHtml ) { HttpResponse response = client . execute ( httpget ) ; responseBody = responseHandler . handleResponse ( response ) ; Session tmp = setSessionData ( req , response ) ; current . setSessionBE ( tmp . getSessionBE () ) ; sHandler . addSession ( current ) ; res = ServletHelper . handleResponseHeader ( current , res , response ) ; } else { responseBody = client . execute ( httpget , responseHandler ) ; } // --- print response --if ( isHtml ) manipulateResponse ( current , res , responseBody ) ; else printResponse ( res , responseBody ) ; } finally { client . getConnectionManager () . shutdown () ; } } Listing A.2: doPost()-Methode des ProxyServlet
1 2 3 4 5 6 7 8 9 10 11
@SuppressWarnings ( " unchecked " ) @Override protected void doPost ( HttpServletRequest req , HttpServletResponse res ) throws ServletException , IOException { HttpClient client = new DefaultHttpClient () ; Session current ; String responseBody = " " ; boolean isAjax = false ; // --- init ---
Nico Pleyer
43
A. Anhang
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
if ( sHandler . containsFEId ( req . getSession () . getId () ) ) current = sHandler . getSessionByFEId ( req . getSession () . getId () ) ; else { current = new Session () ; current . setSessionFE ( req . getSession () . getId () ) ; } try { // --- set requested URL --HttpPost httppost = new HttpPost ( ServletHelper . editUrl ( req ) ) ; // --- set request parameters --List < NameValuePair > nameValuePairs = new ArrayList < NameValuePair >() ; Map < String , String [] > params = req . getParameterMap () ; for ( String key : params . keySet () ) { nameValuePairs . add ( new BasicNameValuePair ( key , params . get ( key ) [0]) ) ; } httppost . setEntity ( new UrlEncodedFormEntity ( nameValuePairs , " UTF -8 " ) ) ; // --- set request headers --Enumeration < String > e = req . getHeaderNames () ; while ( e . hasMoreElements () ) { String name = e . nextElement () ; String value = req . getHeader ( name ) ; if ( " faces - request " . equalsIgnoreCase ( name ) && " partial / ajax " . equalsIgnoreCase ( value ) ) { isAjax = true ; } if (! " content - length " . equalsIgnoreCase ( name ) ) { if ( " cookie " . equalsIgnoreCase ( name ) && value . contains ( " JSESSIONID " ) ) { value = " JSESSIONID = " + current . getSessionBE () + " ; Path =/ jsf2 - example " ; } httppost . setHeader ( name , value ) ; } } // --- executing request --ResponseHandler < String > responseHandler = new BasicResponseHandler () ; HttpResponse response = client . execute ( httppost ) ;
Nico Pleyer
44
A. Anhang
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
responseBody = responseHandler . handleResponse ( response ) ; Session tmp = setSessionData ( req , response ) ; current . setUserlevel ( tmp . getUserlevel () ) ; sHandler . addSession ( current ) ; res = ServletHelper . handleResponseHeader ( current , res , response ) ; // --- print response --if ( isAjax ) printResponse ( res , responseBody ) ; else manipulateResponse ( current , res , responseBody ) ; } finally { client . getConnectionManager () . shutdown () ; } }
Nico Pleyer
45
A. Anhang
<? xml version = " 1.0 " encoding = " UTF -8 " ? > <! DOCTYPE UNI_TRANSPORT SYSTEM " ../ dtd / uni / uni_transport . dtd " > < UNI_TRANSPORT > < SERVICE > </ SERVICE > < ERROR > </ ERROR > < TRANSFORM_ID > PREMIUM_HOME_VKB </ TRANSFORM_ID > < VU_SESSION_ID > </ VU_SESSION_ID > < USER_LEVEL >2 </ USER_LEVEL > < CONTENT > < ![ CDATA [ <? xml version = " 1.0 " encoding = " ISO -8859 -1 " ? > <! DOCTYPE KUNDENREGISTRIERUNG SYSTEM " ../ dtd / kundenregistrierung . dtd " > < KUNDENREGISTRIERUNG > < UNI_KUNDENREGISTRIERUNG > < UNI_ALLG_ADR > < ADR_NAME > < ADR_NACHNAME > < UNI_DC > < FACH_VAL > Mustermann </ FACH_VAL > </ UNI_DC > </ ADR_NACHNAME > < ADR_ANREDE > < UNI_DC > < FACH_VAL > Herr </ FACH_VAL > </ UNI_DC > </ ADR_ANREDE > </ ADR_NAME > </ UNI_ALLG_ADR > < ANMELDEDATEN > < BENUTZER_KENNUNG > < UNI_DC > < FACH_VAL > Muster </ FACH_VAL > </ UNI_DC > </ BENUTZER_KENNUNG > </ ANMELDEDATEN > < LETZTE_ERFOLGR_ANMELDUNG > < LETZTE_ERFOLGR_ANM_DATUM > < UNI_DC > < FACH_VAL > 1.01.2011 </ FACH_VAL > </ UNI_DC > </ LETZTE_ERFOLGR_ANM_DATUM > </ LETZTE_ERFOLGR_ANMELDUNG > </ UNI_KUNDENREGISTRIERUNG > </ KUNDENREGISTRIERUNG >]] > </ CONTENT > </ UNI_TRANSPORT >
Nico Pleyer
46
A. Anhang
Abbildung A.1: Projektstruktur der Backendanwendung, Quelle: eigene Darstellung (erstellt mit Eclipse)
Nico Pleyer
47
A. Anhang
Nico Pleyer
48
A. Anhang
Tabelle A.1: Nutzer der Backendanwendung, Quelle: eigene Darstellung Zur Weiterentwicklung beziehungsweise zum Analysieren der Anwendungen, knnen die Projekte in Eclipse importiert werden. Die Eclipse Java EE IDE for Web Developers bietet hierzu eine Funktion an, die ber den Menpunkt File > Import... erreicht werden kann. ber die Kategorie General und den Punkt Existing Projects into Workspace knnen die Projekte in den Eclipse Workspace integriert werden. Es empehlt sich in der Entwicklungsumgebung das Plugin m2eclipse zu installieren. Mit Hilfe dessen knnen die Projekte ber die Kategorie Maven und den Punkt Existing Maven Projecs direkt als Maven-Projekte eingebunden werden.
Nico Pleyer
49
Abbildungsverzeichnis
1.1 2.1 2.2 2.3 2.4 4.1 4.2 6.1 6.2 6.3 6.4 Kommunikation zwischen Koop Front- und Backend . . . . . . . . . . InetP Systembersicht . . . Aufbau des Koop-Frontends Aufbau des Koop-Backends Ablauf einer Anfrage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 3 5 6 7
Aufbau einer Portalseite . . . . . . . . . . . . . . . . . . . . . . . . . 15 Aufbau einer JAXB-Anwendung . . . . . . . . . . . . . . . . . . . . . 16 Aufbau des technischen Durchstichs . . . . Projektstruktur der Frontendanwendung . Klassendiagramm der Frontendanwendung Phasen der Bearbeitung einer Anfrage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 24 25 26
Nico Pleyer
50
Tabellenverzeichnis
2.1 3.1 6.1 Elemente des Koop-XML . . . . . . . . . . . . . . . . . . . . . . . . . 4 Bewertung der Anforderungen . . . . . . . . . . . . . . . . . . . . . . 12 Scopes einer ManagedBean . . . . . . . . . . . . . . . . . . . . . . . . 36
Nico Pleyer
51
Listings
6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13 6.14 6.15 6.16 6.17 Port-Konguration des Tomcat in der server.xml . . . Initialisieren der Sitzung . . . . . . . . . . . . . . . . Deklaration und Initialisierung des HttpClient . . . . Methode zum Bearbeiten der Anfrage-URL . . . . . . Methode zum Lesen des Query-Strings . . . . . . . . Setzen der Request-Parameter in der GET-Methode . Setzen der Request-Header in der GET-Methode . . . Senden eines Request ber die GET-Methode . . . . Methode zum Behandeln der Sessiondaten . . . . . . Methode zum bernehmen der Response-Header . . . Methode zum Ausgeben von HTML-Antworten . . . Methode zum Ausgeben von Ressourcen . . . . . . . POST Objekt initialisieren und deklarieren . . . . . . Setzen der Request-Parameter in der POST-Methode Setzen der Request-Header in der POST-Methode . . Senden eines Request ber die POST-Methode . . . . Methode zum Ausfhren der Login-Aktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 26 27 27 27 28 28 29 30 31 31 32 33 33 34 34 35
A.1 doGet()-Methode des ProxyServlet . . . . . . . . . . . . . . . . . . . 42 A.2 doPost()-Methode des ProxyServlet . . . . . . . . . . . . . . . . . . . 43 A.3 Beispiel der Transport-XML einer Begrungsseite . . . . . . . . . . 46
Nico Pleyer
52
Eidesstattliche Erklrung
Ich versichere an Eides Statt durch meine eigenhndige Unterschrift, dass ich die vorliegende Arbeit selbststndig und ohne fremde Hilfe angefertigt habe. Alle Stellen, die wrtlich oder dem Sinn nach auf Publikationen oder Vortrgen anderer Autoren beruhen, sind als solche kenntlich gemacht. Ich versichere auerdem, dass ich keine andere als die angegebene Literatur verwendet habe. Diese Versicherung bezieht sich auch auf alle in der Arbeit enthaltenen Zeichnungen, Skizzen, bildlichen Darstellungen und dergleichen. Die Arbeit wurde bisher keiner anderen Prfungsbehrde vorgelegt und auch noch nicht verentlicht.
Nico Pleyer
53