FOM Hochschule für Oekonomie & Management
Studienzentrum Essen
Master-Thesis
zur Erlangung des Grades eines
Master of Arts (M.A.)
über das Thema
Konzeption eines IDML Servers
von
Peyman Pouryekta
Erstgutachter		 Professor Dr.-Ing. Torsten Finke
Matrikelnummer	 198124
Abgabedatum		 2013-04-15
2
Inhaltsverzeichnis
1 Einleitung........................................................................................................................................... 4
1.1 Sachliche Motivation................................................................................................................ 4
1.2 Ziele.......................................................................................................................................... 4
1.3 Leserkreis................................................................................................................................. 4
1.4 Typografische Konventionen.................................................................................................... 5
1.5 Literaturdiskussion................................................................................................................... 5
2 Grundlagen......................................................................................................................................... 6
2.1 Softwarearchitektur.................................................................................................................. 6
2.1.1 Definition........................................................................................................................ 6
2.1.2 Architekturmuster........................................................................................................... 8
2.1.3 Entwurfsmuster............................................................................................................. 10
2.2 Webservice............................................................................................................................. 12
2.2.1 Definition...................................................................................................................... 12
2.2.2 SOAP............................................................................................................................ 12
2.2.3 REST............................................................................................................................ 13
2.3 Grails...................................................................................................................................... 14
2.3.1 Einordnung................................................................................................................... 14
2.3.2 Groovy.......................................................................................................................... 15
2.3.3 Spring........................................................................................................................... 20
2.3.4 Konzepte....................................................................................................................... 21
2.3.5 Applikation................................................................................................................... 21
2.4 IDML...................................................................................................................................... 30
2.4.1 InDesign........................................................................................................................ 30
2.4.2 Dateiformat................................................................................................................... 32
2.4.3 IDMLlib........................................................................................................................ 35
3 Umsetzung....................................................................................................................................... 37
3.1 Konzept.................................................................................................................................. 37
3.1.1 Anforderungen.............................................................................................................. 37
3.1.2 Systemarchitektur......................................................................................................... 37
3.1.3 Webservice.................................................................................................................... 39
3.1.4 Process-Engine............................................................................................................. 41
3.2 Praktische Umsetzung............................................................................................................ 42
3.2.1 Systemanforderungen................................................................................................... 42
3.2.2 Prototyp........................................................................................................................ 42
3.2.3 Szenarien...................................................................................................................... 53
4 Schlussbetrachtung.......................................................................................................................... 61
3
4.1 Ergebnisse.............................................................................................................................. 61
4.2 Bewertung.............................................................................................................................. 62
4.3 Blick in die Zukunft .............................................................................................................. 63
Abbildungsverzeichnis........................................................................................................................ 65
Abkürzungsverzeichnis....................................................................................................................... 66
Literaturverzeichnis............................................................................................................................ 68
Stichwortverzeichnis........................................................................................................................... 71
4
1 Einleitung
Diese Thesis beschäftigt sich mit der Fragestellung, wie ein IDML-Server aufgebaut sein und ob die-
ser Vorteile bringen kann. Es wird ein Konzept erstellt, auf dessen Basis ein IDML-Server entwickelt
werden kann. Durch unterschiedliche Szenarien, die mit Hilfe des IDML-Servers abgebildet werden,
können die Vorzüge eines solchen Servers aufgezeigt werden.
Es folgen die sachliche Motivation, die Ziele und die Literaturdiskussion dieser Arbeit.
1.1 Sachliche Motivation
In der Druck- und Medienindustrie wird zur Erstellung von Medienprodukten häufig das Programm
Adobe InDesign (im weiteren Verlauf InDesign) verwendet. InDesign ist proprietär und das Dateifor-
mat kann somit nur von InDesign verwendet werden. Ab der CS4 Version von InDesign hat das Unter-
nehmen Adobe ein neues Dateiformat eingeführt das sich InDesign Markup Language (IDML) nennt.
Dieses Format ist einmal für die Versionskompatibilität zwischen den InDesign Versionen ab CS4
verantwortlich und zum anderen für die externe Verarbeitung von InDesign-Dokumenten. Dadurch das
IDML offengelegt wurde, können neue Möglichkeiten im Bereich von Automatisierungen außerhalb
von InDesign entwickelt werden. IDML ist jedoch ein komplexes Dateiformat und der Umgang damit
erfordert tiefes Wissen über InDesign und IDML. Um diese Komplexität beherrschbar zu machen,
sind Systeme notwendig, die von IDML-Spezialisten entwickelt werden und den Umgang mit IDML
zu verweinfachen. Oft kommt es in der Druck- und Medienindustrie vor, dass Kosten durch wieder-
kehrende Prozesse entstehen. Häufig können solche Prozesse individuell durch IDML automatisiert
werden. Ein weiterer Aspekt ist, dass einfache Aufgaben oft abhängig von InDesign sind, wodurch
zusätzlicher Arbeitsaufwand sowie Lizenzkosten entstehen können. Durch den Einsatz von IDML
kann in bestimmten Bereichen eine von InDesign unabhängige und in andere Systeme integrierbare
Lösung geboten werden.
1.2 Ziele
Diese Arbeit zeigt ein Konzept auf, mit dem der Umgang von IDML-Dateien gestaltet werden kann.
Der IDML-Server fungiert dabei als ein Werkzeug, welches man für die IDML-Verarbeitung verwen-
den kann. In dieser Arbeit steht der IDML-Server im Fokus. Darüber hinaus soll der produktive Ein-
satz eines solchen Servers dargestellt werden. Dazu werden aus der Druck- und Medienindustrie unter-
schiedliche Szenarien betrachtet, die den produktiven Einsatz eines IDML-Servers bestätigen sollen.
1.3 Leserkreis
Die Arbeit ist hauptsächlich an Personen aus der Informationstechnik gerichtet, die sich mit IDML
beschäftigen und dessen Einsatzmöglichkeiten betrachten wollen. Ein grundsolides Vorwissen über
5
Softwareentwicklung im Bereich Java und über Desktop-Publishing mit InDesign wird vorausgesetzt.
Ein Vorwissen über die Themen aus dem Grundlagenkapitel ist von Vorteil. Tieferes Wissen kann und
soll über die Referenzen aus dem Literaturverzeichnis herangezogen werden.
1.4 Typografische Konventionen
In dieser Arbeit wird auf die typografischen Konventionen Wert gelegt, um dem Leser das komplexe
Thema bestmöglich zu erläutern. Folgende Konventionen werden eingehalten:
Fließtext: Die Schriftart für den Fließtext ist eine Times in der Größe 12 pt.
Code: Groovy, HTML, XML, IDML, Grails-Kommandos, URLs, Parameter und alle Elemente,
die darin verwendet werden, werden in der Schriftart Courier New mit 11 pt ausgezeichnet.
Dateinamen: Datei-, Ordnernamen und Pfade werden in der Schriftart Times mit dem Stil Italic
ausgezeichnet.
Diagramm: Die Typografie in den Diagrammen wird in Arial mit 11 pt und 8 pt ausgezeichnet.
1.5 Literaturdiskussion
Der Kern dieser Thesis beschäftigt sich mit der Orchestrierung der Themen aus dem Grundlagenkapi-
tel zu einer Komposition - dem Konzept. Dabei wird bei den Grundlagenthemen auf ihre Kernkonzep-
te eingegangen, um ein Basisverständnis zu vermitteln.
Die wichtigsten Literaturangaben dieser Arbeit beziehen sich auf den Bereich der Frameworks. Da das
Grails- und das Spring-Framework eine zentrale Rolle in dieser Konzeption spielen, wurde hier auf
den Verweis der Primärliteratur besonderer Wert gelegt. Rod Johnson (Spring-Framework), Graeme
Rocher (Grails-Framework) und Guillaume Laforge (Groovy) sind dabei die Köpfe der jeweiligen
Technologien. Zum Thema IDML ist kaum Literatur vorhanden, deshalb wird hauptsächlich mit der
IDML-Spezifikation gearbeitet. Diese behandelt jedoch nicht ausreichend den Einsatz von IDML,
weshalb Vorwissen über InDesign und eine eigenständige Motivation zur Erarbeitung von Kenntnissen
im Bereich IDML vorausgesetzt wird.
6
2 Grundlagen
Dieses Kapitel beschäftigt sich mit den grundlegenden Themen, die für das Verständnis der Arbeit re-
levant sind. Als Erstes wird der Begriff Softwarearchitektur beleuchtet. Hier wird vor allem erläutert,
was eine Softwarearchitektur ist, welche Ziele sie verfolgt und wie diese umgesetzt werden kann.
Im Kapitel 2.2 wird erläutert, was unter einem Webservice zu verstehen ist. Dabei werden die Techno-
logien Simple Object Access Protocol (SOAP) und Representational State Transfer (REST) betrachtet
sowie ihre Funktionsweise erläutert.
Das Kapitel 2.3 beschäftigt sich mit dem Grails-Framework. Hier werden die Konzepte des Frame-
works erläutert. Auch die eingesetzte Sprache Groovy wird hier betrachtet und grundsätzlich gezeigt,
wie eine Grails-Applikation aufgebaut ist.
Anschließend wird im Kapitel 2.4 auf die IDML eingegangen. Zunächst wird erklärt, was überhaupt
InDesign ist. Danach wird das Dateiformat IDML betrachtet und sein Aufbau beschrieben. Danach
wird auf die Möglichkeit eingegangen, wie dieses Format verarbeitet werden kann.
In allen Grundlagenkapitel werden nur die wesentlichen Aspekte angesprochen. Genauere Informatio-
nen können anhand des Literaturverzeichnisses herangezogen werden.
2.1 Softwarearchitektur
In diesem Abschnitt wird der Begriff Softwarearchitektur erläutert. Es beginnt mit der Definition des
Begriffes. Dann wird auf dieArchitekturmuster und Entwurfsmuster eingegangen. Diese sind abstrakte
Beschreibungen einer Lösung für häufig vorkommende Probleme. Dabei betrachtenArchitekturmuster
zum einen das gesamte System, während Entwurfsmuster auf sehr spezielle Probleme ausgerichtet
sind.
2.1.1 Definition
Softwarearchitektur befasst sich mit der Gestaltung und der Struktur eines Softwaresystems. Es exis-
tiert eine Vielzahl an Definitionen.
Philippe Kruchten erläutert den Begriff auf diese Weise:
Software architecture deals with abstraction, with decomposition and composition,
with style and esthetics. [Kruchten1995, S.1]
Der Fokus von Kruchten liegt dabei auf Abstraktion, Zerlegung, Zusammensetzung, Ästhetik und Stil
der Softwarearchitektur.
Das Carnegie Mellon Software Engineering Institute (SEI) stellt auf seiner Webseite mehr als 100
Definitionen zur Verfügung [vgl. Carnegie2012]. Anhand dieser Sammlung kann grundsätzlich gesagt
werden, dass Softwarearchitektur sich mit folgenden Aspekten beschäftigt:
7
Struktur: Eine Softwarearchitektur beschreibt die Komponenten eines Softwaresystems. Es geht
hierbei nicht nur um den Aufbau, sondern auch um das Zusammenspiel, die Beziehungen und die
Eigenschaften der Komponenten. Somit ist die Softwarearchitektur nicht nur der Bauplan, sondern
auch der Ablaufplan des Softwaresystems. [vgl. Starke2009, S.16] Eines ihrer der Hauptziele ist
es, die Komplexität eines Softwaresystems mit Hilfe einer Struktur beherrschbar zu machen.
Beschreibung einer Lösung: Eine Softwarearchitektur wird in Form von Plänen realisiert. Sie
beschreibt eine Lösung und besteht aus abstrakten Komponenten. Diese Pläne führen durch die
konkrete Implementierung zur Realisierung eines Systems. [vgl. Starke2009, S.16]
Entwurfsentscheidungen: Eine Softwarearchitektur basiert auf Entwurfsentscheidungen. Hier-
bei spielt sowohl die Wahl der Technologie, als auch die Wahl des Aufbaus von Komponenten eine
wichtige Rolle. [vgl. Starke2009, S.17] An dieser Stelle können Entwurfsmuster (design patterns)
ansetzen, um eine Lösung für bekannte Entwurfsprobleme zu bieten.
Übergang von der Analyse zur Realisierung: Eine Softwarearchitektur ist das Bindeglied zwi-
schen der Analyse und der konkreten Implementierung des Softwaresystems. [vgl. Starke2009,
S.17] Generell wird Software entwickelt, um ein bestehendes oder zukünftiges Problem zu lö-
sen. Dieses Problem wird im Rahmen der Analyse erfasst. Die Softwarearchitektur beschreibt die
Funktionsweise und den Aufbau des Systems, welches das Problem löst. Sie dient bei der Soft-
wareentwicklung als Vorgehensmodel.
Sichten: Eine Softwarearchitektur wird in unterschiedlichen Sichten dargestellt. Philippe Kruch-
ten unterscheidet dabei die fünf folgenden Sichten:
•	 logical view
•	 process view
•	 development view
•	 physical view
•	 scenario
Durch die Sicht auf die Architektur aus einem bestimmten Blickwinkel kann die Architektur ge-
nauer betrachtet und gestaltet werden, da andere Bereiche so ausgeblendet werden. Eine genaue
Erläuterung der Sichten ist zu finden unter: [Kruchten1995, S.1f].
Verständlichkeit: Eine Softwarearchitektur schafft Ordnung und ermöglicht einen Überblick über
das System. Um die Komplexität eines Systems verständlich zu machen, werden die Anforderun-
gen in Strukturen überführt und dokumentiert. Die Dokumentation ist hierbei ein wichtiger Punkt.
8
Denn nur so können alle Beteiligten ein Verständnis über die einzelnen Komponenten und deren
Zusammenspiel bekommen. [vgl. Starke2009, S.18]
Flexibilität: Eine Softwarearchitektur sorgt dafür, dass das Softwaresystem weiterentwickelt wer-
den kann. Die Software muss einen Aufbau gewährleisten, der es ermöglicht, das System flexibel
zu erweitern. [vgl. Starke2009, S.19] Das bedeutet auch, dass in der Praxis generell keine perfekte
Softwarearchitekturen entstehen, da diese häufig nicht flexibel hinsichtlich ihrer Weiterentwick-
lung sind. [vgl. Wolff2009]
Abstraktion: Eine Softwarearchitektur beschreibt ein abstraktes System. Dabei werden Informa-
tionen bewusst weggelassen, um die Verständlichkeit des Systems zu erhöhen. Die wesentlichen
Kerneigenschaften der Software werden in einer Softwarearchitektur dargestellt. [vgl. Starke2009,
S.19]
Qualität: Eine durchdachte Softwarearchitektur kann die Qualität der Software erhöhen. Die Qua-
lität besteht aus mehreren Kriterien, wie zum Beispiel Performance, Verständlichkeit, Flexibilität
etc. [vgl. Starke2009, S.19]
Um diese Aspekte auch realisieren zu können, wird häufig auf bestehende Methoden wie beispielswei-
se Architekturmuster zurückgegriffen.
2.1.2 Architekturmuster
Architekturmuster unterstützen bei der Entwicklung eines Softwaresystems, da sie dieses aus einer
abstrakten und ganzheitlichen Sicht beschreiben. Im Folgenden wird das Schichtenmuster und das
Model View Controller (MVC) Muster erläutert. Diese sind für die spätere Umsetzung relevant:
Schichtenmuster: Das Schichtenmuster hat die Aufgabe, Struktur zu schaffen. Das Softwaresys-
tem wird dabei in unterschiedliche Schichten unterteilt (layering). Jede Schicht hat eine Aufgabe
und bietet der darüber liegenden Schicht eine definierte Anzahl an Diensten an. Der Aufbau eines
solchen Systems wird häufig mit einer Zwiebel verglichen. Jede Schicht kapselt ihre internen De-
tails und verbirgt die darunter liegenden Schichten. Die Nutzung der Dienste einer Schicht erfolgt
generell über die darüber liegende Schicht. Eine Mehrfachnutzung von Diensten durch andere
Schichten ist zu vermeiden, da die Abhängigkeiten der Schichten dadurch erhöht werden. [vgl.
Starke2009, S.149f]
Eine mögliche Aufteilung der Schichten für ein Softwaresystem wäre die Unterteilung in: Daten-,
Domänen-, Anwendungs- und Präsentationsschicht.
9
Folgende Vor- und Nachteile ergeben sich durch den Einsatz eines Schichtenmusters:
Vorteile
•	 Unabhängigkeit der Schichten in der Erstellung und im Betrieb
•	 Implementierung einer Schicht kann aufgrund ihrer Unabhängigkeit ausgetauscht werden
•	 Minimierung der Abhängigkeiten zwischen Komponenten des Systems
•	 Leicht zu verstehendes Strukturkonzept
[vgl. Starke2009, S.150]
Nachteile
•	 Beeinträchtigung der Performance, da eine Anfrage unter Umständen durch mehrere Schich-
ten durchgereicht werden muss
•	 Erweiterungen eines Systems beinhaltet oft Änderungen in alle Schichten
[vgl. Starke2009, S.150f]
MVC: Das MVC Muster ist ein Quasi-Standard bei objektorientierten Anwendungen. Es dient
der Strukturierung von Softwaresystemen und beinhaltet die Einteilung in drei Einheiten: Model
(Datenmodell), View (Präsentation) und Controller (Programmsteuerung). Ziel des MVC Musters
ist es, eine bessere Wartbarkeit und Flexibilität der Software zu erreichen. [vgl. Starke2009, S.246]
Abbildung 1 zeigt den Ablauf des MVC Musters. Dabei stellen die durchgezogenen Pfeile direkte
und die gestrichelten indirekte Assoziationen dar.
•	 Das Model stellt den Programmteil dar, der die bearbeiteten Daten verwaltet.
•	 Die View stellt einen Zustand der Anwendung dar. Sie ist verantwortlich für die Anzeige der
Daten.
•	 Der Controller ist für die Steuerung verantwortlich. Er interpretiert die Operationen, die über
die View kommen und bestimmt den Folgezustand der Anwendung.
[vgl. Starke2009, S.247]
Abb. 1 MVC Ablauf [vgl. Starke2008, S.247]
Model
View Controller
Statusabfrage Statusänderung
Neuer Status
View anzeigen
Benutzer Eingabe
10
Diese beiden Architekturmuster werden häufig verwendet, um die ganzheitliche Sicht eines Systems
zu organisieren. Oft tauchen während der Implementierungsphase jedoch auch Probleme auf, die nicht
mit Architekturmustern abgedeckt werden können. Hier setzen Entwurfsmuster an.
2.1.3 Entwurfsmuster
Ein Entwurfsmuster (design pattern) ist die abstrakte Beschreibung einer Lösung für ein häufig vor-
kommendes Problem. Allgemein betrachtet besitzt ein Muster vier Elemente:
Mustername: Der Mustername ist die aussagekräftige Benennung des Entwurfsproblems und der
Lösung mit ein oder zwei Worten. Sie erweitert das Entwurfsvokabular und sorgt für einen einfa-
chen Umgang bei der Dokumentation und der Kommunikation mit anderen. [vgl. Gamma2011,
S.3]
Problemabschnitt: Der Problemabschnitt beschreibt, wann das Entwurfsmuster anzuwenden ist,
welches Problem es löst und in welchem Kontext es sich befindet. Es beschreibt spezifische Ent-
wurfsprobleme und Bedingungen, die erfüllt sein müssen. [vgl. Gamma2011, S.3]
Lösungsabschnitt: Der Lösungsabschnitt beschreibt die Elemente des Entwurfs und deren Be-
ziehungen, Zuständigkeiten und Interaktionen. Die dargestellte Lösung ist als eine Schablone zu
sehen, die in unterschiedlichen Situationen Anwendung finden kann. [vgl. Gamma2011, S.4]
Konsequenzabschnitt: Der Konsequenzabschnitt beschreibt die Vor- und Nachteile des Ent-
wurfs. Diese sind relevant für die Beurteilung des Entwurfs gegenüber anderen Alternativen. [vgl.
Gamma2011, S.4]
Es gibt unterschiedliche Arten von Entwurfsmustern. Erich Gamma klassifiziert sie nach drei Aufga-
benbereichen:
Erzeugung: Die Erzeugungsmuster sind dafür zuständig, Objekte zu erzeugen. Sie kapseln den
Prozess der Erzeugung und vereinfachen den Umgang damit. Der Einsatz von Erzeugungsmustern
gewährleistet die Kontrolle über den Erzeugungsprozess, da in einem Muster entschieden wird,
was, wer, wann und wie erzeugt wird. [vgl. Gamma2011, S.101]
Struktur: Die Strukturmuster sind dafür zuständig, den Aufbau von Objekten und deren Bezie-
hungen untereinander zu vereinfachen. Der Einsatz von Strukturmuster kann die Komplexität ei-
ner Software minimieren. [vgl. Gamma2011, S.169]
Verhalten: Die Verhaltensmuster schaffen einen einheitlichen Umgang in der Kommunikation
11
zwischen den Objekten. Der Einsatz von Verhaltensmustern kann die Flexibilität der Software im
Bereich der Kommunikation zwischen Objekten erhöhen. [vgl. Gamma2011, S.271]
Entwurfsmuster werden häufig in Frameworks verwendet. Für die spätere Umsetzung werden hier
einige kurz dargestellt:
Singleton: Das Singleton Entwurfsmuster gehört zu den Erzeugungsmustern und ist objektbasie-
rend. Der Zweck des Musters ist die Erzeugung genau eines Exemplars einer Klasse mit einem
globalen Zugriff darauf. Um dies zu gewährleisten, wird die Zuständigkeit der Verwaltung des
Exemplars in die Klasse gelegt. Die Klasse selber kann somit entscheiden, ob ein neues Objekt
erzeugt werden muss, oder nicht. [vgl. Gamma2011, S.157f]
Builder: Das Builder Entwurfsmuster gehört zu den Erzeugungsmustern und ist objektbasierend.
Der Zweck des Musters ist die Vereinfachung der Erzeugung von komplexen Objekten. Es trennt
die Erzeugung des Objektes von seiner Representation. Somit kann derselbe Erzeugungsprozess
unterschiedliche Representationen hervorbringen. [vgl. Gamma2011, S.119f]
Command: Das Command Entwurfsmuster ist ein Verhaltensmuster und ist objektbasierend. Der
Zweck des Musters ist die Vereinfachung bei Ausführung mehrerer komplexer Aktionen. Dabei
wird eine Anfrage in ein Command gekapselt. Durch das Ausführen eines Commands werden
mehrere Aktionen ausgeführt, die von außen nicht ersichtlich sind. Entwurfsmuster werden auch
häufig miteinander kombiniert. Zum Erzeugen von Commands kann zum Beispiel das Builder
Entwurfsmuster verwendet werden. [vgl. Freeman2004, S.206]
State: Das State Entwurfsmuster gehört zu den Verhaltensmustern und ist objektbasierend. Der
Zweck des Musters ist es Objekten die Möglichkeit zu geben, ihren Zustand zu definieren und auf
diesen aufmerksam zu machen. Eine Kombination mit dem Command-Entwurfsmuster könnte
so aussehen, dass sich bei der Beendigung der Ausführung eines Commands der Zustand eines
Objekts ändert und darauf aufmerksam macht, dass diese Ausführung beendet wurde. [vgl. Free-
man2004, S.410]
Diese Entwurfsmuster lösen spezielle Probleme und bringen oft mehr Organisation und Struktur in
eine Software.
Ein weiterer wichtiger Aspekt von Softwaresystemen ist die Bedienung. Oftmals wird die Bedienung
des Systems über eine Benutzeroberfläche realisiert. Ist das System jedoch auf die Kommunikation
mit anderen Maschinen ausgerichtet, so kann die Kommunikation über einen Webservice stattfinden.
12
2.2 Webservice
Der folgende Abschnitt beginnt mit der Definition des Begriffs Webservice. Danach werden wie zuvor
erwähnt die Technologien SOAP und REST beschrieben und ihre Funktionsweise voneinander abge-
grenzt.
2.2.1 Definition
In der Literatur und in verschiedenen Fachzeitschriften existiert eine Vielzahl von Definitionen des
Begriffs Webservice. Das Standardisierungsgremium World Wide Web Consortium (W3C) bietet fol-
gende Definition an:
A Web service is a software system designed to support interoperable machine-to-
machine interaction over a network. It has an interface described in a machine-pro-
cessable format (specifically WSDL). Other systems interact with the Web service in a
manner prescribed by its description using SOAP messages, typically conveyed using
HTTP with an XML serialization in conjunction with other Web-related standards.
[Booth2004]
Dabei fällt auf, dass das W3C in dieser Definition weitere Technologien aufführt, wie zum Beispiel:
Web Service Description Language (WSDL), SOAP, Hypertext Transfer Protocol (HTTP) und Exten-
sible Markup Language (XML).
Der Begriff Webservice wird im weiteren Verlauf ohne die genannten Abhängigkeiten verstanden und
kann unter gegebenen Umständen andere Formate und Technologien implementieren. Die Kernauf-
gabe von Webservices, sind die Maschine zu Maschine Interaktion über ein Netzwerk und über einem
plattformunabhängigen Kommunikationsformat.
2.2.2 SOAP
Ursprünglich wurde SOAP von UserLand, DevelopMentor, IBM und Microsoft entwickelt. In der Ver-
sion 1.1 wurde SOAP als Kommunikationsprotokoll betrachtet. Aktuell liegt SOAP in der Version 1.2
vor, in der es mehr die Funktion eines Messaging-Framework übernimmt. [vgl. Frotscher2007, S. 28]
Um strukturierte Daten versenden zu können, ist eine Transportmöglichkeit notwendig. Bei einem
Webservice erfolgt dies in den häufigsten Fällen über HTTP. Dabei stellt sich die Frage, wie diese
Daten vorliegen. SOAP bietet hier eine XML basierte Lösung.
Relevant für diese Kommunikation ist die SOAP-Nachricht und das WSDL:
SOAP-Nachricht: Eine SOAP-Nachricht basiert auf XML und besteht aus einem Envelope. In
diesem wird der Namesraum der Nachricht definiert:
13
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
<env:Header> </env:Header>
<env:Body> </env:Body>
</env:Envelope>
In dem Envelope befindet sich ein optionaler Header und ein zwingend erforderlicher Body.
Der Header enthält mehrere Headerblöcke, die Angaben zu Routing, Auslieferung, Authentifizie-
rung, Autorisierung und Transaktionskontexte beinhalten können. Der Body beinhaltet die eigent-
liche Nachricht, die ausgeliefert und verarbeitet werden soll. [vgl. Snell2002, S.15f]
Abb. 2 SOAP-Nachricht
WSDL: WSDL ist eine XML-Spezifikation. Es handelt sich um eine Sprache, die es ermöglicht,
einen Webservice standardisiert zu beschreiben. Die Beschreibung enthält alle notwendigen In-
formationen, um den Webservice anwenden zu können. Darin enthalten sind alle Operationen
der zu versendenden Nachrichten und Datentypen. Außerdem kann WSDL definieren, wie dieser
Webservice aufzurufen und unter welcher Adresse er zu erreichen ist. Werden diese Vorgaben ein-
gehalten, kann über Code-Generierung die Interaktion mit dem Webservice automatisiert werden.
WSDL ist wie auch SOAP plattformunabhängig. [Frotscher2007, S.44]
2.2.3 REST
REST ist generell keine festgelegte Norm. In der Literatur und in Fachzeitschriften weichen die Mei-
nungen voneinander ab.
Die Grundidee ist, dass über ein Uniform Resource Identifier (URI) eine serverseitige Aktion ausge-
führt werden kann, die genau ein Ergebnis liefert. Das erfolgt bei REST in den häufigsten Fällen über
HTTP. [vgl. Fielding2000]
Im Folgenden wird dargestellt, welche HTTP Standardmethoden REST im Webanwedungskontext
hauptsächlich verwendet:
Envelope
Header
Body
14
GET: Beim Aufruf einer GET-Methode wird vom Server eine Ressource gefordert. Dabei kann
eine GET-Anfrage beliebig oft abgesendet werden. Die Methode kann ähnlich betrachtet werden
wie die Read-Methode bei Datenbankoperationen. [vgl. Bayer2002]
POST: Beim Aufruf einer POST-Methode wird vom Server eine Änderung einer Ressource gefor-
dert. Dabei können Prozesse oder Datenbankfelder verändert werden. Die Methode kann ähnlich
betrachtet werden, wie die Update-Methode bei Datenbankoperationen. [vgl. Bayer2002]
PUT: Beim Aufruf einer PUT-Methode wird vom Server eine Änderung einer Ressource gefordert
oder eine neue erzeugt. Die Methode kann ähnlich betrachtet werden, wie die Kombination aus
Create- und Update-Methode bei Datenbankoperationen. [vgl. Bayer2002]
DELETE: Beim Aufruf einer DELETE-Methode wird vom Server die Entfernung einer Ressour-
ce gefordert. Die Methode kann ähnlich betrachtet werden, wie die Delete-Methode bei Daten-
bankoperationen. [vgl. Bayer2002]
2.3 Grails
Dieser Abschnitt stellt die wesentlichen Aspekte des Grails-Framework dar. Es beginnt mit der Ein-
ordnung des Frameworks in der Java-Welt. Darauf folgt die Betrachtung der Sprache Groovy, die ein
wesentlicher Bestandteil des Frameworks ist. Außerdem wird auf das Spring-Framework eingegangen
sowie die Konzepte des Grails-Frameworks. Im letzten Abschnitt wird der Aufbau einer Grails-Appli-
kation betrachtet.
2.3.1 Einordnung
Das Grails-Framework baut auf bestehenden Standards auf, die sich in der Industrie durchgesetzt ha-
ben. Spring und Hibernate sind dabei die wesentlichen Frameworks die Grails verwendet. Abbildung
3 veranschaulicht die Beziehungen:
Abb. 3 Grails Einordnung [vgl. Rocher2009, S.3]
Java Virtual Machine
Java
Groovy
JDK
Java EE Spring Hibernate SiteMash
Grails
15
SiteMesh ist dabei ein Layout Framework mit dem es möglich ist, Seitendekorationen in der View auf
einfachem Weg zu gestalten.
Das Hibernate-Framework ist ein Persistenz-Framework und behandelt Object Relational Mapping
(ORM) mit dem es möglich ist, Plain Old Java Objects (POJOs) in relationalen Datenbanken zu spei-
chern. Im Folgenden wird auf die Sprache Groovy und auf das Spring-Framework eingegangen, wel-
ches die Kerntechnologien des Grails-Frameworks sind. [vgl. Rocher2009, S.2f]
2.3.2 Groovy
Groovy ist eine dynamische Programmiersprache, die in der Java Virtual Machine (JVM) läuft. Es
liegt mit der Sprache Java auf einer Ebene und bedient sich auch ihrer. Groovy kann somit als eine
Erweiterung von Java angesehen werden.
Abb. 4 Groovy/Java Plattform [vgl. Grandeur2009, S.11]
James Strachan, der die Grundidee für Groovy hatte, wurde bei der Entwicklung von Groovy von den
Eigenschaften der Sprachen Python, Ruby und Smalltalk inspiriert. [vgl. König2007, S.3f] Es folgen
die wesentlichen Besonderheiten von Groovy gegenüber Java:
Dynamisch: Groovy ist eine dynamisch typisierte Sprache. Das bedeutet, anders als bei Java,
welche statisch typisiert ist, kann zur Laufzeit der geschriebene Groovy Code manipuliert werden.
Dadurch ist die Sprache flexibler für den Entwickler. Das zeichnet sich vor allem darin aus, dass
die Entwicklung mit einer dynamischen Sprache oft schneller ist, da die Syntax der Sprache kür-
zer gehalten und aussagekräftiger ist. Dem gegenüber steht die langsamere Geschwindigkeit bei
der Ausführung. Dadurch, das während der Laufzeit der Code verändert werden kann, und somit
neu kompiliert werden muss, können bei der Geschwindigkeit Einbußen entstehen. [vgl. Gran-
deur2009, S.12]
Import: Das Groovy Development Kit (GDK) erweitert das Java Development Kit (JDK) mit
zusätzlichen Methoden und der funktionalen Erweiterung durch Closures. Dabei werden automa-
tisch folgende Importierungen eingebunden:
Plattform (Linux, Windows...)
Java Virtual Machine
JavaGroovy
16
•	 groovy.lang.*;
•	 groovy.util.*;
•	 java.lang.*;
•	 java.util.*;
•	 java.net.*;
•	 java.io.*;
•	 java.Math.BigInteger;
•	 java.Math.BigDecimal;
[Davis2008, S.42]
Zusätzlich wird eine Anzahl an Methoden verkürzt. Beispielsweise wird System.out.print in
Groovy mit print aufgerufen. [vgl. Grandeur2009, S.13]
Closure: Eines der wichtigsten Konzepte in Groovy ist das Konzept der Closure. Sie stammen aus
dem Bereich der funktionalen Programmierung und sorgen für mehr Flexibilität. Es sind Code-
blöcke, die referenziert und als Argument oder Rückgabewert in anderen Funktionen verwendet
werden können. [vgl. König2007, S.130f]
Die Syntax eines Closure ist wie folgt definiert [vgl. Groovy2012]:
{ [closureArguments->] statements }
Dabei ist closureArguments-> eine optionale, kommagetrennte Liste von Argumenten. Wenn
nur ein Argument verwendet wird, wird automatisch auf das Argument mit dem Schlüsselwort it
referenziert. [vgl. Grandeur2009, S.19]
def sayIt = { println "Hallo $it"}
sayIt "Welt!"
//Ausgabe: "Hallo Welt!"
def sayValue = {value -> println "Hallo $value"}
sayValue "Welt!"
//Ausgabe: "Hallo Welt!"
Semikolon: In Groovy ist der Einsatz von Semikolons vollkommen optional. Nur beim mehr-
fachen Aufruf in einer Zeile sind Semikolons notwendig. [Davis2008, S.42]
17
print 'Hallo'
print 'Welt!'
//Ausgabe: Hallo Welt!
print 'Hallo'; print 'Welt!';
//Ausgabe: Hallo Welt!
Datentypen: In Groovy müssen keine Datentypen definiert werden. Stattdessen wird das Schlüs-
selwort def verwendet. Dabei stellt Groovy zur Laufzeit fest, um welchen Datentyp es sich han-
delt. [vgl. Grandeur2009, S.13f]
def word = 'Hallo Welt!'
print word.class
//Ausgabe: java.lang.String
def append(word){
'Hallo ' + word
}
append('Welt!')
//Input: String, Ausgabe: Hallo Wellt!
Integer i = 20
append(i)
//Input Integer, Ausgabe: Hallo 20
GString: Groovy hat eine eigene erweiterte Implementierung des Strings genannt Groovy-String
(GString). GString erlaubt dem Entwickler die Einbindung in einen String mit den Auszeichnun-
gen $ und {}. [vgl. Grandeur2009, S.14f]
def word = "Welt!"
def gstring= "Hallo ${word}"
println word.class
//Ausgabe: class java.lang.String
println gstring
//Ausgabe: Hallo Welt!
18
println gstring.class
//Ausgabe: class org.codehaus.groovy.runtime.GStringImpl
Collections: In Groovy gibt es drei Arten von Collections: List, Map und Range. List und Map
sind von der funktionsweise genauso wie in Java verwendbar, nur die Darstellung ist eine andere.
Ranges hingegen sind sehr speziell und bei dynamischen Sprachen einmalig. [vgl. Grandeur2009,
S.16]
def list =['a', 'b', 'c', 'd', 'e']
def map = [0:'a', 1:'b', 2:'c']
def range= 1..10
println list.get(0)
//Ausgabe: a
println map.get(1)
//Ausgabe: b
println range
//Ausgabe [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Return: In Groovy ist das return Statement am Ende einer Methode optional. Groovy gibt au-
tomatisch die letzte Zeile zurück. [vgl. Grandeur2009, S.17]
def method(){
"Hallo Welt!"
}
print method()
//Ausgabe: Hallo Welt!
NULL-Check: In Groovy können Objekte durch ein ? auf NULL geprüft werden. Dadurch kön-
nen NullPointerExceptions vermieden werden. [vgl. Grandeur2009, S.17]
def string = "Hallo Welt!"
println string.size()
//Ausgabe: 12
19
def empty = null
println empty.size()
//Ausgabe: java.lang.NullPointerException: Cannot invoke method size()
on null object
println empty?.size()
//Ausgabe: null
Scripting: Ein weiterer wesetlicher Unterschied zu Java ist, dass Groovy skriptfähig ist. Ist Groo-
vy auf einem Betriebsystem installiert, so können ohne weiteres Skripte erstellt und ausgeführt
werden. Es ist nicht zwingend notwendig wie in Java Klassen zu erstellen. Ein einfaches Skript
(test.groovy) könnte wie folgt aussehen:
#!/usr/bin/env groovy
println "Hallo Welt!"
XML: Groovy bietet eine einfache Möglichkeit über Groovy-Path (GPath) mit XML umzugehen.
<?xml version="1.0" encoding="UTF-8"?>
<customers>
<corporate>
<customer name="Bill Gates" company="Microsoft"/>
<customer name="Steve Jobs" company="Apple"/>
<customer name="Jonathan Schwartz" company="Sun"/>
</corporate>
</customers>
Um diese XML nun einlesen zu können wird der XmlSlurper verwendet:
def customers = new XmlSlurper().parse(new File("test.xml"))
customers.corporate.customer.each{
println "${it.@name} works for ${it.@company}"
}
/*Ausgabe:
Bill Gates works for Microsoft
Steve Jobs works for Apple
20
Jonathan Schwartz works for Sun
*/
2.3.3 Spring
Spring ist ein Open-Source-Framework. Es liefert zur Entwicklung einer Anwendung Fertigbausteine,
um die Entwicklung zu vereinfachen. Dabei ist Spring leichtgewichtig und flexibel, da es keine Vor-
gaben hinsichtlich der Architektur macht. Es liefert eine Menge an Libraries, die eingebunden werden
können, aber nicht zwingend erforderlich sind. Außerdem hat es den Anspruch, den Anwendungscode
unabhängig gestalten zu können, sodass es wiederverwendbar ist und auch ohne das Spring-Frame-
work eingesetzt werden kann. [vgl. Oltmanns2007, S.]
Das Spring-Framework ist in mehrere Module aufgeteilt. Vollständigkeitshalber werden im folgenden
Diagramm diese aufgeführt:
Abb. 5 Spring Modules [vgl. SpringDocu2012]
Der Core-Container ist das wichtigste Modul im Framework, da es sich mit den Kernkonzepten befasst.
Inversion of Control (IoC) und Dependency Injection (DI) sind dabei die fundamentalsten Konzepte.
IoC: IoC ist abstakt zu betrachten und befasst sich mit dem Lebenszyklus von Objekten. Das Hol-
lywood Principle verdeutlich dieses Konzept: "Don´t call us, we´ll call you". [vgl. Johnson2004,
S.128f], [vgl. Johnson2005, S.8f], [vgl. Freeman2004, S.296f]
Spring Framework Runtime
Data Access/Integration
AOP
Web (MVC/Remoting)
Aspects Intrumentation
Core Container
Test
Beans Core Context
Expression
Language
Web
Portlet
Servlet
Struts
JDBS ORM
OXM JMS
Transactions
21
DI: DI ist eine Spezialisierung von IoC und wird auf zwei Wegen eingesetzt: Die erste Möglich-
keit ist Setter-Injection. Dabei wird über eine Setter-Methode ein Objekt injiziert. Die zweite Mög-
lichkeit ist die Constructor-Injection. Hierbei wird über den Konstruktor ein Objekt injiziert. Bei
beiden Möglichkeiten wir die Konfiguration der Klassen entweder über Annotationen oder über
eine externe XML-Datei konfiguriert.
2.3.4 Konzepte
Das Grails-Framework hat zum Ziel, die Java Enterprise Web Entwicklung zu vereinfachen und auf
die nächste Ebene der Abstraktion zu heben. Es bietet Möglichkeiten die andere Frameworks seit Jah-
ren bieten aber bislang nicht in der Java-Welt auf einfachem Wege verfügbar waren. Der Anspruch an
die Flexibilität ist dabei ein wesentlicher Punkt, den das Grails-Framework bietet. Das Framework ori-
entiert sich dabei an Frameworks wie Ruby on Rails, Django und TurboGears und bringt die Vorteile
dieser Frameworks in die Java Welt. [vgl. Rocher2009, S.1]
Die wesentlich Konzepte, die das Grails Framework verfolgt, sind Convention over Configuration
(CoC) und Don´t Repeat Yourself (DRY):
CoC: Bei CoC geht es um die Vereinfachung der Konfiguration einer Software. Dabei einigt man
sich auf Konventionen, wie beispielsweise gleichartige Benennungen, die dann dafür sorgen, dass
Konfigurationen wegfallen können. Ein Beispiel dafür ist die Benennung von Datenbanktabellen
und das Mapping dieser auf eine Klasse. Durch den Einsatz von CoC kann erheblich an Konfigu-
ration eingespart werden, was durch das einheitliche Vorgehen die Verständlichkeit des Systems
erhöht und die Fehleranfälligkeit reduziert.
DRY: Bei DRY geht es um die Vermeidung von Redundanzen. Ein Problem bei der Softwareent-
wicklung ist, dass der Entwickler in einer ständigen Wartungsphase ist. Sobald sich Anforderun-
gen verändern, müssen diese aufgenommen und im Code angepasst werden. Bei einem redun-
danten Code ist dies sehr aufwändig, da dieser an mehreren Stellen anpasst werden muss. Dies
ist folglich zeit- und kostenintensiv. Durch das DRY-Prinzip wird dieses Problem minimiert. [vgl.
Hunt2003, S.25f]
2.3.5 Applikation
Eine Grails-Applikation ist auf einfachem Weg zu erstellen. Ist Grails auf dem Betriebssystem instal-
liert, so gibt es eine Menge an vordefinierten Kommandos, welche bei der Entwicklung hilfreich sind.
Der Aufbau der Kommandos sieht dabei wie folgt aus:
grails [command name]
22
Um eine Grails-Applikation zu erstellen wird das Kommando grails create-app verwendet.
Dieses Kommando fordert einen Namen für die Applikation. Nach Eingabe des Namens werden alle
notwendigen Dateien erstellt.
Der Aufbau einer Grails-Applikation sieht dabei wie folgt aus:
Abb. 6 Grails Applikation
Die application.properties Datei hält Properties, die angepasst werden können. In dieser Datei sind
beispielsweise die Versionsnummer und auch der Name der Applikation definiert.
In dem grails-app Ordner findet die Hauptentwicklung der Applikation statt. Hier sind Ordner zu fin-
den, die unterschiedliche Bereiche abdecken:
config: Alle relevanten Konfigurationsdateien für die Applikation sind in diesem Konfigurations-
ordner enthalten.
Die BootStrap.groovy Datei ermöglicht vor dem Start der Applikation oder nach dem Herunterfah-
ren der Applikation zusätzlichen Code auszuführen. So kann diese beispielsweise dazu verwendet
werden, einen Defaultbenutzer anzulegen, der beim Start der Applikation erzeugt wird.
Die BuildConfig.groovy Datei ist zuständig für das Buildmanagement der Applikation. Hier kön-
nen beispielsweise Maven-Repositories und Grails-Plugins eingebunden werden.
Die Config.groovy ist für die Konfiguration der Applikation gedacht. Hier werden Log4J, Enco-
ding und weitere Konfigurationsmöglichkeiten geboten.
Die DataSource.groovy behandelt die Konfiguration der Datenquelle. Wird in der Applikation
mit einer Datenbank gearbeitet, so besteht hier die Möglichkeit für unterschiedliche Umgebungen
(Entwicklungsumgebung, Testumgebung, Produktionsumgebung) eigene Datenbanken zu konfi-
gurieren.
Der hibernate und spring Ordner ist optional nutzbar. Gibt es beispielsweise Java-Klassen in dem
23
src Ordner, die als Bean in der Grails-Applikation verwendet werden sollen, so kann diese hier
eingebunden werden. Die Spring-Konfiguration kann dann als XML oder in Groovy definiert wer-
den.
Die UrlMappings.groovy definiert ein einheitliches Uniform Resource Locator (URL) Verhalten
der Applikation.
domain: In dem domain Ordner werden die Domain-Klassen abgelegt. Die Erzeugung kann über
das Kommando grails create-domain-class erfolgen. Wird eine Domain-Klasse erzeugt,
sind Objekte dieser Klasse immer direkt auch Objekte, welche in der Datenbank abgelegt werden
können. Zu der Domain-Klasse Person gibt es beispielsweise direkt auch eine Datenbank-Tabelle
dazu.
Domain-Klassen können außerdem constraints besitzen. Das sind Angaben zu Attributen der
Klasse, die bei der Erzeugung eines Objekts validiert werden. [vgl. Rocher2009, S.45f]
class Person {
	 String firstname
	 String lastname
	 int age
	 String emailadress
	 static constraints{
		 firstname(blank: false)
		 lastname(blank: false)
		 age(min: 1)
		 emailadress(email: true)
	 }
}
Der Validator blank: false sorgt dafür, dass die Werte firstname und lastname nicht leer
sein dürfen. min:1 dagegen prüft, ob der Wert age mindestens bei 1 liegt. Der Validator email:
true überprüft, ob der Wert emailadress eine valide Email-Adresse ist.
Grails bietet im Bereich der Domainklassen ein Grails Object Relational Mapping (GORM). Dies
erleichtert den Umgang mit den Objekten und stellt gleichzeitig Create, Read, Update, Delete
(CRUD) Funktionalität zur Verfügung.
Um ein Objekt aus der Datenbank auszulesen wird die get() Methode verwendet.
def person = Person.get(id)
24
Dabei fällt auf, dass die Klasse Person keine get() Methode definiert. Alle Domain-Klassen
bekommen zur Laufzeit diese Methoden hinzugefügt. Grails ermöglicht dies mit Groovy über Me-
taprogramming. [vgl. Rocher2009, S.249f] Um mehrere Personen als Liste zurück zu bekommen
kann die getAll() Methode verwendet werden:
def persons = Person.getAll(1,2,3)
Die list() Methode bietet zusätzliche Funktionen wie beispielsweise die Sortierungsfunktion:
def persons = Person.list(sort:'age', order:'desc')
Um ein Objekt in der Datenbank zu speichern oder zu aktualisieren, wird die save() Methode
verwendet:
def newPerson = new Person(params)
newPerson.save()
def person = Person.get(id)
person.save()
Dabei stellt im Hintergrund Hibernate automatisch fest, ob es ein Structured Query Language
(SQL) INSERT oder ein UPDATE verwenden muss. [vgl. Rocher2009, S.251]
Zum Löschen eines Objektes wird die delete() Methode angewandt:
person.delete()
Zum Suchen eines bestimmten Objekts aus der Datenbank bietet GORM die Dynamic-Finders.
[vgl. Rocher2009, S.255f] Diese setzen sich aus den Klasseneigenschaften und Schlüsselwörtern
zusammen:
Person.findByFirstnameAndLastname("John","Doe")
service: In dem service Ordner werden Service-Klassen abgelegt. Erzeugen kann man diese über
das Kommando grails create-service. Service-Klassen sind in Grails standardmäßig Sin-
geltons. Sie können über das Autowiring-Konzept von Spring automatisch über DI in einem Ser-
vice oder einem Controller injiziert werden. [vgl. Rocher2009, S.289f]
25
class PersonController{
	 def personService
	 ...
}
Eine Service-Klasse arbeitet im Normalfall mit den Domain-Klassen und repräsentiert die Busi-
nesslogik der Anwendung. Die Operationen in der Service-Klasse können Datenbankänderungen
behandeln. Somit müssen die Service-Klassen transaktional sein. Jede bietet die Möglichkeit die
Transaktionalität zu setzen. [vgl. Rocher2009, S.295f]
class PersonService{
	 boolean transactional = true
	 ...
}
Transaktionalität wird beschrieben durchAtomicity, Consistency, Isolation und Durability (ACID):
•	 Atomicity bedeutet, dass jede atomare Operation in der Transaktion entweder ganz oder gar
nicht ausgeführt wird.
•	 Consistency bedeutet, dass nach der Ausführung einer Transaktion die Datenbank konsistent
sein muss - vorausgesetzt sie war auch vorher konsistent.
•	 Isolation bedeutet, es wird verhindert, dass mehrere parallel laufende Operationen sich gegen-
seitig behindern.
•	 Durability bedeutet, dass nach einer Transaktion gewährleistet wird, dass die Daten dauerhaft
in der Datenbank abgespeichert werden.
[vgl. Rocher2009, S.295f]
Service-Klassen können unterschiedliche scopes aufweisen. Bei Bedarf kann diese Eigenschaft
angepasst werden. [vgl. Rocher2009, S.297f]
class PersonService{
	 boolean transactional = true
	 static scope = 'request'
}
Das Schlüsselwort request bedeutet hier, dass für jede Anfrage ein Service erzeugt wird.
26
controller: In dem controller Ordner werden Controller-Klassen abgelegt. Erzeugen kann man
diese mit dem Kommando grails create-controller. Controller-Klassen behandeln die
eingehenden Anfragen. Sie entscheiden wie die Anfrage verarbeitet wird und liefern ein Ergebnis
an den Anfragenden. [vgl. Rocher2009, S.65f]
class PersonController{
	 def index = {}
}
Ein Controller kann mehrere Closures beinhalten. Jeder Closure ist eine eigene Action und kann
über die URL angesteuert werden (/person/index). Der Name des Clousures (hier: index)
wird automatisch für die View verwendet (CoC). Somit wird vorausgesetzt, dass eine View mit
dem Dateinamen index.gsp existiert. Um eine individuelle View zu rendern, gibt es die Möglich-
keit diese explizit zu setzen. [vgl. Rocher2009, S.76f]
class PersonController{
	 def show = {
		 render(view:myview, model[person: Person.get(id)])
	 }
}
Die View muss hier myview.gsp lauten und das Objekt, welches an die Person übergeben wird,
lautet person.
Controller-Klassen bieten außerdem noch Aspect-Oriented-Programming (AOP) in Form von In-
terceptors. Somit kann vor oder nach einem Closure zusätzlicher Code ausgeführt werden. [vgl.
Rocher2009, S.90f]
def beforeInterceptor = {
	 log.trace("Executing action $actionName with params $params")
}
def afterInterceptor = {model->
	 log.trace("Executed action $actionName result model: $model")
}
Controller-Klassen können als Rückgabe an die View direkt auch XML oder JavaScript Object
Notation (JSON) zurückgeben. Dies wird im Zusammenhang mit Asynchronous JavaScript and
27
XML (AJAX) oder beispielsweise direkt als Webservice verwendet. Die einfachste Möglichkeit,
die Grails hier bietet, sind die grails.converters.*.
import grails.converters.XML
def person = Person.get(id)
render person as XML
import grails.converters.JSON
def person = Person.get(id)
render person as JSON
Eine weitere Funktion die Grails bietet ist das Scaffolding. Scaffolding hilft unerfahrenen Ent-
wicklern beim Start mit dem Grails-Framework. Außerdem wird es oft im Bereich des Prototyping
eingesetzt, um eine erste Version zu erstellen. Scaffolding kann in Grails dynamisch und statisch
verwendet werden. Das dynamische Scaffolding von einer CRUD-Anwendung erzeugt während
der Laufzeit die Controller Logik und die Views. Um das Scaffolding zu aktivieren, wird das At-
tribut scaffold mit der jeweiligen Domainklasse gesetzt. [vgl. Rocher2009, S.19f]
class PersonController{
	 def scaffold = Person
}
Beim statischen Scaffolding werden einmalig der Controller und die dazugehörigen Views gene-
riert. Mit dem Kommando grails generate-controller wird der Controller erzeugt. Mit
dem Kommando grails generate-views werden die dazugehörigen Views erzeugt. Möchte
man beides mit einem Kommando generieren lassen, kann das Kommando grails generate-
all verwendet werden. [vgl. Rocher2009, S.27f]
views: In dem views Ordner werden die Groovy Server Pages (GSP) abgelegt. Sie sind an die Java
Server Pages (JSP) angelehnt, haben jedoch Vorteile, die durch die Sprache Groovy mitgebracht
werden, wie beispielsweise Dynamic Dispatching und die Expression Language (EL). [vgl. Ro-
cher2009, S.107f]
In dem views Ordner liegen normalerweise weitere Unterordner, welche die gleiche Benennung
haben, wie die jeweilige Domain-Klasse. In diesen Ordnern liegen dann die GSP-Dateien.
Grails arbeitet mit SiteMesh. Das Grundlayout liegt unter views/layouts/main.gsp. In der jeweili-
gen GSP wird das Layout dann über ein meta Tag eingebunden:
28
<html>
	 <head>
		 <meta name="layout" content="main"/>
	 </head>
	 ...
