fuhrparkverwaltung - architekturbeschreibunggeschäftslogikschicht: die geschäftslogikschicht ist...

44
Fuhrparkverwaltung - Architekturbeschreibung - im Studiengang Application Architectures / Master of Science an der Fakultät Wirtschaftsinformatik der Hochschule Furtwangen University vorgelegt von: Michael Hupe, Florian Kalisch, Andreas Lauer, Denis Radjenovic Vorlesung : Softwarearchitektur Betreuer : Prof. Dr. Ulf Schreier eingereicht am : 30.06.2012 / Sommersemester 2012

Upload: others

Post on 15-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

Fuhrparkverwaltung

- Architekturbeschreibung -

im Studiengang Application Architectures / Master of Science

an der Fakultät Wirtschaftsinformatik der Hochschule Furtwangen University

vorgelegt von:

Michael Hupe, Florian Kalisch, Andreas Lauer,

Denis Radjenovic

Vorlesung : Softwarearchitektur

Betreuer : Prof. Dr. Ulf Schreier

eingereicht am : 30.06.2012 / Sommersemester 2012

Page 2: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

I

Inhaltsverzeichnis

1 Einführung und Ziele ......................................................................................................... 1

1.1 Ziele des Dokuments ................................................................................................... 1

1.2 Architektonische Ziele ................................................................................................. 1

2 Allgemeine Festlegungen ................................................................................................... 2

2.1 Festlegung der Schichten.............................................................................................. 2

2.1.1 Client-Präsentationsschicht .................................................................................... 2

2.1.2 Play Framework 2.0 .............................................................................................. 3

2.1.3 Datenhaltungsschicht ............................................................................................ 3

2.2 Festlegung der Sprachen .............................................................................................. 3

2.3 Festlegung der Systeme ................................................................................................ 3

2.3.1 Systeme zur Entwicklung....................................................................................... 3

2.3.2 Systeme zum Betrieb ............................................................................................. 4

2.4 Festlegung der Bibliotheken ......................................................................................... 4

2.5 Festlegung der Struktursicht ......................................................................................... 5

2.6 Projekt- und Paketstruktur ........................................................................................... 5

3 Architekturrichtlinien ......................................................................................................... 7

3.1 Allgemein ................................................................................................................... 7

3.2 Präsentationslogik ....................................................................................................... 8

3.2.1 Templating allgemein ............................................................................................ 8

3.2.2 Scala Templating................................................................................................... 9

3.2.3 Einsatz von JavaScript ........................................................................................... 9

3.2.4 Tabellendarstellung per jQuery ............................................................................ 10

3.2.4.1 Definition der Daten in Form eines DataSets ................................................. 10

3.2.4.2 Definition der Tabellenstruktur ...................................................................... 11

3.2.4.3 Formatierung des Erscheinungsbildes der Tabelle ........................................... 12

3.2.4.4 Definition eines Handlers zur Abfrage selektierter Zeilen ................................ 13

3.2.5 Google Maps Integration ..................................................................................... 14

3.2.6 CSS .................................................................................................................... 15

3.2.7 HTTP-Routing und Controller-Handling .............................................................. 15

3.3 Fachlogik .................................................................................................................. 16

3.3.1 Fassade-Muster ................................................................................................... 16

3.3.2 Strategie-Muster .................................................................................................. 17

3.4 Datenzugriffslogik ..................................................................................................... 18

3.4.1 Finder ................................................................................................................. 19

Page 3: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

II

3.5 Änderbarkeit ............................................................................................................. 20

3.6 Andere technische Richtlinien .................................................................................... 20

3.6.1 Code Konventionen ............................................................................................ 20

3.6.2 Flash, Session und Cache .................................................................................... 20

3.6.3 Testdaten ............................................................................................................ 22

4 Dekomposition ................................................................................................................ 23

4.1 Struktursicht .............................................................................................................. 23

4.1.1 Komponentenübersicht Fuhrparkverwaltung ........................................................ 23

4.1.2 Benutzer-Komponente ......................................................................................... 24

4.1.3 Reservierungs-Komponente ................................................................................. 24

4.1.4 Fahrzeug-Komponente ........................................................................................ 25

4.1.5 Rollen-Komponente ............................................................................................ 25

4.1.6 Führerschein-Komponente .................................................................................. 26

4.1.7 Standort-Komponente ......................................................................................... 26

4.2 Ablaufsicht ................................................................................................................ 27

4.3 Verteilungssicht ......................................................................................................... 28

4.3.1 Standalone Mode ................................................................................................ 28

4.3.2 Erstellen einer Standalone Version der Applikation ............................................... 28

4.3.3 Weitere Deploy-Möglichkeiten ............................................................................ 28

4.4 Datensicht ................................................................................................................. 29

5 Querschnittliche Systemaufgaben ..................................................................................... 30

5.1 Sicherheit .................................................................................................................. 30

5.2 Transaktionsmanagement .......................................................................................... 30

5.3 Protokollierung ......................................................................................................... 31

5.4 Ausnahmebehandlung ............................................................................................... 32

5.5 JNDI ........................................................................................................................ 34

6 Alternativen..................................................................................................................... 35

6.1 jQuery ....................................................................................................................... 35

6.2 Play Framework ........................................................................................................ 35

6.2.1 Business-Sicht ..................................................................................................... 35

6.2.2 Technische Sicht ................................................................................................. 36

6.2.3 Entwickler-Sicht .................................................................................................. 37

6.2.3.1 Entwurfsmuster ............................................................................................ 37

6.2.3.2 Extreme Zustandslosigkeit ............................................................................. 37

6.2.3.3 Vergleich mit JSF .......................................................................................... 38

6.2.4 Fazit ................................................................................................................... 39

Page 4: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

III

Abbildungsverzeichnis

Abbildung 1: Schichtenarchitektur ............................................................................................ 2

Abbildung 2: Architekturübersicht ............................................................................................ 5

Abbildung 3: Paketstruktur ...................................................................................................... 5

Abbildung 4: Ablauf eines HTTP-Request ................................................................................ 7

Abbildung 5: Abstrakte Projektstruktur ..................................................................................... 8

Abbildung 6: Attributänderungen ........................................................................................... 20

Abbildung 7: Komponentenübersicht Fuhrparkverwaltung ...................................................... 23

Abbildung 8: Benutzer-Komponente ...................................................................................... 24

Abbildung 9: Reservierungs-Komponente ............................................................................... 24

Abbildung 10: Fahrzeug-Komponente .................................................................................... 25

Abbildung 11: Rollen-Komponente ........................................................................................ 25

Abbildung 12: Führerschein-Komponente .............................................................................. 26

Abbildung 13: Standort-Komponente ..................................................................................... 26

Abbildung 14: Sequenzdiagramm „Reservieren eines Fahrzeuges“ .......................................... 27

Abbildung 15: Datensicht ...................................................................................................... 29

Abbildung 16: View-Kompositum .......................................................................................... 37

Tabellenverzeichnis

Tabelle 1: Festlegung der verwendeten Sprachen ....................................................................... 3 Tabelle 2: Tabellenkonventionen in JPA ................................................................................. 19 Tabelle 3: Logging Level und ihr Einsatz ................................................................................ 31 Tabelle 4: Vergleich JSF und Play .......................................................................................... 38

Page 5: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

IV

Listing-Verzeichnis

Listing 1: Einbindung der main.scala.html ................................................................................ 9

Listing 2: Definition der übergebenen Parameter ....................................................................... 9

Listing 3: Einbinden von Parameter innerhalb der Views ........................................................... 9

Listing 4: Prüfung ob DOM aufgebaut ist ................................................................................. 9

Listing 5: Einbinden des Datepickers ........................................................................................ 9

Listing 6: Exemplarische JavaScript DataSource Definition ..................................................... 10

Listing 7: Beispiel-DataSet anhand der Reservierungsdaten ..................................................... 11

Listing 8: jQuery Tabellenstruktur .......................................................................................... 11

Listing 9: Verankerung der DataTables im Html ..................................................................... 12

Listing 10: Setzen der Zeilenmarkierung ................................................................................. 13

Listing 11: Definition des Click Handlers ................................................................................ 13

Listing 12: Einbindung der Google Maps-API ........................................................................ 14

Listing 13: Funktion initialize() .............................................................................................. 14

Listing 14: Einbindung der Map in den HTML-Code .............................................................. 14

Listing 15: Funkion calcRoute() ............................................................................................. 14

Listing 16: Aufruf der Funktion calcRoute() ............................................................................ 15

Listing 17: Abbildung von HTTP-Routen auf Controller-Methoden ......................................... 15

Listing 18: Abstrakte Controller-Implementierung ................................................................... 16

Listing 19: Beispiel einer Fassaden-Klasse ............................................................................... 17

Listing 20: Beispiel eines Strategie-Interfaces........................................................................... 17

Listing 21: Beispiel einer Strategie-Implementierung ............................................................... 18

Listing 22: Beispiel der Verwendung eines Strategie-Interfaces ................................................. 18

Listing 23: Beispiel einer Finder-Implementierung .................................................................. 19

Listing 24: Flash-Beispiel ....................................................................................................... 21

Listing 25: Session-Beispiel .................................................................................................... 21

Listing 26: Cache-Beispiel ...................................................................................................... 21

Listing 27: Beispiel um Testdaten anzulegen ........................................................................... 22

Listing 28: Aufruf zum Starten eines Webservers .................................................................... 28

Listing 29: Erzeugen eines Zip-Files (enthält alle notwendigen JAR-Files)................................ 28

Listing 30: Authensisierungs-Annotation ................................................................................ 30

Listing 31: Beispiel @Transactional ........................................................................................ 30

Listing 32: Beispiel TxRunnable ............................................................................................. 30

Listing 33: Beispiel Transaktion mit try-finally ........................................................................ 31

Listing 34: Beispiel für Ausnahmebehandlung ......................................................................... 33

Listing 35: Beispiel Log an Throw .......................................................................................... 33

Listing 36: Beispiel "checked Exception"................................................................................. 33

Listing 37: Beispiel Destruktives Wrapping ............................................................................. 33

Listing 38: Datenbank über JNDI veröffentlichen ................................................................... 34

Page 6: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

1

1 Einführung und Ziele

