Apache Cocoon
# Apache Cocoon

Cocoon ist ein XML-Publishing-System der Apache Software Foundation. Dieses Framework wurde geschaffen, um Daten in XML-Form zu speichern und mittels XSL formatiert auszugeben. Als Ausgabeprodukte von XML-Daten können XHTML, PDF, RTF und viele weitere (siehe unten) stehen.

   „Cocoon ist ein ‚Publishing Framework Servlet‘, das […] ein XML-Quelldokument je nach anfragendem Client in ein beliebiges Zielformat transformiert.“

Der Quellcode von Cocoon fällt unter die Apache-Lizenz und ist somit freie Software.

## Entstehung

Cocoon wurde 1998 von dem italienischen Studenten Stefano Mazzocchi geschrieben (angefangen), während er den Science-Fiction-Film Cocoon sah, wonach das System benannt wurde.

## Einführung

Das Konzept von Cocoon baut im Vergleich zu anderen webbasierten Frameworks auf einem neuen Ansatz auf. Bei HTML-Dokumenten werden in der Regel die Schichten Inhalt, Layout und Programmierlogik fest miteinander verbunden, oftmals sogar in einer Datei codiert. Cocoon geht einen anderen Weg zur Veröffentlichung der Informationen. Die drei erwähnten Schichten werden strikt voneinander getrennt und müssen in separaten Dateien bearbeitet werden. Dies bedeutet für den Entwickler anfangs einen größeren Aufwand beim Erstellen der Webseiten, da er drei Dateien erstellen und pflegen muss. Dieser Mehraufwand kann bei großen Projekten im Verlauf der Entwicklung mehrfach ausgeglichen werden, da einzelne Logik- oder Layoutteile problemlos durch Wechseln der entsprechenden Datei ausgetauscht, in andere Projekte integriert und somit wieder verwertet werden können.

Um das Konzept der Trennung der einzelnen Schichten in Cocoon umzusetzen, wurde XML gewählt, da XML diese Anforderungen konsequent erfüllt. Über den drei Schichten steht das Management, das jeden Teil der Entwicklung steuert.

Bei einem Cocoon-Projekt könnte beispielsweise ein Designer für ein Stylesheet (Layout) zuständig sein, ein Programmierer für die Logik und ein Redakteur für den Inhalt einer XML-Datei. Weiterhin ist Cocoon mit Java entwickelt worden, weshalb es plattformunabhängig ist. Cocoon unterstützt außerdem die Steuerung des Seitenflusses (Cocoon Control Flow), EAI-Anforderungen sowie die Errichtung von Webportalen. Darüber hinaus integriert es sich nahtlos in die J2EE-Welt.

### Funktionsweise

Technisch basiert Cocoon auf der Servlet-Technologie. Ein Servlet ist eine Java-Klasse, die Client-Anfragen an Webserver entgegennimmt und verarbeitet. Innerhalb dieser Verarbeitung wird eine Antwort erzeugt, die dann wiederum an den Webserver übergeben wird. Tomcat der Apache Software Foundation ist die Referenzimplementierung dieser Technologie, die die Programmiersprache Java der Firma Sun Microsystems benutzt.

Mittels Cocoon lassen sich nicht nur dynamische Webanwendungen erstellen, auch die lokale Benutzung ist möglich. Apache Lenya ist ein Content-Management-System, welches auf Cocoon aufbaut.

Darüber hinaus bringt Cocoon auch eine Portal Engine mit, mit der sich Portale erstellen lassen.

### Aufbau

Cocoon hat ein vollständig objektorientiertes Funktionsmodell. Dadurch wird es sehr leicht möglich, neue Komponenten zu integrieren oder bestehende zu ersetzen. Alle Komponenten basieren auf dem Modell von Apache Excalibur, das den genauen Aufbau jeder Komponente vorgibt. Es besteht die Möglichkeit, eigene Komponenten zu entwickeln, die sich durch Vererbung in das bestehende Modell integrieren lassen.

### Cocoon 2