</html>
Um der View Funktionalität zu verleihen und eine Trennung von Inhalt und Funktion zu erlangen,
werden Tags eingesetzt. Alle diese GSP-Tags haben ein g: vorangestellt. Grails verwendet drei
unterschiedliche Arten von Tags:
Built-in Tags sind vordefinierte Tags, die das Framework Grails bietet. Sie werden beispielsweise
als logische oder iterative Funktionalitätsmöglichkeit in der View eingesetzt. [vgl. Rocher2009,
S.111f]
<g:if test="${firstname == 'John'}">
	 Hallo ${firstname}
</g:if>
<g:each in="${persons}">
	 <p>Firstname: ${it.firstname}</p>
	 <p>Lastname: ${it.lastname}</p>
</g:each>
Dynamic Tags sind Tags, welche unterschiedliche Darstellungen annehmen können. Einerseits
können sie wie die Built-in Tags in XML Form dargestellt werden [vgl. Rocher2009, S.116f]:
<a href="<g:createLink action="list" />">
	 dynamic link
</a>
Andererseits gibt es die Möglichkeit, die gleiche Funktionalität durch einen Methoden-Aufruf zu
realisieren:
<a href="${createLink(action:'list')}">
	 dynamic link
</a>
29
Diese zweite Darstellungsmöglichkeit wird als sauberer empfunden, da die XML Tags nicht mehr-
fach ineinander verschachtelt sind.
Custom Tags sind dynamic Tags. Sie können individuell vom Entwickler programmiert werden,
um spezielle Aufgaben zu bewältigen. Sie werden in dem taglib Ordner positioniert.
taglib: Individuelle Tag-Libraries können mit dem Kommando grails create-tag-lib ge-
neriert werden. Ein einfaches Tag kann wie folgt aussehen:
class PersonTagLib{
	 def personname = {attrs, body ->
		 attrs.in?.each{
			 body(it)
		 }
	 }
}
Das zugehörige Tag in der View sieht wie folgt aus:
<g:personname in="${persons}">
	 Hallo ${it.firstname}
</g:personname>
Im lib Ordner können weiter Libraries platziert werden, die dann von der Applikation in Anspruch
genommen werden können.
Im scripts Ordner können zusätzliche Skripte hinterlegt werden. Diese können dann über das grails
Kommando ausgeführt werden.
Der src Ordner beinhaltet einen java und einen groovy Ordner. In diesen Ordnern können jeweils
Java und Groovy Code eingebunden werden. Gibt es beispielsweise bereits Businesslogik, die in Java
implementiert wurde, können die Java-Klassen hier in dem java Ordner platziert und somit von der
Grails-Applikation genutzt werden.
In dem test Ordner werden Integrationstests und Unittests platziert. Hier kann die Funktionalität der
Applikation ausgiebig getestet werden.
Der web-app Ordner beinhaltet den WEB-INF Ordner mit den Spring und SiteMesh Konfigurations-
30
dateien. Darüber hinaus sind Cascading Style Sheets (CSS), Bild und JavaScript (JS) Ordner verfüg-
bar, in denen die jeweiligen benötigten Dateien positioniert werden können.
Eine Grails Applikation ist sofort nach der Erstellung ausführbar. Mit dem Kommando grails run-
app kann der integrierte Tomcat gestartet werden. Um ein Web Application Archive (WAR) zu erstel-
len kann das Kommando grails war verwendet werden.
2.4 IDML
Dieser Abschnitt beginnt mit der Erläuterung von dem Programm InDesign. Der wesentliche Aufbau,
die Ziele und die Ideen des IDML-Formats werden anschließend beschrieben. Im letzten Abschnitt
wird eine Möglichkeit dargestellt, IDML-Dateien zu verarbeiten.
2.4.1 InDesign
InDesign ist ein Desktop-Publishing (DTP) Programm. DTP Programme ermöglichen es alle Tätigkei-
ten, die vor dem Druck einer Publikation erfolgen müssen, an einem Desktop-Computer zu erledigen.
Zu diesen Tätigkeiten gehören: Text-, Bild- und Grafikbearbeitung sowie das Zusammenstellen dieser
zu einem Layout. [vgl. Kipphan2000, S.28]
Adobe bietet im DTP-Bereich eine Sammlung an Programmen an. Diese Sammlung wird Adobe Crea-
tive Suite (CS) genannt. InDesign ist dabei ein Teil der CS und verfolgt das Hauptziel, die Typografie
und das Layout für Print, aber auch für digitale Publikationen zu erstellen.
InDesign bietet dabei sehr viele Funktionen. Das gängige Vorgehen kann in die Bereiche Dokumen-
tenerstellung, Elementplatzierung und Dokumentenausgabe eingeteilt werden [vgl. Pouryekta2011,
S.16f]:
Dokumenterstellung: Bei der Dokumenterstellung werden die grundlegenden Werte gesetzt, die
das Dokument aufweisen soll. Die relevantesten Werte sind:
•	 Die Seitenanzahl legt fest, wie viele Seiten das Dokument haben soll. Dieser Wert kann dyna-
misch später bei der Bearbeitung verändert werden.
•	 Die Doppelseiten-Funktion entscheidet, ob das Dokument doppelseitig erzeugt werden soll.
Dies ist beispielsweise bei Büchern oder Broschüren relevant.
•	 Die Seitengröße kann individuell in unterschiedlichen Einheiten festgelegt werden.
•	 Die Ausrichtung der Seite entscheidet, ob das Dokument als Hoch- oder Querformat angelegt
wird.
•	 Spalten können eine Struktur in dem Dokument erzeugen. Die Anzahl der Spalten und der
jeweilige Steg1
kann angegeben werden.
1	 Als Steg wird der Abstand zwischen den Spalten bezeichnet.
31
•	 Die Ränder können in unterschiedlichen Einheiten definiert werden.
•	 Die Beschnittzugabe ist bei Dokumenten relevant, die später in den Druck kommen. Hier kön-
nen Beschnittzugaben definiert werden, um Blitzer2
zu vermeiden.
Elementplatzierung: Ist das Dokument erstellt, können auf diesem unterschiedliche Arten von
Elementen platziert werden:
•	 Text-Elemente werden für die Textdarstellung verwendet. Hier können umfangreiche typo-
grafische Auszeichnungen vorgenommen werden und Stile auf Absatz- oder Zeichenebene
zugewiesen werden.
•	 Rechteck-Elemente können als grafische Darstellung definiert werden. Diese können bei-
spielsweise Farb-, Bild- oder Videoinhalte aufweisen.
•	 Polygon-Elemente können individuelle Formen annehmen und wie Rechteck-Elemente Inhal-
te aufweisen.
•	 Oval-Elemente sind für kreisförmige Darstellungen ausgelegt. Auch diese können wiederum
Inhalte aufweisen.
•	 Linien-Elemente können Kurven darstellen.
•	 Formfelder und Knöpfe können zur Erzeugung von Formularen verwendet werden.
•	 Gruppen fassen alle möglichen Elemente zusammen.
Dokumentenausgabe: Je nach InDesign Version gibt es unterschiedliche Ausgabemöglichkeiten.
Die grundlegenden Ausgabemöglichkeiten sind:
•	 InDesign Document Format (INDD) ist das proprietäre Dateiformat, welches von InDesign
genutzt wird. Dieses Dateiformat ist nicht abwärtskompatibel.
•	 Adobe Portable Document Format (PDF) lässt sich mit umfangreichen Einstellungsmöglich-
keiten in InDesign definieren, um bestmögliche Druck-, Web- oder interaktive PDF-Doku-
mente zu erstellen.
•	 Electronic Publication (EPUB) ist ein offener Standard für electronic books (eBook), welches
im mobilen Bereich eingesetzt wird.
•	 InDesign Markup Language (IDML) ist zum einen das Dateiformat, mit dem die Versions-
kompabilität von InDesign gewährleistet wird und zum anderen ein offenes Dateiformat, wel-
ches anders als bei INDD die Möglichkeit bietet, es lesen und somit durch Drittsysteme ver-
arbeiten zu können.
2	 Blitzer sind weiße Zwischenräume, die an den Rändern eines Dokumentes auftauchen, wenn keine Beschnitt	
	 zugabe definiert wurde.
32
2.4.2 Dateiformat
Das Dateiformat IDML wurde mit der InDesign Version CS4 eingeführt und repräsentiert ein In-
Design-Dokument als XML. Es ist ein Konstruktionsplan für InDesign-Dokumente. Wird eine IDML-
Datei in InDesign geöffnet erzeugt InDesign aus dem IDML ein INDD.
Außerdem löst IDML das InDesign Interchange Format (INX) ab und sorgt für die Versionskompatibi-
lität ab CS4. Ein wesentlicher Unterschied zu INX besteht darin, dass INX zwar auch XML basierend
ist, aber es nur maschinenlesbar und somit hauptsächlich nur für den internen Gebrauch in InDesign
verwendet wird. Die IDML-Spezifikationen hingegen sind öffentlich. Das Format kann somit verstan-
den werden. Mit IDML ist man dadurch nicht mehr an InDesign gebunden und kann IDML-Dateien
extern lesen und schreiben. [vgl. Adobe2012, S.12f]
Einige Bereiche in denen IDML eingesetzt werden kann sind [vgl. Adobe2012, S.15]:
•	 Generierung von IDML-Dokumenten oder Dokumententeilen aus einer Datenquelle.
•	 Programmatische Wiederverwendung von IDML-Elementen.
•	 Transformierung über Extensible Stylesheet Language Transformation (XSLT).
•	 Auffinden von Inhalten über XML Path Language (XPath) oder XML Query Language (XQuery).
•	 Validierungs- und Vergleichsmöglichkeit von Inhalten über unterschiedliche Versionen von Doku-
menten.
Die Ziele, die IDML nach der Spezifikation verfolgt, sind folgende [vgl. Adobe2012, S.15f]:
Vollständigkeit: Alle Elemente, die in InDesign erzeugt werden können, sollen in IDML darge-
stellt werden. Dabei ist darauf hinzuweisen, dass es rein um die Darstellung einer INDD als IDML
geht. IDML liefert keine Funktionen, die in InDesign verfügbar sind.
Lesbarkeit: IDML hat den Anspruch menschenlesbar und verständlich zu sein. Jemand der den
grundlegenden Umgang mit InDesign kennt, soll sich im IDML-Dokument zurecht finden können.
Verarbeitung: IDML-Dokumente sollen durch externe Applikationen gelesen und geschrieben
werden können.
Robustheit: Das IDML-Format soll robust sein. Das bedeutet Fehler in einem IDML-Dokument
sollten keine schwerwiegenden Auswirkungen haben. Das Regular Language Description for
XML New Generation (RNG) Schema definiert den Aufbau einer IDML und bietet somit Validie-
rungsmöglichkeiten, um grobe Fehler in IDML zu vermeiden.
33
Rückwärtskompatibilität: Die Rückwärtskompatibilität zu einer Vorgängerversion soll durch
IDML gewähleistet werden.
Performanz: Die Performanz von INX-Dateien soll durch IDML übersteigern.
Verbesserungen gegenüber INX: IDML soll eine Verbesserung gegenüber INX sein. Es ist zum
einen ein offenes Format und beinhaltet keine unklaren Elemente wie bei INX. Zum anderen ver-
wendet es ein Schema zur Validierung und hat keine Prozessanweisungen mehr in Textbereichen.
Das IDML-Format ist ein Containerformat. Es beinhaltet mehrere XML-Dateien, welche das In-
Design-Dokument beschreiben. Dieses Containerformat ist ein Universal Container Format (UCF).
Es ist grundlegend ein ZIP-Archiv mit speziellen Bedingungen, die beispielsweise Kompression und
Encoding betreffen. [vgl. Adobe2012, S.394f]
Der Aufbau des IDML Formats sieht wie folgt aus:
Abb. 7 IDML Container Aufbau [Adobe2012, S.20]
34
Multipurpose Internet Mail Extensions Type (MIMETYPE): Diese Datei beschreib den Datei-
typ. Bei IDML sieht der Inhalt wie folgt aus [vgl. Adobe2012, S.399f]:
application/vnd.adobe.indesign-idml-package
designmap.xml: Diese XML ist das Rückgrad der IDML-Datei. Alle weiteren Dateien in der
IDML werden von ihr referenziert. Außerdem sind die Reihenfolge und Beziehungen, die in dieser
XML aufgeführt sind wesentlich. [vgl. Adobe2012, S.44f]
MasterSpreads: MasterSpreads sind Vorlagen für einen Druckbogen. Hier kann der Druckbogen
(Spread) vordefiniert werden. Die MasterSpreads liegen in dem MasterSpread Ordner. Die Mas-
terspread.xml Dateien definieren den MasterSpread und können Elemente (PageItem) beinhalten,
die auf der MasterSpread positioniert werden. [vgl. Adobe2012, S.87] Die Benennung der IDML-
Komponenten folgt einem festen Schema, welche in den Spezifikationen zu finden ist. [vgl. Ado-
be2012, S.23f]
Resources: Dieser Ordner beinhaltet vier XML-Dateien, die Vorgaben und Einstellungen des In-
Design Dokumentes repräsentieren [vgl. Adobe2012, S.21]:
•	 Die Graphic.xml definiert beispielsweise Farben (Color), Rahmenstile (StrokeStyle) und Ver-
läufe (Gradients), die in dem InDesign-Dokument definiert wurden. Auf diese Definitionen
kann referenziert werden. [vgl. Adobe2012, S.263f]
•	 Die Fonts.xml definiert Defaultschriften und alle Schriften, die in dem InDesign-Dokument
verwendet werden. [vgl. Adobe2012, S.259f]
•	 Die Styles.xml definiert alle Stile, die in dem InDesign-Dokument definiert werden. Dazu
zählen: paragraph, character, object, cell, table und table of contens styles. [vgl. Adobe2012,
S.345f]
•	 Die Preferences.xml definiert Grundeinstellungen und Darstellungsmöglichkeiten des Doku-
mentes in InDesign. Es hat keine Auswirkungen auf das Dokument selbst. [vgl. Adobe2012,
S.281f]
Spreads: Spreads sind Druckbögen. Der Spread Ordner hält alle Spreads, die in dem InDesign-
Dokument definiert werden als Spread.xml Datei. Ein Spread kann mehrere Seiten (Page) bein-
halten. Auf einem Spread können PageItems platziert werden. [vgl. Adobe2012, S.87f] Die Be-
nennung der IDML Komponenten folgt einem festen Schema, welches in den Spezifikationen zu
finden ist. [vgl. Adobe2012, S.23f]
Stories: Stories definieren den Textinhalt eines Dokumentes. Der Stories Ordner hält alle Stories,
35
die in dem InDesign Dokument definiert werden als Story.xml. Diese Stories beinhalten den Text,
die zugehörigen Stile und eine Referenz auf den zugehörigen Textrahmen (TextFrame). [vgl. Ado-
be2012, S.163f] Die Benennung der IDML-Komponenten folgt einem festen Schema, welches in
den Spezifikationen zu finden ist. [vgl. Adobe2012, S.23f]
XML: Der XML-Ordner beinhaltet drei weitere XML-Dateien, die für speziellere Aufgaben ver-
wendet werden [vgl. Adobe2012, S.22f]:
•	 Die BackingStory.xml definiert Inhalte, die noch keinem PageItem zugeordnet wurden.
•	 Die Tags.xml definiert alle Tags, die in InDesign mit der Tagfunktion erstellt wurden.
•	 Die Mapping.xml definiert die Beziehungen zwischen Tag und Styles.
META-INF: Dieser Ordner hält einmal die container.xml Datei. Diese ist notwendig für den UCF
Standard und referenziert auf die designmap.xml. Zum anderen metadata.xml welche beispiels-
weise Extensible Metadata Platform (XMP) und Resource Description Framework (RDF) Inhalte
definieren. [vgl. Adobe2012, S.401f]
2.4.3 IDMLlib
Die IDMLlib ist eine Java Library, die es ermöglicht IDML-Dokumente zu lesen und zu schrei-
ben. Ein weiteres Ziel der Library ist es, die Komplexität des IDML-Formates zu reduzieren und
eine Schnittstelle zu bieten, mit der es möglich ist IDML-Dokumente zu verarbeiten. IDMLlib kann
IDML-Dokumente und InDesign Snippets (IDMS) verarbeiten. Des Weiteren bietet die IDMLlib [vgl.
IDMLlib2013]:
•	 Ein Java Objektmodell
•	 Automatische Typ Konvertierung von XML nach Java
•	 Spezielle Klasse für die IDML-Elemente
•	 Lazy loading Mechanismus
•	 Polyglot Programming3
(Groovy, JRuby, Scala etc.)
•	 Vollen Zugriff auf die IDML-Elemente
•	 Kapselung der XML und somit keine notwendige XML Erfahrung
Die IDMLlib läuft auf den Betriebssystemen Windows, Linux und Mac OS. Vorausgesetzt wird das
JDK 5. Außerdem ist die IDMLlib unabhängig von InDesign. Somit lassen sich Workflows konzipie-
ren, die Automatisierungsaufgaben außerhalb von InDesign ersetzen und diese flexibler und perfor-
manter umsetzen können.
3	 Polyglot bedeutet mehrsprachig. In diesem Zusammenhang ist der Zugriff von anderen Sprachen auf die 		
	 IDMLlib gemeint.