Dieses Dokument beschreibt die Architektur des Systems Fuhrparkverwaltung. Dabei werden die

Bausteine und deren Zusammenwirken vorgestellt, zu verwendende Architektur- und Entwurfs-

muster hervorgehoben, getroffene Entscheidungen begründet sowie dazu existierende Alternati-

ven vorgestellt.

1.1 Ziele des Dokuments

Die hier vorliegende Architekturbeschreibung gibt den Programmierern festgesetzte Richtlinien

vor, anhand welcher die Entwicklung des Systems auszurichten ist.

1.2 Architektonische Ziele

Dieses Unterkapitel stellt die architektonischen Zielsetzungen vor, unter welchen die Anwendung

entworfen wird. Die nachfolgende Auflistung gibt darüber Auskunft:

1. Komponenten und Wiederverwendbarkeit

Beim Design der Anwendung soll, im Rahmen der Dekomposition, die Aufteilung der

Funktionalitäten in Module erfolgen, welche als Bausteine für die Komponenten dienen.

Diese sollen eine starke Kohäsion und eine lose Kopplung (nach IEEE 610) aufweisen.

Für eine Verbesserung der Wiederverwendbarkeit ist die lose Kopplung auf Data Coup-

lin-Niveau anzustreben. Der Einsatz von Entwurfsmustern kann sich ebenfalls positiv

auswirken.

2. Einsatz von Entwurfsmustern

Der sinnvolle und zielgerichtete Einsatz von Entwurfsmustern soll angestrebt werden. Ein

blinder Einsatz dieser ist jedoch zu vermeiden, da es eventuell bessere Lösungen für den

konkreten Fall geben kann.

3. Flexibilität für zukünftige Ergänzungen

Eine Flexibilität für zukünftige Ergänzungen ist wichtig, um schnell auf sich ändernde

Anforderungen reagieren zu können. Erreicht wird das durch die zwei vorhergehend be-

schriebenen Punkte und eine vorausschauende Programmierart.

Page 7: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

2

2 Allgemeine Festlegungen

Dieses Kapitel beschreibt die festgelegten Schichten, verwendete Sprachen, zum Einsatz kom-

mende Bibliotheken und Systeme. Dabei wird auf allgemeine Richtlinien der Architektur einge-

gangen. Diese umfassen sowohl die Projektstruktur, als auch Besonderheiten im Ablauf und der

Verteilung. Falls sich mindestens die Minor-Version einer eingebundenen Bibliothek ändert,

muss diese vor dem Produktiv-Einsatz in einem Test-System ausgiebig analysiert werden.

2.1 Festlegung der Schichten

Einen ersten groben Überblick über die Anwendungsarchitektur gibt Abbildung 1. Die Architek-

tur-Muster, Komponenten des Systems sowie deren Abhängigkeiten werden aufgezeigt. Wie in

Abbildung 1 zu sehen ist, teilt sich die gesamte Anwendung in fünf Schichten auf.

Abbildung 1: Schichtenarchitektur

Diese Schichten sind in den nachfolgenden Teilkapiteln ausführlicher beschrieben.

2.1.1 Client-Präsentationsschicht

Die Client-Präsentationsschicht dient zur Eingabe und Darstellung von Daten für den Benutzer.

Bei der Anwendung „Fuhrparkverwaltung“ dient ein JavaScript-fähiger Browser als Darstel-

lungsmedium zur Anzeige der Bildschirmmasken (Views). Die Bildschirmmasken sind HTML-

Dateien, deren Funktionalität durch JavaScript-Funktionen erweitert sein kann. Um ein einheit-

liches Look & Feel zu erreichen, kommt ein individuelles für die Anwendung entwickeltes CSS-

Design zum Einsatz. Die folgende Liste zählt alle verwendeten JavaScript-Bibliotheken auf:

jQuery (Version 1.7)

jQuery UI (Version 1.8)

DataTables (Version 1.9) Plug-In für jQuery UI

Page 8: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

3

jQuery UI Timepicker (Version 0.3)1 Plug-In für jQuery UI

Google Maps API (Version 3)

2.1.2 Play Framework 2.0

Das Play Framework 2.0 stellt die zentrale Architektur der Anwendung zur Verfügung, welches

auf dem MVC-Muster basiert (Kapitel 3.1). Das Framework selber unterteilt sich in drei Schich-

ten. Wie in Abbildung 1 zu sehen ist, sind das folgende Schichten:

Server-Präsentationsschicht: Um dynamische Views zu erstellen, bietet das Play Framework

eine Template-Notation, die auf der Sprache Scala basiert.

Geschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old

Java Objects) umgesetzt.

Datenzugriffsschicht: Das Management der Daten erfolgt nicht durch einen Zugriff direkt

auf die Datenbank, sondern mit Hilfe des Java Persistence API konformen relationalen Map-

pers EBeans.

2.1.3 Datenhaltungsschicht

Für das Speichern und Laden der Daten ist eine PostgreSQL Datenbank in der Version 9.1.3

zuständig.

2.2 Festlegung der Sprachen

Folgende Tabelle fasst alle verwendeten Sprachen zur Entwicklung der Anwendung zusammen:

Sprache Verwendung

Java Geschäftslogik

Scala View-Templating

JavaScript, CSS, HTML Gestaltung und Funktionalität der Views

Tabelle 1: Festlegung der verwendeten Sprachen

2.3 Festlegung der Systeme

In diesem Kapitel werden die verwendeten Systeme zur Entwicklung und für den Betrieb der

Anwendung beschrieben. Das Play Framework bringt Techniken, Mechanismen und Systeme

mit, welche die Entwicklung vereinfachen und den Betrieb der Anwendung gewährleisten.

2.3.1 Systeme zur Entwicklung

Eclipse (Version 3.7 „Indigo“)

Play erlaubt eine Projekterstellung über die Konsole und auch eine Programmierung ohne jegli-

che IDE wäre möglich. Da eine IDE einige Vorzüge (z.B. Code-Completion, Debugging und

Syntax-Highlighting) mit sich bringt, bietet Play die Möglichkeit ein Projekt in ein Eclipse-Projekt

zu konvertieren.

1 http://fgelinas.com/code/timepicker/

Page 9: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

4

Subversion (Version 1.7)

Die Versionspflege des Projektes erfolgt mittels Subversion. Die Verwaltung der Version kann

direkt über das Plugin „Subclipse“ in der Eclipse IDE stattfinden.

Simple Build Tool (SBT 0.11)

Dies ist ein auf Apache Ivy basierendes Dependency-Management System. Damit werden Ab-

hängigkeiten zu Bibliotheken (ähnlich Maven) verwaltet.

2.3.2 Systeme zum Betrieb

JBoss Netty (3.2)

JBoss Netty ist ein automatisch von Play eingebundener und vorkonfigurierter Application-

Server. Dieser unterstützt Features, wie z.B. Hot-Deployment und die Anzeige von Kompilie-

rungsfehlern im Browser.

PostgreSQL Datenbank (Version 9.1)

Für das Projekt kommt die PostgreSQL Datenbank zum Einsatz. Diese ist frei verfügbar und

kann über ein beiliegendes Administrations-Tool verwaltet werden.

2.4 Festlegung der Bibliotheken

Die Bibliotheken sollen an dieser Stelle nur kurz aufgelistet und beschrieben werden. Ihre Ver-

wendung ist in Kapitel 3 ausführlicher beschrieben.

jQuery (Version 1.7)

Dieses JavaScript-Framework ist die Basis für die Bibliotheken jQuery UI und DataTables.

jQuery UI (Version 1.8)

Erweitert jQuery um die Möglichkeit, Benutzeroberflächen zu gestalten und mit Funktionalität

zu füllen.

DataTables (Version 1.9)

Hierbei handelt es sich um ein Plugin für jQuery zur Darstellung von Tabellen.

jQuery UI Timepicker (Version 0.3)

Ermöglicht eine komfortable Zeiteingabe in die Views.

Google Maps API (Version 3)

Um eine Routenberechnung für die Reservierungen zu ermöglichen, kommt die Google Maps

API zum Einsatz.

JDBC Treiber (Level 4) für die PostgreSQL Datenbank (Version 9.1)

Notwendiger Treiber für den Zugriff auf die Datenbank.

Page 10: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

5

2.5 Festlegung der Struktursicht

Die Struktursicht dient der Verdeutlichung, welche Komponenten in welcher Schicht zum Ein-

satz kommen (siehe Abbildung 2).

Präsentationssicht (Client)

Komponente Fuhrparkverwaltung

jQuery 1.7

Präsentationssicht(Server)

Datenhaltung PostgreSQL 9.1DB Schema

EBeans 2.7

Google Maps 3.0

Scala-Templating

jOuery UI 1.8

jOuery UI Timepicker 0.3

DataTables 1.9

Abbildung 2: Architekturübersicht

2.6 Projekt- und Paketstruktur

In diesem Kapitel wird die Projektstruktur der Anwendung detailliert dargestellt. Eine dazu gehö-

rende visuelle Übersicht gibt die Abbildung 3.

app

controllers

forms

security

model

model.komponente

entities

facades

views

views.komponente

conf public

routes app conf images javascript stylesheets

libs logs

Abbildung 3: Paketstruktur

Page 11: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

6

In dem Ordner „app“ sind die Komponenten der Anwendung abgelegt. Die Komponenten unter-

teilen sich in die Pakete „models“, „controllers“, „views , „forms“, „security“ und „context“.

Eine Besonderheit stellt hierbei die Datei „Global.java“ dar, die sich im Root-Ordner „app“ be-

findet. Mit dieser Datei werde die Testdaten in die Datenbank geschrieben. Der Ort ist fest vom

Play Framework vorgeschrieben und lässt sich nicht verändern. Sollte diese Datei angepasst wer-

den, ist darauf zu achten das ihre Position beibehalten wird.

Im „models“-Paket liegen die Unterpakte für die verschiedenen Entitäts-Komponenten („reserva-

tion“, „user“ und „vehicle“). Eine Entität besteht aus den Paketen „entities“ und „facades“. „en-

tities“ ist prinzipiell ein Bestandteil einer Entität, wohingegen „facades“ nicht bei jeder Entität

vorhanden sein muss. Unter „entities“ liegt die Entitäten-Klasse der Komponente. Unter