Mit Cocoon 2.x haben sich die Entwickler entschlossen, Cocoon neu zu implementieren, um aus den Fehlern der Version 1.x zu lernen. Verändert wurde die interne Architektur sowie das Konzept von Cocoon. Hinzugekommen ist die flexible Sitemap, mit der sich Processing Instructions in beliebiger Reihenfolge durchführen lassen. Weiter wurde die Performance signifikant verbessert – einerseits durch eine schnellere Caching-Technik und weiter durch eine optimierte Abarbeitung der XML-Dokumente: Statt mit dem DOM-Parser komplexe Baumstrukturen aufzubauen, wird nun der ereignisgesteuerte SAX-Parser eingesetzt.

Durch diese Reimplementierung besitzt Cocoon heute zwei Standbeine: Während die älteren Konzepte nach wie vor existieren, sind durch die Reimplementierung viele neue, notwendige und hilfreiche Techniken hinzugekommen. Aufgrund der Abwärtskompatibilität ist es möglich, sowohl ältere als auch neuere Techniken zu verwenden oder sie sogar zu kombinieren.

## Cocoon 2.2

Seit Mai 2008 ist die grundlegend überarbeitete Version 2.2.0 von Apache Cocoon als „stabil“ gekennzeichnet. Während den Vorgänger-Versionen das inzwischen eingestellte Apache-Avalon-Framework zugrunde lag, basiert die neue Version auf Spring. Weiterhin wurde das Build-Tool Ant durch Apache Maven ersetzt.

Cocoon 2.2 ist, wie auch seine Vorgänger, stark komponentenorientiert ausgelegt. Die Entwicklung findet nun in eigenständigen Modulen, sogenannten Blocks, statt. Diese neue Architektur bietet erhebliche Vorteile, beispielsweise durch den Rapid Class Reloader, der das Kompilieren von JAVA-Quellcode automatisiert, oder die Möglichkeit zur Integration von Funktionalität des Spring-Frameworks. Auch die Handhabung (Anlegen von Blocks, Kommunikation von Blocks untereinander, Eclipse-Integration etc.) wurde im Vergleich zu den Vorgängern wesentlich verbessert.

## Bestandteile

Cocoon ist auf der Basis des Java-Frameworks Spring implementiert und kann beliebig um eigene Java-Komponenten erweitert werden. Die eigentliche Arbeit von Cocoon wird in Pipelines ausgeführt. Die Pipeline besteht aus bis zu sieben Komponententypen, welche jeweils der Logik oder zur Bearbeitung dienen.

### Sitemap

Die Sitemap ist der Mittelpunkt jeder Cocoon-Anwendung. Die Sitemap ist eine XML-Datei mit Namen sitemap.xmap. Diese befindet sich immer im Wurzelverzeichnis des aktuellen Projektes. Unterverzeichnisse des Projektes können eine Subsitemap enthalten. Sie definiert die unterschiedlichen Cocoon-Komponenten und die Client-/Server-Interaktionen in den sogenannten Pipelines. Die Aufgabe einer Sitemap ist es zu entscheiden, was passiert, wenn ein bestimmter Request vom Benutzer oder dem System angefordert wird, z. B. das Aufrufen einer bestimmten Webseite.

Um zu erkennen, welche Aktionen nach einem bestimmten Request durchgeführt werden, besitzt die Sitemap so genannte Matcher.

**Matcher**

Benutzer-Anfragen (Requests wie beispielsweise URLs oder Cookies) werden in der Sitemap gegen die Matcher getestet bis eine Übereinstimmung gegeben ist. Die Antwort (Response) ergibt sich dann aus der Ausführung der zum Matcher gehörenden Aufgaben. Die Matcher selbst enthalten Folgen von Zeichen, die Wildcards oder Regulären Ausdrücken entsprechen.

**Selektor**

Der Selektor wertet bestimmte Informationen des Requests aus. Dabei wird meist ein HTTP-Header übertragen, wenn eine Webseite angefordert wird. Ein Selektor stellt eine Art Switch-Anweisung dar.

Es stehen ca. 8 Selektoren zur Verfügung, hier nur die wichtigsten:

* BrowserSelector (Prüfung des verwendeten Browsers)
* HostSelector (Prüfung des Hostparameters des HTTP-Requests)
* ParameterSelector (Prüfung eines definierten Parameters innerhalb Cocoons)
* HeaderSelector (Prüfung des Inhaltes des HTTP-Request-Headers)

## Pipeline