36
Einige Einsatzmöglichkeiten werden auf der IDMLlib Webseite genannt [vgl. IDMLlib2013]:
•	 Individuelle Validierung von Dokumenten.
•	 Vorbereiten von InDesign-Dokumenten für InDesign.
•	 Publizieren von Inhalten, die aus InDesign-Dokumenten ausgelesen werden.
•	 Qualitätssicherung durch Validierung und Vergleichen von Dokumenten.
•	 Übersetzungsworkflows für mehrsprachige Dokumente.
•	 Einbinden von InDesign-Dokumenten in Drittsysteme.
37
3 Umsetzung
Dieses Kapitel beschäftigt sich mit der Umsetzung des IDML-Servers. Nachdem in Kapitel 2 die
Grundlagen betrachtet wurde, wird zunächst auf das Konzept des IDML-Servers eingegangen. Im
Kapitel 3.2 erfolgt darauf die praktische Umsetzung, welche die Realisierung des Konzepts bestätigen
soll. Sowohl das Konzept, als auch die praktische Umsetzung bauen auf den vorherigen Grundlagen-
kapitel auf.
3.1 Konzept
Das Konzept beginnt mit den Anforderungen an den IDML-Server. Hier wird festgelegt, welche As-
pekte für das System relevant sind. Darauf folgt die Systemarchitektur, welche maßgeblich durch die
eingesetzten Frameworks definiert wird. Ferner werden Entwurfsentscheidungen hier festgelegt und
beschrieben. Im Anschluss darauf wird der Webservice definiert, der beim IDML-Server zum Einsatz
kommt. Im letzten Abschnitt werden die Funktionsweise und der Aufbau der Process-Engine definiert.
Diese Punkte zusammen dienen als Basis für die praktische Umsetzung.
3.1.1 Anforderungen
Das Konzept eines Systems, welches IDML-Dokumente verarbeiten kann, hat folgende Anforderun-
gen:
Verarbeitung: Das System soll in der Lage sein, IDML-Dateien verarbeiten zu können.
Vereinfachung: Das System soll den Umgang mit IDML vereinfachen. Da das IDML-Format
sehr komplex aufgebaut ist, soll das System diese Komplexität kapseln und über leicht verständli-
che Funktionen verfügbar machen.
Einbindung: Das System soll in bestehende Workflows integriert werden sowie Prozesse verein-
fachen und automatisieren können.
Erweiterbarkeit: Das System soll erweiterbar sein, um zukünftigen Anforderungen gerecht wer-
den zu können.
3.1.2 Systemarchitektur
Die Systemarchitektur ergibt sich in erster Linie aus den Anforderungen. Eines der Ziele des Systems
ist die Einbindung in bestehende Workflows. Da im Druck- und Medien-Bereich Workflowsysteme oft
als zentrales Serversystem vorliegen, wird hier das Konzept eines IDML-Servers gewählt. Folgende
Vor- und Nachteile ergeben sich bei dem Einsatz eines Servers:
38
Vorteile
•	 Ein Server ist generell ein zentrales System und kann in Workflows integriert werden. In einem
Workflow können so Probleme schneller erkannt werden, da es eine klare Aufgabenverteilung gibt
und so deutlich wird, welcher Server für welche Aufgaben verantwortlich ist.
•	 Die Datensicherung ist bei einem zentralen Server einfacher zu handhaben, da die Daten an einem
Ort einheitlich gesichert werden können.
•	 Server können in bestehende Workflows über Schnittstellen eingebunden werden.
•	 Eine Cloudversion eines Servers ist möglich.
Nachteile
•	 Initialkosten eines Serversystems sind oft höher als bei Desktopsystemen, da die technische Kom-
plexität höher liegt.
•	 Single Point of Failure
Der Server ist ein System zur Verarbeitung von IDML-Dateien und wird in drei Bereiche unterteilt:
Eingabe, Verarbeitung und Ausgabe (EVA-Prinzip). Der Ein- und Ausgabe Bereich wird dabei über
den Komponente Webservice realisiert. Der Verarbeitungsbereich wird über die Komponente Process-
Engine realisiert.
Abb. 8 IDML-Server
Anfragen an den Server über den Webservice erfolgen über HTTP (üblicherweise wird HTTP/Port 80
für Webservices gewählt, da Firewalls den Port 80 normalerweise nicht blockieren. Es kann jedoch
auch ein anderer Port definiert werden.). Die Anfragen sind in Form von Parametern oder Dateien zu
definieren. Der Webservice nimmt die Anfrage entgegen und leitet diese weiter an die Process-Engine.
Die Process-Engine ist für die Ausführung von vordefinierten Abläufen zuständig. Diese führt die
nötigen Funktionen aus und liefert ein Ergebnis. Das Ergebnis wird wieder zurück an den Webservice
geleitet, der die Daten als Antwort in Form von XML (üblicherweise wird XML verwendet. Es können
jedoch auch andere Formate verwendet werden, wie zum Beispiel JSON.) an den Anfragenden wieder
zurück sendet.
IDML-Server
Webservice Process-Engine
IDML, Parameter
IDML, XML
39
Der Server ist nach dem MVC-Muster und dem Schichtenmuster aufgebaut. Dabei ist das Model im
Bereich der Process-Engine anzuordnen. Dieser ist zuständig für die Verarbeitung der Daten. Die View
und der Controller sind im Bereich des Webservices einzuordnen. Die View ist hier die Darstellung der
Ergebnisse in Form von XML. Der Controller nimmt die Anfrage entgegen und ist dafür zuständig, die
Daten in der View darzustellen.
Das Schichtenmuster wird in mehreren Bereichen angewendet. Einmal ist der Server im Kontext eines
Workflows zu betrachten. Dabei ist der IDML-Server eine Komponente des Workflows (eine Schicht)
mit einer klaren Aufgabenstellung. Der IDML-Server hat das Ziel, die Komplexität des IDML-Forma-
tes zu kapseln. Deswegen wird der IDML-Server weiter in die Komponenten (Schichten) Webservice
und Process-Engine unterteilt. Auch diese Komponenten haben wieder eine klare Aufgabenstellung.
Zuletzt ist der IDML-Server aus Entwicklersicht zu betrachten, in dem Programmteile in Schichten
unterteilt werden, um wieder Aufgabenbereiche klar zu definieren.
Die konkrete Implementierung des Systems basiert auf Industriestandards, die sich im Laufe der Zeit
bewiesen haben. Das gewählte Framework für die Implementierung ist das Grails-Framework. Die
darunterliegenden Technologien, wie beispielsweise Spring-Framework, Groovy, Java und IDMLlib,
gewährleisten, dass die Anforderungen an das System erfüllt werden. Java und das Spring-Framework
liefern dabei eine sehr große Anzahl an erprobten Libraries, die in unterschiedlichsten Bereichen der
Softwareentwicklung eingesetzt werden können. Außerdem bietet Java Plattformunabhängigkeit so-
wie sichere und robuste Funktionen auf die das Grails-Framework und damit der IDML-Server auf-
baut. Die Sprache Groovy bringt durch ihre Eigenschaften, der dynamischen Typisierung und der
Skriptfähigkeit der Sprache starke Vorteile in den Bereichen der Flexibilität eines Systems. Des Weite-
ren liefert der Einsatz des Grails-Frameworks vor allem Vorteile in den Bereichen Prototyping und der
Erweiterbarkeit eines Systems durch Grails-Plugins. Diese können zu einer Grails-Web-Applikation
entwickelt und installiert werden. Außerdem bietet das Grails-Framework die Möglichkeit, Java-Klas-
sen und Libraries in das System einzubinden. Im Fall des IDML-Servers wird dies mit dem Einsatz
der IDMLlib in Anspruch genommen. Die IDMLlib ist im Kontext des IDML-Servers dafür zuständig,
die Komplexität des IDML Formats zu kapseln und Zugang und Verarbeitung von IDML-Dateien zu
gewähren.
3.1.3 Webservice
Der Webservice des IDML-Servers muss die Anforderungen wie Vereinfachung, Einbindung und Er-
weiterbarkeit erfüllen.
In erster Linie sollte der Webservice selbsterklärend und einfach zu bedienen sein. Hier ist die Wahl
auf eine XML basierende REST-Schnittstelle gefallen, statt auf eine SOAP-Schnittstelle, da REST
über das Grails-Framework auf einfachem Weg zu implementieren ist. SOAP hingegen ist bei der
Implementierung des Webservices oftmals komplexer umzusetzen als REST. Die Wahl XML zu ver-
wenden beruht auch darauf, dass die meisten Webservice-Schnittstellen XML basierend sind und das
Einbinden der Schnittstelle auch für Dritte möglichst einfach gestaltet werden soll. Alternative zu
40
XML wäre hier JSON. JSON hat im Vergleich zu XML eine einfachere Syntax. Diese ist kürzer und
minimalistischer ausgelegt. Für eine Weiterentwicklung des IDML-Servers kann eine JSON/REST
Schnittstelle auch über das Grails-Framework auf einfachem Weg implementiert werden.
Die Einbindung des IDML-Servers in bestehende Workflows erfolgt durch die REST-Schnittstelle. Die
Bedienung der REST-Schnittstelle ist im Vergleich zu SOAP einfacher umzusetzten. Der Hauptgrund
dafür ist, das REST keine festgelegte Norm ist und somit flexibler gestaltet werden kann. Außerdem
entfällt im Vergleich zu SOAP ein XML-Overhead, da REST beispielsweise kein WSDL benötigt.
Die Erweiterbarkeit der REST-Schnittstelle wird über eine Parameter-Liste gewährleistet. Diese be-
steht aus einer Anzahl fest definierter Parameter, die für eine spezielle Anfrage notwendig sind und
einer flexiblen Anzahl an Parametern, die individuell je nach Anforderung definiert werden können.
Der Webservice behandelt drei Arten von Anfragen:
Upload: Die Uploadanfrage ist zuständig für den Upload von Dateien, wobei der Webservice eine
Erfolgs- oder Fehlermeldung als Ergebnis zurückgibt.
Aktion: Eine Aktionsanfrage beinhaltet keine Binärdaten. Hier wird über die Anfrage mit spe-
ziellen Parametern eine bestimmte Aktion ausgeführt, die eine Erfolgs- oder Fehlermeldung als
Ergebnis zurückgibt.
Download: Eine Downloadanfrage liefert Binärdaten. Bei einem Fehler wird eine Fehlermeldung
als Ergebnis geliefert.
Da der Server von mehreren Akteuren bedient wird, soll das Konzept einer Session im IDML-Server
implementiert. Diese garantiert, dass ein Akteur in seinem eigenen Kontext arbeitet und keine Daten
anderer Akteuere manipuliert. Ein möglicher Ablauf könnte wie folgt aussehen:
1.	 Erzeugung einer Session und eines Universally Unique Identifier (UUID). Diese ID muss bei allen
weiteren Aktionen immer mitgegeben werden.
2.	 Upload von Dateien
3.	 Anstoß eines Verarbeitungsprozess
4.	 Download der Ergebnisse des Verarbeitungsprozess
5.	 Beendigung der Session
Abb. 9 Workflow Ablauf
Session
Erzeugung
Verarbeitung
Session
Beendigung
Datei
Upload
Datei
Download
41
3.1.4 Process-Engine
Um zu verstehen, wie die Process-Engine aufgebaut ist, wird anhand des Ablaufs (Abb.9) jeder Schritt
beschrieben:
Session Erzeugung: Bei der Session-Erzeugung über den Webservice wird als erstes in der Pro-
cess-Engine eine UUID erzeugt. Diese UUID wird benötigt, um einen Sessionordner zu erzeugen,
in dem die Session dann für den weiteren Ablauf behandelt wird. In diesem Sessionordner werden
drei weitere Ordner erzeugt. Der erste ist ein Inputordner, welcher für die eingehenden Dateien
zuständig ist. Der zweite ist ein Outputordner, in dem die Ergebnisdateien der Verarbeitung plat-
ziert werden. Der dritte Ordner ist ein Temporaryordner, in dem Dateien platziert werden können,
die beispielsweise im Verarbeitungsprozess abgelegt werden müssen. Das Ergebnis der Session-
Erzeugung ist im günstigsten Fall eine Erfolgsmeldung. Dabei wird eine XML zurückgesendet,
welche die UUID enthält.
Datei Upload: Ist die Session erzeugt, können Dateien hochgeladen werden. Zwingend notwendig
ist dabei das Angeben der UUID. Anhand der UUID kann entschieden werden, in welchem Sessio-
nordner die Datei abgelegt wird. Alle hochgeladenen Dateien landen immer in dem Inputordner.
Das Ergebnis eines erfolgreichen Uploads ist wiederum eine XML, welche die UUID enthält.
Verarbeitung: Bei der Verarbeitung stellt sich die Frage, wie die Daten genau verarbeitet werden
sollen. Um dieses Problem möglichst flexibel zu gestalten, wird ein Workflowordner in dem Sys-
tem definiert. In diesem Ordner können weitere Ordner platziert werden. Diese Ordner repräsentie-
ren einen Workflow. In dem Ordner können individuelle Groovy-Skripte abgelegt werden und alle
nötigen Dateien, die für diesen Workflow benötigt werden. Die Gruppierung der Groovy-Skripte
in Workflows hat den Sinn, das System überschaulich und strukturiert verwalten zu können. Der
Workflow und das jeweilige Groovy-Skript kann über den Webservice anhand von definierten
Paramterern angesteuert und somit ausgeführt werden. Die Ausführung selber erfolgt dann in dem
Sessionordner, wobei die Dateien aus dem Inputordner für die Ausführung verwendet werden und
das Binär Ergebnis der Verarbeitung in dem Outputordner platziert wird. Das Groovy-Skript kann
dabei auf alle Libraries zugreifen, die im System verfügbar sind und somit jede Art von Dateien
verarbeiten. Es ist somit also nicht nur beschränkt auf IDML-Dateien, sondern kann beispielswei-
se auch XML verarbeiten. Das Ergebnis der Webservice-Anfrage ist wiederrum XML und besitzt
eine Anzahl an fest definierten Werten, die das System mitliefert, sowie einen frei gestaltbaren
Bereich, der in dem ausgeführten Groovy-Skript gesetzt werden kann.
Datei Download: Ist die Verarbeitung abgeschlossen und wurden dabei Binärdaten erzeugt, findet
man diese in dem Outputordner. Um nun Zugang auf die Dateien zu ermöglichen, kann der Out-
putordner heruntergeladen werden. Dabei wird der ganze Outputordner in ein ZIP-Format gepackt
42
und über den Webservice zur Verfügung gestellt.
Session Beendigung: Nachdem alle Prozesse abgearbeitet wurden muss die Session nun auch
beendet werden. Dies kann über den Webservice angestoßen werden. Die Process-Engine löscht
durch den Anstoß über den Webservice den Sessionordner und alle enthalteten Informationen.
Sollte die Session nicht über den Webservice beendet werden existiert zusätzlich ein Task, der
zeitgesteuert über die bestehenden Sessionordner iteriert und kontrolliert, ob der Sessionordner
eine festgelegte Zeit überschritten hat. Ist dies der Fall, wird der Sessionordner gelöscht. Dadurch
können Sessions beendet werden, die beispielsweise versehentlich vergessen wurden beendet zu
werden.
3.2 Praktische Umsetzung
Um das Konzept (Kapitel 3.1) zu bestätigen und produktive Einsatzszenarien durchspielen zu können,
wird ein Prototyp entwickelt. Dieser hat keinen Anspruch auf Vollständigkeit und kann Fehler beinhal-
ten. Zunächst wird auf die Systemanforderungen eingegangen, die notwendig sind für den Prototypen.
Im nächsten Schritt wird detailliert die Funktionsweise des Prototyps beschrieben. Zum Schluss sind
die produktiven Einsatzszenarien relevant, die über die Groovy-Skripts implementiert werden.
3.2.1 Systemanforderungen
Die Systemanforderungen liegen zunächst im technischen Bereich. Als Betriebsystem sind Windows,
Linux oder Mac OS X zu empfehlen. Der Prototyp wird auf einem Mac OS X 10.7.5 entwickelt und
getestet. Auf dem jeweiligen Betriebsystem muss eine Java 6 Version installiert sein. Außerdem ist für
den Prototyp ein Tomcat notwendig. Zu empfehlen ist der Tomcat 6.0.32. Der zugewiesene Speicher
sollte mit 512 Megabyte generell ausreichen. Je nach Last und Größe der zu verarbeitenden Daten
kann der Wert variieren und sollte angepasst werden. Die verwendete Grails Version liegt bei 2.1.0 und
die IDMLlib Version bei 1.1.5. Die IDML-Daten, die in das System einfließen, sollten von InDesign
CS4 erzeugt worden sein und der Document Object Model (DOM) Version 6.0 entsprechen.
Weitere wesentliche Anforderungen ergeben sich durch die auszuführenden Groovy-Skripte, die nicht
direkt Teil des Servers sind, sondern individuell je nach Einsatzgebiet gestaltet werden können. Hier
ist vor allem das Verständnis für die Sprache Groovy und das IDML-Format notwendig, um diese
Groovy-Skripte erstellen zu können.
3.2.2 Prototyp
Der Prototyp orientiert sich an dem Konzept des IDML-Servers. Die Architektur des Prototyps beruht
somit auf der vorgegebenen Grails Architektur.
Der IDML-Server kann über das Kommando grails run-app gestartet werden. Ist die Applikation
gestartet kann sie unter http://localhost:8080/IDML-Server betrachtet werden. Dabei wird
43
im Browser die Standard Index Seite dargestellt:
Abb. 10 IDML-Server Index Seite
Diese zeigt den Status der Applikation, die installierten Plugins und die Controller, die das System zur
Verfügung stellt. Bei genauer Betrachtung erkennt man in den Plugins auch den Tomcat Server, der mit
dem Kommando grails run-app gestartet wird.
Um den IDML-Server detailliert zu durchleuchten, werden alle Prozesse des Workflow Diagramms
(Abb.9) wiederum durchlaufen:
Session Erzeugung: Die Session-Erzeugung wird über den ProcessController angestoßen.
Klickt man über die Index Seite auf den ProcessController wird dabei die URL http://lo-
calhost:8080/IDML-Server/process/index aufgerufen. Der URL Teil process deutet
auf den Controller hin, der hier angesprochen wird. Der URL Teil index deutet auf die Action hin,
die ausgeführt werden soll. Dieses Verhalten der Controller ist einheitlich gelöst und vereinfacht
den Umgang mit dem System. Dieser URLAufbau ist standardmäßig von dem Grails-Framework
vorgegeben kann aber bei Bedarf unter config/UrlMappings.groovy angepasst werden:
44
static mappings = {
	 ʺ/$controller/$action?/$id?"{
		 constraints {
			 // apply constraints here
		 }
	 }
	 "/"(view:"/index")
	 "500"(view:'/error')
}
Die Action in dem ProcessController sieht dabei wie folgt aus:
def index() {}
Diese Action ist sehr einfach gehalten. Was hier passiert ist, der Einsatz von CoC. Über die Be-
nennung der Action wird automatisch auf die zugehörige gleichnamige GSP-Seite verwiesen und
diese als Antwort auf die Anfrage zurückgegeben:
Abb. 11 IDML-Server Process Index Seite
Die GSP-Seiten dienen lediglich zur optischen Darstellung für den Entwickler oder Benutzer, der
den Webservice manuell testen möchte. Ein späterer produktiver Einsatz erfolg direkt über die
URLs.
Um eine Session zu erzeugen, kann die zugehörige URL http://localhost:8080/IDML-
Server/process/createSession aufgerufen werden. Diese spricht folgende Action im
ProcessController an:
45
def createSession(){
def result = processService.createSession()
render result as XML
}
Hier wird die Funktion createSession() des ProcessServices angesprochen. Der Service
wird getrennt vom Controller in einer eigenen Schicht untergebracht, um eine klare Aufgabenver-
teilung zu haben. Die Serviceklassen sind im MVC-Muster im Bereich des Model anzuordnen.
Die createSession() Methode des ProcessServices sieht wie folgt aus:
def createSession() {
def id = UUID.randomUUID()
fileStructureService.createSessionStructure(id)
def result = [:]
result.put("type", "success")
result.put("id", id.toString())
return result
}
Hier wird dafür gesorgt, dass die Session ID und alle notwendigen Strukturen erzeugt werden.
Als erstes wird eine zufällige UUID generiert. Anhand dieser UUID wird über den FileStruc-
tureService die Funktion createSessionStructure(id)aufgerufen. Diese ist dafür ver-
antwortlich die lokale Ordnerstruktur zu erzeugen, in der später dann die Verarbeitung stattfindet:
def createSessionStructure(id) {
new File(getInPath(id)).mkdirs()
new File(getOutPath(id)).mkdirs()
new File(getTmpPath(id)).mkdirs()
}
Das Erzeugen der Pfade wird in weitere Funktionen ausgelagert. Hier wird nur die Funktion ge-
tInPath() betrachtet, da alle anderen sehr ähnliche Funktionsweisen aufweisen. Diese Funktion
baut den Inputordner Pfad anhand konfigurierter Eigenschaften, die in der config.properties ge-
setzt werden, auf. Um auf diese Eigenschaften zugreifen zu können, bietet das Grails-Framework
das Interface GrailsApplication. Über diese kann dann direkt auf die config.properties und
die darin konfigurierten Werte zugegriffen werden (grailsApplication.config...):
46
def getInPath(id) {
	 getWorkPath() + id + File.separator + grailsApplication.config.idml.	
	 server.local.work.in.folder.name + File.separator
}
In der config.properties ist somit folgender Name für den Inputordner definiert:
idml.server.local.work.in.folder.name=in
Die config.properties Datei ist dabei eine extern verwaltete Konfigurationsdatei. Diese liegt nor-
malerweise außerhalb der Applikation. Der Grund für die externe Verwaltung ist, dass sich bei
Updates oder Bugfixes eines Systems oft die Konfiguration gar nicht ändert. Anstatt jedes Mal
erneut die Applikation zu konfigurieren, kann so nur die Applikation ausgetauscht und die Konfi-
guration beibehalten werden. Die config.properties muss eingebunden werden, damit das System
auch Zugriff auf die Daten hat. Dies erfolgt über die JVM option -Didmlserver.config.loca-
tion=/path/to/config.properties. Wie diese JVM option benannt ist, wird in der config/
config.groovy definiert:
grails.config.locations = []
if(System.properties["idmlserver.config.location"]) {
	 grails.config.locations << "file:" + System.properties["idmlserver.		
	 config.location"]
}
Sind die Pfade und alle notwendigen Ordner erzeugt, wird in der createSession() Funktion
ein Ergebnis erstellt. Dieses Ergebnis ist vom Typ Map und beinhaltet einen type und die UUID.
Die Wahl, das Ergebnis als eine Map zu realisieren, hat den Grund, dass eine Map dynamisch er-
weiterbar ist und der Zugriff auf die Werte sehr einfach über Schlüsselwörter erfolgen kann. Einer
dieser Schlüsselwörter ist type. Dieser ist dafür zuständig zu unterscheiden, ob das Ergebnis ein
erfolgreiches oder ein fehlgeschlagenes Ergebnis ist.
Ist das Ergebnis erzeugt, wird es zurück an den Controller gegeben, der nichts anderes macht als
diese Map als XML zu rendern (render result as XML).
Das XML Ergebnis was zurückgegeben wird sieht wie folgt aus:
<map>
	 <entry key="type">success</entry>
	 <entry key="id">764c7d8e-c276-4ef2-be2f-45b00fda0868</entry>
</map>
47
Das Wichtigste an diesem Ergebnis ist die ID. Diese muss während des ganzen Prozesses mitge-
liefert werden. Sie sorgt für die eindeutige Identifizierung der Session.
Datei Upload: Nachdem die Session erzeugt wurde, kann nun eine Datei in das System hochge-
laden werden. Dies erfolgt über den UploadController. Der UploadController enthält die
Funktion upload(). Diese kann über die URL http://localhost:8080/IDML-Server/
upload/upload angesteuert werden. Dabei werden die Parameter id und file für einen erfolg-
reichen Upload benötigt:
def upload() {
def id = params.id
def result = [:]
if (id) {
result = uploadService.uploadFile(id, request.getFile("file"))
} else {
def errormessage = "error: ID does not exists!"
result.put("type", "error")
result.put("errormessage", errormessage)
}
render result as XML
}
Sind diese Parameter verfügbar, wird die Datei über den UploadService mit der Funktion
uploadFile(id, file) in das System hochgeladen:
def uploadFile(id, file) {
	def targetDirPath = fileStructureService.getInPath(id)
	def targetPath = targetDirPath + File.separator + file.originalFile	
	 name
	def uploadedFile = new File(targetPath)
	file.transferTo(uploadedFile)
	def result = [:]
	result.put("type", "success")
	result.put("id", id.toString())
	return result
}
Dabei wird als erstes der Pfad zum Inputordner der jeweiligen Session zusammengebaut, an
48
dem die Datei platziert werden soll. Dies geschieht wiederum in einer speziellen Service-Klasse
(FileStructureService) die diese Art von Aufgabenstellung übernimmt. Anschließend wird
die Datei hochgeladen und ein Ergebnis vom Typ Map erzeugt, der wiederum die UUID und einen
type enthält. Wird im UploadController keine UUID als Parameter übergeben, wird sofort
ein Ergebnis mit einer Fehlermeldung erzeugt. In beiden Fällen wird die Map vom Controller in
XML gewandelt und zurückgegeben. Die XML sieht bei einem erfolgreichen Upload wie folgt
aus:
<map>
	 <entry key="type">success</entry>
	 <entry key="id">764c7d8e-c276-4ef2-be2f-45b00fda0868</entry>
</map>
Verarbeitung: Ist der Upload der Daten abgeschlossen, kann nun mit dem Verarbeitungsprozess
begonnen werden. Zum Anstoßen einer Verarbeitung wird der ProcessController verwendet.
Dieser enthält die Action execute():
def execute() {
	 def result = processService.executeScript(params?.script, params?.	
	 workflow, params?.id, params)
	 render result as XML
}
Die Action greift auf den ProcessService zu und führt die executeScript() Funktion aus.
Das Ergebnis wird als XML wieder zurückgegeben. Die executeScript() Funktion erwartet
mindestens drei Parameter. Der erste Parameter ist der Skript-Parameter. Dieser identifiziert das
Groovy-Skript, das ausgeführt werden soll. Auch hier wird wieder CoC angewendet, um mög-
lichst einheitlich und einfach die Verarbeitung anzustoßen. Der zweite Parameter ist der Work-
flow-Parameter. Dieser definiert den Workflow, der angestoßen wird. Die Groovy-Skripte sind in
mehrere Workflows gruppiert. Dadurch können dieselben Skripte in unterschiedlichen Workflows
verwendet werden. Die Gruppierung der Skripte in Workflows dient vor allem der Strukturierung
der Skripte. Der dritte Parameter ist der UUID Parameter. Hier wird die UUID der Session erwar-
tet. Durch diese UUID kann die Session identifiziert werden. In dem Kontext der Session wird
dann das Skript ausgeführt. Als letztes erwartet die Funktion das ganze Parameter-Objekt. Dieses
Parameter-Objekt enthält alle Parameter, die übergeben wurden. Dies bietet die Möglichkeit, wei-
tere individuelle Parameter mitzugeben, die unter Umständen in dem Skript benötigt werden.
Die programmatische Ausführung sieht wie folgt aus:
49
def executeScript(script, workflow, id, Map<String, String> params) {
def result = [:]
def binding = handleParams(params, id)
String[] roots = getRoots()
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
def scriptPath = fileStructureService.getScriptPath(workflow, script)
def scriptFile = new File(scriptPath)
if (scriptFile.exists()) {
result = gse.run(scriptPath, binding);
result.put("type", "success")
} else {
def errormessage = "error: script does not exists!"
result.put("type", "error")
result.put("errormessage", errormessage)
log.error(scriptFile.getAbsolutePath() + ", " + errormessage)
}
result.put("workflow", workflow)
result.put("script", script)
result.put("id", id.toString())
return result
}
Zunächst werden durch die Funktion handleParams() alle Parameter und Werte, die übergeben
werden in ein Binding platziert:
def handleParams(Map<String, String> params, id) {
Binding binding = new Binding();
params.keySet().each {key ->
binding.setVariable(key, params.get(key));
}
binding.setVariable("inPath", fileStructureService.getInPath(id))
binding.setVariable("outPath", fileStructureService.getOutPath(id))
return binding
}
Durch das Binding hat das auszuführende Skript später Zugriff auf die jeweiligen Parameter und
kann somit alle nötigen Informationen verwerten. Außerdem werden der Inputordner Pfad und der
Outputordner Pfad für die nötigen Zugriffe in das Binding gesetzt. Ist das Binding gesetzt, gibt
50
es zusätzlich noch die Möglichkeit Zugriff auf weitere Ressourcen zu nehmen. Über die getRo-
ots() Funktion können weitere Klassenpfade (Classpath) in die Ausführung mit eingebunden
werden. Diese Klassenpfade können URLs oder lokale Pfade sein, die über die config.properties
Datei gesetzt werden können.
String[] getRoots() {
	 def commaRoots = grailsApplication.config.idml.server.groovy.script.	
	 engine.roots
	 def roots = commaRoots.split(",")
	 return roots
}
Als nächstes wird das GroovyScriptEngine Objekt mit den optionalen Klassenpfaden erzeugt.
Dieses Objekt ist für die Ausführung des Skripts verantwortlich. Welches Skript ausgeführt wer-
den soll, wird über den workflow und den script Parameter entschieden. Der FileStructure-
Service sorgt dafür, dass der richtige Pfad des Skripts erzeugt wird. Ist das Skript verfügbar, wird
das Groovy-Skript mit den jeweiligen Bindings ausgeführt. Das Ergebnis der Skriptausführung
muss eine Map sein. Diese Map kann in den Skripten dann mit den Ergebniswerten befüllt werden,
die für das jeweilige Szenario relevant sind. Somit hat der Entwickler des Skripts eigenständig
die Möglichkeit zu entscheiden, was als Ergebnis angezeigt werden soll. Zu dieser Map wird zu-
sätzlich ein success type hinzugefügt. Ist das Skript jedoch nicht verfügbar, wird eine Fehler-
meldung und der zugehörige error type dem Ergebnis hinzugefügt. Zum Schluss werden die
drei erforderlichen Parameter script, workflow und id unabhängig von Erfolg oder Fehlschlag
des Skriptes dem Ergebnis hinzugefügt. Ein Ergebnis in XML-Darstellung könnte dann wie folgt
aussehen:
<map>
<entry key="type">success</entry>
<entry key="workflow">export</entry>
<entry key="script">ExtractText</entry>
<entry key="id">764c7d8e-c276-4ef2-be2f-45b00fda0868</entry>
</map>
Datei Download: Nachdem der Verarbeitungsprozess durchlaufen wurde, können die Ergebnisse
als XML an den Anfragenden zurückgegeben worden sein. Aber es können auch Binärdaten er-
zeugt worden sein. Um Zugang zu diesen Binärdaten zu erhalten, gibt es die Möglichkeit über den
DownloadController den Outputordner herunterzuladen. Dieser Vorgang kann im Download-
Controller über die Action download() angestoßen werden:
51
def download() {
	 def id = params.id
	 def resultFile = downloadService.getZippedOutFolder(id)
	 response.setContentType("application/zip")
	 response.setHeader("Content-disposition", "attachment;filename=${resu	
	 ltFile.getName()}")
	 response.outputStream << resultFile.newInputStream()
}
Um den Outputordner herunterzuladen wird die UUID benötigt. Mit dieser kann der Download-
Service über die getZippedOutFolder() Funktion den als ZIP verpackten Outputordner be-
reitstellen:
def File getZippedOutFolder(id) {
	 def outFolder = new File(fileStructureService.getOutPath(id))
	 File outZipFile = new File(fileStructureService.getTmpPath(id) + 		
	 File.separator + outFolder.getName() + ".zip")
	 new AntBuilder().zip(destfile: outZipFile.getAbsolutePath(), basedir: 	
	 outFolder.getAbsolutePath())
	 return outZipFile
}
Über den FileStructureService werden die benötigten Output- und Temporaryordner Pfade
bereitgestellt. Anschließend wird mit dem AntBuilder dann der Outputordner gepackt und in
dem Temporaryordner abgelegt. Die Entscheidung den Outputordner zu packen, resultiert aus dem
Grund, dass unter Umständen die binären Ergebnisse sehr groß werden können. Um die Daten
möglichst performant bereitzustellen, wurde hier der ganze Ordner gepackt. Eine spätere Optimie-
rung dieser Funktion kann in einer zweiten Version des Servers erfolgen.
Die getZippedOutFolder() Funktion gibt somit den gepackten Outputordner zurück. Der Re-
sponse wird dann mit einem Header, ContentType und der gepackten Datei befüllt und an den
Anfragenden gesendet. So werden die Binärdaten aus dem Outputordner bereitgestellt und können
weiter verarbeitet werden.
Session Beendigung: Nach dem der Vorgang abgeschlossen ist, sollte die Session beendet wer-
den, um keine Dateileichen auf dem System zu haben. Dies kann über zwei Möglichkeiten erfol-
gen. Die erste und manuelle Möglichkeit erfolgt über den ProcessController. Dieser enthält
folgende Action:
52
def closeSession() {
def id = params?.id
def result = processService.closeSession(id)
render result as XML
}
Notwendig für den Prozess ist die UUID. Diese wird entgegengenommen und an die closeSes-
sion() Funktion des ProcessServices übergeben.
def closeSession(id) {
fileStructureService.deleteSessionFolder(id)
def result = [:]
result.put("type", "success")
result.put("id", id.toString())
return result
}
Diese Funktion arbeitet ähnlich wie die createSession(). Sie unterscheiden sich lediglich dar-
in, dass sie die Sessionstruktur nicht erzeugt, sondern den Sessionornder mit der jeweiligen UUID
löscht. Das Löschen übernimmt der FileStructureService mit der Funktion deleteSes-
sionFolder():
def deleteSessionFolder(String id) {
def folder = new File(getWorkPath() + id)
FileUtils.deleteDirectory(folder)
}
Die zweite Möglichkeit die Session zu beenden, ist über den automatischen Task. Der Task ist in
der config/spring/resources.xml definiert:
<task:scheduler id="singleTaskScheduler" pool-size="1"/>
<task:scheduled-tasks>
	 <task:scheduled ref="cleanUpWorkDirService" method="run" 			
	 cron="${idml.server.tasks.cleanup.workdir.cronexpression}"/>
</task:scheduled-tasks>
Dieser greift zeitgesteuert auf die Funktion run() des CleanUpWorkDirServices zu. Die Zeit-
steuerung wird in der config.properties Datei über eine Cron Expression geregelt. Die run()
53
Funktion sieht wie folgt aus:
def run() {
	 log.info("start cleanUpWorkDirTask")
	 new File(fileStructureService.getWorkPath()).eachFile {File 			
	 uuidFolder ->
		 if (uuidFolder.isDirectory()) {
			 def now = new Date()
			 long limit = grailsApplication.config.idml.server.tasks.	
			 cleanup.workdir.time.limit as long
			 def folderDateWithLimit = new Date(uuidFolder.lastModi		
			 fied() + limit)
			 if (now.after(folderDateWithLimit)) {
				 log.info("delete folder: " + uuidFolder.getAbsolute	
				 Path())
				 fileStructureService.deleteSessionFolder(uuidFolder)
			 }
		 }
	 }
	 log.info("end cleanUpWorkDirTask")
}
Der Task betrachtet den Workordner in dem alle Sessionordner liegen. Alle Sessionordner werden
durchlaufen, um das Datum der letzten Änderung eines Ordners mit dem aktuellen Datum, plus
einem konfigurierbarem Werte, zu vergleichen. Wird dieser Wert übertroffen, wird der Session-
ordner als zu alt angesehen und direkt gelöscht. Sessions, die beispielsweise versehentlich nicht
beendet wurden, können somit automatisch nach einem festen konfigurierten Zeitlimit gelöscht
werden. Dies gewährleistet, dass eine Session eine maximale Lebensdauer hat.
3.2.3 Szenarien
In diesem Abschnitt werden die Szenarien beschrieben und dargestellt, welche Vorzüge diese haben
können. Sie werden über Groovy-Skripte realisiert und sind für den Verarbeitungsprozess verantwort-
lich. Die Groovy-Skripte gehören nicht direkt zum IDML-Server, können aber nach individuellen An-
forderungen entwickelt und in diesen eingebunden werden. Die Skripte sind auf vorgegebene IDML-
Dateien ausgerichtet. Diese sind speziell vorbereitet, um die ausgewählten Szenarien darstellen zu
können. Es werden sechs Skripte betrachtet, die jeweils ein Szenario darstellen:
54
ExtractText.groovy: Dieses Skript ist, dafür zuständig Texte zu extrahieren. Das Skript sieht wie
folgt aus:
def resultMap = [:]
StringBuilder sb = new StringBuilder()
new File(inPath).eachFileRecurse {
def idml = new Idml(it.getAbsolutePath())
def spreadIterator = DocumentUtil.getSpreadIterator(idml)
while (spreadIterator.hasNext()) {
def pageItemIterator = SpreadUtil.getPageItemIterator(spreadIterat
or.next())
while (pageItemIterator.hasNext()) {
def pageItem = pageItemIterator.next()
if (pageItem.isTextFrame()) {
def story = PageItemUtil.getParentStory(pageItem.getAsText-
Frame())
def content = StoryUtil.getContent(story)
sb.append(content)
}
}
}
idml.save()
idml.close()
}
resultMap.put("text", sb.toString())
resultMap
Als erstes wird zunächst in dem Skript eine resultMap erzeugt. Dies ist das Ergebnis, welches
später befüllt und als XML an der Webservice-Schnittstelle dargestellt wird. Da das Skript Zugriff
auf den Inputordner hat, können alle Dateien aus diesem Ordner verarbeitet werden. Hier wird
davon ausgegangen, dass es sich um IDML-Dateien handelt. Diese IDML-Dateien werden über
alle Spreads und PageItems durchlaufen und kontrolliert, ob das jeweilige PageItem eine
TextFrame ist. Trifft dies zu, wird auf die zugehörige Story zugegriffen und der Textinhalt über
einen StringBuilder zu einem String zusammengefasst. Somit werden alle Texte aus dem
Dokument zu einem String zusammengefasst und in der resultMap positioniert.
Das Szenario soll in erster Linie zeigen, dass es ohne großen Programmieraufwand mit dem IDML-
Server möglich ist auf die Texte einer IDML-Datei zuzugreifen. Es kommt oftmals vor, dass auf-
wendig Unternehmensbroschüren, Flyer oder andere Medienprodukte mit InDesign produziert
55
werden und die Texte aus diesen Produkten dann in anderen Medien verwendet werden sollen.
Oft wird dann manuell mit InDesign das Dokument geöffnet, um den jeweiligen Text zu kopieren.
Dabei können Fehler entstehen und das manuelle Öffnen der Datei erfordert das Programm In-
Design. Mit dem IDML-Server und diesem Skript könnten die Textinhalte einer IDML-Datei über
den Webservice zur Verfügung gestellt und dann weiter verarbeitet werden. Beispielsweise können
die Texte auf Webseiten, mobilen Endgeräten dargestellt oder in Suchengines platziert werden, um
die Inhalte durchsuchbar zu machen.
TextManipulation.groovy: Dieses Skript bietet die Möglichkeit, Texte aus einer IDML-Datei zu
verändern und neu abzuspeichern:
def resultMap = [:]
new File(inPath).eachFileRecurse {
def idml = new Idml(it.getAbsolutePath())
def spreadIterator = DocumentUtil.getSpreadIterator(idml)
while (spreadIterator.hasNext()) {
def pageItemIterator = SpreadUtil.getPageItemIterator(spreadIterat
or.next())
while (pageItemIterator.hasNext()) {
def pageItem = pageItemIterator.next()
if (pageItem.isTextFrame()) {
def story = PageItemUtil.getParentStory(pageItem.getAsText-
Frame())
story.getParagraphStyleRangeList().get(0).getCharacterStyleR-
angeList().get(0).setContent(content);
}
}
}
def out = outPath + it.getName()
idml.saveAs(out)
idml.close()
}
resultMap
Dieses Skript arbeitet ähnlich wie das vorherige Skript. Alle Dateien werden aus dem Inputordner
durchlaufen und über alle Spreads und PageItems iteriert. Ist das PageItem ein TextFrame
wird wieder auf die Story zugegriffen. Zugriff auf den Textinhalt bekommt man über die Para-
graphstylRageList und CharacterStyleRangeList. Hier wird davon ausgegangen, dass
56
nur ein ParagraphenstyleRange und ein CharacterStyleRange existieren. Der Inhalt des
CharacterStyleranges wird neu gesetzt mit der Variable content. Diese Variable ist wie
der outPath und inPath nicht in dem Skript deklariert. Der Wert ist ein Parameter, der durch
den Webservice über das Binding in dem Skript verfügbar gemacht wird. Zum Schluss wird die
Änderung in einer neuen IDML-Datei im Outputordner abgespeichert.
Diese Art von Skript kann bei Übersetzungen verwendet werden. Gibt es beispielsweise Medien-
produkte, die in verschiedenen Sprachen publiziert werden sollen, bietet der IDML-Server eine
Möglichkeit dies zu realisieren. Wichtig in dem Fall ist, dass der reine Textinhalt verändert wird,
jedoch keine Stile, Positionen oder andere wichtige Corporate-Design-Vorgaben, die eingehalten
werden müssen. Zu beachten ist außerdem noch, dass die TextFrames in dem Grunddokument
dafür ausgerichtet sein müssen und genug Platz aufzuweisen. Übersetzte Texte können unter Um-
ständen länger werden als der Orginaltext. Das Erkennen eines Textüberschusses in einem Text-
Frame kann in IDML nicht direkt erfasst werden. Dazu muss das Dokument beispielsweise einmal
mit InDesign gerendert werden.
Ein weiterer Bereich für den Einsatz des Skripts liegt im Korrekturworkflow. Eine Web Applika-
tion könnte über den Webservice des IDML-Servers auf die Daten zugreifen und die Texte, die
Fehler beinhalten, verändern, ohne dass dabei gestalterische Merkmale verändert werden. Der
Benutzer, der diese Webapplikation dann verwendet, benötigt kein InDesign Wissen.
Validate.groovy: Dieses Skript stellt einfache Validierungsmöglichkeiten von IDML-Dateien vor.
Es wird hier in einer minimierten Version dargestellt, da die Möglichkeiten zur Prüfung der Datei
sehr umfangreich sein können:
def resultMap = [:]
new File(inPath).eachFileRecurse {
def idml = new Idml(it.getAbsolutePath())
def firstSpread = DocumentUtil.getSpreadIterator(idml).next();
def nameExists = false
def pageItemIterator = SpreadUtil.getPageItemIterator(firstSpread,
new IPageItemFilter() {
public boolean accept(AbstractIdmlPageItem pageItem) {
return LabelUtil.hasLabel(pageItem, "Label");
}
});
while (pageItemIterator.hasNext()) {
AbstractIdmlPageItem pageItem = pageItemIterator.next();
if (pageItem.isTextFrame()) {
KeyValuePair label = LabelUtil.getLabel(pageItem.getAsText-
57
Frame(), "Label");
if (label.getValue().equals("name")) {
nameExists = true
}
}
}
idml.close()
resultMap.put("nameExists", nameExists)
}
resultMap
Das Ziel des Skriptes ist es zu identifizieren, ob ein bestimmtes PageItem in der IDML enthalten
ist. Auch hier wird wieder auf die PageItems zugegriffen, jedoch mit dem Unterschied, dass ein
Filter verwendet wird, der nur PageItems zurück gibt, die ein Label besitzen. Labels sind
Markierungen die über InDesign an PageItems gesetzt werden können.
Abb. 12 InDesign Script Label
Über diese PageItems wird nun iteriert und kontrolliert, ob es ein TextFrame ist. Trifft dies zu,
wird weiter der Wert des Labels geprüft. Wenn dieser den Wert name beinhaltet, ist das jeweilige
Element gefunden worden und es wird ein true Wert in die resultMap platziert. Über den Web-
service wird dieser dann dargestellt und das Dokument kann als valid weiter behandelt werden.
Es sind auch weitere Validierungsmöglichkeiten gegeben. Beispielsweise kann nach Bildern va-
lidiert und anhand des Dateinamens kontrolliert werden, ob ein Logo mit speziellem Dateinamen
in dem Dokument platziert wurde. Andere Möglichkeiten wären Schriften, Positionen und Farben
in einem Dokument zu kontrollieren. Corporate-Design-Vorgaben können somit automatisch kon-
trolliert werden.
IdmsGroupExport.groovy: Dieses Skript ist dafür zuständig, Teile einer IDML-Datei als IDMS-
Dateien zu exportieren, um diese wieder verwenden zu können. In dem Skript wird eine Funktion
verwendet, die aus einer IDML-Datei alle PageItems vom Typ Group in einer Liste zur Verfü-
58
gung zu stellen. Diese sieht wie folgt aus:
def List<Group> getGroups(Idml idml) {
List<Group> groupResult = new ArrayList<Group>();
SpreadIterator spreadIterator = DocumentUtil.getSpreadIterator(idml);
while (spreadIterator.hasNext()) {
Spread spread = spreadIterator.next();
PageItemIterator pageItemIterator = SpreadUtil.
getPageItemIterator(spread, new IPageItemFilter() {
public boolean accept(AbstractIdmlPageItem abstractIdmlPageItem)
{
return abstractIdmlPageItem.isGroup();
}
});
spread.close();
while (pageItemIterator.hasNext()) {
Group currentGroup = (Group) pageItemIterator.next();
groupResult.add(currentGroup);
}
}
return groupResult;
}
Die programmatische Umsetzung erfolgt über einen PageItemFilter. Dieser prüft, ob das Pa-
geItem vom Typ Group ist und diese Gruppe anschließend in einer groupResult Liste ablegt.
def resultMap = [:]
def idmsFiles = new ArrayList<String>();
new File(inPath).eachFileRecurse {
def idml = new Idml(it.getAbsolutePath())
def groups = getGroups(idml)
def snippetBuilder = SnippetBuilder.get()
groups.each {group ->
def idmsFile = new File(outPath + group.self + ".idms")
snippetBuilder.createSnippet(group, idmsFile)
idmsFiles.add(idmsFile.getAbsolutePath())
}
59
idml.close()
}
resultMap.put("idms files", idmsFiles)
resultMap
Diese Liste wird weiter verarbeitet und für jede Gruppe, die gefunden wurde, wird eine IDMS-
Datei erzeugt, die als Dateinamen die SelfId der Gruppe trägt. Diese ist in einem Dokument
immer eindeutig. Die Pfade der erzeugten IDMS-Dateien werden in einer Liste abgelegt und zu
der resultMap hinzugefügt. Diese werden anschließend im Webservice dargestellt.
Ein solches Szenario ist bei wiederkehrenden Elementen im IDML sinnvoll. Hat man beispiels-
weise einen Handzettel mit unterschiedlichen Produkten, können diese Produkte als IDMS-Datei
exportiert und in späteren Ausgaben wieder verwendet werden. Dabei können zu einem Produkt
unterschiedliche Elemente gehören. Besteht ein Produkt aus einem Bild, einem Beschreibungstext
und einem Preis, können diese drei Elemente in InDesign als Gruppe zusammengefasst werden
und dann mit diesem Skript exportiert werden. Der Vorteil durch diese Wiederverwendbarkeit liegt
darin, dass die IDMS-Dateien alle gestalterischen Merkmale beibehalten. Ist ein Produkt einmal
gestaltet und exportiert worden kann die exportierte IDMS-Datei in anderen InDesign-Dokumen-
ten mit allen Stilen, Farben, etc. platziert werden.
ImportIdms.groovy: Dieses Skript ist das Gegenstück zum IdmsGroupExport.groovy. Das Ziel
ist es, IDMS-Dateien in IDML-Dateien zu importieren. Dazu werden mehrere IDMS-Dateien in
einer IDML platziert und als neue IDML-Datei abgespeichert:
def resultMap = [:]
def idmlList = new File(inPath).listFiles({d, f -> f ==~ /.*.idml/ }
as FilenameFilter).toList()
def idmsList = new File(inPath).listFiles({d, f -> f ==~ /.*.idms/ }
as FilenameFilter).toList()
idmlList.each {idmlFile ->
def idml = new Idml(idmlFile.getAbsolutePath())
idmsList.each {idmsFile ->
def idms = new Idml(idmsFile.getAbsolutePath())
DocumentUtil.importSnippet(idml, idms, 0)
}
def out = outPath + idmlFile.getName()
new File(out).getParentFile().mkdirs()
idml.saveAs(out)
60
idml.close()
}
resultMap
Ein solches Szenario kann dazu dienen vollautomatisch IDML-Dateien zu erzeugen. Betrach-
tet man das vorherige Export-Skript, kann eine denkbare Kombination eine Art Baustein-System
sein. Mit dem Export-Skript können Produkte eines Handzettels exportiert und als einzelne Bau-
steine in einem System abgelegt werden. Mit dem Import-Skript kann das System dann mehrere
Produkte zu einem Handzettel zusammenbauen. In Kombination mit dem Skript der Textmanipu-
lation können dann sogar Texte verändert oder übersetzt werden.
DatabasePublishing.groovy: Dieses Skript ist aus einer vorherigen Arbeit adaptiert und für den
IDML-Server optimiert worden. Die zugehörigen Informationen sind zu finden unter [Pouryek-
ta2011] und das Video dazu unter [DatabasePublishing2011]. Das Skript stellt ein Database-Pu-
blishing-Szenario dar. Aus einer XML mit Personendaten (welches als Datenbank fungiert) und
einer IDML (welches als Template fungiert) werden pro Person Visitenkarten erzeugt. Das Skript
kann in den beigefügten Quellen betrachtet werden. Es ist eine Kombination aus dem Validate.
groovy Skript und dem TextManipulation.groovy Skript. Über die Labels können wie im Valida-
te.groovy die jeweiligen PageItems identifiziert werden. Wie bei dem TextManipulation.groovy
werden die Texte dann ausgetauscht, die aus der XML-Datei kommen. Hier wird deutlich, dass
der IDML-Server nicht nur IDML-Dateien, sondern auch XML-Dateien ohne Probleme verarbei-
ten kann. Auch weitere Formate sind möglich. Bilder werden auch in diesem Skript ausgetauscht.
Dazu müssen die Bilder mit in das System geladen werden und in dem XML verfügbar sein. Was
in IDML dann passiert ist, dass die Pfade des Bildes verändert werden und so im IDML das neue
Bild dargestellt wird.
Die Vorteile von Database-Publishing liegen vor allem in der Geschwindigkeit, in der die Doku-
mente generiert werden und in der minimierten Fehleranfälligkeit im Vergleich zur manuellen
Umsetzung.
61
4 Schlussbetrachtung
In diesem letzten Kapitel werden noch einmal die Ergebnisse der Umsetzung zusammengetragen und
bewertet. Es werden Empfehlungen für die Bereiche angesprochen, in denen ein IDML-Server sinn-
voll genutzt werden kann. Da das Konzept nur für eine erste Version des IDML-Servers konzipiert
wurde, wird zum Schluss zusätzlich ein Blick in die Zukunft geworfen und mögliche Weiterentwick-
lungen des Systems betrachtet.
4.1 Ergebnisse
Die Ergebnisse sind in zwei Bereiche einzuteilen. Der erste Bereich beschäftigt sich mit den Ergebnis-
sen des Prototyps. Der zweite mit den Szenarien, welche den produktiven Einsatz ermöglichen:
Prototyp: Bei der Entwicklung des Prototyps ist deutlich geworden, wie ein IDML-Server aus-
sehen kann. Die Themen aus den Grundlagen spielen dabei eine wesentliche Rolle. Vor allem der
Einsatz des Grails-Frameworks bietet sehr viele Möglichkeiten im Bereich der Entwicklung.
Die vier Anforderungen an das System konnten mit dem Konzept und dem Prototypen bestätigt
werden. Die Anforderung der Verarbeitung wird dabei in der Process-Engine realisiert. Sie kap-
selt den Verarbeitungsprozess und realisiert ihn durch individuell gestaltbare Groovy-Skripte. Die
Vereinfachung des Umgangs mit IDML wird durch den ganzen IDML-Server realisiert. Dabei
fassen die Skripte spezielle und komplexe Aufgaben zusammen und können durch einen einfach
zu bedienenden Webservice angesteuert werden. Die Anforderung der Einbindung des Systems
wird auch über den Webservice realisiert. Dieser ist in Teilen individuell durch die Groovy-Skripte
erweiterbar. Dies ist auch somit die letzte Anforderung. Die Erweiterbarkeit wird über die Webser-
vice-Parameter, die Groovy-Skripte und dem Grails-Pluginsystem gewährleistet.
Szenarien: Die Szenarien zeigen mögliche Einsatzbereiche des IDML-Servers. Das ExtractText.
groovy Skript zeigt wie Inhalte über einen Webservice zur Verfügung gestellt und somit über an-
dere Systeme publiziert werden können. Das TextManipulation.groovy Skript beschreibt den Ein-
satzbereich von Web-to-Print-Systemen. Hiermit können Übersetzungs- und Korrekturworkflows
realisiert werden. Das Validate.groovy Skript ist im Bereich der Qualitätskontrolle einzuordnen.
Mit derartigen Skripten kann gewährleistet werden, dass IDML-Dateien eine bestimmt Form auf-
weisen. Fehlerhafte Dateien können somit automatisch aussortiert werden. Das IdmlGroupExport.
groovy und das ImportIdms.groovy Skript können zusammen im Bereich von Bausteinsystemen
verwendet werden. Ganze IDML-Elemente können so wieder verwendet und regelbasiert, vollau-
tomatisch zu ganzen Dokumenten zusammengeführt werden. Das DatabasePublishing.groovy hat
gezeigt, dass mit IDML auch Database-Publishing möglich ist. Hier wurden individuelle IDML-
Dateien in wenigen Sekunden erzeugt.
62
4.2 Bewertung
Die Bewertung der Ergebnisse wird auch wieder in den zwei Bereichen Prototyp und Szenarien be-
trachtet:
Prototyp: Bei dem Prototypen hat sich herauskristallisiert, dass die Wahl der Technologie und
die Orchestrierung dieser eine wesentliche Rolle spielen. Das Grails-Framework in Kombination
mit der Sprache Groovy war hier der richtige Ansatz, um das Konzept über einen Prototypen zu
bestätigen. Die größten Vorteile liegen einmal darin, dass dieser IDML-Server in der Lage ist
ein komplexes Format zu kapseln. Wichtig ist hier zu erwähnen, dass der IDML-Server nicht die
Komplexität von IDML minimiert, sondern diese nur in den Bereich der Groovy-Skripte ver-
schiebt. Über die Groovy-Skripte wird dann die Verarbeitung gewährleistet. Diese Verarbeitung
kann über eine einfache URL angestoßen werden. Der Benutzer, der diese URL anstößt, muss kein
Wissen über das zu verarbeitende Format haben, da die Skripte die Komplexität behandeln und
für die Verarbeitung zuständig sind. Ein weiterer Vorteil, welcher sich während der praktischen
Umsetzung deutlich zeigt, ist dass es auf Erweiterbarkeit ausgelegt und nicht zwingend auf IDML
beschränkt ist. In diesem System wurde lediglich der Fokus auf IDML gesetzt. Es ist jedoch so
flexibel ausgelegt, dass es ohne große Anpassungen auch andere Formate verarbeiten kann. Somit
sind die Anforderungen an den IDML-Server zufriedenstellend erfüllt.
Szenarien: Die Skripte, welche die Szenarien darstellen, können komplexe Prozesse abbilden
und durch diese Art von Automatisierung Vorteile bewirken. Diese Vorteile können vor allem im
Bereich der Produktion liegen, da Prozesse verkürzt und optimiert werden. Auch die Qualität der
Produkte kann über spezielle Skripte so gewährleistet werden. Im Bereich der Wirtschaftlichkeit
können hier für Unternehmen Vorteile entstehen, da diese Art von IDML-Verarbeitung sonst nur
mit einem kostenintensiven InDesign-Server möglich ist. Die Skripte sind speziell für angepasste
IDML-Dateien vorbereitet worden. Um diese Groovy-Skripte zu entwickeln, sind Spezialisten
notwendig, die Erfahrung in InDesign, IDML und Groovy besitzen. Ein wirklich produktiver Ein-
satz der Skripte setzt außerdem einheitliche und strukturierte IDML-Dateien vorraus. Diese Art
von Verarbeitung kann jedoch selten im künstlerischen Bereich eingesetzt werden. Es ist in erster
Linie darauf ausgelegt, strukturierte Abläufe zu optimieren.
Zusammenfassend kann gesagt werden, dass der Einsatz eines IDML-Servers große Vorteile bringen
kann. Wichtig ist, dass die IDML-Dateien strukturiert aufbereitet sind und die Skripte professionell
erstellt werden. Das bedeutet allerdings auch, dass man sich mit diesen Themen intensiv auseinander
setzten muss, um wirklich produktiv diese Vorteile zu erzielen.
63
4.3 Blick in die Zukunft
Das Konzept, das hier betrachtet wurde, kann und soll weiterentwickelt werden. Folgend werden Ideen
betrachtet, die in Zukunft in den IDML-Server einfließen können:
JSON: In dieser ersten Version des IDML-Servers gibt der Webservice die Daten als XML zurück.
Es kann von Vorteil sein hier auch das JSON-Format zu unterstützen, da es die gleichen Daten oft
kleiner als XML darstellen kann. Die Anpassung ist in dem Grails-Framework sehr einfach umzu-
setzen und könnte über den Webservice per Parameter beeinflusst werden.
Ergebnis: Das Ergebnis, was über den Webservice dargestellt wird, ist in dieser ersten Version
eine Map. Um den Webservice strukturierter aufzubauen, kann eine Ergebnis-Klasse erzeugt wer-
den, die feste und variable Werte aufnehmen kann. Die festen Werte können dann beispielsweise
für spezielle Nachrichten und Codes verwendet werden, die immer in einem Webservice-Ergebnis
vorhanden sein müssen. Die variablen Werte können dann individuell beansprucht werden.
Versionierung: Bei einer Weiterentwicklung des Webservices sollte eine Versionierung des Web-
service in Betracht gezogen werden. Ist der IDML-Server einmal in bestehende Workflows ein-
gebunden, können Veränderungen des Webservices den ganzen Workflow gefährden. Der Einsatz
eines versionierten Webservices könnte hier Abhilfe schaffen.
Multiupload: In dieser ersten Version kann pro Serveranfrage immer nur eine Datei hochgeladen
werden. Für zukünftige Versionen könnte man einen Multiupload entwickeln, der den Ablauf be-
schleunigen könnte.
Parameter: Der Webservice kann individuelle Parameter beinhalten, die dann von den Groovy-
Skripten verarbeitet werden können. Diese Parameter werden in dieser ersten Version nicht im
Webservice-Ergebnis angebunden. Hier sollten der Vollständigkeit halber nicht nur die festen Pa-
rameter, sondern auch die variable Parameter gesetzt werden.
Asynchron: Der Server arbeitet in dieser ersten Version synchron. Das bedeutet, es ist möglich an
den Server eine Anfrage zu stellen. Diese wird dann verarbeitet und es wird ein Ergebnis zurück
gegeben. Dieser Verarbeitungsvorgang kann unter Umständen lange dauern. Daher könnte man
einen asynchronen Ansatz wählen, indem man in der Process-Engine mit einer Queue arbeitet, die
Kommandos entgegen nehmen kann. Der Ansatz beruht hier auf dem Command-Muster. Dieser in
Kombination mit dem State-Muster kann eine asynchronen Verarbeitungsprozess realisieren. Der
Anfragende stößt somit nicht direkt die Verarbeitung an, sondern fügt der Queue ein Kommando
hinzu. Ein Ergebnis, ob das Kommando in dem Verarbeitungsprozess angekommen ist kann sofort
64
zurück gegeben werden. Wann genau das Kommando verarbeitet wurde und wann genau er abge-
schlossen wird, ist nicht direkt für den Anfragenden sichtbar. Er kann aber den Status der Verarbei-
tung über den Webservice abfragen, der einem dann sofort zurückgeben kann, ob die Verarbeitung
noch im Gange oder bereits abgeschlossen ist.
Benutzerverwaltung: Eine weitere Möglichkeit liegt in der Einführung einer Benutzerverwal-
tung. Die Unterscheidung zwischen einem Benutzer für das System und einem Administrator kann
eine deutliche Trennung zwischen den Aufgabenbereichen darstellen. Ein Administrator kann so-
mit das System konfigurieren und Benutzer verwalten. Benutzer können so unterschiedliche Rech-
te auf Verarbeitungsprozesse haben. Ein Benutzer kann somit beispielsweise nur Verarbeitungen
im Qualitätsbereich ausführen, die keine Veränderungen der Dateien vornehmen. Im Gegensatz
dazu könnte ein Übersetzter Rechte auf Verarbeitungen im Bereich der Textmanipulation haben.
Skriptverwaltung: Die Skripte könnten in einer weiteren Version des IDML-Servers über eine
Benutzeroberfläche verwaltet werden. Dazu könnte es über die Benutzerverwaltung eine Rolle des
Entwicklers geben, der Zugriff auf die Skripte hat und diese hochladen, erstellen und verändern
kann.
Datenbank: Die Verwendung einer Datenbank könnte den IDML-Server weiter optimieren. Da-
bei könnten Informationen über die Benutzer und die Skripte in der Datenbank platziert werden.
Download: Der Downloadprozess ist in erster Version des IDML-Servers sehr einfach gehalten.
Er stellt den ganzen Output zur Verfügung. Bei einer Verarbeitung in der mehrere Dateien erzeugt
werden, kann es erforderlich sein nur Zugriff auf eine spezielle Datei zu erhalten. Der Download-
prozess könnte so weiterentwickelt werden, dass auch einzelne Dateien aus dem Outputordner
heruntergeladen werden können.
Temporaryordner: Der Temporaryordner wird bislang nur im Downloadprozess verwendet. Der
Zugriff auf diesen Ordner könnte aber auch in Groovy-Skripten Verwendung finden.
Zusammenfassend kann gesagt werden, dass es noch viele Möglichkeiten gibt, diesen IDML-Server
sinnvoll auszubauen. Der Blick in die Zukunft zeigt mögliche Entwicklungen.
65
Abbildungsverzeichnis
Abbildung Beschreibung Seite
1 MVC Ablauf 9
2 SOAP-Nachricht 13
3 Grails Einordnung 14
4 Groovy/Java Plattform 15
5 Spring Modules 20
6 Grails Applikation 22
7 IDML Container Aufbau 33
8 IDML-Server 38
9 Workflow Ablauf 40
10 IDML-Server Index Seite 43
11 IDML-Server Process Index Seite 44
12 InDesign Script Label 57
66
Abkürzungsverzeichnis
Abkürzung Beschreibung
ACID Atomicity Consistency Isolation Durability
AJAX Asynchronous JavaScript and XML
AOP Aspect-Oriented Programming
CoC Convention over Configuration
CS Creative Suite
CSS Cascading Style Sheets
DOM Document Object Model
DI Dependency Injection
DRY Don´t Repeat Yourself
DTP Desktop Publishing
eBook Electronic Book
EL Expression Language
EPUB Electronic Publication
EVA Eingabe, Verarbeitung, Ausgabe
GDK Groovy Development Kit
GORM Grails Object Relational Mapping
GPath Groovy Path Language
GSP Groovy Server Page
GString Groovy String
HTTP Hypertext Transfer Protocol
IDML InDesign Markup Language
IDMS InDesign Snippet
INDD InDesign Document Format
INX InDesign Interchange Format
IoC Inversion of Control
JDK Java DevelopmentKit
JS JavaScript
JSON JavaScript Object Notation
JSP Java Server Page
JVM Java Virtual Machine
MIMETYPE Multipurpose Internet Mail Extensions Type
MVC Model View Controller
ORM Object Relational Mapping
PDF Portable Document Format
67
Abkürzung Beschreibung
POJO Plain Old Java Object
RDF Resource Description Framework
REST Representational State Transfer
RNG Regular Language Description for XML New Generation
SEI Software Engineering Institute
SOAP Simple Object Access Protocol
SQL Structured Query Language
UCF Universal Container Format
URI Uniform Resource Identifier
URL Uniform Resource Locator
UUID Universally Unique Identifier
W3C World Wide Web Consortium
WSDL Web Service Description Language
XML Extensible Markup Language
XPath XML Path Language
XQuery XML Query Language
XMP Extensible Metadata Platform
XSLT Extensible Stylesheet Language Transformation
68
Literaturverzeichnis
[Adobe2012] Adobe Systems 2012, https://wwwimages2.adobe.com/content/dam/
Adobe/en/devnet/indesign/sdk/cs6/idml/idml-specification.pdf (2013-
01-07)
[Bayer2002] Thomas Bayer, REST Web Services, 2002, http://www.oio.de/public/
xml/rest-webservices.pdf (2012-12-19)
[Booth2004] David Booth, Hugo Haas, Francis McCabe, Eric Newcomer, Michael
Champion, Chris Ferris, David Orchard: Web Services Architecture,
2004, http://www.w3.org/TR/ws-arch/ (2012-12-18)
[Carnegie2012] Carnegie Mellon Software Engineering Institute, http://www.sei.cmu.
edu/architecture/start/glossary/community.cfm#definitions (2012-11-
06)
[DatabasePublishing2011] Database Publishing mit IDML 2011, https://www.youtube.com/
watch?v=IpbJudaJFH4 (2013-02-17)
[Davis2008] Scott Davis: Groovy Recipes Greasing the Wheels of Java, The
Pragmatic Programmers, 2008
[Fielding2000] Roy Thomas Fielding: Architectural Styles and the Design of
Network-based Software Architectures, 2000, https://www.ics.uci.
edu/~fielding/pubs/dissertation/rest_arch_style.htm (2012-12-19)
[Freeman2004] Eric Freeman, Elisabeth Freeman, Bert Bates, Kathy Sierra: Head First
Design Patterns, O‘Reilly Media, 2004
[Frotscher2007] Thilo Frotscher, Marc Teufel, Dapeng Wang: Java Web Services mit
Apache Axis2, entwickler.press, 2007
[Gamma2011] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Ent-
wurfsmuster: Elemente wiederverwendbarer objektorientierter Soft-
ware, Addion-Wesley Verlag, 2011
69
[Grandeur2009] Grandeur: researching groovy & grails, 2009, http://www.gayadesign.
com/scripts/uploads/researchpaper.pdf (2012-12-21)
[Groovy2012] Groovy Closures - Formal Definition, http://groovy.codehaus.org/
Closures+-+Formal+Definition (2012-12-29)
[Hunt2003] Andrew Hunt, David Thomas: Der Pragmatische Programmierer, Han-
ser, 2003
[IDMLlib2013] IDMLlib for Java, http://idmllib.com/ILWebsite/Products/IDMLlib-
for-Java (2013-01-13)
[Johnson2004] Rod Johnson, Juergen Hoeller: J2EE Development without EJB, Wi-
ley Publishing Inc, 2004
[Johnson2005] Rod Johnson,Juergen Hoeller,Alef Arendsen,Thomas Risberg,Colin
Sampaleanu: Professional Java Development with the Spring Frame-
work, Wiley Publishing Inc, 2005
[Kipphan2000] Helmut Kipphan: Handbuch der Printmedien, Springer Verlag, 2000
[König2007] Dierk König, Andrew Glover, Paul King, Guillaume Laforge, Jon
Skeet: Groovy in Action, Manning Publications Co., 2007
[Kruchten1995] Philippe Kruchten: Architectural Blueprints—The “4+1” View Model
of Software Architecture, IEEE Software November 1995 http://www.
cs.ubc.ca/~gregor/teaching/papers/4+1view-architecture.pdf (2012-
11-06)
[Oltmanns2007] Daniel Oltmanns, Stefan Edlich: Spring 2 für Grünschnäbel, Books
on Demand GmbH, 2007
[Pouryekta2011] Peyman Pouryekta: Analyse und Bewertung der InDesign Markup
Language - Desktop Publishing vs. Database Publishing, VDM Ver-
lag Dr. Müller, 2011
[Rocher2009] Graeme Rocher, Jeff Brown: The Definitive Guide to Grails, Apress,
2009
70
[Snell2002] James Snell,Doug Tidwell,Paul Kulchenko: Webservice-Programmie-
rung mit SOAP, O‘Reilly, 2002
[SpringDocu2012] Spring Documentation: 1. Introduction to Spring, http://static.
springsource.org/spring/docs/3.0.x/reference/overview.html, (2012-
12-30)
[Starke2009] Gernot Starke: Effektive Software Architekturen, Ein praktischer Leit-
faden, Hanser Verlag 2009
[Wolff2009] Eberhard Wolff: Über Architekturen und Perfektion, http://jandi-
andme.blogspot.de/2009/10/uber-architekturen-und-perfektion.html
(2010-11-07)
71
A
Ablaufplan 7
abstraction 6
Abstraktion 6, 8
ACID 25
Adobe 4
Adobe Creative Suite 30
AJAX 27
Analyse 7
AOP 26
application.properties 22
Arbeitsaufwand 4
Architekturmuster 8
Aspect-Oriented-Programming 26
Assoziationen 9
Ästhetik 6
Asynchron 63
Asynchronous JavaScript and XML
26
Atomicity 25
Auslieferung 13
Authentifizierung 13
Autorisierung 13
B
BackingStory.xml 35
Bauplan 7
Benutzerverwaltung 64
Beschnittzugabe 31
Blitzer 31
Body 13
BootStrap.groovy 22
BuildConfig.groovy 22
Builder 11
Built-in Tag 28
C
Carnegie Mellon Software Enginee-
ring Institute 6
Classpath 50
Closure 16
Cloud 38
CoC 21, 48
Code-Generierung 13
Collection 18
Color 34
Command 11
composition 6
Config.groovy 22
config.properties 45, 46, 50
Consistency 25
Constructor-Injection 21
Containerformat 33
container.xml 35
Controller 9, 26
Convention over Configuration 21
Corporate-Design-Vorgaben 56, 57
CRUD 27
CS4 4
Custom Tag 29
D
Database-Publishing 60, 61
DatabasePublishing.groovy 60
DataSource.groovy 22
Datei Download 41
Dateinamen 5
Datei Upload 41, 47
Datenmodell 9
Datentypen 17
decomposition 6
DELETE-Methode 14
Dependency Injection 20
designmap.xml 34
design pattern 7, 10
Desktop-Publishing 5, 30
development view 7
DI 21
Diagramm 5
Dokumenterstellung 30
Don´t Repeat Yourself 21
Druck- und Medienindustrie 4
DRY 21
DTP 30
Durability 25
Dynamic Dispatching 27
Dynamic Tag 28
dynamisch typisiert 15
E
eBook 31
electronic book 31
Electronic Publication 31
Encoding 33
Entwicklungsumgebung 22
Entwurfsentscheidungen 7
Entwurfsmuster 7, 10
Entwurfsprobleme 7
Envelope 12
EPUB 31
Erich Gamma 10
Erzeugungsmuster 10
esthetics 6
EVA-Prinzip 38
Expression Language 27
Extensible Markup Language 12
Extensible Metadata Platform 35
Extensible Stylesheet Language
Stichwortverzeichnis
72
Transformation 32
ExtractText.groovy 54
F
Flexibilität 8, 9
Fließtext 5
Flyer 54
Fonts.xml 34
Formfelder 31
Framework 5
G
GET-Methode 14
GORM 23, 24
GPath 19
Gradients 34
Graeme Rocher 5
Grails 5, 14
grails-app 22
Grails-Applikation 21
Grails-Framework 5, 6, 14
Grails-Kommando 5
Grails Object Relational Mapping 23
Graphic.xml 34
Groovy 5, 6, 15
Groovy-Path 19
Groovy Server Page 27
Groovy-Skripte 41
Groovy-String 17
Grundlayout 27
Gruppen 31
GSP 27
GString 17
Guillaume Laforge 5
H
Handzettel 59
Header 13
Hibernate-Framework 15
HTML 5
HTTP 12
Hypertext Transfer Protocol 12
I
IDML 5, 30
IDML-Spezifikation 5, 32
IDMS 35
IdmsGroupExport.groovy 57
Import 15
ImportIdms.groovy 59
INDD 31
InDesign 30
InDesign Document Format 31
InDesign Markup Language 4
InDesign Snippet 35
Informationstechnik 4
Interchange Format 32
Inversion of Control 20
INX 32, 33
IoC 20
Isolation 25
J
James Strachan 15
JavaScript Object Notation 26
Java Server Page 27
Java Virtual Machine 15
JSON 26, 63
JSP 27
JVM 15
K
Kapselung 35
Klassenpfad 50
Knöpfe 31
Komplexität 7
Komponenten 7
Komposition 5
Kompression 33
Konsequenzabschnitt 10
Konstruktionsplan 32
Konventionen 5
Konzept 4
L
layering 8
Lazy loading Mechanismus 35
Linien-Elemente 31
List 18
Lizenzkosten 4
logical view 7
Lösungsabschnitt 10
M
Map 18
Mapping.xml 35
MasterSpread 34
Medienprodukt 54
Messaging-Framework 12
metadata.xml 35
meta Tag 27
MIMETYPE 34
Model 9, 39
Model View Controller 8
Multipurpose Internet Mail Extensi-
ons Type 34
Multiupload 63
Mustername 10
MVC 8, 9, 45
N
NULL-Check 18
NullPointerException 18
O
73
Object Relational Mapping 15
Open-Source-Framework 20
Orchestrierung 5
Ordnung 7
ORM 15
Oval-Elemente 31
P
PDF 31
Performance 8, 9
Persistenz-Framework 15
Philippe Kruchten 6, 7
physical view 7
Plain Old Java Object 15
Pläne 7
POJO 15
Polyglot Programming 35
Polygon-Elemente 31
Portable Document Format 31
POST-Methode 14
Präsentation 9
Preferences.xml 34
Problemabschnitt 10
Process-Engine 39, 41
process view 7
Produktionsumgebung 22
Programmsteuerung 9
proprietär 4, 31
Prototyp 42, 61, 62
PUT-Methode 14
Python 15
Q
Qualität 8
Qualitätssicherung 36
Quasi-Standard 9
R
Range 18
RDF 35
Realisierung 7
Rechteck-Elemente 31
Regular Language Description for
XML New Generation 32
Representational State Transfer 6
Resource Description Framework 35
Resources 34
REST 6, 12, 13, 39
return Statement 18
RNG 32
Rod Johnson 5
Routing 13
Ruby 15
S
Scaffolding 27
scenario 7
Schichten 8, 39
Schichtenmuster 8
Scripting 19
SEI 6
Semikolon 16
Session Beendigung 42, 51
Session Erzeugung 41, 43
Setter-Injection 21
Sichten 7
Simple Object Access Protocol 6
Single Point of Failure 38
Singleton 11
SiteMesh 15, 27
Skriptverwaltung 64
Smalltalk 15
SOAP 6, 12
SOAP-Nachricht 12
SOAP-Schnittstelle 39
Softwarearchitektur 6
Softwareentwicklung 5
Spread 34
Spring 20
Spring-Framework 5
SQL 24
State 11
Stil 6
Stories 34
Story.xml 35
StrokeStyle 34
Structured Query Language 24
Struktur 7
Strukturmuster 10
style 6
Styles.xml 34
T
taglib 29
Tags.xml 35
Testumgebung 22
Text-Elemente 31
TextManipulation.groovy 55
Tomcat 30, 43
Transaktionskontext 13
Transformierung 32
Typografie 5, 30
Typografische Konventionen 5
U
Übersetzungsworkflow 36
UCF 33
Uniform Resource Identifier 13
Universal Container Format 33
Universally Unique Identifier 40
Unternehmensbroschüren 54
URI 13
URL 5
UrlMappings.groovy 23
74
UUID 40
V
Validate.groovy 56
Validator 23
Verarbeitung 41, 48
Verhaltensmuster 10
Versionierung 63
Versionskompatibilität 4
Verständlichkeit 7, 8
View 9
W
W3C 12
WAR 30
Wartbarkeit 9
Web Application Archive 30
Webservice 6, 12, 39
Web Service Description Language
12
Web-to-Print 61
Werkzeug 4
Wiederverwendbarkeit 59
World Wide Web Consortium 12
WSDL 12, 13, 40
X
XML 5, 12, 19
XML-Overhead 40
XML Path Language 32
XML Query Language 32
XMP 35
XPath 32
XQuery 32
XSLT 32
Z
Zerlegung 6
ZIP 51
ZIP-Archiv 33
Zusammensetzung 6
Zwiebel 8