„facades“ befindet sich eine Fassaden-Klasse, die statische Methoden für komplexe Funktionali-

täten zur jeweiligen Entität bereitstellt.

Unter „controllers“ liegen die einzelnen Controller-Klassen der Ansichten (Views). Diese Klassen

lassen sich nicht in eigene Pakete unterteilen. Dies scheint eine Restriktion des Play Frameworks

zu sein. Zu jedem HMTL-Formular gehört auch eine Form-Klasse die sich im Unterpaket

„forms“ befindet, welche die Anfrage auf diese Klasse abbildet und damit vom Controller ausge-

wertet werden kann.

In den „views“ liegen die Templates für die verschiedenen Ansichten. Unterteilt werden diese in

„admin“, „settings“ und „reservation“. Das Pakte „admin“ beinhaltet alle Ansichten die nur von

Rolle Administrator aufgerufen werden können, wohingegen „settings“ und „reservation“ für alle

Rollen zugänglich sind.

Weitere wichtige Ordner innerhalb des Projekts sind „conf“ mit den wichtigen Konfigurationsda-

teien und „public“, welches die zusätzlichen Bibliotheken beherbergt. Hierfür ist das „public“-

Verzeichnis noch in „stylesheets“ für CSS-Dateien, „javascripts“ für alle verwendeten Java Script

Bibliotheken (z.B. jQuery) und in „images“ für notwendige Bilder.

Alle verwendeten Java-Bibliotheken liegen im Verzeichnis „lib“. Protokollierungen zur Laufzeit

der Anwendung werden in dem Verzeichnis „logs“ abgelegt.

Page 12: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

7

3 Architekturrichtlinien

3.1 Allgemein

Wie bereits erwähnt verwendet das Play Framework das MVC-Muster als zentrales Architektur-

muster. Das Sequenzdiagramm in

Abbildung 4 beschreibt den Ablauf eines HTTP-Request bis zu einem HTTP-Response und das

Zusammenspiel zwischen Model, View und Controller.

An dieser Stelle soll erwähnt werden, dass sich das Play Framework bei der Client-Server-

Kommunikation an den REST-Standard hält. Dabei verläuft diese Kommunikation komplett

zustandslos. Einer der Vorteile der zustandslosen Kommunikation ist die Skalierbarkeit der An-

wendung, zum Beispiel das Verteilen der Anfragen auf mehrere Server. Ein weiterer Vorteil ist

die Repräsentation der Daten in unterschiedlichen Formaten (HTML. JSON oder XML), die

sich je nach Bedarf anpassen lassen.

Browser routes ViewController Model

http Request

weiterleiten an Controller

update Model

retrieve Model

Überprüfung der übergeben Daten

render View (Übergabe der Daten)

http Response

Datenbank

synchonisieren

synchronisieren

Abbildung 4: Ablauf eines HTTP-Request

Das folgende Paket- und Klassendiagramm (Abbildung 5) zeigt eine abstrakte Struktur des Pro-

jektes. Daraus sollen die Beziehungen und Kardinalitäten der Komponenten und Klassen ersicht-

lich werden, welche bei der weiteren Entwicklung unbedingt eingehalten werden sollte.

Page 13: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

8

Abbildung 5: Abstrakte Projektstruktur

3.2 Präsentationslogik

Im Bereich der Präsentationsschicht sind viele Richtlinien wie die Views aufgebaut sind und ge-

staltet werden. Jede Komponente hat dabei ihre eigenen Views („views.Komponentenname“). In

den nächsten Unterkapiteln werden genaueren Richtlinien und Vorgaben zur Gestaltung der

Views beschreiben. Dies soll einen gewissen Standard fördern und die Wartbarkeit verbessert.

3.2.1 Templating allgemein

Alle Views, bis auf „login.scala.html“ importieren die „main.scala.html“, da sie selber nur der

Content für den jeweiligen Bereich beinhalten.

Import der main-Datei geschieht folgender Maßen:

@main {

<!-- Content -->

}

Page 14: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

9

Listing 1: Einbindung der main.scala.html

In der „main.scala.html“ wird der Header (Banner und Menü) sowie Footer gepflegt. Weiterhin

werden hier auch die Anmeldedaten (Benutzer, Rolle und Restriktion) aus der Session ausgelesen

und angezeigt.

3.2.2 Scala Templating

Am Anfang werden alle vom Controller übergebenen Parameter in der View definiert, damit

später per Annotation auf diese zugegriffen werden kann. Beispiele dafür sehen wie folgt aus.

Definition der übergebenen Parameter:

@(Parameter: Type, Parameter: List[Type])

Listing 2: Definition der übergebenen Parameter

Verwendung des Parameters:

@Parameter

@Parameter.get("Parameter")

Listing 3: Einbinden von Parameter innerhalb der Views

In der gesamten View kann nach der Definition der Parameter auf die Daten zugegriffen werden.

3.2.3 Einsatz von JavaScript

Der Einsatz von JavaScript dient der dynamischen Veränderung von Inhalt, Struktur und Layout

einer HTML Seite durch die Manipulation des korrespondierenden DOM-Baums. Auf diese

Funktionalität wird auch in dieser Anwendung zurückgegriffen, jedoch mit Hilfe der Library

jQuery, welche viele Best-Practices kapselt, eine browserübergreifende Kompatibilität gewährleis-

tet und eine vereinfachte Handhabung von JavaScript ermöglicht. Da JavaScript auf dem Client

abläuft, muss die hier entwickelte Anwendung JavaScript-Code generieren, welcher dann vom

Browser ausgeführt wird.

Grundsätzlich ist als Richtlinie bei der Verwendung von jQuery-Code zu beachten, dass dieser

immer innerhalb des Funktionskörpers aus Listing 4 gesetzt wird. Dies gewährleistet, dass jegli-

cher Zugriff auf den DOM-Baum erst geschieht, wenn dieser vollständig aufgebaut ist.

$(document).ready(function() {

// Handler for .ready() called.

});

Listing 4: Prüfung ob DOM aufgebaut ist

Der Einsatz von JavaScript erfolgt wie auch bei JSF und JSP direkt in der HTML-Datei und soll-

te direkt vor dem zu veränderten Objekt platziert werden.

<script>

$(function() {

$.datepicker.setDefaults($.datepicker.regional[""]);

$("#startdatepicker").datepicker($.datepicker.regional["de"]);

});

</script>

Listing 5: Einbinden des Datepickers

Page 15: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

10

Bei größeren Scripten werden diese am Anfang, nach dem „Main-Import“, definiert oder in eine

separate Datei unter „public/javascripts“ abgelegt und eingebunden. Auf die Einbindung der

Tabelle per JavaScript wird im nächsten Absatz noch einmal genauer eingegangen, da diese eines

der Hauptelemente der Anwendung ist.

3.2.4 Tabellendarstellung per jQuery

Die Tabelle ist eines der Hauptobjekte der Anwendung und wird in vielen Views zur Darstellung

verwendet. Die Tabelle wird immer am Anfang der View definiert. Als Darstellungskomponente

für die Tabellenstrukturen wird auf das jQuery Plugin DataTables2 gesetzt.

Die Handhabung von Tabellen teilt sich in die nachfolgenden vier Teile auf:

1. Definition der Daten in Form eines DataSets

2. Definition der Tabellenstruktur und die Position dieser innerhalb der HTML Datei

3. Formatierung des Erscheinungsbildes der Tabelle

4. Definition eines geeigneten Handlers zum Auslesen des selektierten Datensatzes

3.2.4.1 Definition der Daten in Form eines DataSets

Die Daten müssen vom Server zur Anzeige auf den Client übertragen werden. Dazu sind prinzi-

piell mehrere Arten möglich, das DataSet zur Verfügung zu stellen.

1) Definition der Daten in Form eines JavaScript Arrays

2) Zugriff auf einen AJAX-DataSource

3) Datenübertragung mittels JASONP Aufruf

Diese Anwendung setzt auf die Datendefinition mittels JavaScript-Array (d.h. die erste Umset-

zungsmöglichkeit), da auf nicht gebrauchten Overhead wie AJAX verzichtet werden soll. Die

Daten sind dabei im Klartext auf der Client-Seite sichtbar. Sollten sich die Anforderungen zu-

künftig dahingehend ändern, dass die Daten nicht im Quellcode der HTML-Seite sichtbar sein

dürfen, muss dies über ein geeignetes DataSet-Handling gelöst werden. Weiterhin kann es zu

Problemen kommen, wenn die Anzahl anzuzeigender Daten die geschätzte Anzahl übersteigt.

Der Einstieg in die DataSet-Definition soll anhand eines exemplarischen, sich selbst erklärenden,

Datensatzes verdeutlicht werden, welcher nachfolgend dargestellt ist und stellvertretend für den

realen, generierten, Code stehen kann.

var dataSet = [

['Zeile1Spalte1', 'Zeile1Spalte2','Zeile1Spalte3','Zeile1Spalte4'],

['Zeile2Spalte1', 'Zeile2Spalte2','Zeile2Spalte3','Zeile2Spalte4']

];

Listing 6: Exemplarische JavaScript DataSource Definition

Zur Generierung wird auf die Scala-Notation zurückgegriffen, bei welcher mit einer for-Schleife über die anzuzeigenden Datenzeilen iteriert und jede relevante Spalte ausgegeben wird. Dieses Vorgehen zeigt das nachfolgende Listing.

2 http://datatables.net/

Page 16: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

11

var aDataSet = [

@for(reservation <- reservationList) {

@if(reservation.getReservedBy().getId() == Long.valueOf(

session.get("user_id"))) {

['@reservation.getId()',

'@if(reservation.getPermittedBy() == null){offen} else {genehmigt}',

'@reservation.getPurpose().getType()',

'@reservation.getStartLocation().getAddress().getName()',

'@reservation.getEndLocation().getAddress().getName()',

'@reservation.getReservationStart()',

'@reservation.getReservationEnd()',

'@reservation.getVehicle().getName()',

'@reservation.getReservationComment().getContent()'

],}

}

];

Listing 7: Beispiel-DataSet anhand der Reservierungsdaten

Während bei den Spalten ab Spalte 2 eine beliebige Reihenfolge gewählt werden kann, so muss