Der Matcher und seine dazugehörenden Aufgaben werden als XML Pipeline bezeichnet. Eine typische Pipeline besteht aus einem Generator, eventuell gefolgt von einem oder mehreren Transformern und schließlich einem Serializer.

Die Aufgaben innerhalb der Pipeline werden seriell abgearbeitet. Matcher sind das Bindeglied zwischen einer Anfrage (durch einen Client an Cocoon) und den auszuführenden nachfolgenden Operationen der Pipeline.

Die folgende Abbildung verdeutlicht das Konzept der Pipeline, in welchem zuerst ein Request an die Sitemap geschickt wird, danach der passende Matcher aufgerufen und die Aufgaben der Reihe nach durchgeführt werden. Die bereits mehrfach erwähnten Aufgaben werden von so genannten Komponenten erledigt, die in Cocoon eingebunden werden. Die Komponenten, die innerhalb der Pipeline zum Einsatz kommen, sind ein Generator, ein Transformer und ein Serializer.

### Generatoren

Der Generator ist der Startpunkt der Bearbeitungskomponente der Pipeline. Generatoren haben die Aufgabe, strukturierte Daten, z. B. XML-Daten oder Inhalte einer Datenbank, in einen SAX-Stream umzuwandeln. Dieser wird dann an den Transformator weitergegeben. Es kann pro Pipeline nur einen Generator geben.

### Transformer / Transformatoren

Transformatoren wandeln die vom Generator erzeugten XML-Elemente um. Es kann pro Pipeline mehrere optionale Transformatoren geben. Jeder Transformator kümmert sich oftmals nur um bestimmte Elemente des SAX-Streams. Es können mehrere Transformatoren hintereinander ausgeführt werden, um ein Dokument mit Inhalt und Layout zu erzeugen. Auch eine Pipeline ohne Transformatoren ist möglich. Der Transformator kommt besonders bei Webseiten mit mehrsprachigem Inhalt zur Anwendung (Internationalisierung). Häufig wird ein Transformationsschritt mit Hilfe eines XSLT-Stylesheet durchgeführt.

### Serializer

Der Serializer wandelt die Ausgabe des Transformators, den SAX-Stream, in ein Zieldokument um, in dem der Inhalt dann repräsentiert werden kann. Die Ausgabe erfolgt als Stream (binär oder Zeichen) und wird als Response gesendet. Normalerweise endet eine Pipeline mit dem Serializer.

### Reader

Der Reader eignet sich für sehr einfache Pipelines, da hier Dateien ohne weitere Verarbeitung an den Client zurückgeliefert werden können. Er ist hauptsächlich für Nicht-XML-Dateien in einer Cocoon-Site geeignet.

Zwei Reader sind bereits mit Cocoon mitgeliefert:

* ResourceReader (zum Lesen von Binärdaten)
* JSPReader (zum Lesen von Ausgaben von JSP-Seiten)

### Action

Eine Action dient zur Steuerung von Abläufen auf einer Site. Dabei werden dynamische Laufzeiten manipuliert oder Operationen auf dem Server durchgeführt. Eine Action erzeugt also keine dargestellten Daten, sondern steuert den Ablauf innerhalb der Pipeline.

## Mögliche Ausgabeformate

* XML
* HTML
* XHTML
* WML
* PDF
* RTF
* Excel
* Flash
* PHP
* etc.

## XSP