Konzeption eines IDML Servers

  • 1.
    FOM Hochschule fürOekonomie & Management Studienzentrum Essen Master-Thesis zur Erlangung des Grades eines Master of Arts (M.A.) über das Thema Konzeption eines IDML Servers von Peyman Pouryekta Erstgutachter Professor Dr.-Ing. Torsten Finke Matrikelnummer 198124 Abgabedatum 2013-04-15
  • 2.
    2 Inhaltsverzeichnis 1 Einleitung........................................................................................................................................... 4 1.1Sachliche Motivation................................................................................................................ 4 1.2 Ziele.......................................................................................................................................... 4 1.3 Leserkreis................................................................................................................................. 4 1.4 Typografische Konventionen.................................................................................................... 5 1.5 Literaturdiskussion................................................................................................................... 5 2 Grundlagen......................................................................................................................................... 6 2.1 Softwarearchitektur.................................................................................................................. 6 2.1.1 Definition........................................................................................................................ 6 2.1.2 Architekturmuster........................................................................................................... 8 2.1.3 Entwurfsmuster............................................................................................................. 10 2.2 Webservice............................................................................................................................. 12 2.2.1 Definition...................................................................................................................... 12 2.2.2 SOAP............................................................................................................................ 12 2.2.3 REST............................................................................................................................ 13 2.3 Grails...................................................................................................................................... 14 2.3.1 Einordnung................................................................................................................... 14 2.3.2 Groovy.......................................................................................................................... 15 2.3.3 Spring........................................................................................................................... 20 2.3.4 Konzepte....................................................................................................................... 21 2.3.5 Applikation................................................................................................................... 21 2.4 IDML...................................................................................................................................... 30 2.4.1 InDesign........................................................................................................................ 30 2.4.2 Dateiformat................................................................................................................... 32 2.4.3 IDMLlib........................................................................................................................ 35 3 Umsetzung....................................................................................................................................... 37 3.1 Konzept.................................................................................................................................. 37 3.1.1 Anforderungen.............................................................................................................. 37 3.1.2 Systemarchitektur......................................................................................................... 37 3.1.3 Webservice.................................................................................................................... 39 3.1.4 Process-Engine............................................................................................................. 41 3.2 Praktische Umsetzung............................................................................................................ 42 3.2.1 Systemanforderungen................................................................................................... 42 3.2.2 Prototyp........................................................................................................................ 42 3.2.3 Szenarien...................................................................................................................... 53 4 Schlussbetrachtung.......................................................................................................................... 61
  • 3.
    3 4.1 Ergebnisse.............................................................................................................................. 61 4.2Bewertung.............................................................................................................................. 62 4.3 Blick in die Zukunft .............................................................................................................. 63 Abbildungsverzeichnis........................................................................................................................ 65 Abkürzungsverzeichnis....................................................................................................................... 66 Literaturverzeichnis............................................................................................................................ 68 Stichwortverzeichnis........................................................................................................................... 71
  • 4.
    4 1 Einleitung Diese Thesisbeschäftigt sich mit der Fragestellung, wie ein IDML-Server aufgebaut sein und ob die- ser Vorteile bringen kann. Es wird ein Konzept erstellt, auf dessen Basis ein IDML-Server entwickelt werden kann. Durch unterschiedliche Szenarien, die mit Hilfe des IDML-Servers abgebildet werden, können die Vorzüge eines solchen Servers aufgezeigt werden. Es folgen die sachliche Motivation, die Ziele und die Literaturdiskussion dieser Arbeit. 1.1 Sachliche Motivation In der Druck- und Medienindustrie wird zur Erstellung von Medienprodukten häufig das Programm Adobe InDesign (im weiteren Verlauf InDesign) verwendet. InDesign ist proprietär und das Dateifor- mat kann somit nur von InDesign verwendet werden. Ab der CS4 Version von InDesign hat das Unter- nehmen Adobe ein neues Dateiformat eingeführt das sich InDesign Markup Language (IDML) nennt. Dieses Format ist einmal für die Versionskompatibilität zwischen den InDesign Versionen ab CS4 verantwortlich und zum anderen für die externe Verarbeitung von InDesign-Dokumenten. Dadurch das IDML offengelegt wurde, können neue Möglichkeiten im Bereich von Automatisierungen außerhalb von InDesign entwickelt werden. IDML ist jedoch ein komplexes Dateiformat und der Umgang damit erfordert tiefes Wissen über InDesign und IDML. Um diese Komplexität beherrschbar zu machen, sind Systeme notwendig, die von IDML-Spezialisten entwickelt werden und den Umgang mit IDML zu verweinfachen. Oft kommt es in der Druck- und Medienindustrie vor, dass Kosten durch wieder- kehrende Prozesse entstehen. Häufig können solche Prozesse individuell durch IDML automatisiert werden. Ein weiterer Aspekt ist, dass einfache Aufgaben oft abhängig von InDesign sind, wodurch zusätzlicher Arbeitsaufwand sowie Lizenzkosten entstehen können. Durch den Einsatz von IDML kann in bestimmten Bereichen eine von InDesign unabhängige und in andere Systeme integrierbare Lösung geboten werden. 1.2 Ziele Diese Arbeit zeigt ein Konzept auf, mit dem der Umgang von IDML-Dateien gestaltet werden kann. Der IDML-Server fungiert dabei als ein Werkzeug, welches man für die IDML-Verarbeitung verwen- den kann. In dieser Arbeit steht der IDML-Server im Fokus. Darüber hinaus soll der produktive Ein- satz eines solchen Servers dargestellt werden. Dazu werden aus der Druck- und Medienindustrie unter- schiedliche Szenarien betrachtet, die den produktiven Einsatz eines IDML-Servers bestätigen sollen. 1.3 Leserkreis Die Arbeit ist hauptsächlich an Personen aus der Informationstechnik gerichtet, die sich mit IDML beschäftigen und dessen Einsatzmöglichkeiten betrachten wollen. Ein grundsolides Vorwissen über
  • 5.
    5 Softwareentwicklung im BereichJava und über Desktop-Publishing mit InDesign wird vorausgesetzt. Ein Vorwissen über die Themen aus dem Grundlagenkapitel ist von Vorteil. Tieferes Wissen kann und soll über die Referenzen aus dem Literaturverzeichnis herangezogen werden. 1.4 Typografische Konventionen In dieser Arbeit wird auf die typografischen Konventionen Wert gelegt, um dem Leser das komplexe Thema bestmöglich zu erläutern. Folgende Konventionen werden eingehalten: Fließtext: Die Schriftart für den Fließtext ist eine Times in der Größe 12 pt. Code: Groovy, HTML, XML, IDML, Grails-Kommandos, URLs, Parameter und alle Elemente, die darin verwendet werden, werden in der Schriftart Courier New mit 11 pt ausgezeichnet. Dateinamen: Datei-, Ordnernamen und Pfade werden in der Schriftart Times mit dem Stil Italic ausgezeichnet. Diagramm: Die Typografie in den Diagrammen wird in Arial mit 11 pt und 8 pt ausgezeichnet. 1.5 Literaturdiskussion Der Kern dieser Thesis beschäftigt sich mit der Orchestrierung der Themen aus dem Grundlagenkapi- tel zu einer Komposition - dem Konzept. Dabei wird bei den Grundlagenthemen auf ihre Kernkonzep- te eingegangen, um ein Basisverständnis zu vermitteln. Die wichtigsten Literaturangaben dieser Arbeit beziehen sich auf den Bereich der Frameworks. Da das Grails- und das Spring-Framework eine zentrale Rolle in dieser Konzeption spielen, wurde hier auf den Verweis der Primärliteratur besonderer Wert gelegt. Rod Johnson (Spring-Framework), Graeme Rocher (Grails-Framework) und Guillaume Laforge (Groovy) sind dabei die Köpfe der jeweiligen Technologien. Zum Thema IDML ist kaum Literatur vorhanden, deshalb wird hauptsächlich mit der IDML-Spezifikation gearbeitet. Diese behandelt jedoch nicht ausreichend den Einsatz von IDML, weshalb Vorwissen über InDesign und eine eigenständige Motivation zur Erarbeitung von Kenntnissen im Bereich IDML vorausgesetzt wird.
  • 6.
    6 2 Grundlagen Dieses Kapitelbeschäftigt sich mit den grundlegenden Themen, die für das Verständnis der Arbeit re- levant sind. Als Erstes wird der Begriff Softwarearchitektur beleuchtet. Hier wird vor allem erläutert, was eine Softwarearchitektur ist, welche Ziele sie verfolgt und wie diese umgesetzt werden kann. Im Kapitel 2.2 wird erläutert, was unter einem Webservice zu verstehen ist. Dabei werden die Techno- logien Simple Object Access Protocol (SOAP) und Representational State Transfer (REST) betrachtet sowie ihre Funktionsweise erläutert. Das Kapitel 2.3 beschäftigt sich mit dem Grails-Framework. Hier werden die Konzepte des Frame- works erläutert. Auch die eingesetzte Sprache Groovy wird hier betrachtet und grundsätzlich gezeigt, wie eine Grails-Applikation aufgebaut ist. Anschließend wird im Kapitel 2.4 auf die IDML eingegangen. Zunächst wird erklärt, was überhaupt InDesign ist. Danach wird das Dateiformat IDML betrachtet und sein Aufbau beschrieben. Danach wird auf die Möglichkeit eingegangen, wie dieses Format verarbeitet werden kann. In allen Grundlagenkapitel werden nur die wesentlichen Aspekte angesprochen. Genauere Informatio- nen können anhand des Literaturverzeichnisses herangezogen werden. 2.1 Softwarearchitektur In diesem Abschnitt wird der Begriff Softwarearchitektur erläutert. Es beginnt mit der Definition des Begriffes. Dann wird auf dieArchitekturmuster und Entwurfsmuster eingegangen. Diese sind abstrakte Beschreibungen einer Lösung für häufig vorkommende Probleme. Dabei betrachtenArchitekturmuster zum einen das gesamte System, während Entwurfsmuster auf sehr spezielle Probleme ausgerichtet sind. 2.1.1 Definition Softwarearchitektur befasst sich mit der Gestaltung und der Struktur eines Softwaresystems. Es exis- tiert eine Vielzahl an Definitionen. Philippe Kruchten erläutert den Begriff auf diese Weise: Software architecture deals with abstraction, with decomposition and composition, with style and esthetics. [Kruchten1995, S.1] Der Fokus von Kruchten liegt dabei auf Abstraktion, Zerlegung, Zusammensetzung, Ästhetik und Stil der Softwarearchitektur. Das Carnegie Mellon Software Engineering Institute (SEI) stellt auf seiner Webseite mehr als 100 Definitionen zur Verfügung [vgl. Carnegie2012]. Anhand dieser Sammlung kann grundsätzlich gesagt werden, dass Softwarearchitektur sich mit folgenden Aspekten beschäftigt:
  • 7.
    7 Struktur: Eine Softwarearchitekturbeschreibt die Komponenten eines Softwaresystems. Es geht hierbei nicht nur um den Aufbau, sondern auch um das Zusammenspiel, die Beziehungen und die Eigenschaften der Komponenten. Somit ist die Softwarearchitektur nicht nur der Bauplan, sondern auch der Ablaufplan des Softwaresystems. [vgl. Starke2009, S.16] Eines ihrer der Hauptziele ist es, die Komplexität eines Softwaresystems mit Hilfe einer Struktur beherrschbar zu machen. Beschreibung einer Lösung: Eine Softwarearchitektur wird in Form von Plänen realisiert. Sie beschreibt eine Lösung und besteht aus abstrakten Komponenten. Diese Pläne führen durch die konkrete Implementierung zur Realisierung eines Systems. [vgl. Starke2009, S.16] Entwurfsentscheidungen: Eine Softwarearchitektur basiert auf Entwurfsentscheidungen. Hier- bei spielt sowohl die Wahl der Technologie, als auch die Wahl des Aufbaus von Komponenten eine wichtige Rolle. [vgl. Starke2009, S.17] An dieser Stelle können Entwurfsmuster (design patterns) ansetzen, um eine Lösung für bekannte Entwurfsprobleme zu bieten. Übergang von der Analyse zur Realisierung: Eine Softwarearchitektur ist das Bindeglied zwi- schen der Analyse und der konkreten Implementierung des Softwaresystems. [vgl. Starke2009, S.17] Generell wird Software entwickelt, um ein bestehendes oder zukünftiges Problem zu lö- sen. Dieses Problem wird im Rahmen der Analyse erfasst. Die Softwarearchitektur beschreibt die Funktionsweise und den Aufbau des Systems, welches das Problem löst. Sie dient bei der Soft- wareentwicklung als Vorgehensmodel. Sichten: Eine Softwarearchitektur wird in unterschiedlichen Sichten dargestellt. Philippe Kruch- ten unterscheidet dabei die fünf folgenden Sichten: • logical view • process view • development view • physical view • scenario Durch die Sicht auf die Architektur aus einem bestimmten Blickwinkel kann die Architektur ge- nauer betrachtet und gestaltet werden, da andere Bereiche so ausgeblendet werden. Eine genaue Erläuterung der Sichten ist zu finden unter: [Kruchten1995, S.1f]. Verständlichkeit: Eine Softwarearchitektur schafft Ordnung und ermöglicht einen Überblick über das System. Um die Komplexität eines Systems verständlich zu machen, werden die Anforderun- gen in Strukturen überführt und dokumentiert. Die Dokumentation ist hierbei ein wichtiger Punkt.
  • 8.
    8 Denn nur sokönnen alle Beteiligten ein Verständnis über die einzelnen Komponenten und deren Zusammenspiel bekommen. [vgl. Starke2009, S.18] Flexibilität: Eine Softwarearchitektur sorgt dafür, dass das Softwaresystem weiterentwickelt wer- den kann. Die Software muss einen Aufbau gewährleisten, der es ermöglicht, das System flexibel zu erweitern. [vgl. Starke2009, S.19] Das bedeutet auch, dass in der Praxis generell keine perfekte Softwarearchitekturen entstehen, da diese häufig nicht flexibel hinsichtlich ihrer Weiterentwick- lung sind. [vgl. Wolff2009] Abstraktion: Eine Softwarearchitektur beschreibt ein abstraktes System. Dabei werden Informa- tionen bewusst weggelassen, um die Verständlichkeit des Systems zu erhöhen. Die wesentlichen Kerneigenschaften der Software werden in einer Softwarearchitektur dargestellt. [vgl. Starke2009, S.19] Qualität: Eine durchdachte Softwarearchitektur kann die Qualität der Software erhöhen. Die Qua- lität besteht aus mehreren Kriterien, wie zum Beispiel Performance, Verständlichkeit, Flexibilität etc. [vgl. Starke2009, S.19] Um diese Aspekte auch realisieren zu können, wird häufig auf bestehende Methoden wie beispielswei- se Architekturmuster zurückgegriffen. 2.1.2 Architekturmuster Architekturmuster unterstützen bei der Entwicklung eines Softwaresystems, da sie dieses aus einer abstrakten und ganzheitlichen Sicht beschreiben. Im Folgenden wird das Schichtenmuster und das Model View Controller (MVC) Muster erläutert. Diese sind für die spätere Umsetzung relevant: Schichtenmuster: Das Schichtenmuster hat die Aufgabe, Struktur zu schaffen. Das Softwaresys- tem wird dabei in unterschiedliche Schichten unterteilt (layering). Jede Schicht hat eine Aufgabe und bietet der darüber liegenden Schicht eine definierte Anzahl an Diensten an. Der Aufbau eines solchen Systems wird häufig mit einer Zwiebel verglichen. Jede Schicht kapselt ihre internen De- tails und verbirgt die darunter liegenden Schichten. Die Nutzung der Dienste einer Schicht erfolgt generell über die darüber liegende Schicht. Eine Mehrfachnutzung von Diensten durch andere Schichten ist zu vermeiden, da die Abhängigkeiten der Schichten dadurch erhöht werden. [vgl. Starke2009, S.149f] Eine mögliche Aufteilung der Schichten für ein Softwaresystem wäre die Unterteilung in: Daten-, Domänen-, Anwendungs- und Präsentationsschicht.
  • 9.
    9 Folgende Vor- undNachteile ergeben sich durch den Einsatz eines Schichtenmusters: Vorteile • Unabhängigkeit der Schichten in der Erstellung und im Betrieb • Implementierung einer Schicht kann aufgrund ihrer Unabhängigkeit ausgetauscht werden • Minimierung der Abhängigkeiten zwischen Komponenten des Systems • Leicht zu verstehendes Strukturkonzept [vgl. Starke2009, S.150] Nachteile • Beeinträchtigung der Performance, da eine Anfrage unter Umständen durch mehrere Schich- ten durchgereicht werden muss • Erweiterungen eines Systems beinhaltet oft Änderungen in alle Schichten [vgl. Starke2009, S.150f] MVC: Das MVC Muster ist ein Quasi-Standard bei objektorientierten Anwendungen. Es dient der Strukturierung von Softwaresystemen und beinhaltet die Einteilung in drei Einheiten: Model (Datenmodell), View (Präsentation) und Controller (Programmsteuerung). Ziel des MVC Musters ist es, eine bessere Wartbarkeit und Flexibilität der Software zu erreichen. [vgl. Starke2009, S.246] Abbildung 1 zeigt den Ablauf des MVC Musters. Dabei stellen die durchgezogenen Pfeile direkte und die gestrichelten indirekte Assoziationen dar. • Das Model stellt den Programmteil dar, der die bearbeiteten Daten verwaltet. • Die View stellt einen Zustand der Anwendung dar. Sie ist verantwortlich für die Anzeige der Daten. • Der Controller ist für die Steuerung verantwortlich. Er interpretiert die Operationen, die über die View kommen und bestimmt den Folgezustand der Anwendung. [vgl. Starke2009, S.247] Abb. 1 MVC Ablauf [vgl. Starke2008, S.247] Model View Controller Statusabfrage Statusänderung Neuer Status View anzeigen Benutzer Eingabe
  • 10.
    10 Diese beiden Architekturmusterwerden häufig verwendet, um die ganzheitliche Sicht eines Systems zu organisieren. Oft tauchen während der Implementierungsphase jedoch auch Probleme auf, die nicht mit Architekturmustern abgedeckt werden können. Hier setzen Entwurfsmuster an. 2.1.3 Entwurfsmuster Ein Entwurfsmuster (design pattern) ist die abstrakte Beschreibung einer Lösung für ein häufig vor- kommendes Problem. Allgemein betrachtet besitzt ein Muster vier Elemente: Mustername: Der Mustername ist die aussagekräftige Benennung des Entwurfsproblems und der Lösung mit ein oder zwei Worten. Sie erweitert das Entwurfsvokabular und sorgt für einen einfa- chen Umgang bei der Dokumentation und der Kommunikation mit anderen. [vgl. Gamma2011, S.3] Problemabschnitt: Der Problemabschnitt beschreibt, wann das Entwurfsmuster anzuwenden ist, welches Problem es löst und in welchem Kontext es sich befindet. Es beschreibt spezifische Ent- wurfsprobleme und Bedingungen, die erfüllt sein müssen. [vgl. Gamma2011, S.3] Lösungsabschnitt: Der Lösungsabschnitt beschreibt die Elemente des Entwurfs und deren Be- ziehungen, Zuständigkeiten und Interaktionen. Die dargestellte Lösung ist als eine Schablone zu sehen, die in unterschiedlichen Situationen Anwendung finden kann. [vgl. Gamma2011, S.4] Konsequenzabschnitt: Der Konsequenzabschnitt beschreibt die Vor- und Nachteile des Ent- wurfs. Diese sind relevant für die Beurteilung des Entwurfs gegenüber anderen Alternativen. [vgl. Gamma2011, S.4] Es gibt unterschiedliche Arten von Entwurfsmustern. Erich Gamma klassifiziert sie nach drei Aufga- benbereichen: Erzeugung: Die Erzeugungsmuster sind dafür zuständig, Objekte zu erzeugen. Sie kapseln den Prozess der Erzeugung und vereinfachen den Umgang damit. Der Einsatz von Erzeugungsmustern gewährleistet die Kontrolle über den Erzeugungsprozess, da in einem Muster entschieden wird, was, wer, wann und wie erzeugt wird. [vgl. Gamma2011, S.101] Struktur: Die Strukturmuster sind dafür zuständig, den Aufbau von Objekten und deren Bezie- hungen untereinander zu vereinfachen. Der Einsatz von Strukturmuster kann die Komplexität ei- ner Software minimieren. [vgl. Gamma2011, S.169] Verhalten: Die Verhaltensmuster schaffen einen einheitlichen Umgang in der Kommunikation
  • 11.
    11 zwischen den Objekten.Der Einsatz von Verhaltensmustern kann die Flexibilität der Software im Bereich der Kommunikation zwischen Objekten erhöhen. [vgl. Gamma2011, S.271] Entwurfsmuster werden häufig in Frameworks verwendet. Für die spätere Umsetzung werden hier einige kurz dargestellt: Singleton: Das Singleton Entwurfsmuster gehört zu den Erzeugungsmustern und ist objektbasie- rend. Der Zweck des Musters ist die Erzeugung genau eines Exemplars einer Klasse mit einem globalen Zugriff darauf. Um dies zu gewährleisten, wird die Zuständigkeit der Verwaltung des Exemplars in die Klasse gelegt. Die Klasse selber kann somit entscheiden, ob ein neues Objekt erzeugt werden muss, oder nicht. [vgl. Gamma2011, S.157f] Builder: Das Builder Entwurfsmuster gehört zu den Erzeugungsmustern und ist objektbasierend. Der Zweck des Musters ist die Vereinfachung der Erzeugung von komplexen Objekten. Es trennt die Erzeugung des Objektes von seiner Representation. Somit kann derselbe Erzeugungsprozess unterschiedliche Representationen hervorbringen. [vgl. Gamma2011, S.119f] Command: Das Command Entwurfsmuster ist ein Verhaltensmuster und ist objektbasierend. Der Zweck des Musters ist die Vereinfachung bei Ausführung mehrerer komplexer Aktionen. Dabei wird eine Anfrage in ein Command gekapselt. Durch das Ausführen eines Commands werden mehrere Aktionen ausgeführt, die von außen nicht ersichtlich sind. Entwurfsmuster werden auch häufig miteinander kombiniert. Zum Erzeugen von Commands kann zum Beispiel das Builder Entwurfsmuster verwendet werden. [vgl. Freeman2004, S.206] State: Das State Entwurfsmuster gehört zu den Verhaltensmustern und ist objektbasierend. Der Zweck des Musters ist es Objekten die Möglichkeit zu geben, ihren Zustand zu definieren und auf diesen aufmerksam zu machen. Eine Kombination mit dem Command-Entwurfsmuster könnte so aussehen, dass sich bei der Beendigung der Ausführung eines Commands der Zustand eines Objekts ändert und darauf aufmerksam macht, dass diese Ausführung beendet wurde. [vgl. Free- man2004, S.410] Diese Entwurfsmuster lösen spezielle Probleme und bringen oft mehr Organisation und Struktur in eine Software. Ein weiterer wichtiger Aspekt von Softwaresystemen ist die Bedienung. Oftmals wird die Bedienung des Systems über eine Benutzeroberfläche realisiert. Ist das System jedoch auf die Kommunikation mit anderen Maschinen ausgerichtet, so kann die Kommunikation über einen Webservice stattfinden.
  • 12.
    12 2.2 Webservice Der folgendeAbschnitt beginnt mit der Definition des Begriffs Webservice. Danach werden wie zuvor erwähnt die Technologien SOAP und REST beschrieben und ihre Funktionsweise voneinander abge- grenzt. 2.2.1 Definition In der Literatur und in verschiedenen Fachzeitschriften existiert eine Vielzahl von Definitionen des Begriffs Webservice. Das Standardisierungsgremium World Wide Web Consortium (W3C) bietet fol- gende Definition an: A Web service is a software system designed to support interoperable machine-to- machine interaction over a network. It has an interface described in a machine-pro- cessable format (specifically WSDL). Other systems interact with the Web service in a manner prescribed by its description using SOAP messages, typically conveyed using HTTP with an XML serialization in conjunction with other Web-related standards. [Booth2004] Dabei fällt auf, dass das W3C in dieser Definition weitere Technologien aufführt, wie zum Beispiel: Web Service Description Language (WSDL), SOAP, Hypertext Transfer Protocol (HTTP) und Exten- sible Markup Language (XML). Der Begriff Webservice wird im weiteren Verlauf ohne die genannten Abhängigkeiten verstanden und kann unter gegebenen Umständen andere Formate und Technologien implementieren. Die Kernauf- gabe von Webservices, sind die Maschine zu Maschine Interaktion über ein Netzwerk und über einem plattformunabhängigen Kommunikationsformat. 2.2.2 SOAP Ursprünglich wurde SOAP von UserLand, DevelopMentor, IBM und Microsoft entwickelt. In der Ver- sion 1.1 wurde SOAP als Kommunikationsprotokoll betrachtet. Aktuell liegt SOAP in der Version 1.2 vor, in der es mehr die Funktion eines Messaging-Framework übernimmt. [vgl. Frotscher2007, S. 28] Um strukturierte Daten versenden zu können, ist eine Transportmöglichkeit notwendig. Bei einem Webservice erfolgt dies in den häufigsten Fällen über HTTP. Dabei stellt sich die Frage, wie diese Daten vorliegen. SOAP bietet hier eine XML basierte Lösung. Relevant für diese Kommunikation ist die SOAP-Nachricht und das WSDL: SOAP-Nachricht: Eine SOAP-Nachricht basiert auf XML und besteht aus einem Envelope. In diesem wird der Namesraum der Nachricht definiert:
  • 13.
    13 <?xml version="1.0" encoding="UTF-8"?> <env:Envelopexmlns:env="http://www.w3.org/2001/12/soap-envelope"> <env:Header> </env:Header> <env:Body> </env:Body> </env:Envelope> In dem Envelope befindet sich ein optionaler Header und ein zwingend erforderlicher Body. Der Header enthält mehrere Headerblöcke, die Angaben zu Routing, Auslieferung, Authentifizie- rung, Autorisierung und Transaktionskontexte beinhalten können. Der Body beinhaltet die eigent- liche Nachricht, die ausgeliefert und verarbeitet werden soll. [vgl. Snell2002, S.15f] Abb. 2 SOAP-Nachricht WSDL: WSDL ist eine XML-Spezifikation. Es handelt sich um eine Sprache, die es ermöglicht, einen Webservice standardisiert zu beschreiben. Die Beschreibung enthält alle notwendigen In- formationen, um den Webservice anwenden zu können. Darin enthalten sind alle Operationen der zu versendenden Nachrichten und Datentypen. Außerdem kann WSDL definieren, wie dieser Webservice aufzurufen und unter welcher Adresse er zu erreichen ist. Werden diese Vorgaben ein- gehalten, kann über Code-Generierung die Interaktion mit dem Webservice automatisiert werden. WSDL ist wie auch SOAP plattformunabhängig. [Frotscher2007, S.44] 2.2.3 REST REST ist generell keine festgelegte Norm. In der Literatur und in Fachzeitschriften weichen die Mei- nungen voneinander ab. Die Grundidee ist, dass über ein Uniform Resource Identifier (URI) eine serverseitige Aktion ausge- führt werden kann, die genau ein Ergebnis liefert. Das erfolgt bei REST in den häufigsten Fällen über HTTP. [vgl. Fielding2000] Im Folgenden wird dargestellt, welche HTTP Standardmethoden REST im Webanwedungskontext hauptsächlich verwendet: Envelope Header Body
  • 14.
    14 GET: Beim Aufrufeiner GET-Methode wird vom Server eine Ressource gefordert. Dabei kann eine GET-Anfrage beliebig oft abgesendet werden. Die Methode kann ähnlich betrachtet werden wie die Read-Methode bei Datenbankoperationen. [vgl. Bayer2002] POST: Beim Aufruf einer POST-Methode wird vom Server eine Änderung einer Ressource gefor- dert. Dabei können Prozesse oder Datenbankfelder verändert werden. Die Methode kann ähnlich betrachtet werden, wie die Update-Methode bei Datenbankoperationen. [vgl. Bayer2002] PUT: Beim Aufruf einer PUT-Methode wird vom Server eine Änderung einer Ressource gefordert oder eine neue erzeugt. Die Methode kann ähnlich betrachtet werden, wie die Kombination aus Create- und Update-Methode bei Datenbankoperationen. [vgl. Bayer2002] DELETE: Beim Aufruf einer DELETE-Methode wird vom Server die Entfernung einer Ressour- ce gefordert. Die Methode kann ähnlich betrachtet werden, wie die Delete-Methode bei Daten- bankoperationen. [vgl. Bayer2002] 2.3 Grails Dieser Abschnitt stellt die wesentlichen Aspekte des Grails-Framework dar. Es beginnt mit der Ein- ordnung des Frameworks in der Java-Welt. Darauf folgt die Betrachtung der Sprache Groovy, die ein wesentlicher Bestandteil des Frameworks ist. Außerdem wird auf das Spring-Framework eingegangen sowie die Konzepte des Grails-Frameworks. Im letzten Abschnitt wird der Aufbau einer Grails-Appli- kation betrachtet. 2.3.1 Einordnung Das Grails-Framework baut auf bestehenden Standards auf, die sich in der Industrie durchgesetzt ha- ben. Spring und Hibernate sind dabei die wesentlichen Frameworks die Grails verwendet. Abbildung 3 veranschaulicht die Beziehungen: Abb. 3 Grails Einordnung [vgl. Rocher2009, S.3] Java Virtual Machine Java Groovy JDK Java EE Spring Hibernate SiteMash Grails
  • 15.
    15 SiteMesh ist dabeiein Layout Framework mit dem es möglich ist, Seitendekorationen in der View auf einfachem Weg zu gestalten. Das Hibernate-Framework ist ein Persistenz-Framework und behandelt Object Relational Mapping (ORM) mit dem es möglich ist, Plain Old Java Objects (POJOs) in relationalen Datenbanken zu spei- chern. Im Folgenden wird auf die Sprache Groovy und auf das Spring-Framework eingegangen, wel- ches die Kerntechnologien des Grails-Frameworks sind. [vgl. Rocher2009, S.2f] 2.3.2 Groovy Groovy ist eine dynamische Programmiersprache, die in der Java Virtual Machine (JVM) läuft. Es liegt mit der Sprache Java auf einer Ebene und bedient sich auch ihrer. Groovy kann somit als eine Erweiterung von Java angesehen werden. Abb. 4 Groovy/Java Plattform [vgl. Grandeur2009, S.11] James Strachan, der die Grundidee für Groovy hatte, wurde bei der Entwicklung von Groovy von den Eigenschaften der Sprachen Python, Ruby und Smalltalk inspiriert. [vgl. König2007, S.3f] Es folgen die wesentlichen Besonderheiten von Groovy gegenüber Java: Dynamisch: Groovy ist eine dynamisch typisierte Sprache. Das bedeutet, anders als bei Java, welche statisch typisiert ist, kann zur Laufzeit der geschriebene Groovy Code manipuliert werden. Dadurch ist die Sprache flexibler für den Entwickler. Das zeichnet sich vor allem darin aus, dass die Entwicklung mit einer dynamischen Sprache oft schneller ist, da die Syntax der Sprache kür- zer gehalten und aussagekräftiger ist. Dem gegenüber steht die langsamere Geschwindigkeit bei der Ausführung. Dadurch, das während der Laufzeit der Code verändert werden kann, und somit neu kompiliert werden muss, können bei der Geschwindigkeit Einbußen entstehen. [vgl. Gran- deur2009, S.12] Import: Das Groovy Development Kit (GDK) erweitert das Java Development Kit (JDK) mit zusätzlichen Methoden und der funktionalen Erweiterung durch Closures. Dabei werden automa- tisch folgende Importierungen eingebunden: Plattform (Linux, Windows...) Java Virtual Machine JavaGroovy
  • 16.
    16 • groovy.lang.*; • groovy.util.*; • java.lang.*; • java.util.*; • java.net.*; • java.io.*; • java.Math.BigInteger; • java.Math.BigDecimal; [Davis2008, S.42] Zusätzlich wird eine Anzahl an Methoden verkürzt. Beispielsweise wird System.out.print in Groovy mit print aufgerufen. [vgl. Grandeur2009, S.13] Closure: Eines der wichtigsten Konzepte in Groovy ist das Konzept der Closure. Sie stammen aus dem Bereich der funktionalen Programmierung und sorgen für mehr Flexibilität. Es sind Code- blöcke, die referenziert und als Argument oder Rückgabewert in anderen Funktionen verwendet werden können. [vgl. König2007, S.130f] Die Syntax eines Closure ist wie folgt definiert [vgl. Groovy2012]: { [closureArguments->] statements } Dabei ist closureArguments-> eine optionale, kommagetrennte Liste von Argumenten. Wenn nur ein Argument verwendet wird, wird automatisch auf das Argument mit dem Schlüsselwort it referenziert. [vgl. Grandeur2009, S.19] def sayIt = { println "Hallo $it"} sayIt "Welt!" //Ausgabe: "Hallo Welt!" def sayValue = {value -> println "Hallo $value"} sayValue "Welt!" //Ausgabe: "Hallo Welt!" Semikolon: In Groovy ist der Einsatz von Semikolons vollkommen optional. Nur beim mehr- fachen Aufruf in einer Zeile sind Semikolons notwendig. [Davis2008, S.42]
  • 17.
    17 print 'Hallo' print 'Welt!' //Ausgabe:Hallo Welt! print 'Hallo'; print 'Welt!'; //Ausgabe: Hallo Welt! Datentypen: In Groovy müssen keine Datentypen definiert werden. Stattdessen wird das Schlüs- selwort def verwendet. Dabei stellt Groovy zur Laufzeit fest, um welchen Datentyp es sich han- delt. [vgl. Grandeur2009, S.13f] def word = 'Hallo Welt!' print word.class //Ausgabe: java.lang.String def append(word){ 'Hallo ' + word } append('Welt!') //Input: String, Ausgabe: Hallo Wellt! Integer i = 20 append(i) //Input Integer, Ausgabe: Hallo 20 GString: Groovy hat eine eigene erweiterte Implementierung des Strings genannt Groovy-String (GString). GString erlaubt dem Entwickler die Einbindung in einen String mit den Auszeichnun- gen $ und {}. [vgl. Grandeur2009, S.14f] def word = "Welt!" def gstring= "Hallo ${word}" println word.class //Ausgabe: class java.lang.String println gstring //Ausgabe: Hallo Welt!
  • 18.
    18 println gstring.class //Ausgabe: classorg.codehaus.groovy.runtime.GStringImpl Collections: In Groovy gibt es drei Arten von Collections: List, Map und Range. List und Map sind von der funktionsweise genauso wie in Java verwendbar, nur die Darstellung ist eine andere. Ranges hingegen sind sehr speziell und bei dynamischen Sprachen einmalig. [vgl. Grandeur2009, S.16] def list =['a', 'b', 'c', 'd', 'e'] def map = [0:'a', 1:'b', 2:'c'] def range= 1..10 println list.get(0) //Ausgabe: a println map.get(1) //Ausgabe: b println range //Ausgabe [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Return: In Groovy ist das return Statement am Ende einer Methode optional. Groovy gibt au- tomatisch die letzte Zeile zurück. [vgl. Grandeur2009, S.17] def method(){ "Hallo Welt!" } print method() //Ausgabe: Hallo Welt! NULL-Check: In Groovy können Objekte durch ein ? auf NULL geprüft werden. Dadurch kön- nen NullPointerExceptions vermieden werden. [vgl. Grandeur2009, S.17] def string = "Hallo Welt!" println string.size() //Ausgabe: 12
  • 19.
    19 def empty =null println empty.size() //Ausgabe: java.lang.NullPointerException: Cannot invoke method size() on null object println empty?.size() //Ausgabe: null Scripting: Ein weiterer wesetlicher Unterschied zu Java ist, dass Groovy skriptfähig ist. Ist Groo- vy auf einem Betriebsystem installiert, so können ohne weiteres Skripte erstellt und ausgeführt werden. Es ist nicht zwingend notwendig wie in Java Klassen zu erstellen. Ein einfaches Skript (test.groovy) könnte wie folgt aussehen: #!/usr/bin/env groovy println "Hallo Welt!" XML: Groovy bietet eine einfache Möglichkeit über Groovy-Path (GPath) mit XML umzugehen. <?xml version="1.0" encoding="UTF-8"?> <customers> <corporate> <customer name="Bill Gates" company="Microsoft"/> <customer name="Steve Jobs" company="Apple"/> <customer name="Jonathan Schwartz" company="Sun"/> </corporate> </customers> Um diese XML nun einlesen zu können wird der XmlSlurper verwendet: def customers = new XmlSlurper().parse(new File("test.xml")) customers.corporate.customer.each{ println "${it.@name} works for ${it.@company}" } /*Ausgabe: Bill Gates works for Microsoft Steve Jobs works for Apple
  • 20.
    20 Jonathan Schwartz worksfor Sun */ 2.3.3 Spring Spring ist ein Open-Source-Framework. Es liefert zur Entwicklung einer Anwendung Fertigbausteine, um die Entwicklung zu vereinfachen. Dabei ist Spring leichtgewichtig und flexibel, da es keine Vor- gaben hinsichtlich der Architektur macht. Es liefert eine Menge an Libraries, die eingebunden werden können, aber nicht zwingend erforderlich sind. Außerdem hat es den Anspruch, den Anwendungscode unabhängig gestalten zu können, sodass es wiederverwendbar ist und auch ohne das Spring-Frame- work eingesetzt werden kann. [vgl. Oltmanns2007, S.] Das Spring-Framework ist in mehrere Module aufgeteilt. Vollständigkeitshalber werden im folgenden Diagramm diese aufgeführt: Abb. 5 Spring Modules [vgl. SpringDocu2012] Der Core-Container ist das wichtigste Modul im Framework, da es sich mit den Kernkonzepten befasst. Inversion of Control (IoC) und Dependency Injection (DI) sind dabei die fundamentalsten Konzepte. IoC: IoC ist abstakt zu betrachten und befasst sich mit dem Lebenszyklus von Objekten. Das Hol- lywood Principle verdeutlich dieses Konzept: "Don´t call us, we´ll call you". [vgl. Johnson2004, S.128f], [vgl. Johnson2005, S.8f], [vgl. Freeman2004, S.296f] Spring Framework Runtime Data Access/Integration AOP Web (MVC/Remoting) Aspects Intrumentation Core Container Test Beans Core Context Expression Language Web Portlet Servlet Struts JDBS ORM OXM JMS Transactions
  • 21.
    21 DI: DI isteine Spezialisierung von IoC und wird auf zwei Wegen eingesetzt: Die erste Möglich- keit ist Setter-Injection. Dabei wird über eine Setter-Methode ein Objekt injiziert. Die zweite Mög- lichkeit ist die Constructor-Injection. Hierbei wird über den Konstruktor ein Objekt injiziert. Bei beiden Möglichkeiten wir die Konfiguration der Klassen entweder über Annotationen oder über eine externe XML-Datei konfiguriert. 2.3.4 Konzepte Das Grails-Framework hat zum Ziel, die Java Enterprise Web Entwicklung zu vereinfachen und auf die nächste Ebene der Abstraktion zu heben. Es bietet Möglichkeiten die andere Frameworks seit Jah- ren bieten aber bislang nicht in der Java-Welt auf einfachem Wege verfügbar waren. Der Anspruch an die Flexibilität ist dabei ein wesentlicher Punkt, den das Grails-Framework bietet. Das Framework ori- entiert sich dabei an Frameworks wie Ruby on Rails, Django und TurboGears und bringt die Vorteile dieser Frameworks in die Java Welt. [vgl. Rocher2009, S.1] Die wesentlich Konzepte, die das Grails Framework verfolgt, sind Convention over Configuration (CoC) und Don´t Repeat Yourself (DRY): CoC: Bei CoC geht es um die Vereinfachung der Konfiguration einer Software. Dabei einigt man sich auf Konventionen, wie beispielsweise gleichartige Benennungen, die dann dafür sorgen, dass Konfigurationen wegfallen können. Ein Beispiel dafür ist die Benennung von Datenbanktabellen und das Mapping dieser auf eine Klasse. Durch den Einsatz von CoC kann erheblich an Konfigu- ration eingespart werden, was durch das einheitliche Vorgehen die Verständlichkeit des Systems erhöht und die Fehleranfälligkeit reduziert. DRY: Bei DRY geht es um die Vermeidung von Redundanzen. Ein Problem bei der Softwareent- wicklung ist, dass der Entwickler in einer ständigen Wartungsphase ist. Sobald sich Anforderun- gen verändern, müssen diese aufgenommen und im Code angepasst werden. Bei einem redun- danten Code ist dies sehr aufwändig, da dieser an mehreren Stellen anpasst werden muss. Dies ist folglich zeit- und kostenintensiv. Durch das DRY-Prinzip wird dieses Problem minimiert. [vgl. Hunt2003, S.25f] 2.3.5 Applikation Eine Grails-Applikation ist auf einfachem Weg zu erstellen. Ist Grails auf dem Betriebssystem instal- liert, so gibt es eine Menge an vordefinierten Kommandos, welche bei der Entwicklung hilfreich sind. Der Aufbau der Kommandos sieht dabei wie folgt aus: grails [command name]
  • 22.
    22 Um eine Grails-Applikationzu erstellen wird das Kommando grails create-app verwendet. Dieses Kommando fordert einen Namen für die Applikation. Nach Eingabe des Namens werden alle notwendigen Dateien erstellt. Der Aufbau einer Grails-Applikation sieht dabei wie folgt aus: Abb. 6 Grails Applikation Die application.properties Datei hält Properties, die angepasst werden können. In dieser Datei sind beispielsweise die Versionsnummer und auch der Name der Applikation definiert. In dem grails-app Ordner findet die Hauptentwicklung der Applikation statt. Hier sind Ordner zu fin- den, die unterschiedliche Bereiche abdecken: config: Alle relevanten Konfigurationsdateien für die Applikation sind in diesem Konfigurations- ordner enthalten. Die BootStrap.groovy Datei ermöglicht vor dem Start der Applikation oder nach dem Herunterfah- ren der Applikation zusätzlichen Code auszuführen. So kann diese beispielsweise dazu verwendet werden, einen Defaultbenutzer anzulegen, der beim Start der Applikation erzeugt wird. Die BuildConfig.groovy Datei ist zuständig für das Buildmanagement der Applikation. Hier kön- nen beispielsweise Maven-Repositories und Grails-Plugins eingebunden werden. Die Config.groovy ist für die Konfiguration der Applikation gedacht. Hier werden Log4J, Enco- ding und weitere Konfigurationsmöglichkeiten geboten. Die DataSource.groovy behandelt die Konfiguration der Datenquelle. Wird in der Applikation mit einer Datenbank gearbeitet, so besteht hier die Möglichkeit für unterschiedliche Umgebungen (Entwicklungsumgebung, Testumgebung, Produktionsumgebung) eigene Datenbanken zu konfi- gurieren. Der hibernate und spring Ordner ist optional nutzbar. Gibt es beispielsweise Java-Klassen in dem
  • 23.
    23 src Ordner, dieals Bean in der Grails-Applikation verwendet werden sollen, so kann diese hier eingebunden werden. Die Spring-Konfiguration kann dann als XML oder in Groovy definiert wer- den. Die UrlMappings.groovy definiert ein einheitliches Uniform Resource Locator (URL) Verhalten der Applikation. domain: In dem domain Ordner werden die Domain-Klassen abgelegt. Die Erzeugung kann über das Kommando grails create-domain-class erfolgen. Wird eine Domain-Klasse erzeugt, sind Objekte dieser Klasse immer direkt auch Objekte, welche in der Datenbank abgelegt werden können. Zu der Domain-Klasse Person gibt es beispielsweise direkt auch eine Datenbank-Tabelle dazu. Domain-Klassen können außerdem constraints besitzen. Das sind Angaben zu Attributen der Klasse, die bei der Erzeugung eines Objekts validiert werden. [vgl. Rocher2009, S.45f] class Person { String firstname String lastname int age String emailadress static constraints{ firstname(blank: false) lastname(blank: false) age(min: 1) emailadress(email: true) } } Der Validator blank: false sorgt dafür, dass die Werte firstname und lastname nicht leer sein dürfen. min:1 dagegen prüft, ob der Wert age mindestens bei 1 liegt. Der Validator email: true überprüft, ob der Wert emailadress eine valide Email-Adresse ist. Grails bietet im Bereich der Domainklassen ein Grails Object Relational Mapping (GORM). Dies erleichtert den Umgang mit den Objekten und stellt gleichzeitig Create, Read, Update, Delete (CRUD) Funktionalität zur Verfügung. Um ein Objekt aus der Datenbank auszulesen wird die get() Methode verwendet. def person = Person.get(id)
  • 24.
    24 Dabei fällt auf,dass die Klasse Person keine get() Methode definiert. Alle Domain-Klassen bekommen zur Laufzeit diese Methoden hinzugefügt. Grails ermöglicht dies mit Groovy über Me- taprogramming. [vgl. Rocher2009, S.249f] Um mehrere Personen als Liste zurück zu bekommen kann die getAll() Methode verwendet werden: def persons = Person.getAll(1,2,3) Die list() Methode bietet zusätzliche Funktionen wie beispielsweise die Sortierungsfunktion: def persons = Person.list(sort:'age', order:'desc') Um ein Objekt in der Datenbank zu speichern oder zu aktualisieren, wird die save() Methode verwendet: def newPerson = new Person(params) newPerson.save() def person = Person.get(id) person.save() Dabei stellt im Hintergrund Hibernate automatisch fest, ob es ein Structured Query Language (SQL) INSERT oder ein UPDATE verwenden muss. [vgl. Rocher2009, S.251] Zum Löschen eines Objektes wird die delete() Methode angewandt: person.delete() Zum Suchen eines bestimmten Objekts aus der Datenbank bietet GORM die Dynamic-Finders. [vgl. Rocher2009, S.255f] Diese setzen sich aus den Klasseneigenschaften und Schlüsselwörtern zusammen: Person.findByFirstnameAndLastname("John","Doe") service: In dem service Ordner werden Service-Klassen abgelegt. Erzeugen kann man diese über das Kommando grails create-service. Service-Klassen sind in Grails standardmäßig Sin- geltons. Sie können über das Autowiring-Konzept von Spring automatisch über DI in einem Ser- vice oder einem Controller injiziert werden. [vgl. Rocher2009, S.289f]
  • 25.
    25 class PersonController{ defpersonService ... } Eine Service-Klasse arbeitet im Normalfall mit den Domain-Klassen und repräsentiert die Busi- nesslogik der Anwendung. Die Operationen in der Service-Klasse können Datenbankänderungen behandeln. Somit müssen die Service-Klassen transaktional sein. Jede bietet die Möglichkeit die Transaktionalität zu setzen. [vgl. Rocher2009, S.295f] class PersonService{ boolean transactional = true ... } Transaktionalität wird beschrieben durchAtomicity, Consistency, Isolation und Durability (ACID): • Atomicity bedeutet, dass jede atomare Operation in der Transaktion entweder ganz oder gar nicht ausgeführt wird. • Consistency bedeutet, dass nach der Ausführung einer Transaktion die Datenbank konsistent sein muss - vorausgesetzt sie war auch vorher konsistent. • Isolation bedeutet, es wird verhindert, dass mehrere parallel laufende Operationen sich gegen- seitig behindern. • Durability bedeutet, dass nach einer Transaktion gewährleistet wird, dass die Daten dauerhaft in der Datenbank abgespeichert werden. [vgl. Rocher2009, S.295f] Service-Klassen können unterschiedliche scopes aufweisen. Bei Bedarf kann diese Eigenschaft angepasst werden. [vgl. Rocher2009, S.297f] class PersonService{ boolean transactional = true static scope = 'request' } Das Schlüsselwort request bedeutet hier, dass für jede Anfrage ein Service erzeugt wird.
  • 26.
    26 controller: In demcontroller Ordner werden Controller-Klassen abgelegt. Erzeugen kann man diese mit dem Kommando grails create-controller. Controller-Klassen behandeln die eingehenden Anfragen. Sie entscheiden wie die Anfrage verarbeitet wird und liefern ein Ergebnis an den Anfragenden. [vgl. Rocher2009, S.65f] class PersonController{ def index = {} } Ein Controller kann mehrere Closures beinhalten. Jeder Closure ist eine eigene Action und kann über die URL angesteuert werden (/person/index). Der Name des Clousures (hier: index) wird automatisch für die View verwendet (CoC). Somit wird vorausgesetzt, dass eine View mit dem Dateinamen index.gsp existiert. Um eine individuelle View zu rendern, gibt es die Möglich- keit diese explizit zu setzen. [vgl. Rocher2009, S.76f] class PersonController{ def show = { render(view:myview, model[person: Person.get(id)]) } } Die View muss hier myview.gsp lauten und das Objekt, welches an die Person übergeben wird, lautet person. Controller-Klassen bieten außerdem noch Aspect-Oriented-Programming (AOP) in Form von In- terceptors. Somit kann vor oder nach einem Closure zusätzlicher Code ausgeführt werden. [vgl. Rocher2009, S.90f] def beforeInterceptor = { log.trace("Executing action $actionName with params $params") } def afterInterceptor = {model-> log.trace("Executed action $actionName result model: $model") } Controller-Klassen können als Rückgabe an die View direkt auch XML oder JavaScript Object Notation (JSON) zurückgeben. Dies wird im Zusammenhang mit Asynchronous JavaScript and
  • 27.
    27 XML (AJAX) oderbeispielsweise direkt als Webservice verwendet. Die einfachste Möglichkeit, die Grails hier bietet, sind die grails.converters.*. import grails.converters.XML def person = Person.get(id) render person as XML import grails.converters.JSON def person = Person.get(id) render person as JSON Eine weitere Funktion die Grails bietet ist das Scaffolding. Scaffolding hilft unerfahrenen Ent- wicklern beim Start mit dem Grails-Framework. Außerdem wird es oft im Bereich des Prototyping eingesetzt, um eine erste Version zu erstellen. Scaffolding kann in Grails dynamisch und statisch verwendet werden. Das dynamische Scaffolding von einer CRUD-Anwendung erzeugt während der Laufzeit die Controller Logik und die Views. Um das Scaffolding zu aktivieren, wird das At- tribut scaffold mit der jeweiligen Domainklasse gesetzt. [vgl. Rocher2009, S.19f] class PersonController{ def scaffold = Person } Beim statischen Scaffolding werden einmalig der Controller und die dazugehörigen Views gene- riert. Mit dem Kommando grails generate-controller wird der Controller erzeugt. Mit dem Kommando grails generate-views werden die dazugehörigen Views erzeugt. Möchte man beides mit einem Kommando generieren lassen, kann das Kommando grails generate- all verwendet werden. [vgl. Rocher2009, S.27f] views: In dem views Ordner werden die Groovy Server Pages (GSP) abgelegt. Sie sind an die Java Server Pages (JSP) angelehnt, haben jedoch Vorteile, die durch die Sprache Groovy mitgebracht werden, wie beispielsweise Dynamic Dispatching und die Expression Language (EL). [vgl. Ro- cher2009, S.107f] In dem views Ordner liegen normalerweise weitere Unterordner, welche die gleiche Benennung haben, wie die jeweilige Domain-Klasse. In diesen Ordnern liegen dann die GSP-Dateien. Grails arbeitet mit SiteMesh. Das Grundlayout liegt unter views/layouts/main.gsp. In der jeweili- gen GSP wird das Layout dann über ein meta Tag eingebunden:
  • 28.
    28 <html> <head> <metaname="layout" content="main"/> </head> ... </html> Um der View Funktionalität zu verleihen und eine Trennung von Inhalt und Funktion zu erlangen, werden Tags eingesetzt. Alle diese GSP-Tags haben ein g: vorangestellt. Grails verwendet drei unterschiedliche Arten von Tags: Built-in Tags sind vordefinierte Tags, die das Framework Grails bietet. Sie werden beispielsweise als logische oder iterative Funktionalitätsmöglichkeit in der View eingesetzt. [vgl. Rocher2009, S.111f] <g:if test="${firstname == 'John'}"> Hallo ${firstname} </g:if> <g:each in="${persons}"> <p>Firstname: ${it.firstname}</p> <p>Lastname: ${it.lastname}</p> </g:each> Dynamic Tags sind Tags, welche unterschiedliche Darstellungen annehmen können. Einerseits können sie wie die Built-in Tags in XML Form dargestellt werden [vgl. Rocher2009, S.116f]: <a href="<g:createLink action="list" />"> dynamic link </a> Andererseits gibt es die Möglichkeit, die gleiche Funktionalität durch einen Methoden-Aufruf zu realisieren: <a href="${createLink(action:'list')}"> dynamic link </a>
  • 29.
    29 Diese zweite Darstellungsmöglichkeitwird als sauberer empfunden, da die XML Tags nicht mehr- fach ineinander verschachtelt sind. Custom Tags sind dynamic Tags. Sie können individuell vom Entwickler programmiert werden, um spezielle Aufgaben zu bewältigen. Sie werden in dem taglib Ordner positioniert. taglib: Individuelle Tag-Libraries können mit dem Kommando grails create-tag-lib ge- neriert werden. Ein einfaches Tag kann wie folgt aussehen: class PersonTagLib{ def personname = {attrs, body -> attrs.in?.each{ body(it) } } } Das zugehörige Tag in der View sieht wie folgt aus: <g:personname in="${persons}"> Hallo ${it.firstname} </g:personname> Im lib Ordner können weiter Libraries platziert werden, die dann von der Applikation in Anspruch genommen werden können. Im scripts Ordner können zusätzliche Skripte hinterlegt werden. Diese können dann über das grails Kommando ausgeführt werden. Der src Ordner beinhaltet einen java und einen groovy Ordner. In diesen Ordnern können jeweils Java und Groovy Code eingebunden werden. Gibt es beispielsweise bereits Businesslogik, die in Java implementiert wurde, können die Java-Klassen hier in dem java Ordner platziert und somit von der Grails-Applikation genutzt werden. In dem test Ordner werden Integrationstests und Unittests platziert. Hier kann die Funktionalität der Applikation ausgiebig getestet werden. Der web-app Ordner beinhaltet den WEB-INF Ordner mit den Spring und SiteMesh Konfigurations-
  • 30.
    30 dateien. Darüber hinaussind Cascading Style Sheets (CSS), Bild und JavaScript (JS) Ordner verfüg- bar, in denen die jeweiligen benötigten Dateien positioniert werden können. Eine Grails Applikation ist sofort nach der Erstellung ausführbar. Mit dem Kommando grails run- app kann der integrierte Tomcat gestartet werden. Um ein Web Application Archive (WAR) zu erstel- len kann das Kommando grails war verwendet werden. 2.4 IDML Dieser Abschnitt beginnt mit der Erläuterung von dem Programm InDesign. Der wesentliche Aufbau, die Ziele und die Ideen des IDML-Formats werden anschließend beschrieben. Im letzten Abschnitt wird eine Möglichkeit dargestellt, IDML-Dateien zu verarbeiten. 2.4.1 InDesign InDesign ist ein Desktop-Publishing (DTP) Programm. DTP Programme ermöglichen es alle Tätigkei- ten, die vor dem Druck einer Publikation erfolgen müssen, an einem Desktop-Computer zu erledigen. Zu diesen Tätigkeiten gehören: Text-, Bild- und Grafikbearbeitung sowie das Zusammenstellen dieser zu einem Layout. [vgl. Kipphan2000, S.28] Adobe bietet im DTP-Bereich eine Sammlung an Programmen an. Diese Sammlung wird Adobe Crea- tive Suite (CS) genannt. InDesign ist dabei ein Teil der CS und verfolgt das Hauptziel, die Typografie und das Layout für Print, aber auch für digitale Publikationen zu erstellen. InDesign bietet dabei sehr viele Funktionen. Das gängige Vorgehen kann in die Bereiche Dokumen- tenerstellung, Elementplatzierung und Dokumentenausgabe eingeteilt werden [vgl. Pouryekta2011, S.16f]: Dokumenterstellung: Bei der Dokumenterstellung werden die grundlegenden Werte gesetzt, die das Dokument aufweisen soll. Die relevantesten Werte sind: • Die Seitenanzahl legt fest, wie viele Seiten das Dokument haben soll. Dieser Wert kann dyna- misch später bei der Bearbeitung verändert werden. • Die Doppelseiten-Funktion entscheidet, ob das Dokument doppelseitig erzeugt werden soll. Dies ist beispielsweise bei Büchern oder Broschüren relevant. • Die Seitengröße kann individuell in unterschiedlichen Einheiten festgelegt werden. • Die Ausrichtung der Seite entscheidet, ob das Dokument als Hoch- oder Querformat angelegt wird. • Spalten können eine Struktur in dem Dokument erzeugen. Die Anzahl der Spalten und der jeweilige Steg1 kann angegeben werden. 1 Als Steg wird der Abstand zwischen den Spalten bezeichnet.
  • 31.
    31 • Die Ränderkönnen in unterschiedlichen Einheiten definiert werden. • Die Beschnittzugabe ist bei Dokumenten relevant, die später in den Druck kommen. Hier kön- nen Beschnittzugaben definiert werden, um Blitzer2 zu vermeiden. Elementplatzierung: Ist das Dokument erstellt, können auf diesem unterschiedliche Arten von Elementen platziert werden: • Text-Elemente werden für die Textdarstellung verwendet. Hier können umfangreiche typo- grafische Auszeichnungen vorgenommen werden und Stile auf Absatz- oder Zeichenebene zugewiesen werden. • Rechteck-Elemente können als grafische Darstellung definiert werden. Diese können bei- spielsweise Farb-, Bild- oder Videoinhalte aufweisen. • Polygon-Elemente können individuelle Formen annehmen und wie Rechteck-Elemente Inhal- te aufweisen. • Oval-Elemente sind für kreisförmige Darstellungen ausgelegt. Auch diese können wiederum Inhalte aufweisen. • Linien-Elemente können Kurven darstellen. • Formfelder und Knöpfe können zur Erzeugung von Formularen verwendet werden. • Gruppen fassen alle möglichen Elemente zusammen. Dokumentenausgabe: Je nach InDesign Version gibt es unterschiedliche Ausgabemöglichkeiten. Die grundlegenden Ausgabemöglichkeiten sind: • InDesign Document Format (INDD) ist das proprietäre Dateiformat, welches von InDesign genutzt wird. Dieses Dateiformat ist nicht abwärtskompatibel. • Adobe Portable Document Format (PDF) lässt sich mit umfangreichen Einstellungsmöglich- keiten in InDesign definieren, um bestmögliche Druck-, Web- oder interaktive PDF-Doku- mente zu erstellen. • Electronic Publication (EPUB) ist ein offener Standard für electronic books (eBook), welches im mobilen Bereich eingesetzt wird. • InDesign Markup Language (IDML) ist zum einen das Dateiformat, mit dem die Versions- kompabilität von InDesign gewährleistet wird und zum anderen ein offenes Dateiformat, wel- ches anders als bei INDD die Möglichkeit bietet, es lesen und somit durch Drittsysteme ver- arbeiten zu können. 2 Blitzer sind weiße Zwischenräume, die an den Rändern eines Dokumentes auftauchen, wenn keine Beschnitt zugabe definiert wurde.
  • 32.
    32 2.4.2 Dateiformat Das DateiformatIDML wurde mit der InDesign Version CS4 eingeführt und repräsentiert ein In- Design-Dokument als XML. Es ist ein Konstruktionsplan für InDesign-Dokumente. Wird eine IDML- Datei in InDesign geöffnet erzeugt InDesign aus dem IDML ein INDD. Außerdem löst IDML das InDesign Interchange Format (INX) ab und sorgt für die Versionskompatibi- lität ab CS4. Ein wesentlicher Unterschied zu INX besteht darin, dass INX zwar auch XML basierend ist, aber es nur maschinenlesbar und somit hauptsächlich nur für den internen Gebrauch in InDesign verwendet wird. Die IDML-Spezifikationen hingegen sind öffentlich. Das Format kann somit verstan- den werden. Mit IDML ist man dadurch nicht mehr an InDesign gebunden und kann IDML-Dateien extern lesen und schreiben. [vgl. Adobe2012, S.12f] Einige Bereiche in denen IDML eingesetzt werden kann sind [vgl. Adobe2012, S.15]: • Generierung von IDML-Dokumenten oder Dokumententeilen aus einer Datenquelle. • Programmatische Wiederverwendung von IDML-Elementen. • Transformierung über Extensible Stylesheet Language Transformation (XSLT). • Auffinden von Inhalten über XML Path Language (XPath) oder XML Query Language (XQuery). • Validierungs- und Vergleichsmöglichkeit von Inhalten über unterschiedliche Versionen von Doku- menten. Die Ziele, die IDML nach der Spezifikation verfolgt, sind folgende [vgl. Adobe2012, S.15f]: Vollständigkeit: Alle Elemente, die in InDesign erzeugt werden können, sollen in IDML darge- stellt werden. Dabei ist darauf hinzuweisen, dass es rein um die Darstellung einer INDD als IDML geht. IDML liefert keine Funktionen, die in InDesign verfügbar sind. Lesbarkeit: IDML hat den Anspruch menschenlesbar und verständlich zu sein. Jemand der den grundlegenden Umgang mit InDesign kennt, soll sich im IDML-Dokument zurecht finden können. Verarbeitung: IDML-Dokumente sollen durch externe Applikationen gelesen und geschrieben werden können. Robustheit: Das IDML-Format soll robust sein. Das bedeutet Fehler in einem IDML-Dokument sollten keine schwerwiegenden Auswirkungen haben. Das Regular Language Description for XML New Generation (RNG) Schema definiert den Aufbau einer IDML und bietet somit Validie- rungsmöglichkeiten, um grobe Fehler in IDML zu vermeiden.
  • 33.
    33 Rückwärtskompatibilität: Die Rückwärtskompatibilitätzu einer Vorgängerversion soll durch IDML gewähleistet werden. Performanz: Die Performanz von INX-Dateien soll durch IDML übersteigern. Verbesserungen gegenüber INX: IDML soll eine Verbesserung gegenüber INX sein. Es ist zum einen ein offenes Format und beinhaltet keine unklaren Elemente wie bei INX. Zum anderen ver- wendet es ein Schema zur Validierung und hat keine Prozessanweisungen mehr in Textbereichen. Das IDML-Format ist ein Containerformat. Es beinhaltet mehrere XML-Dateien, welche das In- Design-Dokument beschreiben. Dieses Containerformat ist ein Universal Container Format (UCF). Es ist grundlegend ein ZIP-Archiv mit speziellen Bedingungen, die beispielsweise Kompression und Encoding betreffen. [vgl. Adobe2012, S.394f] Der Aufbau des IDML Formats sieht wie folgt aus: Abb. 7 IDML Container Aufbau [Adobe2012, S.20]
  • 34.
    34 Multipurpose Internet MailExtensions Type (MIMETYPE): Diese Datei beschreib den Datei- typ. Bei IDML sieht der Inhalt wie folgt aus [vgl. Adobe2012, S.399f]: application/vnd.adobe.indesign-idml-package designmap.xml: Diese XML ist das Rückgrad der IDML-Datei. Alle weiteren Dateien in der IDML werden von ihr referenziert. Außerdem sind die Reihenfolge und Beziehungen, die in dieser XML aufgeführt sind wesentlich. [vgl. Adobe2012, S.44f] MasterSpreads: MasterSpreads sind Vorlagen für einen Druckbogen. Hier kann der Druckbogen (Spread) vordefiniert werden. Die MasterSpreads liegen in dem MasterSpread Ordner. Die Mas- terspread.xml Dateien definieren den MasterSpread und können Elemente (PageItem) beinhalten, die auf der MasterSpread positioniert werden. [vgl. Adobe2012, S.87] Die Benennung der IDML- Komponenten folgt einem festen Schema, welche in den Spezifikationen zu finden ist. [vgl. Ado- be2012, S.23f] Resources: Dieser Ordner beinhaltet vier XML-Dateien, die Vorgaben und Einstellungen des In- Design Dokumentes repräsentieren [vgl. Adobe2012, S.21]: • Die Graphic.xml definiert beispielsweise Farben (Color), Rahmenstile (StrokeStyle) und Ver- läufe (Gradients), die in dem InDesign-Dokument definiert wurden. Auf diese Definitionen kann referenziert werden. [vgl. Adobe2012, S.263f] • Die Fonts.xml definiert Defaultschriften und alle Schriften, die in dem InDesign-Dokument verwendet werden. [vgl. Adobe2012, S.259f] • Die Styles.xml definiert alle Stile, die in dem InDesign-Dokument definiert werden. Dazu zählen: paragraph, character, object, cell, table und table of contens styles. [vgl. Adobe2012, S.345f] • Die Preferences.xml definiert Grundeinstellungen und Darstellungsmöglichkeiten des Doku- mentes in InDesign. Es hat keine Auswirkungen auf das Dokument selbst. [vgl. Adobe2012, S.281f] Spreads: Spreads sind Druckbögen. Der Spread Ordner hält alle Spreads, die in dem InDesign- Dokument definiert werden als Spread.xml Datei. Ein Spread kann mehrere Seiten (Page) bein- halten. Auf einem Spread können PageItems platziert werden. [vgl. Adobe2012, S.87f] Die Be- nennung der IDML Komponenten folgt einem festen Schema, welches in den Spezifikationen zu finden ist. [vgl. Adobe2012, S.23f] Stories: Stories definieren den Textinhalt eines Dokumentes. Der Stories Ordner hält alle Stories,
  • 35.
    35 die in demInDesign Dokument definiert werden als Story.xml. Diese Stories beinhalten den Text, die zugehörigen Stile und eine Referenz auf den zugehörigen Textrahmen (TextFrame). [vgl. Ado- be2012, S.163f] Die Benennung der IDML-Komponenten folgt einem festen Schema, welches in den Spezifikationen zu finden ist. [vgl. Adobe2012, S.23f] XML: Der XML-Ordner beinhaltet drei weitere XML-Dateien, die für speziellere Aufgaben ver- wendet werden [vgl. Adobe2012, S.22f]: • Die BackingStory.xml definiert Inhalte, die noch keinem PageItem zugeordnet wurden. • Die Tags.xml definiert alle Tags, die in InDesign mit der Tagfunktion erstellt wurden. • Die Mapping.xml definiert die Beziehungen zwischen Tag und Styles. META-INF: Dieser Ordner hält einmal die container.xml Datei. Diese ist notwendig für den UCF Standard und referenziert auf die designmap.xml. Zum anderen metadata.xml welche beispiels- weise Extensible Metadata Platform (XMP) und Resource Description Framework (RDF) Inhalte definieren. [vgl. Adobe2012, S.401f] 2.4.3 IDMLlib Die IDMLlib ist eine Java Library, die es ermöglicht IDML-Dokumente zu lesen und zu schrei- ben. Ein weiteres Ziel der Library ist es, die Komplexität des IDML-Formates zu reduzieren und eine Schnittstelle zu bieten, mit der es möglich ist IDML-Dokumente zu verarbeiten. IDMLlib kann IDML-Dokumente und InDesign Snippets (IDMS) verarbeiten. Des Weiteren bietet die IDMLlib [vgl. IDMLlib2013]: • Ein Java Objektmodell • Automatische Typ Konvertierung von XML nach Java • Spezielle Klasse für die IDML-Elemente • Lazy loading Mechanismus • Polyglot Programming3 (Groovy, JRuby, Scala etc.) • Vollen Zugriff auf die IDML-Elemente • Kapselung der XML und somit keine notwendige XML Erfahrung Die IDMLlib läuft auf den Betriebssystemen Windows, Linux und Mac OS. Vorausgesetzt wird das JDK 5. Außerdem ist die IDMLlib unabhängig von InDesign. Somit lassen sich Workflows konzipie- ren, die Automatisierungsaufgaben außerhalb von InDesign ersetzen und diese flexibler und perfor- manter umsetzen können. 3 Polyglot bedeutet mehrsprachig. In diesem Zusammenhang ist der Zugriff von anderen Sprachen auf die IDMLlib gemeint.
  • 36.
    36 Einige Einsatzmöglichkeiten werdenauf der IDMLlib Webseite genannt [vgl. IDMLlib2013]: • Individuelle Validierung von Dokumenten. • Vorbereiten von InDesign-Dokumenten für InDesign. • Publizieren von Inhalten, die aus InDesign-Dokumenten ausgelesen werden. • Qualitätssicherung durch Validierung und Vergleichen von Dokumenten. • Übersetzungsworkflows für mehrsprachige Dokumente. • Einbinden von InDesign-Dokumenten in Drittsysteme.
  • 37.
    37 3 Umsetzung Dieses Kapitelbeschäftigt sich mit der Umsetzung des IDML-Servers. Nachdem in Kapitel 2 die Grundlagen betrachtet wurde, wird zunächst auf das Konzept des IDML-Servers eingegangen. Im Kapitel 3.2 erfolgt darauf die praktische Umsetzung, welche die Realisierung des Konzepts bestätigen soll. Sowohl das Konzept, als auch die praktische Umsetzung bauen auf den vorherigen Grundlagen- kapitel auf. 3.1 Konzept Das Konzept beginnt mit den Anforderungen an den IDML-Server. Hier wird festgelegt, welche As- pekte für das System relevant sind. Darauf folgt die Systemarchitektur, welche maßgeblich durch die eingesetzten Frameworks definiert wird. Ferner werden Entwurfsentscheidungen hier festgelegt und beschrieben. Im Anschluss darauf wird der Webservice definiert, der beim IDML-Server zum Einsatz kommt. Im letzten Abschnitt werden die Funktionsweise und der Aufbau der Process-Engine definiert. Diese Punkte zusammen dienen als Basis für die praktische Umsetzung. 3.1.1 Anforderungen Das Konzept eines Systems, welches IDML-Dokumente verarbeiten kann, hat folgende Anforderun- gen: Verarbeitung: Das System soll in der Lage sein, IDML-Dateien verarbeiten zu können. Vereinfachung: Das System soll den Umgang mit IDML vereinfachen. Da das IDML-Format sehr komplex aufgebaut ist, soll das System diese Komplexität kapseln und über leicht verständli- che Funktionen verfügbar machen. Einbindung: Das System soll in bestehende Workflows integriert werden sowie Prozesse verein- fachen und automatisieren können. Erweiterbarkeit: Das System soll erweiterbar sein, um zukünftigen Anforderungen gerecht wer- den zu können. 3.1.2 Systemarchitektur Die Systemarchitektur ergibt sich in erster Linie aus den Anforderungen. Eines der Ziele des Systems ist die Einbindung in bestehende Workflows. Da im Druck- und Medien-Bereich Workflowsysteme oft als zentrales Serversystem vorliegen, wird hier das Konzept eines IDML-Servers gewählt. Folgende Vor- und Nachteile ergeben sich bei dem Einsatz eines Servers:
  • 38.
    38 Vorteile • Ein Serverist generell ein zentrales System und kann in Workflows integriert werden. In einem Workflow können so Probleme schneller erkannt werden, da es eine klare Aufgabenverteilung gibt und so deutlich wird, welcher Server für welche Aufgaben verantwortlich ist. • Die Datensicherung ist bei einem zentralen Server einfacher zu handhaben, da die Daten an einem Ort einheitlich gesichert werden können. • Server können in bestehende Workflows über Schnittstellen eingebunden werden. • Eine Cloudversion eines Servers ist möglich. Nachteile • Initialkosten eines Serversystems sind oft höher als bei Desktopsystemen, da die technische Kom- plexität höher liegt. • Single Point of Failure Der Server ist ein System zur Verarbeitung von IDML-Dateien und wird in drei Bereiche unterteilt: Eingabe, Verarbeitung und Ausgabe (EVA-Prinzip). Der Ein- und Ausgabe Bereich wird dabei über den Komponente Webservice realisiert. Der Verarbeitungsbereich wird über die Komponente Process- Engine realisiert. Abb. 8 IDML-Server Anfragen an den Server über den Webservice erfolgen über HTTP (üblicherweise wird HTTP/Port 80 für Webservices gewählt, da Firewalls den Port 80 normalerweise nicht blockieren. Es kann jedoch auch ein anderer Port definiert werden.). Die Anfragen sind in Form von Parametern oder Dateien zu definieren. Der Webservice nimmt die Anfrage entgegen und leitet diese weiter an die Process-Engine. Die Process-Engine ist für die Ausführung von vordefinierten Abläufen zuständig. Diese führt die nötigen Funktionen aus und liefert ein Ergebnis. Das Ergebnis wird wieder zurück an den Webservice geleitet, der die Daten als Antwort in Form von XML (üblicherweise wird XML verwendet. Es können jedoch auch andere Formate verwendet werden, wie zum Beispiel JSON.) an den Anfragenden wieder zurück sendet. IDML-Server Webservice Process-Engine IDML, Parameter IDML, XML
  • 39.
    39 Der Server istnach dem MVC-Muster und dem Schichtenmuster aufgebaut. Dabei ist das Model im Bereich der Process-Engine anzuordnen. Dieser ist zuständig für die Verarbeitung der Daten. Die View und der Controller sind im Bereich des Webservices einzuordnen. Die View ist hier die Darstellung der Ergebnisse in Form von XML. Der Controller nimmt die Anfrage entgegen und ist dafür zuständig, die Daten in der View darzustellen. Das Schichtenmuster wird in mehreren Bereichen angewendet. Einmal ist der Server im Kontext eines Workflows zu betrachten. Dabei ist der IDML-Server eine Komponente des Workflows (eine Schicht) mit einer klaren Aufgabenstellung. Der IDML-Server hat das Ziel, die Komplexität des IDML-Forma- tes zu kapseln. Deswegen wird der IDML-Server weiter in die Komponenten (Schichten) Webservice und Process-Engine unterteilt. Auch diese Komponenten haben wieder eine klare Aufgabenstellung. Zuletzt ist der IDML-Server aus Entwicklersicht zu betrachten, in dem Programmteile in Schichten unterteilt werden, um wieder Aufgabenbereiche klar zu definieren. Die konkrete Implementierung des Systems basiert auf Industriestandards, die sich im Laufe der Zeit bewiesen haben. Das gewählte Framework für die Implementierung ist das Grails-Framework. Die darunterliegenden Technologien, wie beispielsweise Spring-Framework, Groovy, Java und IDMLlib, gewährleisten, dass die Anforderungen an das System erfüllt werden. Java und das Spring-Framework liefern dabei eine sehr große Anzahl an erprobten Libraries, die in unterschiedlichsten Bereichen der Softwareentwicklung eingesetzt werden können. Außerdem bietet Java Plattformunabhängigkeit so- wie sichere und robuste Funktionen auf die das Grails-Framework und damit der IDML-Server auf- baut. Die Sprache Groovy bringt durch ihre Eigenschaften, der dynamischen Typisierung und der Skriptfähigkeit der Sprache starke Vorteile in den Bereichen der Flexibilität eines Systems. Des Weite- ren liefert der Einsatz des Grails-Frameworks vor allem Vorteile in den Bereichen Prototyping und der Erweiterbarkeit eines Systems durch Grails-Plugins. Diese können zu einer Grails-Web-Applikation entwickelt und installiert werden. Außerdem bietet das Grails-Framework die Möglichkeit, Java-Klas- sen und Libraries in das System einzubinden. Im Fall des IDML-Servers wird dies mit dem Einsatz der IDMLlib in Anspruch genommen. Die IDMLlib ist im Kontext des IDML-Servers dafür zuständig, die Komplexität des IDML Formats zu kapseln und Zugang und Verarbeitung von IDML-Dateien zu gewähren. 3.1.3 Webservice Der Webservice des IDML-Servers muss die Anforderungen wie Vereinfachung, Einbindung und Er- weiterbarkeit erfüllen. In erster Linie sollte der Webservice selbsterklärend und einfach zu bedienen sein. Hier ist die Wahl auf eine XML basierende REST-Schnittstelle gefallen, statt auf eine SOAP-Schnittstelle, da REST über das Grails-Framework auf einfachem Weg zu implementieren ist. SOAP hingegen ist bei der Implementierung des Webservices oftmals komplexer umzusetzen als REST. Die Wahl XML zu ver- wenden beruht auch darauf, dass die meisten Webservice-Schnittstellen XML basierend sind und das Einbinden der Schnittstelle auch für Dritte möglichst einfach gestaltet werden soll. Alternative zu
  • 40.
    40 XML wäre hierJSON. JSON hat im Vergleich zu XML eine einfachere Syntax. Diese ist kürzer und minimalistischer ausgelegt. Für eine Weiterentwicklung des IDML-Servers kann eine JSON/REST Schnittstelle auch über das Grails-Framework auf einfachem Weg implementiert werden. Die Einbindung des IDML-Servers in bestehende Workflows erfolgt durch die REST-Schnittstelle. Die Bedienung der REST-Schnittstelle ist im Vergleich zu SOAP einfacher umzusetzten. Der Hauptgrund dafür ist, das REST keine festgelegte Norm ist und somit flexibler gestaltet werden kann. Außerdem entfällt im Vergleich zu SOAP ein XML-Overhead, da REST beispielsweise kein WSDL benötigt. Die Erweiterbarkeit der REST-Schnittstelle wird über eine Parameter-Liste gewährleistet. Diese be- steht aus einer Anzahl fest definierter Parameter, die für eine spezielle Anfrage notwendig sind und einer flexiblen Anzahl an Parametern, die individuell je nach Anforderung definiert werden können. Der Webservice behandelt drei Arten von Anfragen: Upload: Die Uploadanfrage ist zuständig für den Upload von Dateien, wobei der Webservice eine Erfolgs- oder Fehlermeldung als Ergebnis zurückgibt. Aktion: Eine Aktionsanfrage beinhaltet keine Binärdaten. Hier wird über die Anfrage mit spe- ziellen Parametern eine bestimmte Aktion ausgeführt, die eine Erfolgs- oder Fehlermeldung als Ergebnis zurückgibt. Download: Eine Downloadanfrage liefert Binärdaten. Bei einem Fehler wird eine Fehlermeldung als Ergebnis geliefert. Da der Server von mehreren Akteuren bedient wird, soll das Konzept einer Session im IDML-Server implementiert. Diese garantiert, dass ein Akteur in seinem eigenen Kontext arbeitet und keine Daten anderer Akteuere manipuliert. Ein möglicher Ablauf könnte wie folgt aussehen: 1. Erzeugung einer Session und eines Universally Unique Identifier (UUID). Diese ID muss bei allen weiteren Aktionen immer mitgegeben werden. 2. Upload von Dateien 3. Anstoß eines Verarbeitungsprozess 4. Download der Ergebnisse des Verarbeitungsprozess 5. Beendigung der Session Abb. 9 Workflow Ablauf Session Erzeugung Verarbeitung Session Beendigung Datei Upload Datei Download
  • 41.
    41 3.1.4 Process-Engine Um zuverstehen, wie die Process-Engine aufgebaut ist, wird anhand des Ablaufs (Abb.9) jeder Schritt beschrieben: Session Erzeugung: Bei der Session-Erzeugung über den Webservice wird als erstes in der Pro- cess-Engine eine UUID erzeugt. Diese UUID wird benötigt, um einen Sessionordner zu erzeugen, in dem die Session dann für den weiteren Ablauf behandelt wird. In diesem Sessionordner werden drei weitere Ordner erzeugt. Der erste ist ein Inputordner, welcher für die eingehenden Dateien zuständig ist. Der zweite ist ein Outputordner, in dem die Ergebnisdateien der Verarbeitung plat- ziert werden. Der dritte Ordner ist ein Temporaryordner, in dem Dateien platziert werden können, die beispielsweise im Verarbeitungsprozess abgelegt werden müssen. Das Ergebnis der Session- Erzeugung ist im günstigsten Fall eine Erfolgsmeldung. Dabei wird eine XML zurückgesendet, welche die UUID enthält. Datei Upload: Ist die Session erzeugt, können Dateien hochgeladen werden. Zwingend notwendig ist dabei das Angeben der UUID. Anhand der UUID kann entschieden werden, in welchem Sessio- nordner die Datei abgelegt wird. Alle hochgeladenen Dateien landen immer in dem Inputordner. Das Ergebnis eines erfolgreichen Uploads ist wiederum eine XML, welche die UUID enthält. Verarbeitung: Bei der Verarbeitung stellt sich die Frage, wie die Daten genau verarbeitet werden sollen. Um dieses Problem möglichst flexibel zu gestalten, wird ein Workflowordner in dem Sys- tem definiert. In diesem Ordner können weitere Ordner platziert werden. Diese Ordner repräsentie- ren einen Workflow. In dem Ordner können individuelle Groovy-Skripte abgelegt werden und alle nötigen Dateien, die für diesen Workflow benötigt werden. Die Gruppierung der Groovy-Skripte in Workflows hat den Sinn, das System überschaulich und strukturiert verwalten zu können. Der Workflow und das jeweilige Groovy-Skript kann über den Webservice anhand von definierten Paramterern angesteuert und somit ausgeführt werden. Die Ausführung selber erfolgt dann in dem Sessionordner, wobei die Dateien aus dem Inputordner für die Ausführung verwendet werden und das Binär Ergebnis der Verarbeitung in dem Outputordner platziert wird. Das Groovy-Skript kann dabei auf alle Libraries zugreifen, die im System verfügbar sind und somit jede Art von Dateien verarbeiten. Es ist somit also nicht nur beschränkt auf IDML-Dateien, sondern kann beispielswei- se auch XML verarbeiten. Das Ergebnis der Webservice-Anfrage ist wiederrum XML und besitzt eine Anzahl an fest definierten Werten, die das System mitliefert, sowie einen frei gestaltbaren Bereich, der in dem ausgeführten Groovy-Skript gesetzt werden kann. Datei Download: Ist die Verarbeitung abgeschlossen und wurden dabei Binärdaten erzeugt, findet man diese in dem Outputordner. Um nun Zugang auf die Dateien zu ermöglichen, kann der Out- putordner heruntergeladen werden. Dabei wird der ganze Outputordner in ein ZIP-Format gepackt
  • 42.
    42 und über denWebservice zur Verfügung gestellt. Session Beendigung: Nachdem alle Prozesse abgearbeitet wurden muss die Session nun auch beendet werden. Dies kann über den Webservice angestoßen werden. Die Process-Engine löscht durch den Anstoß über den Webservice den Sessionordner und alle enthalteten Informationen. Sollte die Session nicht über den Webservice beendet werden existiert zusätzlich ein Task, der zeitgesteuert über die bestehenden Sessionordner iteriert und kontrolliert, ob der Sessionordner eine festgelegte Zeit überschritten hat. Ist dies der Fall, wird der Sessionordner gelöscht. Dadurch können Sessions beendet werden, die beispielsweise versehentlich vergessen wurden beendet zu werden. 3.2 Praktische Umsetzung Um das Konzept (Kapitel 3.1) zu bestätigen und produktive Einsatzszenarien durchspielen zu können, wird ein Prototyp entwickelt. Dieser hat keinen Anspruch auf Vollständigkeit und kann Fehler beinhal- ten. Zunächst wird auf die Systemanforderungen eingegangen, die notwendig sind für den Prototypen. Im nächsten Schritt wird detailliert die Funktionsweise des Prototyps beschrieben. Zum Schluss sind die produktiven Einsatzszenarien relevant, die über die Groovy-Skripts implementiert werden. 3.2.1 Systemanforderungen Die Systemanforderungen liegen zunächst im technischen Bereich. Als Betriebsystem sind Windows, Linux oder Mac OS X zu empfehlen. Der Prototyp wird auf einem Mac OS X 10.7.5 entwickelt und getestet. Auf dem jeweiligen Betriebsystem muss eine Java 6 Version installiert sein. Außerdem ist für den Prototyp ein Tomcat notwendig. Zu empfehlen ist der Tomcat 6.0.32. Der zugewiesene Speicher sollte mit 512 Megabyte generell ausreichen. Je nach Last und Größe der zu verarbeitenden Daten kann der Wert variieren und sollte angepasst werden. Die verwendete Grails Version liegt bei 2.1.0 und die IDMLlib Version bei 1.1.5. Die IDML-Daten, die in das System einfließen, sollten von InDesign CS4 erzeugt worden sein und der Document Object Model (DOM) Version 6.0 entsprechen. Weitere wesentliche Anforderungen ergeben sich durch die auszuführenden Groovy-Skripte, die nicht direkt Teil des Servers sind, sondern individuell je nach Einsatzgebiet gestaltet werden können. Hier ist vor allem das Verständnis für die Sprache Groovy und das IDML-Format notwendig, um diese Groovy-Skripte erstellen zu können. 3.2.2 Prototyp Der Prototyp orientiert sich an dem Konzept des IDML-Servers. Die Architektur des Prototyps beruht somit auf der vorgegebenen Grails Architektur. Der IDML-Server kann über das Kommando grails run-app gestartet werden. Ist die Applikation gestartet kann sie unter http://localhost:8080/IDML-Server betrachtet werden. Dabei wird
  • 43.
    43 im Browser dieStandard Index Seite dargestellt: Abb. 10 IDML-Server Index Seite Diese zeigt den Status der Applikation, die installierten Plugins und die Controller, die das System zur Verfügung stellt. Bei genauer Betrachtung erkennt man in den Plugins auch den Tomcat Server, der mit dem Kommando grails run-app gestartet wird. Um den IDML-Server detailliert zu durchleuchten, werden alle Prozesse des Workflow Diagramms (Abb.9) wiederum durchlaufen: Session Erzeugung: Die Session-Erzeugung wird über den ProcessController angestoßen. Klickt man über die Index Seite auf den ProcessController wird dabei die URL http://lo- calhost:8080/IDML-Server/process/index aufgerufen. Der URL Teil process deutet auf den Controller hin, der hier angesprochen wird. Der URL Teil index deutet auf die Action hin, die ausgeführt werden soll. Dieses Verhalten der Controller ist einheitlich gelöst und vereinfacht den Umgang mit dem System. Dieser URLAufbau ist standardmäßig von dem Grails-Framework vorgegeben kann aber bei Bedarf unter config/UrlMappings.groovy angepasst werden:
  • 44.
    44 static mappings ={ ʺ/$controller/$action?/$id?"{ constraints { // apply constraints here } } "/"(view:"/index") "500"(view:'/error') } Die Action in dem ProcessController sieht dabei wie folgt aus: def index() {} Diese Action ist sehr einfach gehalten. Was hier passiert ist, der Einsatz von CoC. Über die Be- nennung der Action wird automatisch auf die zugehörige gleichnamige GSP-Seite verwiesen und diese als Antwort auf die Anfrage zurückgegeben: Abb. 11 IDML-Server Process Index Seite Die GSP-Seiten dienen lediglich zur optischen Darstellung für den Entwickler oder Benutzer, der den Webservice manuell testen möchte. Ein späterer produktiver Einsatz erfolg direkt über die URLs. Um eine Session zu erzeugen, kann die zugehörige URL http://localhost:8080/IDML- Server/process/createSession aufgerufen werden. Diese spricht folgende Action im ProcessController an:
  • 45.
    45 def createSession(){ def result= processService.createSession() render result as XML } Hier wird die Funktion createSession() des ProcessServices angesprochen. Der Service wird getrennt vom Controller in einer eigenen Schicht untergebracht, um eine klare Aufgabenver- teilung zu haben. Die Serviceklassen sind im MVC-Muster im Bereich des Model anzuordnen. Die createSession() Methode des ProcessServices sieht wie folgt aus: def createSession() { def id = UUID.randomUUID() fileStructureService.createSessionStructure(id) def result = [:] result.put("type", "success") result.put("id", id.toString()) return result } Hier wird dafür gesorgt, dass die Session ID und alle notwendigen Strukturen erzeugt werden. Als erstes wird eine zufällige UUID generiert. Anhand dieser UUID wird über den FileStruc- tureService die Funktion createSessionStructure(id)aufgerufen. Diese ist dafür ver- antwortlich die lokale Ordnerstruktur zu erzeugen, in der später dann die Verarbeitung stattfindet: def createSessionStructure(id) { new File(getInPath(id)).mkdirs() new File(getOutPath(id)).mkdirs() new File(getTmpPath(id)).mkdirs() } Das Erzeugen der Pfade wird in weitere Funktionen ausgelagert. Hier wird nur die Funktion ge- tInPath() betrachtet, da alle anderen sehr ähnliche Funktionsweisen aufweisen. Diese Funktion baut den Inputordner Pfad anhand konfigurierter Eigenschaften, die in der config.properties ge- setzt werden, auf. Um auf diese Eigenschaften zugreifen zu können, bietet das Grails-Framework das Interface GrailsApplication. Über diese kann dann direkt auf die config.properties und die darin konfigurierten Werte zugegriffen werden (grailsApplication.config...):
  • 46.
    46 def getInPath(id) { getWorkPath() + id + File.separator + grailsApplication.config.idml. server.local.work.in.folder.name + File.separator } In der config.properties ist somit folgender Name für den Inputordner definiert: idml.server.local.work.in.folder.name=in Die config.properties Datei ist dabei eine extern verwaltete Konfigurationsdatei. Diese liegt nor- malerweise außerhalb der Applikation. Der Grund für die externe Verwaltung ist, dass sich bei Updates oder Bugfixes eines Systems oft die Konfiguration gar nicht ändert. Anstatt jedes Mal erneut die Applikation zu konfigurieren, kann so nur die Applikation ausgetauscht und die Konfi- guration beibehalten werden. Die config.properties muss eingebunden werden, damit das System auch Zugriff auf die Daten hat. Dies erfolgt über die JVM option -Didmlserver.config.loca- tion=/path/to/config.properties. Wie diese JVM option benannt ist, wird in der config/ config.groovy definiert: grails.config.locations = [] if(System.properties["idmlserver.config.location"]) { grails.config.locations << "file:" + System.properties["idmlserver. config.location"] } Sind die Pfade und alle notwendigen Ordner erzeugt, wird in der createSession() Funktion ein Ergebnis erstellt. Dieses Ergebnis ist vom Typ Map und beinhaltet einen type und die UUID. Die Wahl, das Ergebnis als eine Map zu realisieren, hat den Grund, dass eine Map dynamisch er- weiterbar ist und der Zugriff auf die Werte sehr einfach über Schlüsselwörter erfolgen kann. Einer dieser Schlüsselwörter ist type. Dieser ist dafür zuständig zu unterscheiden, ob das Ergebnis ein erfolgreiches oder ein fehlgeschlagenes Ergebnis ist. Ist das Ergebnis erzeugt, wird es zurück an den Controller gegeben, der nichts anderes macht als diese Map als XML zu rendern (render result as XML). Das XML Ergebnis was zurückgegeben wird sieht wie folgt aus: <map> <entry key="type">success</entry> <entry key="id">764c7d8e-c276-4ef2-be2f-45b00fda0868</entry> </map>
  • 47.
    47 Das Wichtigste andiesem Ergebnis ist die ID. Diese muss während des ganzen Prozesses mitge- liefert werden. Sie sorgt für die eindeutige Identifizierung der Session. Datei Upload: Nachdem die Session erzeugt wurde, kann nun eine Datei in das System hochge- laden werden. Dies erfolgt über den UploadController. Der UploadController enthält die Funktion upload(). Diese kann über die URL http://localhost:8080/IDML-Server/ upload/upload angesteuert werden. Dabei werden die Parameter id und file für einen erfolg- reichen Upload benötigt: def upload() { def id = params.id def result = [:] if (id) { result = uploadService.uploadFile(id, request.getFile("file")) } else { def errormessage = "error: ID does not exists!" result.put("type", "error") result.put("errormessage", errormessage) } render result as XML } Sind diese Parameter verfügbar, wird die Datei über den UploadService mit der Funktion uploadFile(id, file) in das System hochgeladen: def uploadFile(id, file) { def targetDirPath = fileStructureService.getInPath(id) def targetPath = targetDirPath + File.separator + file.originalFile name def uploadedFile = new File(targetPath) file.transferTo(uploadedFile) def result = [:] result.put("type", "success") result.put("id", id.toString()) return result } Dabei wird als erstes der Pfad zum Inputordner der jeweiligen Session zusammengebaut, an
  • 48.
    48 dem die Dateiplatziert werden soll. Dies geschieht wiederum in einer speziellen Service-Klasse (FileStructureService) die diese Art von Aufgabenstellung übernimmt. Anschließend wird die Datei hochgeladen und ein Ergebnis vom Typ Map erzeugt, der wiederum die UUID und einen type enthält. Wird im UploadController keine UUID als Parameter übergeben, wird sofort ein Ergebnis mit einer Fehlermeldung erzeugt. In beiden Fällen wird die Map vom Controller in XML gewandelt und zurückgegeben. Die XML sieht bei einem erfolgreichen Upload wie folgt aus: <map> <entry key="type">success</entry> <entry key="id">764c7d8e-c276-4ef2-be2f-45b00fda0868</entry> </map> Verarbeitung: Ist der Upload der Daten abgeschlossen, kann nun mit dem Verarbeitungsprozess begonnen werden. Zum Anstoßen einer Verarbeitung wird der ProcessController verwendet. Dieser enthält die Action execute(): def execute() { def result = processService.executeScript(params?.script, params?. workflow, params?.id, params) render result as XML } Die Action greift auf den ProcessService zu und führt die executeScript() Funktion aus. Das Ergebnis wird als XML wieder zurückgegeben. Die executeScript() Funktion erwartet mindestens drei Parameter. Der erste Parameter ist der Skript-Parameter. Dieser identifiziert das Groovy-Skript, das ausgeführt werden soll. Auch hier wird wieder CoC angewendet, um mög- lichst einheitlich und einfach die Verarbeitung anzustoßen. Der zweite Parameter ist der Work- flow-Parameter. Dieser definiert den Workflow, der angestoßen wird. Die Groovy-Skripte sind in mehrere Workflows gruppiert. Dadurch können dieselben Skripte in unterschiedlichen Workflows verwendet werden. Die Gruppierung der Skripte in Workflows dient vor allem der Strukturierung der Skripte. Der dritte Parameter ist der UUID Parameter. Hier wird die UUID der Session erwar- tet. Durch diese UUID kann die Session identifiziert werden. In dem Kontext der Session wird dann das Skript ausgeführt. Als letztes erwartet die Funktion das ganze Parameter-Objekt. Dieses Parameter-Objekt enthält alle Parameter, die übergeben wurden. Dies bietet die Möglichkeit, wei- tere individuelle Parameter mitzugeben, die unter Umständen in dem Skript benötigt werden. Die programmatische Ausführung sieht wie folgt aus:
  • 49.
    49 def executeScript(script, workflow,id, Map<String, String> params) { def result = [:] def binding = handleParams(params, id) String[] roots = getRoots() GroovyScriptEngine gse = new GroovyScriptEngine(roots); def scriptPath = fileStructureService.getScriptPath(workflow, script) def scriptFile = new File(scriptPath) if (scriptFile.exists()) { result = gse.run(scriptPath, binding); result.put("type", "success") } else { def errormessage = "error: script does not exists!" result.put("type", "error") result.put("errormessage", errormessage) log.error(scriptFile.getAbsolutePath() + ", " + errormessage) } result.put("workflow", workflow) result.put("script", script) result.put("id", id.toString()) return result } Zunächst werden durch die Funktion handleParams() alle Parameter und Werte, die übergeben werden in ein Binding platziert: def handleParams(Map<String, String> params, id) { Binding binding = new Binding(); params.keySet().each {key -> binding.setVariable(key, params.get(key)); } binding.setVariable("inPath", fileStructureService.getInPath(id)) binding.setVariable("outPath", fileStructureService.getOutPath(id)) return binding } Durch das Binding hat das auszuführende Skript später Zugriff auf die jeweiligen Parameter und kann somit alle nötigen Informationen verwerten. Außerdem werden der Inputordner Pfad und der Outputordner Pfad für die nötigen Zugriffe in das Binding gesetzt. Ist das Binding gesetzt, gibt
  • 50.
    50 es zusätzlich nochdie Möglichkeit Zugriff auf weitere Ressourcen zu nehmen. Über die getRo- ots() Funktion können weitere Klassenpfade (Classpath) in die Ausführung mit eingebunden werden. Diese Klassenpfade können URLs oder lokale Pfade sein, die über die config.properties Datei gesetzt werden können. String[] getRoots() { def commaRoots = grailsApplication.config.idml.server.groovy.script. engine.roots def roots = commaRoots.split(",") return roots } Als nächstes wird das GroovyScriptEngine Objekt mit den optionalen Klassenpfaden erzeugt. Dieses Objekt ist für die Ausführung des Skripts verantwortlich. Welches Skript ausgeführt wer- den soll, wird über den workflow und den script Parameter entschieden. Der FileStructure- Service sorgt dafür, dass der richtige Pfad des Skripts erzeugt wird. Ist das Skript verfügbar, wird das Groovy-Skript mit den jeweiligen Bindings ausgeführt. Das Ergebnis der Skriptausführung muss eine Map sein. Diese Map kann in den Skripten dann mit den Ergebniswerten befüllt werden, die für das jeweilige Szenario relevant sind. Somit hat der Entwickler des Skripts eigenständig die Möglichkeit zu entscheiden, was als Ergebnis angezeigt werden soll. Zu dieser Map wird zu- sätzlich ein success type hinzugefügt. Ist das Skript jedoch nicht verfügbar, wird eine Fehler- meldung und der zugehörige error type dem Ergebnis hinzugefügt. Zum Schluss werden die drei erforderlichen Parameter script, workflow und id unabhängig von Erfolg oder Fehlschlag des Skriptes dem Ergebnis hinzugefügt. Ein Ergebnis in XML-Darstellung könnte dann wie folgt aussehen: <map> <entry key="type">success</entry> <entry key="workflow">export</entry> <entry key="script">ExtractText</entry> <entry key="id">764c7d8e-c276-4ef2-be2f-45b00fda0868</entry> </map> Datei Download: Nachdem der Verarbeitungsprozess durchlaufen wurde, können die Ergebnisse als XML an den Anfragenden zurückgegeben worden sein. Aber es können auch Binärdaten er- zeugt worden sein. Um Zugang zu diesen Binärdaten zu erhalten, gibt es die Möglichkeit über den DownloadController den Outputordner herunterzuladen. Dieser Vorgang kann im Download- Controller über die Action download() angestoßen werden:
  • 51.
    51 def download() { def id = params.id def resultFile = downloadService.getZippedOutFolder(id) response.setContentType("application/zip") response.setHeader("Content-disposition", "attachment;filename=${resu ltFile.getName()}") response.outputStream << resultFile.newInputStream() } Um den Outputordner herunterzuladen wird die UUID benötigt. Mit dieser kann der Download- Service über die getZippedOutFolder() Funktion den als ZIP verpackten Outputordner be- reitstellen: def File getZippedOutFolder(id) { def outFolder = new File(fileStructureService.getOutPath(id)) File outZipFile = new File(fileStructureService.getTmpPath(id) + File.separator + outFolder.getName() + ".zip") new AntBuilder().zip(destfile: outZipFile.getAbsolutePath(), basedir: outFolder.getAbsolutePath()) return outZipFile } Über den FileStructureService werden die benötigten Output- und Temporaryordner Pfade bereitgestellt. Anschließend wird mit dem AntBuilder dann der Outputordner gepackt und in dem Temporaryordner abgelegt. Die Entscheidung den Outputordner zu packen, resultiert aus dem Grund, dass unter Umständen die binären Ergebnisse sehr groß werden können. Um die Daten möglichst performant bereitzustellen, wurde hier der ganze Ordner gepackt. Eine spätere Optimie- rung dieser Funktion kann in einer zweiten Version des Servers erfolgen. Die getZippedOutFolder() Funktion gibt somit den gepackten Outputordner zurück. Der Re- sponse wird dann mit einem Header, ContentType und der gepackten Datei befüllt und an den Anfragenden gesendet. So werden die Binärdaten aus dem Outputordner bereitgestellt und können weiter verarbeitet werden. Session Beendigung: Nach dem der Vorgang abgeschlossen ist, sollte die Session beendet wer- den, um keine Dateileichen auf dem System zu haben. Dies kann über zwei Möglichkeiten erfol- gen. Die erste und manuelle Möglichkeit erfolgt über den ProcessController. Dieser enthält folgende Action:
  • 52.
    52 def closeSession() { defid = params?.id def result = processService.closeSession(id) render result as XML } Notwendig für den Prozess ist die UUID. Diese wird entgegengenommen und an die closeSes- sion() Funktion des ProcessServices übergeben. def closeSession(id) { fileStructureService.deleteSessionFolder(id) def result = [:] result.put("type", "success") result.put("id", id.toString()) return result } Diese Funktion arbeitet ähnlich wie die createSession(). Sie unterscheiden sich lediglich dar- in, dass sie die Sessionstruktur nicht erzeugt, sondern den Sessionornder mit der jeweiligen UUID löscht. Das Löschen übernimmt der FileStructureService mit der Funktion deleteSes- sionFolder(): def deleteSessionFolder(String id) { def folder = new File(getWorkPath() + id) FileUtils.deleteDirectory(folder) } Die zweite Möglichkeit die Session zu beenden, ist über den automatischen Task. Der Task ist in der config/spring/resources.xml definiert: <task:scheduler id="singleTaskScheduler" pool-size="1"/> <task:scheduled-tasks> <task:scheduled ref="cleanUpWorkDirService" method="run" cron="${idml.server.tasks.cleanup.workdir.cronexpression}"/> </task:scheduled-tasks> Dieser greift zeitgesteuert auf die Funktion run() des CleanUpWorkDirServices zu. Die Zeit- steuerung wird in der config.properties Datei über eine Cron Expression geregelt. Die run()
  • 53.
    53 Funktion sieht wiefolgt aus: def run() { log.info("start cleanUpWorkDirTask") new File(fileStructureService.getWorkPath()).eachFile {File uuidFolder -> if (uuidFolder.isDirectory()) { def now = new Date() long limit = grailsApplication.config.idml.server.tasks. cleanup.workdir.time.limit as long def folderDateWithLimit = new Date(uuidFolder.lastModi fied() + limit) if (now.after(folderDateWithLimit)) { log.info("delete folder: " + uuidFolder.getAbsolute Path()) fileStructureService.deleteSessionFolder(uuidFolder) } } } log.info("end cleanUpWorkDirTask") } Der Task betrachtet den Workordner in dem alle Sessionordner liegen. Alle Sessionordner werden durchlaufen, um das Datum der letzten Änderung eines Ordners mit dem aktuellen Datum, plus einem konfigurierbarem Werte, zu vergleichen. Wird dieser Wert übertroffen, wird der Session- ordner als zu alt angesehen und direkt gelöscht. Sessions, die beispielsweise versehentlich nicht beendet wurden, können somit automatisch nach einem festen konfigurierten Zeitlimit gelöscht werden. Dies gewährleistet, dass eine Session eine maximale Lebensdauer hat. 3.2.3 Szenarien In diesem Abschnitt werden die Szenarien beschrieben und dargestellt, welche Vorzüge diese haben können. Sie werden über Groovy-Skripte realisiert und sind für den Verarbeitungsprozess verantwort- lich. Die Groovy-Skripte gehören nicht direkt zum IDML-Server, können aber nach individuellen An- forderungen entwickelt und in diesen eingebunden werden. Die Skripte sind auf vorgegebene IDML- Dateien ausgerichtet. Diese sind speziell vorbereitet, um die ausgewählten Szenarien darstellen zu können. Es werden sechs Skripte betrachtet, die jeweils ein Szenario darstellen:
  • 54.
    54 ExtractText.groovy: Dieses Skriptist, dafür zuständig Texte zu extrahieren. Das Skript sieht wie folgt aus: def resultMap = [:] StringBuilder sb = new StringBuilder() new File(inPath).eachFileRecurse { def idml = new Idml(it.getAbsolutePath()) def spreadIterator = DocumentUtil.getSpreadIterator(idml) while (spreadIterator.hasNext()) { def pageItemIterator = SpreadUtil.getPageItemIterator(spreadIterat or.next()) while (pageItemIterator.hasNext()) { def pageItem = pageItemIterator.next() if (pageItem.isTextFrame()) { def story = PageItemUtil.getParentStory(pageItem.getAsText- Frame()) def content = StoryUtil.getContent(story) sb.append(content) } } } idml.save() idml.close() } resultMap.put("text", sb.toString()) resultMap Als erstes wird zunächst in dem Skript eine resultMap erzeugt. Dies ist das Ergebnis, welches später befüllt und als XML an der Webservice-Schnittstelle dargestellt wird. Da das Skript Zugriff auf den Inputordner hat, können alle Dateien aus diesem Ordner verarbeitet werden. Hier wird davon ausgegangen, dass es sich um IDML-Dateien handelt. Diese IDML-Dateien werden über alle Spreads und PageItems durchlaufen und kontrolliert, ob das jeweilige PageItem eine TextFrame ist. Trifft dies zu, wird auf die zugehörige Story zugegriffen und der Textinhalt über einen StringBuilder zu einem String zusammengefasst. Somit werden alle Texte aus dem Dokument zu einem String zusammengefasst und in der resultMap positioniert. Das Szenario soll in erster Linie zeigen, dass es ohne großen Programmieraufwand mit dem IDML- Server möglich ist auf die Texte einer IDML-Datei zuzugreifen. Es kommt oftmals vor, dass auf- wendig Unternehmensbroschüren, Flyer oder andere Medienprodukte mit InDesign produziert
  • 55.
    55 werden und dieTexte aus diesen Produkten dann in anderen Medien verwendet werden sollen. Oft wird dann manuell mit InDesign das Dokument geöffnet, um den jeweiligen Text zu kopieren. Dabei können Fehler entstehen und das manuelle Öffnen der Datei erfordert das Programm In- Design. Mit dem IDML-Server und diesem Skript könnten die Textinhalte einer IDML-Datei über den Webservice zur Verfügung gestellt und dann weiter verarbeitet werden. Beispielsweise können die Texte auf Webseiten, mobilen Endgeräten dargestellt oder in Suchengines platziert werden, um die Inhalte durchsuchbar zu machen. TextManipulation.groovy: Dieses Skript bietet die Möglichkeit, Texte aus einer IDML-Datei zu verändern und neu abzuspeichern: def resultMap = [:] new File(inPath).eachFileRecurse { def idml = new Idml(it.getAbsolutePath()) def spreadIterator = DocumentUtil.getSpreadIterator(idml) while (spreadIterator.hasNext()) { def pageItemIterator = SpreadUtil.getPageItemIterator(spreadIterat or.next()) while (pageItemIterator.hasNext()) { def pageItem = pageItemIterator.next() if (pageItem.isTextFrame()) { def story = PageItemUtil.getParentStory(pageItem.getAsText- Frame()) story.getParagraphStyleRangeList().get(0).getCharacterStyleR- angeList().get(0).setContent(content); } } } def out = outPath + it.getName() idml.saveAs(out) idml.close() } resultMap Dieses Skript arbeitet ähnlich wie das vorherige Skript. Alle Dateien werden aus dem Inputordner durchlaufen und über alle Spreads und PageItems iteriert. Ist das PageItem ein TextFrame wird wieder auf die Story zugegriffen. Zugriff auf den Textinhalt bekommt man über die Para- graphstylRageList und CharacterStyleRangeList. Hier wird davon ausgegangen, dass
  • 56.
    56 nur ein ParagraphenstyleRangeund ein CharacterStyleRange existieren. Der Inhalt des CharacterStyleranges wird neu gesetzt mit der Variable content. Diese Variable ist wie der outPath und inPath nicht in dem Skript deklariert. Der Wert ist ein Parameter, der durch den Webservice über das Binding in dem Skript verfügbar gemacht wird. Zum Schluss wird die Änderung in einer neuen IDML-Datei im Outputordner abgespeichert. Diese Art von Skript kann bei Übersetzungen verwendet werden. Gibt es beispielsweise Medien- produkte, die in verschiedenen Sprachen publiziert werden sollen, bietet der IDML-Server eine Möglichkeit dies zu realisieren. Wichtig in dem Fall ist, dass der reine Textinhalt verändert wird, jedoch keine Stile, Positionen oder andere wichtige Corporate-Design-Vorgaben, die eingehalten werden müssen. Zu beachten ist außerdem noch, dass die TextFrames in dem Grunddokument dafür ausgerichtet sein müssen und genug Platz aufzuweisen. Übersetzte Texte können unter Um- ständen länger werden als der Orginaltext. Das Erkennen eines Textüberschusses in einem Text- Frame kann in IDML nicht direkt erfasst werden. Dazu muss das Dokument beispielsweise einmal mit InDesign gerendert werden. Ein weiterer Bereich für den Einsatz des Skripts liegt im Korrekturworkflow. Eine Web Applika- tion könnte über den Webservice des IDML-Servers auf die Daten zugreifen und die Texte, die Fehler beinhalten, verändern, ohne dass dabei gestalterische Merkmale verändert werden. Der Benutzer, der diese Webapplikation dann verwendet, benötigt kein InDesign Wissen. Validate.groovy: Dieses Skript stellt einfache Validierungsmöglichkeiten von IDML-Dateien vor. Es wird hier in einer minimierten Version dargestellt, da die Möglichkeiten zur Prüfung der Datei sehr umfangreich sein können: def resultMap = [:] new File(inPath).eachFileRecurse { def idml = new Idml(it.getAbsolutePath()) def firstSpread = DocumentUtil.getSpreadIterator(idml).next(); def nameExists = false def pageItemIterator = SpreadUtil.getPageItemIterator(firstSpread, new IPageItemFilter() { public boolean accept(AbstractIdmlPageItem pageItem) { return LabelUtil.hasLabel(pageItem, "Label"); } }); while (pageItemIterator.hasNext()) { AbstractIdmlPageItem pageItem = pageItemIterator.next(); if (pageItem.isTextFrame()) { KeyValuePair label = LabelUtil.getLabel(pageItem.getAsText-
  • 57.
    57 Frame(), "Label"); if (label.getValue().equals("name")){ nameExists = true } } } idml.close() resultMap.put("nameExists", nameExists) } resultMap Das Ziel des Skriptes ist es zu identifizieren, ob ein bestimmtes PageItem in der IDML enthalten ist. Auch hier wird wieder auf die PageItems zugegriffen, jedoch mit dem Unterschied, dass ein Filter verwendet wird, der nur PageItems zurück gibt, die ein Label besitzen. Labels sind Markierungen die über InDesign an PageItems gesetzt werden können. Abb. 12 InDesign Script Label Über diese PageItems wird nun iteriert und kontrolliert, ob es ein TextFrame ist. Trifft dies zu, wird weiter der Wert des Labels geprüft. Wenn dieser den Wert name beinhaltet, ist das jeweilige Element gefunden worden und es wird ein true Wert in die resultMap platziert. Über den Web- service wird dieser dann dargestellt und das Dokument kann als valid weiter behandelt werden. Es sind auch weitere Validierungsmöglichkeiten gegeben. Beispielsweise kann nach Bildern va- lidiert und anhand des Dateinamens kontrolliert werden, ob ein Logo mit speziellem Dateinamen in dem Dokument platziert wurde. Andere Möglichkeiten wären Schriften, Positionen und Farben in einem Dokument zu kontrollieren. Corporate-Design-Vorgaben können somit automatisch kon- trolliert werden. IdmsGroupExport.groovy: Dieses Skript ist dafür zuständig, Teile einer IDML-Datei als IDMS- Dateien zu exportieren, um diese wieder verwenden zu können. In dem Skript wird eine Funktion verwendet, die aus einer IDML-Datei alle PageItems vom Typ Group in einer Liste zur Verfü-
  • 58.
    58 gung zu stellen.Diese sieht wie folgt aus: def List<Group> getGroups(Idml idml) { List<Group> groupResult = new ArrayList<Group>(); SpreadIterator spreadIterator = DocumentUtil.getSpreadIterator(idml); while (spreadIterator.hasNext()) { Spread spread = spreadIterator.next(); PageItemIterator pageItemIterator = SpreadUtil. getPageItemIterator(spread, new IPageItemFilter() { public boolean accept(AbstractIdmlPageItem abstractIdmlPageItem) { return abstractIdmlPageItem.isGroup(); } }); spread.close(); while (pageItemIterator.hasNext()) { Group currentGroup = (Group) pageItemIterator.next(); groupResult.add(currentGroup); } } return groupResult; } Die programmatische Umsetzung erfolgt über einen PageItemFilter. Dieser prüft, ob das Pa- geItem vom Typ Group ist und diese Gruppe anschließend in einer groupResult Liste ablegt. def resultMap = [:] def idmsFiles = new ArrayList<String>(); new File(inPath).eachFileRecurse { def idml = new Idml(it.getAbsolutePath()) def groups = getGroups(idml) def snippetBuilder = SnippetBuilder.get() groups.each {group -> def idmsFile = new File(outPath + group.self + ".idms") snippetBuilder.createSnippet(group, idmsFile) idmsFiles.add(idmsFile.getAbsolutePath()) }
  • 59.
    59 idml.close() } resultMap.put("idms files", idmsFiles) resultMap DieseListe wird weiter verarbeitet und für jede Gruppe, die gefunden wurde, wird eine IDMS- Datei erzeugt, die als Dateinamen die SelfId der Gruppe trägt. Diese ist in einem Dokument immer eindeutig. Die Pfade der erzeugten IDMS-Dateien werden in einer Liste abgelegt und zu der resultMap hinzugefügt. Diese werden anschließend im Webservice dargestellt. Ein solches Szenario ist bei wiederkehrenden Elementen im IDML sinnvoll. Hat man beispiels- weise einen Handzettel mit unterschiedlichen Produkten, können diese Produkte als IDMS-Datei exportiert und in späteren Ausgaben wieder verwendet werden. Dabei können zu einem Produkt unterschiedliche Elemente gehören. Besteht ein Produkt aus einem Bild, einem Beschreibungstext und einem Preis, können diese drei Elemente in InDesign als Gruppe zusammengefasst werden und dann mit diesem Skript exportiert werden. Der Vorteil durch diese Wiederverwendbarkeit liegt darin, dass die IDMS-Dateien alle gestalterischen Merkmale beibehalten. Ist ein Produkt einmal gestaltet und exportiert worden kann die exportierte IDMS-Datei in anderen InDesign-Dokumen- ten mit allen Stilen, Farben, etc. platziert werden. ImportIdms.groovy: Dieses Skript ist das Gegenstück zum IdmsGroupExport.groovy. Das Ziel ist es, IDMS-Dateien in IDML-Dateien zu importieren. Dazu werden mehrere IDMS-Dateien in einer IDML platziert und als neue IDML-Datei abgespeichert: def resultMap = [:] def idmlList = new File(inPath).listFiles({d, f -> f ==~ /.*.idml/ } as FilenameFilter).toList() def idmsList = new File(inPath).listFiles({d, f -> f ==~ /.*.idms/ } as FilenameFilter).toList() idmlList.each {idmlFile -> def idml = new Idml(idmlFile.getAbsolutePath()) idmsList.each {idmsFile -> def idms = new Idml(idmsFile.getAbsolutePath()) DocumentUtil.importSnippet(idml, idms, 0) } def out = outPath + idmlFile.getName() new File(out).getParentFile().mkdirs() idml.saveAs(out)
  • 60.
    60 idml.close() } resultMap Ein solches Szenariokann dazu dienen vollautomatisch IDML-Dateien zu erzeugen. Betrach- tet man das vorherige Export-Skript, kann eine denkbare Kombination eine Art Baustein-System sein. Mit dem Export-Skript können Produkte eines Handzettels exportiert und als einzelne Bau- steine in einem System abgelegt werden. Mit dem Import-Skript kann das System dann mehrere Produkte zu einem Handzettel zusammenbauen. In Kombination mit dem Skript der Textmanipu- lation können dann sogar Texte verändert oder übersetzt werden. DatabasePublishing.groovy: Dieses Skript ist aus einer vorherigen Arbeit adaptiert und für den IDML-Server optimiert worden. Die zugehörigen Informationen sind zu finden unter [Pouryek- ta2011] und das Video dazu unter [DatabasePublishing2011]. Das Skript stellt ein Database-Pu- blishing-Szenario dar. Aus einer XML mit Personendaten (welches als Datenbank fungiert) und einer IDML (welches als Template fungiert) werden pro Person Visitenkarten erzeugt. Das Skript kann in den beigefügten Quellen betrachtet werden. Es ist eine Kombination aus dem Validate. groovy Skript und dem TextManipulation.groovy Skript. Über die Labels können wie im Valida- te.groovy die jeweiligen PageItems identifiziert werden. Wie bei dem TextManipulation.groovy werden die Texte dann ausgetauscht, die aus der XML-Datei kommen. Hier wird deutlich, dass der IDML-Server nicht nur IDML-Dateien, sondern auch XML-Dateien ohne Probleme verarbei- ten kann. Auch weitere Formate sind möglich. Bilder werden auch in diesem Skript ausgetauscht. Dazu müssen die Bilder mit in das System geladen werden und in dem XML verfügbar sein. Was in IDML dann passiert ist, dass die Pfade des Bildes verändert werden und so im IDML das neue Bild dargestellt wird. Die Vorteile von Database-Publishing liegen vor allem in der Geschwindigkeit, in der die Doku- mente generiert werden und in der minimierten Fehleranfälligkeit im Vergleich zur manuellen Umsetzung.
  • 61.
    61 4 Schlussbetrachtung In diesemletzten Kapitel werden noch einmal die Ergebnisse der Umsetzung zusammengetragen und bewertet. Es werden Empfehlungen für die Bereiche angesprochen, in denen ein IDML-Server sinn- voll genutzt werden kann. Da das Konzept nur für eine erste Version des IDML-Servers konzipiert wurde, wird zum Schluss zusätzlich ein Blick in die Zukunft geworfen und mögliche Weiterentwick- lungen des Systems betrachtet. 4.1 Ergebnisse Die Ergebnisse sind in zwei Bereiche einzuteilen. Der erste Bereich beschäftigt sich mit den Ergebnis- sen des Prototyps. Der zweite mit den Szenarien, welche den produktiven Einsatz ermöglichen: Prototyp: Bei der Entwicklung des Prototyps ist deutlich geworden, wie ein IDML-Server aus- sehen kann. Die Themen aus den Grundlagen spielen dabei eine wesentliche Rolle. Vor allem der Einsatz des Grails-Frameworks bietet sehr viele Möglichkeiten im Bereich der Entwicklung. Die vier Anforderungen an das System konnten mit dem Konzept und dem Prototypen bestätigt werden. Die Anforderung der Verarbeitung wird dabei in der Process-Engine realisiert. Sie kap- selt den Verarbeitungsprozess und realisiert ihn durch individuell gestaltbare Groovy-Skripte. Die Vereinfachung des Umgangs mit IDML wird durch den ganzen IDML-Server realisiert. Dabei fassen die Skripte spezielle und komplexe Aufgaben zusammen und können durch einen einfach zu bedienenden Webservice angesteuert werden. Die Anforderung der Einbindung des Systems wird auch über den Webservice realisiert. Dieser ist in Teilen individuell durch die Groovy-Skripte erweiterbar. Dies ist auch somit die letzte Anforderung. Die Erweiterbarkeit wird über die Webser- vice-Parameter, die Groovy-Skripte und dem Grails-Pluginsystem gewährleistet. Szenarien: Die Szenarien zeigen mögliche Einsatzbereiche des IDML-Servers. Das ExtractText. groovy Skript zeigt wie Inhalte über einen Webservice zur Verfügung gestellt und somit über an- dere Systeme publiziert werden können. Das TextManipulation.groovy Skript beschreibt den Ein- satzbereich von Web-to-Print-Systemen. Hiermit können Übersetzungs- und Korrekturworkflows realisiert werden. Das Validate.groovy Skript ist im Bereich der Qualitätskontrolle einzuordnen. Mit derartigen Skripten kann gewährleistet werden, dass IDML-Dateien eine bestimmt Form auf- weisen. Fehlerhafte Dateien können somit automatisch aussortiert werden. Das IdmlGroupExport. groovy und das ImportIdms.groovy Skript können zusammen im Bereich von Bausteinsystemen verwendet werden. Ganze IDML-Elemente können so wieder verwendet und regelbasiert, vollau- tomatisch zu ganzen Dokumenten zusammengeführt werden. Das DatabasePublishing.groovy hat gezeigt, dass mit IDML auch Database-Publishing möglich ist. Hier wurden individuelle IDML- Dateien in wenigen Sekunden erzeugt.
  • 62.
    62 4.2 Bewertung Die Bewertungder Ergebnisse wird auch wieder in den zwei Bereichen Prototyp und Szenarien be- trachtet: Prototyp: Bei dem Prototypen hat sich herauskristallisiert, dass die Wahl der Technologie und die Orchestrierung dieser eine wesentliche Rolle spielen. Das Grails-Framework in Kombination mit der Sprache Groovy war hier der richtige Ansatz, um das Konzept über einen Prototypen zu bestätigen. Die größten Vorteile liegen einmal darin, dass dieser IDML-Server in der Lage ist ein komplexes Format zu kapseln. Wichtig ist hier zu erwähnen, dass der IDML-Server nicht die Komplexität von IDML minimiert, sondern diese nur in den Bereich der Groovy-Skripte ver- schiebt. Über die Groovy-Skripte wird dann die Verarbeitung gewährleistet. Diese Verarbeitung kann über eine einfache URL angestoßen werden. Der Benutzer, der diese URL anstößt, muss kein Wissen über das zu verarbeitende Format haben, da die Skripte die Komplexität behandeln und für die Verarbeitung zuständig sind. Ein weiterer Vorteil, welcher sich während der praktischen Umsetzung deutlich zeigt, ist dass es auf Erweiterbarkeit ausgelegt und nicht zwingend auf IDML beschränkt ist. In diesem System wurde lediglich der Fokus auf IDML gesetzt. Es ist jedoch so flexibel ausgelegt, dass es ohne große Anpassungen auch andere Formate verarbeiten kann. Somit sind die Anforderungen an den IDML-Server zufriedenstellend erfüllt. Szenarien: Die Skripte, welche die Szenarien darstellen, können komplexe Prozesse abbilden und durch diese Art von Automatisierung Vorteile bewirken. Diese Vorteile können vor allem im Bereich der Produktion liegen, da Prozesse verkürzt und optimiert werden. Auch die Qualität der Produkte kann über spezielle Skripte so gewährleistet werden. Im Bereich der Wirtschaftlichkeit können hier für Unternehmen Vorteile entstehen, da diese Art von IDML-Verarbeitung sonst nur mit einem kostenintensiven InDesign-Server möglich ist. Die Skripte sind speziell für angepasste IDML-Dateien vorbereitet worden. Um diese Groovy-Skripte zu entwickeln, sind Spezialisten notwendig, die Erfahrung in InDesign, IDML und Groovy besitzen. Ein wirklich produktiver Ein- satz der Skripte setzt außerdem einheitliche und strukturierte IDML-Dateien vorraus. Diese Art von Verarbeitung kann jedoch selten im künstlerischen Bereich eingesetzt werden. Es ist in erster Linie darauf ausgelegt, strukturierte Abläufe zu optimieren. Zusammenfassend kann gesagt werden, dass der Einsatz eines IDML-Servers große Vorteile bringen kann. Wichtig ist, dass die IDML-Dateien strukturiert aufbereitet sind und die Skripte professionell erstellt werden. Das bedeutet allerdings auch, dass man sich mit diesen Themen intensiv auseinander setzten muss, um wirklich produktiv diese Vorteile zu erzielen.
  • 63.
    63 4.3 Blick indie Zukunft Das Konzept, das hier betrachtet wurde, kann und soll weiterentwickelt werden. Folgend werden Ideen betrachtet, die in Zukunft in den IDML-Server einfließen können: JSON: In dieser ersten Version des IDML-Servers gibt der Webservice die Daten als XML zurück. Es kann von Vorteil sein hier auch das JSON-Format zu unterstützen, da es die gleichen Daten oft kleiner als XML darstellen kann. Die Anpassung ist in dem Grails-Framework sehr einfach umzu- setzen und könnte über den Webservice per Parameter beeinflusst werden. Ergebnis: Das Ergebnis, was über den Webservice dargestellt wird, ist in dieser ersten Version eine Map. Um den Webservice strukturierter aufzubauen, kann eine Ergebnis-Klasse erzeugt wer- den, die feste und variable Werte aufnehmen kann. Die festen Werte können dann beispielsweise für spezielle Nachrichten und Codes verwendet werden, die immer in einem Webservice-Ergebnis vorhanden sein müssen. Die variablen Werte können dann individuell beansprucht werden. Versionierung: Bei einer Weiterentwicklung des Webservices sollte eine Versionierung des Web- service in Betracht gezogen werden. Ist der IDML-Server einmal in bestehende Workflows ein- gebunden, können Veränderungen des Webservices den ganzen Workflow gefährden. Der Einsatz eines versionierten Webservices könnte hier Abhilfe schaffen. Multiupload: In dieser ersten Version kann pro Serveranfrage immer nur eine Datei hochgeladen werden. Für zukünftige Versionen könnte man einen Multiupload entwickeln, der den Ablauf be- schleunigen könnte. Parameter: Der Webservice kann individuelle Parameter beinhalten, die dann von den Groovy- Skripten verarbeitet werden können. Diese Parameter werden in dieser ersten Version nicht im Webservice-Ergebnis angebunden. Hier sollten der Vollständigkeit halber nicht nur die festen Pa- rameter, sondern auch die variable Parameter gesetzt werden. Asynchron: Der Server arbeitet in dieser ersten Version synchron. Das bedeutet, es ist möglich an den Server eine Anfrage zu stellen. Diese wird dann verarbeitet und es wird ein Ergebnis zurück gegeben. Dieser Verarbeitungsvorgang kann unter Umständen lange dauern. Daher könnte man einen asynchronen Ansatz wählen, indem man in der Process-Engine mit einer Queue arbeitet, die Kommandos entgegen nehmen kann. Der Ansatz beruht hier auf dem Command-Muster. Dieser in Kombination mit dem State-Muster kann eine asynchronen Verarbeitungsprozess realisieren. Der Anfragende stößt somit nicht direkt die Verarbeitung an, sondern fügt der Queue ein Kommando hinzu. Ein Ergebnis, ob das Kommando in dem Verarbeitungsprozess angekommen ist kann sofort
  • 64.
    64 zurück gegeben werden.Wann genau das Kommando verarbeitet wurde und wann genau er abge- schlossen wird, ist nicht direkt für den Anfragenden sichtbar. Er kann aber den Status der Verarbei- tung über den Webservice abfragen, der einem dann sofort zurückgeben kann, ob die Verarbeitung noch im Gange oder bereits abgeschlossen ist. Benutzerverwaltung: Eine weitere Möglichkeit liegt in der Einführung einer Benutzerverwal- tung. Die Unterscheidung zwischen einem Benutzer für das System und einem Administrator kann eine deutliche Trennung zwischen den Aufgabenbereichen darstellen. Ein Administrator kann so- mit das System konfigurieren und Benutzer verwalten. Benutzer können so unterschiedliche Rech- te auf Verarbeitungsprozesse haben. Ein Benutzer kann somit beispielsweise nur Verarbeitungen im Qualitätsbereich ausführen, die keine Veränderungen der Dateien vornehmen. Im Gegensatz dazu könnte ein Übersetzter Rechte auf Verarbeitungen im Bereich der Textmanipulation haben. Skriptverwaltung: Die Skripte könnten in einer weiteren Version des IDML-Servers über eine Benutzeroberfläche verwaltet werden. Dazu könnte es über die Benutzerverwaltung eine Rolle des Entwicklers geben, der Zugriff auf die Skripte hat und diese hochladen, erstellen und verändern kann. Datenbank: Die Verwendung einer Datenbank könnte den IDML-Server weiter optimieren. Da- bei könnten Informationen über die Benutzer und die Skripte in der Datenbank platziert werden. Download: Der Downloadprozess ist in erster Version des IDML-Servers sehr einfach gehalten. Er stellt den ganzen Output zur Verfügung. Bei einer Verarbeitung in der mehrere Dateien erzeugt werden, kann es erforderlich sein nur Zugriff auf eine spezielle Datei zu erhalten. Der Download- prozess könnte so weiterentwickelt werden, dass auch einzelne Dateien aus dem Outputordner heruntergeladen werden können. Temporaryordner: Der Temporaryordner wird bislang nur im Downloadprozess verwendet. Der Zugriff auf diesen Ordner könnte aber auch in Groovy-Skripten Verwendung finden. Zusammenfassend kann gesagt werden, dass es noch viele Möglichkeiten gibt, diesen IDML-Server sinnvoll auszubauen. Der Blick in die Zukunft zeigt mögliche Entwicklungen.
  • 65.
    65 Abbildungsverzeichnis Abbildung Beschreibung Seite 1MVC Ablauf 9 2 SOAP-Nachricht 13 3 Grails Einordnung 14 4 Groovy/Java Plattform 15 5 Spring Modules 20 6 Grails Applikation 22 7 IDML Container Aufbau 33 8 IDML-Server 38 9 Workflow Ablauf 40 10 IDML-Server Index Seite 43 11 IDML-Server Process Index Seite 44 12 InDesign Script Label 57
  • 66.
    66 Abkürzungsverzeichnis Abkürzung Beschreibung ACID AtomicityConsistency Isolation Durability AJAX Asynchronous JavaScript and XML AOP Aspect-Oriented Programming CoC Convention over Configuration CS Creative Suite CSS Cascading Style Sheets DOM Document Object Model DI Dependency Injection DRY Don´t Repeat Yourself DTP Desktop Publishing eBook Electronic Book EL Expression Language EPUB Electronic Publication EVA Eingabe, Verarbeitung, Ausgabe GDK Groovy Development Kit GORM Grails Object Relational Mapping GPath Groovy Path Language GSP Groovy Server Page GString Groovy String HTTP Hypertext Transfer Protocol IDML InDesign Markup Language IDMS InDesign Snippet INDD InDesign Document Format INX InDesign Interchange Format IoC Inversion of Control JDK Java DevelopmentKit JS JavaScript JSON JavaScript Object Notation JSP Java Server Page JVM Java Virtual Machine MIMETYPE Multipurpose Internet Mail Extensions Type MVC Model View Controller ORM Object Relational Mapping PDF Portable Document Format
  • 67.
    67 Abkürzung Beschreibung POJO PlainOld Java Object RDF Resource Description Framework REST Representational State Transfer RNG Regular Language Description for XML New Generation SEI Software Engineering Institute SOAP Simple Object Access Protocol SQL Structured Query Language UCF Universal Container Format URI Uniform Resource Identifier URL Uniform Resource Locator UUID Universally Unique Identifier W3C World Wide Web Consortium WSDL Web Service Description Language XML Extensible Markup Language XPath XML Path Language XQuery XML Query Language XMP Extensible Metadata Platform XSLT Extensible Stylesheet Language Transformation
  • 68.
    68 Literaturverzeichnis [Adobe2012] Adobe Systems2012, https://wwwimages2.adobe.com/content/dam/ Adobe/en/devnet/indesign/sdk/cs6/idml/idml-specification.pdf (2013- 01-07) [Bayer2002] Thomas Bayer, REST Web Services, 2002, http://www.oio.de/public/ xml/rest-webservices.pdf (2012-12-19) [Booth2004] David Booth, Hugo Haas, Francis McCabe, Eric Newcomer, Michael Champion, Chris Ferris, David Orchard: Web Services Architecture, 2004, http://www.w3.org/TR/ws-arch/ (2012-12-18) [Carnegie2012] Carnegie Mellon Software Engineering Institute, http://www.sei.cmu. edu/architecture/start/glossary/community.cfm#definitions (2012-11- 06) [DatabasePublishing2011] Database Publishing mit IDML 2011, https://www.youtube.com/ watch?v=IpbJudaJFH4 (2013-02-17) [Davis2008] Scott Davis: Groovy Recipes Greasing the Wheels of Java, The Pragmatic Programmers, 2008 [Fielding2000] Roy Thomas Fielding: Architectural Styles and the Design of Network-based Software Architectures, 2000, https://www.ics.uci. edu/~fielding/pubs/dissertation/rest_arch_style.htm (2012-12-19) [Freeman2004] Eric Freeman, Elisabeth Freeman, Bert Bates, Kathy Sierra: Head First Design Patterns, O‘Reilly Media, 2004 [Frotscher2007] Thilo Frotscher, Marc Teufel, Dapeng Wang: Java Web Services mit Apache Axis2, entwickler.press, 2007 [Gamma2011] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Ent- wurfsmuster: Elemente wiederverwendbarer objektorientierter Soft- ware, Addion-Wesley Verlag, 2011
  • 69.
    69 [Grandeur2009] Grandeur: researchinggroovy & grails, 2009, http://www.gayadesign. com/scripts/uploads/researchpaper.pdf (2012-12-21) [Groovy2012] Groovy Closures - Formal Definition, http://groovy.codehaus.org/ Closures+-+Formal+Definition (2012-12-29) [Hunt2003] Andrew Hunt, David Thomas: Der Pragmatische Programmierer, Han- ser, 2003 [IDMLlib2013] IDMLlib for Java, http://idmllib.com/ILWebsite/Products/IDMLlib- for-Java (2013-01-13) [Johnson2004] Rod Johnson, Juergen Hoeller: J2EE Development without EJB, Wi- ley Publishing Inc, 2004 [Johnson2005] Rod Johnson,Juergen Hoeller,Alef Arendsen,Thomas Risberg,Colin Sampaleanu: Professional Java Development with the Spring Frame- work, Wiley Publishing Inc, 2005 [Kipphan2000] Helmut Kipphan: Handbuch der Printmedien, Springer Verlag, 2000 [König2007] Dierk König, Andrew Glover, Paul King, Guillaume Laforge, Jon Skeet: Groovy in Action, Manning Publications Co., 2007 [Kruchten1995] Philippe Kruchten: Architectural Blueprints—The “4+1” View Model of Software Architecture, IEEE Software November 1995 http://www. cs.ubc.ca/~gregor/teaching/papers/4+1view-architecture.pdf (2012- 11-06) [Oltmanns2007] Daniel Oltmanns, Stefan Edlich: Spring 2 für Grünschnäbel, Books on Demand GmbH, 2007 [Pouryekta2011] Peyman Pouryekta: Analyse und Bewertung der InDesign Markup Language - Desktop Publishing vs. Database Publishing, VDM Ver- lag Dr. Müller, 2011 [Rocher2009] Graeme Rocher, Jeff Brown: The Definitive Guide to Grails, Apress, 2009
  • 70.
    70 [Snell2002] James Snell,DougTidwell,Paul Kulchenko: Webservice-Programmie- rung mit SOAP, O‘Reilly, 2002 [SpringDocu2012] Spring Documentation: 1. Introduction to Spring, http://static. springsource.org/spring/docs/3.0.x/reference/overview.html, (2012- 12-30) [Starke2009] Gernot Starke: Effektive Software Architekturen, Ein praktischer Leit- faden, Hanser Verlag 2009 [Wolff2009] Eberhard Wolff: Über Architekturen und Perfektion, http://jandi- andme.blogspot.de/2009/10/uber-architekturen-und-perfektion.html (2010-11-07)
  • 71.
    71 A Ablaufplan 7 abstraction 6 Abstraktion6, 8 ACID 25 Adobe 4 Adobe Creative Suite 30 AJAX 27 Analyse 7 AOP 26 application.properties 22 Arbeitsaufwand 4 Architekturmuster 8 Aspect-Oriented-Programming 26 Assoziationen 9 Ästhetik 6 Asynchron 63 Asynchronous JavaScript and XML 26 Atomicity 25 Auslieferung 13 Authentifizierung 13 Autorisierung 13 B BackingStory.xml 35 Bauplan 7 Benutzerverwaltung 64 Beschnittzugabe 31 Blitzer 31 Body 13 BootStrap.groovy 22 BuildConfig.groovy 22 Builder 11 Built-in Tag 28 C Carnegie Mellon Software Enginee- ring Institute 6 Classpath 50 Closure 16 Cloud 38 CoC 21, 48 Code-Generierung 13 Collection 18 Color 34 Command 11 composition 6 Config.groovy 22 config.properties 45, 46, 50 Consistency 25 Constructor-Injection 21 Containerformat 33 container.xml 35 Controller 9, 26 Convention over Configuration 21 Corporate-Design-Vorgaben 56, 57 CRUD 27 CS4 4 Custom Tag 29 D Database-Publishing 60, 61 DatabasePublishing.groovy 60 DataSource.groovy 22 Datei Download 41 Dateinamen 5 Datei Upload 41, 47 Datenmodell 9 Datentypen 17 decomposition 6 DELETE-Methode 14 Dependency Injection 20 designmap.xml 34 design pattern 7, 10 Desktop-Publishing 5, 30 development view 7 DI 21 Diagramm 5 Dokumenterstellung 30 Don´t Repeat Yourself 21 Druck- und Medienindustrie 4 DRY 21 DTP 30 Durability 25 Dynamic Dispatching 27 Dynamic Tag 28 dynamisch typisiert 15 E eBook 31 electronic book 31 Electronic Publication 31 Encoding 33 Entwicklungsumgebung 22 Entwurfsentscheidungen 7 Entwurfsmuster 7, 10 Entwurfsprobleme 7 Envelope 12 EPUB 31 Erich Gamma 10 Erzeugungsmuster 10 esthetics 6 EVA-Prinzip 38 Expression Language 27 Extensible Markup Language 12 Extensible Metadata Platform 35 Extensible Stylesheet Language Stichwortverzeichnis
  • 72.
    72 Transformation 32 ExtractText.groovy 54 F Flexibilität8, 9 Fließtext 5 Flyer 54 Fonts.xml 34 Formfelder 31 Framework 5 G GET-Methode 14 GORM 23, 24 GPath 19 Gradients 34 Graeme Rocher 5 Grails 5, 14 grails-app 22 Grails-Applikation 21 Grails-Framework 5, 6, 14 Grails-Kommando 5 Grails Object Relational Mapping 23 Graphic.xml 34 Groovy 5, 6, 15 Groovy-Path 19 Groovy Server Page 27 Groovy-Skripte 41 Groovy-String 17 Grundlayout 27 Gruppen 31 GSP 27 GString 17 Guillaume Laforge 5 H Handzettel 59 Header 13 Hibernate-Framework 15 HTML 5 HTTP 12 Hypertext Transfer Protocol 12 I IDML 5, 30 IDML-Spezifikation 5, 32 IDMS 35 IdmsGroupExport.groovy 57 Import 15 ImportIdms.groovy 59 INDD 31 InDesign 30 InDesign Document Format 31 InDesign Markup Language 4 InDesign Snippet 35 Informationstechnik 4 Interchange Format 32 Inversion of Control 20 INX 32, 33 IoC 20 Isolation 25 J James Strachan 15 JavaScript Object Notation 26 Java Server Page 27 Java Virtual Machine 15 JSON 26, 63 JSP 27 JVM 15 K Kapselung 35 Klassenpfad 50 Knöpfe 31 Komplexität 7 Komponenten 7 Komposition 5 Kompression 33 Konsequenzabschnitt 10 Konstruktionsplan 32 Konventionen 5 Konzept 4 L layering 8 Lazy loading Mechanismus 35 Linien-Elemente 31 List 18 Lizenzkosten 4 logical view 7 Lösungsabschnitt 10 M Map 18 Mapping.xml 35 MasterSpread 34 Medienprodukt 54 Messaging-Framework 12 metadata.xml 35 meta Tag 27 MIMETYPE 34 Model 9, 39 Model View Controller 8 Multipurpose Internet Mail Extensi- ons Type 34 Multiupload 63 Mustername 10 MVC 8, 9, 45 N NULL-Check 18 NullPointerException 18 O
  • 73.
    73 Object Relational Mapping15 Open-Source-Framework 20 Orchestrierung 5 Ordnung 7 ORM 15 Oval-Elemente 31 P PDF 31 Performance 8, 9 Persistenz-Framework 15 Philippe Kruchten 6, 7 physical view 7 Plain Old Java Object 15 Pläne 7 POJO 15 Polyglot Programming 35 Polygon-Elemente 31 Portable Document Format 31 POST-Methode 14 Präsentation 9 Preferences.xml 34 Problemabschnitt 10 Process-Engine 39, 41 process view 7 Produktionsumgebung 22 Programmsteuerung 9 proprietär 4, 31 Prototyp 42, 61, 62 PUT-Methode 14 Python 15 Q Qualität 8 Qualitätssicherung 36 Quasi-Standard 9 R Range 18 RDF 35 Realisierung 7 Rechteck-Elemente 31 Regular Language Description for XML New Generation 32 Representational State Transfer 6 Resource Description Framework 35 Resources 34 REST 6, 12, 13, 39 return Statement 18 RNG 32 Rod Johnson 5 Routing 13 Ruby 15 S Scaffolding 27 scenario 7 Schichten 8, 39 Schichtenmuster 8 Scripting 19 SEI 6 Semikolon 16 Session Beendigung 42, 51 Session Erzeugung 41, 43 Setter-Injection 21 Sichten 7 Simple Object Access Protocol 6 Single Point of Failure 38 Singleton 11 SiteMesh 15, 27 Skriptverwaltung 64 Smalltalk 15 SOAP 6, 12 SOAP-Nachricht 12 SOAP-Schnittstelle 39 Softwarearchitektur 6 Softwareentwicklung 5 Spread 34 Spring 20 Spring-Framework 5 SQL 24 State 11 Stil 6 Stories 34 Story.xml 35 StrokeStyle 34 Structured Query Language 24 Struktur 7 Strukturmuster 10 style 6 Styles.xml 34 T taglib 29 Tags.xml 35 Testumgebung 22 Text-Elemente 31 TextManipulation.groovy 55 Tomcat 30, 43 Transaktionskontext 13 Transformierung 32 Typografie 5, 30 Typografische Konventionen 5 U Übersetzungsworkflow 36 UCF 33 Uniform Resource Identifier 13 Universal Container Format 33 Universally Unique Identifier 40 Unternehmensbroschüren 54 URI 13 URL 5 UrlMappings.groovy 23
  • 74.
    74 UUID 40 V Validate.groovy 56 Validator23 Verarbeitung 41, 48 Verhaltensmuster 10 Versionierung 63 Versionskompatibilität 4 Verständlichkeit 7, 8 View 9 W W3C 12 WAR 30 Wartbarkeit 9 Web Application Archive 30 Webservice 6, 12, 39 Web Service Description Language 12 Web-to-Print 61 Werkzeug 4 Wiederverwendbarkeit 59 World Wide Web Consortium 12 WSDL 12, 13, 40 X XML 5, 12, 19 XML-Overhead 40 XML Path Language 32 XML Query Language 32 XMP 35 XPath 32 XQuery 32 XSLT 32 Z Zerlegung 6 ZIP 51 ZIP-Archiv 33 Zusammensetzung 6 Zwiebel 8