unbedingt beachtet werden, dass die erste Spalte die ID der korrespondierenden Tabelle enthält.

3.2.4.2 Definition der Tabellenstruktur

Dieses Unterkapitel beschreibt die Konfiguration der Tabellen Komponente, welche eine Vielzahl

an möglichen Szenarien abdeckt und somit angepasst werden muss. Die folgenden Betrachtun-

gen beziehen sich auf das nachfolgende Listing.

1 $('#dynvehicletable').html( '<table cellpadding="0"

2 cellspacing="0" border="0" class="display"

3 id="vehicletable"></table>' );

4 $('#vehicletable').dataTable( {

5 "bJQueryUI": true,

6 "sPaginationType": "full_numbers",

7 "aaData": aDataSet,

8 "bScrollInfinite": true,

9 "bScrollCollapse": true,

10 "sScrollY": "200px",

11 "aoColumns": [

12 { "sTitle": "ID", "sClass": "left", "bVisible": false},

13 { "sTitle": "Name", "sClass": "left"},

14 { "sTitle": "F&uuml;hrerscheinklasse", "sClass": "left"}

15 ,

16 { "sTitle": "Kilometerstand", "sClass": "left"},

17 { "sTitle": "Monate in Benutzung", "sClass": "left" },

18 { "sTitle": "In Benutzung", "sClass": "left" },

19 ],

20 // sets the vehicle id into the id attribute of <tr>

21 "fnRowCallback": function( nRow, aData, iDisplayIndex ) {

22 $(nRow).attr("id", aDataSet[iDisplayIndex][0]);

23 return nRow;

24 }

25 });

Listing 8: jQuery Tabellenstruktur

Page 17: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

12

Als Richtlinie sollte bei jeder Tabelle, die neue hinzugefügt wird, die folgende (sich in drei Teile

gliedernde) Konfiguration vorgenommen werden.

1. Zeilen 5 bis 10:

Diese Zeilen können ohne Anpassung übernommen werden, denn sie stellen ein einheit-

liches Erscheinungsbild der Tabellen sicher. Einzige Ausnahme bildet Zeile 7, welche das

anzuzeigende DataSet als Übergabe erwartet.

2. Zeilen 11 bis 19:

In diesem Bereich erfolgt die Definition der Spalten, welche von den anzuzeigenden Da-

ten abhängen. Zusätzlich wird die erste ID Spalte ausgeblendet („bVisbible“: false) und

die Textausrichtung in der Spalte auf linksbündig gesetzt („sClass“: left).

3. Zeilen 21 bis 23:

Innerhalb dieses Teilbereichs wird die CallBack Funktion fnRowCallBack definiert, wel-

che beim dynamischen Rendern jeder Zeile aufgerufen wird. Jede Zeile bekommt ein At-

tribut id mit dem Wert der Tabellen-ID zugewiesen.

Das folgende Container-Tag (div) ist innerhalb der HTML-Datei zu positionieren und enthält zur

Laufzeit die gerenderte Tabelle.

<div id="dynvehicletable"></div>

Listing 9: Verankerung der DataTables im Html

3.2.4.3 Formatierung des Erscheinungsbildes der Tabelle

Die Formatierung der Tabellen gliedert sich in die Teile

1. Anpassung des mitgelieferten CSS-Designs

2. Definition eines Click Handlers für das dynamische Setzen einer Zeilenmarkierung

Dieses Unterkapitel fokussiert auf den zweiten Punkt und erläutert die Click Handler Definition

näher. Die eigentliche Formatvorgabe für eine selektierte Zeile wird durch CSS festgelegt. Dazu

existiert die Klasse row_selected. Jede Zeile, welche diese Klasse zugewiesen bekommt, wird

als selektiert farblich markiert. Nachfolgendes Listing gibt die Richtlinie vor, wie die Selektier-

Funktionalität umgesetzt werden muss.

Page 18: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

13

// Retrieve the datatable object and store it in the variable oTable

oTable = $('#vehicletable').dataTable();

/*--------------------------------------------------------------------

* Function: Click-Event-Handler for the table row (<tr>).

* Description:

* This click handler highlights/dehiglights the clicked

* row and checks the corresponding radio button.

*--------------------------------------------------------------------

*/

oTable.$('tr').click( function(event) {

// remove the existing selection

var theSelectedRadio = oTable.contents().find('.row_selected');

theSelectedRadio.removeClass('row_selected');

// highlight the table row current row

$(this).addClass('row_selected');

// at this point we are on level of the single row (<tr>)

// and we'll retrieve the underlying checkbox

var theCurrentRadio = $(this).contents().find('.tblradio');

theCurrentRadio.attr('checked', true);

});

Listing 10: Setzen der Zeilenmarkierung

3.2.4.4 Definition eines Handlers zur Abfrage selektierter Zeilen

Im Prozess-Kontext der Anwendung werden die Tabellen eingesetzt, um mehrere Daten in struk-

turierter Form darzustellen. Mittels der Selektion von Zeilen können Datensätze ausgewählt

werden und diese gilt es für einen weiteren Ablauf (beispielsweise Bearbeiten, Löschen, etc.) zu

identifizieren. Dazu ist ein Click Handler zu definieren, welcher die selektierten Zeilen anhand

der gesetzten CSS-Klasse (beschrieben in Kapitel 3.2.4.3) bestimmt. Nachfolgendes Listing gibt

hierzu einen Einblick.

/*--------------------------------------------------------------------

* Function: Click-Event-Handler for the button "getSelection"

* Description:

* Defines a event-handler for the click-event of corresponding

* button. It creates a string representation of the selected

* dataset and displays it at the end.

*--------------------------------------------------------------------

*/

$('#deleteVehicle').click( function () {

var $theSelectedRadio = oTable.$('.row_selected').attr('id');

if($theSelectedRadio != null)

{

window.location = "/deleteVehicle/" + $theSelectedRadio;

}

else

{

alert("Bitte waehlen Sie einen Datensatz aus.");

}

});

Listing 11: Definition des Click Handlers

Page 19: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

14

3.2.5 Google Maps Integration

Folgende Listings beschreiben schematisch die Einbindung der Google Maps API in die Reser-

vierungs-View.

Um die Google Maps API zu verwenden, muss zunächst einen Remote-Verweis auf die Biblio-

thek erstellt werden.

<script type="text/javascript"

src="https://maps.google.com/maps/api/js?sensor=false">

</script>

Listing 12: Einbindung der Google Maps-API

Der JavaScript Code an sich besteht aus zwei Funktionen. Die Funktion „initialize()“ sorgt für

die Anzeige der Map (Karte) in der View. Dies geschieht durch eine Instanz der Klasse

„google.maps.Map“, die auch auf den Bereich in der View verweist. In der Reservations-View

heißt dieser Bereich „map_canvas“.

function initialize() {

//generiert ein MapObjekt

var map = new google.maps.Map(document.getElementById('map_canvas'),

myOptions);

}

Listing 13: Funktion initialize()

<div id="map_canvas"></div>

Listing 14: Einbindung der Map in den HTML-Code

Zur Berechnung der Route, dient die Funktion „calcRoute()“. Die Parameter „startingPoint“ und

„endPoint“ geben den Start und das Ziel der Route an. Gewonnen werden diese Parameter aus

den beiden Eingabefeldern „startLocation“ und „endLocation“ der View.

function calcRoute() {

//berechnet die route mit Hilfe eines startingPoint und endPoint

var endPoint = document.getElementById('endLocation').value;

var request = {

origin: startingPoint,

destination: endPoint,

travelMode: google.maps.DirectionsTravelMode.DRIVING

};

directionsService.route(request, function(response, status) {

if (status == google.maps.DirectionsStatus.OK) {

directionsDisplay.setDirections(response);

}

});

}

Listing 15: Funkion calcRoute()

Nach jeder Eingabe des Zielortes, erfolgt eine Neuberechnung der Route in der Map. Damit das

geschieht wird bei jeder Änderung des Zielorts (Event „onchange“) die Funktion „calcRoute()“

ausgeführt.

Page 20: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

15

<li>

@select(step1Form("endLocation"),

options(models.reservation.entities.Location.list()),

'_label -> "Wo endet die Fahrt?", '_showConstraints -> false,

'onchange -> "calcRoute()")

</li>

Listing 16: Aufruf der Funktion calcRoute()

3.2.6 CSS

Alle CSS-Files werden unter „Public/Stylesheets“ abgelegt und in der „main.scala.html“ einge-

bunden. Es wird ein eigenständiges CSS entwickelt um das Look & Feel der Anwendung zu ver-

bessern und vereinheitlichen. Weiterhin kommt es zur Einbindung von eigenständigen CSS-

Dateien für die Datatables und jQuery UI Elemente.

In den Views selber ist es nicht gestattet CSS-Code direkt einzubinden. CSS-Elemente müssen

aussagekräftige Bezeichnungen besitzen.

3.2.7 HTTP-Routing und Controller-Handling

Alle Seiten, die über den Webbrowser erreicht werden sollen müssen unter „conf/routes“ einge-tragen werden und auf die entsprechende Controller-Funktion verweisen. Die Einbindung erfolgt

Beispielhaft wie im

Listing 17.

GET /URI controllers.ControllerName.controllerMethod1()

POST /URI controllers.ControllerName.controllerMethod2()

GET /URI/:id controllers.ControllerName.controllerMethod3(id:Long)

Listing 17: Abbildung von HTTP-Routen auf Controller-Methoden

Im Controller wird geregelt was dann im speziellen Fall mit der REST-Anfrage geschieht und

welche Daten an die View übertragen werden sollen.

Folgendes Listing zeigt die beispielhafte Implementierung eines Controllers. Zur Vereinfachung

der Auswertung von Formulareingaben bietet Play eine Kapselung der HTTP-Anfrage in eine

extra hierfür implementierte Form-Klasse. Durch diese Funktionalität werden die jeweiligen

Formularfelder auf die entsprechenden Attribute der Form-Klasse abgebildet. Bevor mit der

Form-Klasse im Controller gearbeitet werden kann, muss diese auf Eingabefehler überprüft wer-

den. Das kann über die Methode „hasErrors()“ realisiert werden. Als Rückgabewert dient eine

View.

Page 21: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

16

public class ControllerName extends Controller {

static Form<FormClass> formObject = form(FormClass.class);

public static Result controllerMethod1() {

return ok(view.render(param1 ...));

}

public static Result controllerMethod2() {

Form< FormClass > submittedForm = formObject.bindFromRequest();

if (submittedForm.hasErrors()) {

return redirect(

routes.ControllerName.controllerMethod1());

}

return ok(view.render(param1 ...));

}

public static Result controllerMethod3(Long id) {

return ok(view.render(param1 ...));

}

}

Listing 18: Abstrakte Controller-Implementierung

3.3 Fachlogik

In diesem Kapitel sollen Besonderheiten der Fachlogik erläutert werden, wie z.B. der Einsatz von

Entwurfsmustern. Grundsätzlich ist der Einsatz von Entwurfsmustern bevorzugt, da diese von

Entwicklern in der Regel beherrscht werden und bekannt sind. Durch deren Einsatz kann eine

abstrakte Beschreibung von Problemen und Lösungen erfolgen. Jedoch sollte nicht jede Ge-

schäftsfunktion in ein Muster gepresst werden, wenn die Komplexität dadurch erhöht wird oder

die Lesbarkeit und Wartbarkeit des Codes darunter leiden.

3.3.1 Fassade-Muster

Der Sinn eines Fassade-Musters besteht grundlegend darin, komplexe Funktionalitäten zu kap-

seln und über eine Schnittstelle nach außen bereit zu stellen. Zum Einsatz kommt das Muster in

der Fuhrparkverwaltung bei den Komponenten: Geschäftsfunktionen, die mehrere Entitäten ei-

ner Komponente verwenden, müssen über eine Fassaden-Klasse als öffentliche und statische Me-

thoden angeboten werden. Somit wird erzielt, dass Zugriffe der Präsentationsschicht auf die

Fachlogik über eine zentrale Methode erfolgen. Das erlaubt die Kontrolle und Steuerung dieser

Zugriffe und vereinfacht die Nutzung für den Entwickler. Zu beachten ist, dass jede Komponente

nur über genau eine Fassaden-Klasse verfügen darf.

Eine Ausnahme stellen die einfachen CRUD-Methoden dar: diese können direkt bei den Entitä-

ten implementiert werden, da diese keine komplexen und zu kapselnde Funktionalitäten bieten.

Folgendes Listing zeigt eine Fassaden-Klasse am Beispiel der Reservierungs-Komponente:

Page 22: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

17

public class ReservationFacade {

public static List<Reservation> findReservationByLocation(String

location) {

}

public static boolean acceptReservation(Long reservationId,

Long permittedById) {

}

public static boolean denyReservation(Long id) {

}

public static Reservation transformFormToModel(

ReservationStep1Form step1,

ReservationStep2Form step2, User user) {

}

public static boolean closeReservation(Long id) {

}

public static List<Reservation> findReservationForUser(Long id) {

}

public static List<Reservation> findReservationForVehicle(Long id) {

}

}

Listing 19: Beispiel einer Fassaden-Klasse

3.3.2 Strategie-Muster

Mit Hilfe des Strategie-Musters, können verschiedene Implementierungen für eine Geschäfts-

funktion angeboten werden. Diese können bei Bedarf ausgetauscht werden und erzeugen so eine

höhere Flexibilität gegenüber zukünftigen Änderungen. Voraussetzung dafür ist die Definition

einer Schnittstelle, welche eine solche Methode anbietet. Hier wird der Mechanismus der Poly-

morphie der Sprache Java ausgenutzt: der Zugriff auf die Methoden der Schnittstelle erfolgt über

eine Java-Interface Klasse. Nun kann jede beliebige Implementierungsklasse benutzt werden, die

dieses Interface implementiert. Bei Bedarf kann nun einfach die Implementierungsklasse ausge-

tauscht werden, ohne dass eine Änderung am Interface erfolgen muss.

Folgendes Listing zeigt die Definition eines solchen Interfaces:

public interface IVehicleFilter {

public List<String> getMatchingVehiclesForUser(

ReservationStep1Form step1, Long userId);

}

Listing 20: Beispiel eines Strategie-Interfaces

Page 23: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

18

Nun muss noch eine Implementierungsklasse definiert werden:

public class VehicleFilter implements IVehicleFilter {

public List<String> getMatchingVehiclesForUser(

ReservationStep1Form step1, Long userId) {

}

Listing 21: Beispiel einer Strategie-Implementierung

Zum Einsatz kann dieses Strategie-Muster nun beispielsweise in der Fassaden-Klasse der Fahr-

zeug-Komponente kommen:

public class VehicleFacade {

public static final IVehicleFilter VEHICLE_FILTER =

new VehicleFilter();

}

Listing 22: Beispiel der Verwendung eines Strategie-Interfaces

Mit der öffentlichen und statischen Variable VEHICLE_FILTER, kann die Geschäftsfunktion

des Strategie-Musters nun benutzt werden.

3.4 Datenzugriffslogik

Um die Daten zu persistieren, bringt das Play Framework automatisch das Persistenz-

Framework EBeans mit, welches auch in der Anwendung zum Einsatz kommt. Die Entität „ve-

hicle“ soll exemplarisch als Beschreibung für alle weiteren Entitäten der Anwendung dienen.

Prinzipiell erbt jede Entität von der Basisklasse „play.db.ebean.Model“-Basisklasse. Dieses Vor-

gehen ermöglicht es Standard CRUD – SQL-Operationen (CREATE, READ, UPDATE, DE-

LETE) mit Funktionen wie save(), find(z.B. byId() oder all()), delete(), und update() automatisch

zu verwenden. Zudem lassen sich auch komplexere SQL-Befehle gestalten (z.B. Vehic-

le.find.where().eq("name", name).findUnique();).

Die Beziehung zu anderen Entitäten (@OneToOne, @OneToMany, @ManyToOne,

@ManyToMany), sowie die FetchTypes (LAZY und EAGER) und weitere Konfigurationen

lassen sich durch die Annotationen der Java Persistence API (JPA) kontrollieren. Das Einbinden

von „ja-vax.persistence.*“ ermöglicht den Zugriff auf die JPA. Als FetchType wird LAZY ver-

wendet, um bei @ManyToMany oder @OneToMany-Beziehungen die weiteren Entitäten erst

dann zu laden, wenn Sie auch von der Anwendung benötigt werden.

Die CascadeTypes sollen so verwendet werden, dass keine Datenleichen („Orphans“) entstehen.

Außerdem muss jedes ID-Feld einer Entität die Annotation @GeneratedValue erhalten, damit

das Persistenzframework sich um die Erstellung der IDs kümmert.

Die Namen der Tabellen definieren sich durch den Klassennamen der Entitäten. Die Spaltenna-

men der Tabellen durch deren Attribute. Es werden somit keine expliziten Namen vergeben. Hier

greift das Prinzip „Convention over Configuration“. Zu beachten gilt es, dass Entitätsnamen und

Attributnamen folgendermaßen als Tabellen- oder Spaltennamen in der Datenbank abgebildet

werden:

Page 24: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

19

Name im Code der Anwendung Tabellen- oder Spaltename in der DB

ichBinCamelcase ich_bin_camelcase

monthInUse month_in_use

Tabelle 2: Tabellenkonventionen in JPA

3.4.1 Finder

Eine Besonderheit des Play-Frameworks und des Persistenzframeworks ist die Klasse „Finder“,

welche für den Zugriff auf die Entitäten in der Datenbank genutzt wird (vergleichbar mit dem

EntityManager bei JEE). Ein Finder muss für jede Entität definiert werden und benötigt eine

zusätzliche Typisierung: der erste Parameter beschreibt den Typ der ID der Entität (das Attribut

das mit @Id annotiert wurde) und den Klassennamen der Entität.

Folgendes Listing zeigt die Initialisierung eines Finders für die Entität „Reservation“.

public static Finder<Long, Reservation> find = new Finder<Long,

Reservation>(Long.class, Reservation.class);

Listing 23: Beispiel einer Finder-Implementierung

Der Finder bietet SQL-Funktionen gekapselt als Methoden an, welche auf der Entität angewen-

det werden können. Dadurch müssen keine expliziten SQL-Statements definiert werden, was die

Komplexität und die Fehleranfälligkeit verringert.

Explizite SQL-Statements sollten nur in Ausnahmefällen genutzt werden.

Page 25: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

20

3.5 Änderbarkeit

Attributanpassungen geschehen erst in der untersten Schicht (Datenbankschema) und ziehen sich

dann durch alle Schichten nach oben durch (siehe Abbildung 6).

Abbildung 6: Attributänderungen

3.6 Andere technische Richtlinien

Dieses Kapitel erläutert weitere technische Richtlinien, speziell im Zusammenhang mit dem Play

Framework.

3.6.1 Code Konventionen

Prinzipiell wird sich an die Code Konventionen der jeweiligen Sprachen gehalten, wie z.B. die

Java Code Konventionen von Oracle3.

3.6.2 Flash, Session und Cache

Das Play Framework bietet drei Methoden an, um Daten kurzfristig oder über einen bestimmten

Zeitraum zu speichern, wobei hier keine Datenbank sondern Cookies zum Einsatz kommen. Alle

Varianten bieten das Speichern von Daten durch Schlüssel-Werte-Paare. Mit Flash und Session

können nur Strings gespeichert werden, mit dem Cache dagegen Objekte.

3 http://java.sun.com/docs/codeconv

Page 26: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

21

Flash

mit Flash wird ein sehr kurzzeitiges Speicherformat beschrieben, das nur über die nächste

Anfrage oder Antwort besteht. Die beste Verwendung ist hier der Transport von Status-

Nachrichten (z.B. Anmeldung erfolgreich), welche dann vom Scala-Templating-

Mechanismus ausgewertet und angezeigt werden.

Beispiel:

// String in Flash speichern

public static Result login() {

flash("success", "Anmeldung erfolgreich");

return redirect("/home");

}

Listing 24: Flash-Beispiel

Session

Daten, die mit Hilfe der Session gespeichert werden, sind explizit nur für den zugehöri-

gen Nutzer gültig und zwar solange das Session-Objekt nicht wieder gelöscht wird (z.B.

beim Abmelden).

Beispiel:

// String in Session speichern

public static Result index() {

session("connected", "[email protected]");

return ok("Welcome!");

}

// Session löschen

public static Result index() {

session().clear();

return ok("Bye");

}

Listing 25: Session-Beispiel

Cache

Beim Cache ist zu beachten, dass die Daten nicht für den jeweiligen Benutzer gespeichert

werden, sondern es sich um einen anwendungsweiten Speicher handelt. Um hier die ge-

speicherten Daten wieder einem Nutzer zuordnen zu können, sollte zum Schlüssel des

jeweiligen Werts noch eine eindeutige Bezeichnung, wie z.B. die User-ID hinzugefügt

werden.

Beispiel:

// Objekt im Cache speichern

Cache.set("step1" + session().get("user_id"), step1);

// Objekt aus Cache löschen

Cache.set("step1" + session().get("user_id"), null, 0);

Listing 26: Cache-Beispiel

Page 27: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

22

3.6.3 Testdaten

Sämtliche Testdaten, die im Entwicklungsprozess der Anwendung genutzt werden, können über

die Klasse „Global“ im Wurzelverzeichnis der Paketstruktur angelegt werden. Das Play Frame-

work 2.0 bietet zwar auch die Möglichkeit, Testdaten über die separate Datei „initial-data.yml“

in der YML-Syntax4 zu erzeugen, jedoch ist dieses Vorgehen für komplexe Beziehungsstrukturen

sehr fehleranfällig. Die Methode „onStart(…)“ der Klasse „Global“ wird nach jedem Deploy-

Vorgang ausgeführt. Das Play Framework parst diese Datei und speichert die entsprechenden

Entitäten in der Datenbank.

Als bessere Methode hat sich aber das manuelle Erzeugen der Model-Objekte und anschließende

Speichern in der Datenbank herausgestellt. Diese Methode sollte deswegen auch angewendet

werden.

Folgendes Listing 27 zeigt diese Methode:

public class Global extends GlobalSettings {

public void onStart(Application app) {

InitialData.insert(app);

}

static class InitialData {

public static void insert(Application app) {

if (Ebean.find(User.class).findRowCount() == 0) {

// Rollen einfuegen

Role role = Role.create("Fuhrparkverwalter",

"Verwaltet den Fuhrpark");

Role.save(role);

role = Role.create("Nutzer", "Standardnutzer");

Role.save(role);

Listing 27: Beispiel um Testdaten anzulegen

4 http://www.playframework.org/documentation/1.1/yaml

Page 28: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

23

4 Dekomposition

Die Anwendung ist in mehrere Komponenten gegliedert. Dieses Kapitel zeigt eine Übersicht über

diese Gliederung, aber auch eine genauere Betrachtung der einzelnen Komponenten selber. Au-

ßerdem wird am Beispiel der Reservierung mit Hilfe eines Sequenzdiagrammes (Abbildung 14)

gezeigt, wie diese Komponenten beispielhaft durchlaufen werden.

4.1 Struktursicht

Auf den folgenden Seiten befinden sich eine Komponentenübersicht der kompletten Anwendung,

sowie eine genauere Abbildung der einzelnen Komponenten des Systems.

4.1.1 Komponentenübersicht Fuhrparkverwaltung

Benutzer

Fahrzeug

Reservierung

Rolle

Führerschein

Standort

G

G

GG

G

G

D

D

D

D

D

D

B

FB: BenutzerD: DatenbankG: GrafikF: FahrzeugV: Benutzer JobPositionR: RolleD: FührerscheinL: Location

V

V

Abbildung 7: Komponentenübersicht Fuhrparkverwaltung

Page 29: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

24

4.1.2 Benutzer-Komponente

Benutzer

Statistik

Authentifikation

Kontakt

Job Position

G

A: RolleD: DatenbankF: FahrzeugG: GrafikL: FührerscheinR: ReservierungS: Standort

D

L

S

A

R

F

Abbildung 8: Benutzer-Komponente

4.1.3 Reservierungs-Komponente

Reservierung

Zweck BerichtB: BenutzerF: FahrzeugG: GrafikD: DatenbankS: Standort

F

B

D

G

S

Abbildung 9: Reservierungs-Komponente

Page 30: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

25

4.1.4 Fahrzeug-Komponente

Fahrzeug

Wartung

B: Benutzer Jop PositionD: DatenbankF: FahrzeugG: GrafikL: FührerscheinR: RolleS: Standort

B

F

D

R

G

L

S

Abbildung 10: Fahrzeug-Komponente

4.1.5 Rollen-Komponente

Rolle

B: BenutzerD: DatenbankG: GrafikF: Fahrzeug

F

B

D

G

Abbildung 11: Rollen-Komponente

Page 31: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

26

4.1.6 Führerschein-Komponente

Führerschein

B

D

G

F

B: BenutzerD: DatenbankF: FahrzeugG: Grafik

Abbildung 12: Führerschein-Komponente

4.1.7 Standort-Komponente

Standort

B: BenutzerD: DatenbankG: GrafikF: FahrzeugR: Reservierung

F

B

D

G

R

Abbildung 13: Standort-Komponente

Page 32: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

27

4.2 Ablaufsicht

Für den Ablauf der Anwendung wird hier exemplarisch die Reservierung eines Fahrzeuges als

Sequenzdiagramm dargestellt.

User Reservation Fahrzeug

submitStep1

Benutzer Standort

hasError

getLocation()

getUser()

getVMatchingVehiclesForUser(User, Date, Prupose)

submitStep2

hasError

save(newReservation)

step2 (List<Vehicle>)

user

Location

List<Vehicles>

Abbildung 14: Sequenzdiagramm „Reservieren eines Fahrzeuges“

Page 33: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

28

4.3 Verteilungssicht

Es gibt mit Play 2.0 mehrere Möglichkeiten der Verteilung auf verschiedene Webserver. In den

folgenden Absatz werden wir auf die diese Möglichkeiten genauer eingehen. Hilfe gibt es auch

auf der offiziellen Seite unter Production.

4.3.1 Standalone Mode

Die wohl einfachste Methode einen Webserver bereit zu stellen. Auf dem Rechner/Server muss

dafür Play installiert und die notwendigen Dateien vorhanden sein. Ist der Server soweit einge-

richtet kann durch das Kommando

[My application] $ play start

Listing 28: Aufruf zum Starten eines Webservers

ein eigenständiger Webserver gestartet werden. Dieser Server kann durch die „RUNNING_PID“

mit dem Comando „SIGTERM“ wieder gestoppt werden.

4.3.2 Erstellen einer Standalone Version der Applikation

Eine einfache Methode eine Play-Applikation zu deployen wird vom Framework durch das

Kommando

[My application] $ play dist

Listing 29: Erzeugen eines Zip-Files (enthält alle notwendigen JAR-Files)

bereitgestellt. Dadurch wird eine Binary-Version der Applikation ohne Play-Abhängigkeiten im

ZIP-Container erzeugt. Der Container enthält alle benötigten JAR-Files. Das ZIP-File kann so

problemlos auf einen Tomcat übertragen und auf diesem ausgeführt werden.

Aber auch über Maven lassen sich die notwendigen JAR-Files generieren. Hierfür gibt es auch

die entsprechende Dokumentation unter ProductionDist.

4.3.3 Weitere Deploy-Möglichkeiten

In der Play Dokumentation gibt es noch weitere Möglichkeiten die eigene Applikation zu

deployen. Eine die hier noch erwähnt werden sollte, ist die Möglichkeit die Play Applikation

direkt in die Cloud zu deployen, und zwar über den Dienst „Heroku“. Auch hierzu gibt es eine

entsprechende Dokumentation unter ProductionHeroku.

Mit dem Play Framework in der Version 2.0 ist es nicht möglich, die Anwendung in einem

deploy-fähigen Format (*.war) für einen Application-Server (z.B. Tomcat) zu erstellen. Diese

Funktion soll mit der Version 2.1 möglich sein.

Page 34: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

29

4.4 Datensicht

Folgende Abbildung zeigt die Struktur der Datenbank der Fuhrparkverwaltung. Sichtbar werden

hier die Komponenten „reservation“, „location“, „vehicle“, „user“, „role“ und „driver_license“.

Außerhalb dieser Komponenten befinden sich vom Persistenzframework automatisch erstellte

Tabellen (z.B. „vehicle_purpose“), welche Many-to-many-Beziehungen abbilden. Falls in Zu-

kunft weitere Tabellen dazu kommen, sollten diese einer der bestehenden Komponente zugeord-

net werden, um die vorhandene Struktur beizubehalten.

Abbildung 15: Datensicht

Page 35: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

30

5 Querschnittliche Systemaufgaben

Hier wird beschrieben, wie allgemeine und querschnittliche Systemaufgaben behandelt und gelöst

werden.

5.1 Sicherheit

Eine wichtige Aufgabe ist die Absicherung der Anwendung, so dass nur authentifizierte Nutzer

diese benutzen können. Diese muss bis auf die einzelnen Controller heruntergebrochen werden,

da sie mittels URLs angesteuert werden und bei nicht ordnungsgemäßer Absicherung eine Si-

cherheitslücke darstellen. Bewerkstelligt wird das durch die folgende Play-Annotation, mit wel-

cher jede Controller-Klasse annotiert werden muss.

@Security.Authenticated(Secured.class)

Listing 30: Authensisierungs-Annotation

Dadurch wird bei jedem Zugriff auf einen Controller zuerst die Klasse „Secured“ aufgerufen.

Darin befindet sich die überschriebene Methode „getUserName(…)“, mit der die Session auf

Informationen geprüft wird. Sind diese Informationen nicht vorhanden, wird der Nutzer über die

Methode „onUnauthorized(…)“ auf die Anmeldeseite weitergeleitet. Im anderen Fall wird dem

angemeldeten Nutzer die Controller-Funktionalität bereitgestellt.

5.2 Transaktionsmanagement

Das Standard-Persistenzframework Ebeans verwendet implizite Transaktionen. Somit müssen

Datenbankoperationen nicht explizit als Transaktionen definiert werden. EBeans kümmert sich

automatisch um Transaktionsoperationen wie „commit“ oder „roll-back“.

Sollte jedoch der Bedarf an expliziten Transaktionen bestehen, kann dies über verschiedene Mög-

lichkeiten erzielt werden:

@Transactional

public static Result save() {

...

}

Listing 31: Beispiel @Transactional

Durch die Annotation „@Transactional“ kümmert sich EBeans um die automatische Ausfüh-

rung der Transaktion im Rahmen der ausgeführten Methode oder Klasse.

Die folgende Art entspricht der programmatischen Methode von „@Transactional“:

Ebean.execute(new TxRunnable() {

public void run() {

// durchzuführende Transaktion

}

});

Listing 32: Beispiel TxRunnable

Beide Varianten können ohne Probleme gemischt werden.

Page 36: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

31

Die letzte Art beschreibt die klassiche Variante mit try-finally-Block:

Ebean.beginTransaction();

try {

// fetch some stuff...

User u = Ebean.find(User.class, 1);

...

// save or delete stuff...

Ebean.save(u);

...

Ebean.commitTransaction();

} finally {

Ebean.endTransaction();

}

Listing 33: Beispiel Transaktion mit try-finally

Der Standard Isolation Level von Ebeans ist „READ_COMMITTED“. Um diesen zu ändern

muss in der obigen Methode die Transaktion beispielsweise mit „Ebe-

an.beginTransaction(Transaction.SERIALIZABLE)“ gestartet werden.

5.3 Protokollierung

Die Protokollierung von Ereignissen erfolgt standardmäßig in der Datei „application.log“. Alle

auftretenden Ausnahmen werden hier protokolliert. Sollen explizit bestimmte Ereignisse (z.B. das fehlerhafte Anmelden eines Nutzers) aufgezeichnet werden, kann dies über die Klasse „play.Logger“ erfolgen. Diese Klasse bietet unterschiedliche Stufen an:

Stufe Anwendungsgebiet

Logger.debug() Soll sehr intensiv für Debug und Entwicklerinformationen verwendet wer-den. Information. Diese werden im produktiven Umfeld nicht ausgegeben.

Logger.error()

Deutet auf einen Bug oder eine generelle Fehlerbedingung hin. Es muss sich dabei aber nicht unbedingt um einen Fehler handeln, welcher das Sys-tem zum Absturz bringt.

Logger.fatal() Ist in extremen Situationen einzusetzen.

Logger.info()

Der Einsatz ist für grundlegende Informationen gedacht. Kann vor und nach Code, welcher eine sehr lange Ausführungszeit besitzt, verwendet werden, um festzustellen, was die Anwendung gerade macht. Die Ausga-bemeldungen auf dieser Stufe sollten nicht allzu ausführlich sein.

Logger.warn()

Fehlfunktionen, die sich nicht negativ auf die Ausführung oder das zu er-wartende Resultat bezieht. Z.B. fehlende Konfiguration – es wird mit Defaultwerten weitergearbeitet.

Tabelle 3: Logging Level und ihr Einsatz

Je nach Situation ist der passende Logging-Level auszuwählen. Als Parameter der Methoden dienen ein String, welcher eine Nachricht aufnimmt und bei Bedarf, die Ausnahme, die geworfen wird. Das Mitübergeben der Ausnahme ist anzustreben.

Page 37: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

32

5.4 Ausnahmebehandlung

Eine umfassende Fehlerbehandlung ist Merkmal und integraler Bestandteil einer Anwendung mit

hoher Qualitätsgüte. Dementsprechend wichtig ist die Vorgabe von Richtlinien in der Architek-

turbeschreibung, so dass die Ausnahmebehandlung konsequent und mit Verzicht auf Antipat-

terns umgesetzt werden kann.

Als Konsequenz aus dem Einsatz von Java auf Seiten des Backends, ergibt sich, dass die Java-

Typischen Ausnahmekategorien vorzufinden sind:

„checked exception“:

Diese Ausnahmen stellen ein erkanntes Problem dar, welches während der normalen Sys-

temausführung aufgetreten ist. Dabei kann es sich beispielsweise um fehlerhafte Benut-

zereingaben handeln. Eine der beiden nachfolgenden Reaktionen darauf ist möglich:

o Erneuter Versuch zu einem späteren Zeitpunkt

o Erneuter Versuch mit korrigierten Parametern

„unchecked exception“:

Diese Ausnahmen weisen auf ein unerwartetes Problem hin, welches sehr wahrscheinlich

durch einen Bug im Quellcode hervorgerufen wird.

Allgemein ist als Regel festzuhalten:

Wenn der Client-Code nichts zur Fehlerbehebung beitragen kann, dann ist eine „unche-

cked exception“ zu wählen.

Kann der Client-Code fehlerbehebende Maßnahmen auf Grundlage der Exception-

Information durchführen, dann ist eine „checked exception zu wählen“.

Die Frage ob ein Verhalten jetzt eine Ausnahme ist oder nicht muss immer im Kontext beurteilt

werden. Leitgedanke soll sein, dass wann immer möglich keine Implementierungsdetails nach

außen gegeben werden (Exception Wrapping).

Um die Aussagekraft der Ausnahmen zu erhöhen, sollen nach Möglichkeit „Nested-Exceptions“

verwendet werden. Den fachlichen Ausnahmen sind aussagekräftige Fehlermeldungen zuzuord-

nen. Eine strikte Trennung zwischen der eigentlichen Fehlermeldung und der Klasse der Aus-

nahmen sorgt für Transparenz und kann wie folgt erzielt werden:

Die Fehlermeldung dient dem Benutzer.

Die Fehlerklasse dient der Implementierung, um eventuell mit Hilfe von try-catch spezi-

fisch darauf zu reagieren.

Alle Ausnahmen, die auftreten können, müssen mit der in Kapitel 5.3 dargestellten Maßnahmen

protokolliert werden, damit eine spätere Analyse möglich ist.

Beispiel zum Protokollieren einer Ausnahme beim Parsen eines Datums:

Page 38: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

33

public Date parseDateString(String date, String time) {

Date newDate = null;

try {

newDate = DATE_FORMAT.parse(date + " " + time);

} catch (ParseException e) {

Logger.error("Fehler beim parsen des Datums", e);

}

return newDate;

}

Listing 34: Beispiel für Ausnahmebehandlung

Die nachfolgende Beschreibung stellt existierende Anti-Patterns in Bezug auf die Ausnahmebe-

handlung dar. Diese sind zu vermeiden.

Log and Throw

catch (NoSuchMethodException e) {

LOG.error("Fehlermeldung", e);

throw e;

}

Listing 35: Beispiel Log an Throw

Obige Abbildung zeigt ein Beispiel für diese Art. Ein Loggen und gleichzeitiges Werfen der Aus-

nahme findet statt und ist eine der lästigsten Verwendungen, welche sich sehr negativ für den

Support und die Fehlerbehebung auswirken. Entweder sollte die Ausnahme aufgezeichnet oder

geworfen, aber nicht beides, werden.

Das Werfen von Exceptions

Ein Werfen der abstrakten Fehlerklasse Exception sagt lediglich aus, dass ein Fehler aufgetreten

ist, führt zu keinem Mehrgewinn an Information und ist zu vermeiden.

Das Werfen mehrerer „checked exceptions“

public void myFunction() throws MyException,

NotherExpression, YetAnotherException

{

}

Listing 36: Beispiel "checked Exception"

Das Werfen mehrerer, ähnlicher, Ausnahmen ist ebenfalls zu vermeiden und sollte über ein Kap-

seln (Wrapping) in einer eigenen Ausnahmeklasse vollzogen werden.

Destruktives Wrapping

catch (NoSuchMethodException e) {

throw new MyException("Error Message: " +

e.getMessage());

}

Listing 37: Beispiel Destruktives Wrapping

In jedem Fall ist diese Art Fehlerbehandlung zu vermeiden, da der Stack Trace zerstört wird.

Page 39: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

34

5.5 JNDI

Falls die Datenbank per JNDI veröffentlicht werden soll, kann dies wie folgt geschehen:

db.default.driver=org.h2.Driver

db.default.url="jdbc:h2:mem:play"

db.default.jndiName=DefaultDS

Listing 38: Datenbank über JNDI veröffentlichen

Durch diese Methode wird die In-Memory Datenbank des Play Frameworks über den Name

DefaultDS im JNDI bekannt gemacht. Diese Methode kann mit jeder beliebigen angebundenen

Datenbank geschehen.

Page 40: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

35

6 Alternativen

Dieses Kapitel Begründet, aus welchem Grund die einzelnen Bibliotheken, welche zum Einsatz

kommen, gewählt wurden, gibt eine Bewertung zu diesen ab und führt mögliche Alternativen an.

6.1 jQuery

Im Bereich der Client-Seitigen Bibliotheken gibt es sehr viele mögliche Alternativen. Die

Grundintension dieser besteht darin, die durch JavaScript vorgegebene Funktionalitäten, mit dem

Ziel der einfacheren Handhabung und browserübergreifenden und einheitlichen Ausführung, zu

kapseln.

Durch die hohe Vielzahl an vorhandenen Bibliotheken fällt die Auswahl nicht leicht. Der Einsatz

von jQuery ist aus folgenden Gründen sinnvoll:

Innerhalb des Open-Source Segments die am meisten verwendete Bibliothek

Leichte Einarbeitung möglich – viel qualitativ hochwertige Literatur vorhanden

Weist eine offene PlugIn-Architektur auf, wodurch beliebige Entwickler aus der Open-

Source Community an der Weiterentwicklung partizipieren können. Dies beschleunigt

die Verbesserung und Weiterentwicklung der jQuery Funktionalität.

Im Open Source Bereich existiert keine nennenswerte Alternative. Was in Erwägung gezogen

werden kann, wenn man auch die Bibliotheken unter kommerzieller Lizenz mit einbeziehen

möchte, ist ExtJS ab der Version 4.0. Ein Look-And-Feel, das einer Desktop-Anwendung nahe

kommt, sowie umfangreiche AJAX Unterstützung und eine MVC basierte (über REST angebun-

dene) Oberfläche wird geboten. Hauptsächlich der MVC bedingte Overhead und die Komplexität

der Bibliothek führte zu dem Entscheid, diese Bibliothek nicht einzusetzen.

6.2 Play Framework

Dieses Unterkapitel evaluiert das Play Framework in Bezug auf die Eignung für die Entwicklung

von Enterprise Applications. Dies ist notwendig, da die Architekten und Entwickler noch keine

Expertise darin besitzen und vor der Bewertung keine Aussage dazu treffen können.

6.2.1 Business-Sicht

Die Entwicklung von heutigen Enterprise Anwendungen sieht sich mit zwei hauptsächlichen

Herausforderungen konfrontiert:

1. Time-To-Market

Die Zeit zwischen Projektstart und der Einführung des Produkts am Markt, wird immer

wichtiger.

2. Skalierbarkeit

Ein weiterer wichtiger Aspekt moderner Anwendungen, ist die mögliche Skalierbarkeit

und Ausfallsicherheit. Bei höherer Last sollten mehr Ressourcen zur Verfügung stehen.

Die Auswahl eines geeigneten Frameworks kann nicht immer ganz autark - ohne Einbeziehung

des Projektkontexts - getroffen werden. Viele Faktoren, wie die Art des zu entwickelnden Front-

ends, das Backend und andere existierende Systeme (Integrationsaspekte) müssen mit berücksich-

tigt werden. So ist beispielsweise bei einem existierenden, komplexen, JavaEE Backends der Ein-

satz von Java Server Faces (JSF) sehr naheliegend.

Page 41: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

36

Das Fuhrparkverwalngssystem baut auf keinen existierenden Systemen auf, so dass die Wahl

eines geeigneten Frameworks ohne Berücksichtigung von Einflussfaktoren getroffen werden

kann.

Welcher Play Framework wurde sehr schnell sehr bekannt. Da es noch sehr jung ist, lassen sich

keine repräsentativen Referenzapplikation für eine Bewertung heranziehen. Lediglich die nach-

folgend dargestellten Projekte zeigen, dass es bereits Produktivanwendungen gibt, die mit dem

Play Framework entwickelt wurden:

Französisches Job-Portal „Express Board“:

Dieses Job-Portal5 für Frankreich stellt eine Plattform für die Vermittlung von Jobs aus

dem Bereich der Softwareentwicklung zwischen Unternehmen und Technik-Freaks und

Enthusiasten dar. Die Realisierung geschah mit Play.

Plancruncher:

Die Webanwendung Plancruncher6 dient der einfachen Erstellung kurzer Businesspläne,

anhand eines Wizards. Auch diese Umsetzung erfolgte mit dem Play Framework.

Webseite des Play Frameworks:

Die Webseite des Play-Frameworks basiert selbst auf dem Play Framework und ist etwas

repräsentativer in Bezug auf Enterprise Anwendungen. Dies wird deutlich, wenn man

sich Zugriffszahlen betrachtet. So liegen die Zugriffszahlen bei 100.000 Zugriffen pro Tag,

welche ohne Performanzprobleme möglich sind.

6.2.2 Technische Sicht

Nachdem drei Echtanwendungen vorgestellt wurden, soll sich die Beurteilung des Play Frame-

works in Bezug auf den Einsatz für Enterprise Anwendungen an einer theoretischen Betrachtung

orientieren.

Es bietet einen sehr schnellen Entwicklungsstart dadurch, dass der leistungsstarke Appli-

kationsserver JBoss Netty, das Persistenzframework EBeans, eine In-Memory Daten-

bank, sowie ein Build-Tool (Simple Build Tool) mit ausgeliefert werden. Das beeinflusst

die Time-To-Market Zeit sehr positiv.

Trotzdem besteht volle Flexibilität

o Ein Deployment auf einen externen Applikationsserver ist möglich, wenngleich

die Play Version 2.0 noch Probleme mit der Bildung von Web Application Ar-

chivs (*.war) hat.

o Das Simple Build Tool ermöglicht das Einbinden von Maven Repositories mittels

Apache Ivy.

o Alternative Persistenzframeworks wie Hibernate, etc. können eingebunden wer-

den.

Webapplikationen stehen als zustandslose REST Services zur Verfügung. Dies wirkt sich

positiv auf den Aspekt der Skalierbarkeit von Enterprise Anwendungen aus, denn die Zu-

standslosigkeit erlaubt ein sehr einfaches Stacking mehrerer Applikationsserver, welche

über einen vorgeschalteten Front-Proxy verwaltet werden. Auch die Verfügbarkeit wird

dadurch beeinflusst, denn die Server können wechselseitig aus dem Verbund gelöst wer-

den, um beispielsweise ein Softwareupdate durchzuführen.

5 http://www.express-board.fr/ 6 http://plancruncher.com/

Page 42: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

37

Modularisierung ist von Play über die sogenannten Play-Modules unterstützt. Diese kön-

nen zwar nicht ganz mit der Modularisierung aus der Objektorientierung verglichen wer-

den, jedoch versuchen sie der Entwicklung von Webapplikationen gerecht zu werden.

Funktionalität lässt sich in diesen kapseln und ist prinzipiell vergleichbar mit einem ei-

genständigen Play Projekt. Somit lässt sich die Wiederverwendbarkeit steigern. Viele der

Module stehen aber leider noch nicht für die Play Version 2.x zur Verfügung, da eine Por-

tierung noch nicht erfolgte.

6.2.3 Entwickler-Sicht

Durch das Play Framework werden an die Entwickler verschiedene Anforderungen gestellt, die

beachtet werden müssen. Die Wichtigsten soll dieses Kapitel erläutern.

6.2.3.1 Entwurfsmuster

Das MVC-Muster ist dasjenige, welches am offensichtlichsten und stärksten Einfluss auf die

Entwicklung mit Play ausübt. Dieses Muster hat sich zum Standard bei modernen Webanwen-

dungen entwickelt und bietet durch die klare Trennung von Model, View und Controller eine

lose Kopplung dieser Komponenten.

Die Views des Play Frameworks können nach dem Kompositum-Muster aufgebaut werden:

ViewKomponente

View ViewKompositum

*

Abbildung 16: View-Kompositum

Das erlaubt eine Verschachtelung und Wiederverwendung von sich wiederholenden Teilen einer

Webseite (z.B. Header und Footer).

6.2.3.2 Extreme Zustandslosigkeit

Die starke Zustandslosigkeit, wie sie auch bereits im vorhergehenden Kapitel in Bezug auf die

Skalierbarkeit genannt wurde, führt dazu, dass während der Entwicklung mehr zu beachten ist.

Beispielsweise muss jede Anfrage ausreichend viele Informationen enthalten, so dass diese verar-

beitet werden kann.

Page 43: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

38

6.2.3.3 Vergleich mit JSF

Dieses Unterkapitel vergleicht die Programmierkonzepte der Java Server Faces (JSF) und des

Play Frameworks. Für eine gute Übersichtlichkeit liegt dieser Vergleich in Form einer Tabelle

vor, welche nachfolgend aufgeführt ist.

Java Server Faces (JSF) Play Framework (Play)

Basis Basiert auf der Servlet API (FacesServlet) und muss somit in einem Servlet Container ab-laufen.

Basiert nicht auf der Servlet API und benötigt keinen Serv-let Container zur Ausführung, kann aber, wenn nötig mit der

Servlet API zusammenspielen.

Zustandbehaftetkeit Konzipiert als zustandsbehaftet (stateful) mit folgenden Vortei-len:

Einfacheres Programmier-modell

und Nachteilen:

Layer 7 Load-Balancing

Session Failover

Aber auch stateless ist mit JSF

möglich.

Konzipiert als zustandlos (stateless) mit folgenden Vor-teilen:

Einfaches Load-Balancing durch Hinzufügen beliebig vieler Applikationsserver-Instanzen

und Nachteilen:

Komplexeres Program-miermodell

Templating (Composite Pattern)

Das Templating wird durch spezielle JSF Tags unterstützt um eine Gesamtseite aus Seiten-Fragmenten zusammenzuset-zen.

Das Templating geschieht durch Scala basierte Ausdrücke und ermöglicht ebenfalls das Zusammensetzen von Seiten-fragmenten zu einer Gesamt-seite.

Navigationslogik Die Logik zur Navigation zwi-schen den Seiten ist in einer Datei zentralisiert und ermög-licht eine leichtere Abänderung

des Navigationsflusses, da sich die Änderungen nicht durch mehrere Seiten ziehen. Eine visuelle Darstellung der Seiten-vernetzungen wird mitgeliefert.

Eine zentrale Navigationslogik ist nicht vorhanden und somit steckt das Wissen um den Sei-tenfluss in den einzelnen Seiten

und eine Änderung führt zu Änderungen in den Seiten. Eine visuelle Darstellung der Seitenvernetzung ist nicht mög-lich.

Mapping zwischen HTML/Entity Elementen

Die Zuordnung zwischen den Elementen der Präsentationsschicht und den korrespondierenden Elementen der Modelle geschieht in beiden Frameworks auf eine ähnliche Weise. JSF greift dabei auf eine Expression Language zurück, während in Play die Sprache Scala Anwendung findet.

Tabelle 4: Vergleich JSF und Play

Page 44: Fuhrparkverwaltung - ArchitekturbeschreibungGeschäftslogikschicht: Die Geschäftslogikschicht ist in Java mit simplen POJOs (Plain Old Java Objects) umgesetzt. Datenzugriffsschicht:

39

Zusammenfassend kann festgehalten werden, dass die Frameworks sich hauptsächlich durch die

Zustandsbehaftung und die Umsetzung der Navigationslogik unterscheiden. Die Navigation in

JSF ist besser umgesetzt, während die Zustandslosigkeit in Play als bessere Lösung zu werten ist.

Beide Frameworks eignen sich gut für die Umsetzung von Enterprise Anwendungen, jedoch

kann dem Play Framework, durch die genannten Argumente, dennoch ein leichter Vorzug gege-

ben werden. Gerade durch den geringen Konfigurationsaufwand, kann zu Projektbeginn viel Zeit

gespart werden.

6.2.4 Fazit

Zusammenfassend bleibt noch die Frage offen, ob das Play Framework für den Einsatz bei der

Entwicklung von Enterprise Anwendungen empfohlen werden kann. Die betrachteten Punkte

legen dies nahe, womit prinzipiell eine Empfehlung ausgesprochen werden kann. Die mangelnde

Portierung der Module von Version 1.x auf 2.x wirkt sich aber stark auf die Produktivität und

Möglichkeiten aus, so dass der Einsatz erst ab Version 2.1 empfohlen werden kann.