Eine weit verbreitete und bereits in Cocoon 1.x eingesetzte Möglichkeit, um Cocoon Applikationen zu entwickeln, ist das Konzept der eXtensible-Server-Pages (XSP). Eine eXtensible-Server-Page ist ein normales und gültiges XML-Dokument. Dieses enthält i. d. R. einen statischen Inhalt oder bestimmte Funktionen, die einen dynamischen Inhalt aus einer Datenquelle (Datenbank, Hash-Tabelle, Datei) einlesen. Im Gegensatz zu normalen JavaServer Pages liefert die XSP-Datei kein HTML-, sondern ein XML-Dokument zurück, das den Inhalt für weitere Transformationen liefert. Das XSP-Dokument wird direkt an den Generator übergeben, der es in eine Server-Page umwandelt. Die im XSP-Dokument enthaltenen Funktionen werden dabei in Java-Code umgewandelt. Die XSP-Seite besitzt zusätzlich zu den bereits erklärten Möglichkeiten einen optionalen Logik-Bestandteil. Dieser enthält häufig JavaScript (andere Programmiersprachen sind theoretisch möglich). Der Logik-Bestandteil wird direkt in das XSP-Dokument integriert und hat die Aufgabe, per POST-Request übergebene Parameter zu prüfen oder weiter zu verarbeiten. Dabei sind alle Möglichkeiten vorhanden, die in JavaScript zur Verfügung stehen. Wird ein Logik-Bestandteil in das XSP-Dokument integriert, geht die strikte Trennung von Logik, Layout und Inhalt verloren. Dieses Problem kann durch Verwendung von so genannten Logicsheets gelöst werden; das ist jedoch nur beim Einsatz in großen Projekten sinnvoll. Ein weiterer Bestandteil, der zusammen mit XSP zum Einsatz kommt, ist die eXtensible Transformer Language (XSLT). Diese hat die Aufgabe, die durch den Generator erzeugten XML-Daten weiter zu verarbeiten. Dazu werden die bereits erwähnten Transformer eingesetzt. Um den Ablauf von Generator und Transformator zu steuern, muss die Sitemap-Datei angepasst werden. An dieser Stelle kommen die eigentlichen Stärken von Cocoon zum Vorschein, da hier durch Trennung der Logik und des Layouts eine sehr übersichtliche Lösung gebaut werden kann, bei der jederzeit bestimmte Komponenten durch andere ersetzt werden können. Beispielsweise ist es möglich, verschiedene XSP-Dateien an den Generator einer Pipeline zu übergeben, wodurch sich der Inhalt der Web-Seite, nicht jedoch das Layout, ändert.

## Control Flow

Durch die Einführung des Konzepts der Flusssteuerung (Control-Flow) stehen einem Cocoon-Entwickler Möglichkeiten zur Verfügung, die bisher nur bei einer lokalen Anwendung einsetzt werden konnten. Traditionell funktionieren Webanwendungen über das zustandslose HTTP, was bedeutet, dass auf jede Anfrage eine prompte Antwort generiert wird, ohne dabei den Zustand der Webanwendung zu speichern, bzw. bei erneuter Anfrage den Programmfluss an der gleichen Stelle fortzuführen. Durch eindeutige Session-IDs innerhalb von Cookies und durch URL-Rewriting wird versucht, diesen Umstand bei Servlets zu umgehen. Dabei wird jedoch der Programmcode immer wieder von vorne durchlaufen und auf Grund von Session-IDs in verschiedene Funktionen verzweigt. Vor allem bei größeren Anwendungen wird dies schnell unübersichtlich und kompliziert. Bei Arbeiten mit Formularen und darin abgespeicherten Werten tauchen vor allem dann Probleme auf, wenn der Benutzer versucht, eine oder mehrere Seiten zurück zu navigieren. Dort eingegebene Werte (mit POST oder GET übermittelt) können oft nicht mehr geladen werden. Damit sich der Entwickler in erster Linie um seine Anwendung kümmern kann, wurde mit Cocoon 2.1 das Konzept der Continuations im Zusammenhang mit FlowScript eingeführt.

### FlowScript

FlowScript basiert auf der im Internet weit verbreiteten Sprache JavaScript. Da es in erster Linie zur Steuerung des Applikationsablaufs gedacht ist und nicht zur Integration von Businesslogik in die Cocoon-Anwendung, sind die Einschränkungen gegenüber Java nicht weiter störend. Werden komplexe Abläufe und Modelle benötigt, können diese in Form von Java-Klassen in JavaScript importiert werden.

### Continuations

Ein häufiges Problem im Web ist, dass getätigte Eingaben auf einer Webseite beim erneuten Laden dieser Seite spurlos verschwunden sind. In Cocoon wurde dieses Problem durch das Konzept der Continuations vollständig gelöst. Eine Continuation wird innerhalb des FlowScripts erzeugt. Dies geschieht automatisch durch den Aufruf cocoon.sendPageAndWait. Ein Continuation-Objekt hat die Aufgabe, den aktuellen Zustand des Programms abzuspeichern, inklusive des Programms Counter (der Stelle im FlowScript), aller lokalen Variablen und Eingaben durch den Benutzer sowie des Stacks. Das Continuation-Objekt erhält beim Erzeugen automatisch eine eindeutige ID. Nach dem Erzeugen der Continuation wird dieses in einer globalen Hash-Tabelle abgelegt und kann bei Bedarf wieder geladen werden. Zu diesem Zeitpunkt ist das Continuation-Objekt noch leer. Nach dem Ablegen in der Hash-Tabelle wird die gewünschte Webseite an den Benutzer verschickt. Das FlowScript hält nach Ausführung des Befehls cocoon.sendPageAndWait an und wartet auf eine Eingabe vom Benutzer. Erst dann wird das FlowScript fortgesetzt. Nachdem der Benutzer seine Eingaben - beispielsweise in einem Formular - getätigt hat, sendet er die eingegebenen Daten und fordert das aktuelle, in der Hash-Tabelle abgelegte Continuation-Objekt an. Dieses speichert die Werte, die vom Benutzer in das Webformular eingegeben wurden. Erst jetzt ist das Continuation-Objekt vollständig verarbeitet und kann jederzeit wieder mit den vom Benutzer eingetragenen Werten geladen werden.

Der Einsatz von Continuations ist nur dann sinnvoll, wenn eine echte Interaktion mit dem Benutzer stattfindet.

Das folgende Flussdiagramm in Abbildung verdeutlicht zusammenfassend den vollständigen Ablauf einer Continuation über alle Flusssteuerungskomponenten hinweg.

## Cocoon Forms (Woody)

Das mit Abstand leistungsfähigste Formular-Framework, das zurzeit in Cocoon verfügbar ist, heißt Cocoon Forms (cForms). Es bietet eine Vielzahl an Möglichkeiten, z. B. Formularprüfung, Erstellen von Pop-Ups und einfaches Einbinden visueller grafischer Elemente. Forms befindet sich zurzeit im Entwicklungsstadium, weshalb es möglich ist, dass sich bestimmte Elemente ändern werden. Beispielsweise wurde Forms bis zur Cocoon Version 2.1.4 noch unter dem Codenamen Woody entwickelt. Beim Wechsel auf Cocoon Version 2.1.5 wurden der Name und damit auch alle Bibliotheksbezeichnungen und Pfade geändert. Forms wird das offizielle Standard-Framework für die Formularverarbeitung werden.

### Aufbau vom Cocoon Forms

Das Konzept von Forms trennt wie fast alles in Cocoon, den Inhalt von der Logik und dem Layout. Aus diesem Grund besteht ein Formular, das mit Forms erstellt wurde, aus zwei Dateien:

* Form-Definitionen
* Form-Templates

Form-Definitionen beschreiben die einzelnen Elemente, die in einem Formular benötigt werden. Eine Form-Definitions-Datei enthält keine Präsentationsdaten. Sie kann deshalb zusammen mit beliebig vielen Präsentationsdateien wieder verwertet werden. Die Elemente in der Form-Definitionen-Datei werden als so genannte Widgets bezeichnet. Dem Entwickler steht dabei eine große Anzahl an Widgets zur Verfügung, beispielsweise Buttons, Edit-Felder oder Combo-Boxen. Jedes dieser Widgets kann mit einem individuellen Aussehen, Verhalten und sogar mit Funktionen versehen werden. Um Widgets ein spezifisches Verhalten zu ermöglichen, existieren sehr komplexe Möglichkeiten, angefangen bei der Angabe der Bezeichnung und Beschreibung eines Objektes über die Deklaration einfacher Datentypen, die ein Widget annehmen kann, bis hin zum Ausführen von JavaScript-Code, der durch bestimmte vordefinierte Ereignisse im Widget ausgelöst wird.

Form-Templates sind vom Prinzip her XSL-Transformations-Dateien. Sie enthalten die Präsentationslogik und binden die einzelnen Widgets. Es müssen nicht alle Widgets einer Definition-Datei eingebunden werden. Darüber hinaus legt das Form-Template bestimmte Eigenschaften wie Größe und Farbe jedes Widgets fest.

### Forms Verarbeitung

Um eine Webseite mit Forms zu erzeugen, müssen spezielle Forms-Transformatoren und ein Forms-Generator eingesetzt werden. Außerdem muss das ganze Konzept von FlowScript gesteuert werden.

