Die Frontend-Komponenten

Dokumentation für 2.2 (in Arbeit)
Funktionsprinzipien und Implementierungen von Kernkomponenten verschiedener Anwenderzugänge wie die MyCoRe-Kommandozeile und die Webanwendung.

Der Layout-Service

ToDo: Allgemeine Beschreibung des Layout-Services

XSL-Info-Servlet

Das XSL-Info-Servlet hilft dabei die Übersicht über verwendete XSL-Stylesheets zu behalten. Dazu durchsucht es zur Laufzeit die Webanwendung (WEB-INF/classes/xsl/ und alle WEB-INF/lib/*.jar) nach *.xsl-Stylesheets, listet deren Abhängigkeiten und die darin enthaltenen Templates. Das Ergebnis sieht etwa so aus, für ein einzelnes Stylesheet:

<stylesheet name="MCRMetadataSchema.xsl">
  <origin>lib/mycore-complete-2.1.80-SNAPSHOT.jar</origin>
  <includes>MCRMetadataTemplates.xsl</includes>
  <includes>MCRMetadataCoreTemplates.xsl</includes>
  <includes>MCRMetadataCoreTypes.xsl</includes>
  <includes>MCRMetadataTypes.xsl</includes>
  <xsl:template match="/"/>
  <xsl:template match="/configuration/structure"/>
  <xsl:template match="/configuration/metadata"/>
  <xsl:template match="/configuration/derivate"/>
  <xsl:template match="/configuration/service"/>
</stylesheet>
   

Das Element origin zeigt den Ursprung der XSL-Datei und kann evtl. mehrmals auftreten (etwa wenn das Stylesheet in classes/xsl/ überschrieben wird).

Um die Abhängigkeiten zu visualisieren, wandelt ein XSL-Stylesheet die Ausgabe in das GraphML-Format um. Das wiederum stelle ich mit CytoscapeWeb (GNU LGPL, Flash, JavaScript) im Browser dar. Den Graphen kann man nun zoomen und im Detail ansehen.

Weitere Details werden in einer Tabelle ausgegeben, die man im Browser durchsuchen und filtern kann (JQuery Datatables). Die enthaltenen XSL-Templates können über Buttons aufgeklappt werden.

Die Herkunft des Stylesheets wird farblich gekennzeichnet:

  • grün - aus WEB-INF/classes/xsl/
  • blau - aus *.jar
  • gelb - zur Laufzeit eingebundene Stylesheets über URIs
  • rot - Stylesheet wird referenziert, ist aber nicht auffindbar

Das Frontend für das XSL-Info-Servlet ist als DocPortal-Modul verfügbar, das standardmäßig nicht eingebunden wird: docportal/modules/xslinfo/ bzw. online unter http://www.mycore.de:8291/servlets/MCRXSLInfoServlet

XSL-FO

Im LayoutService von MyCoRe ist es neben der Umsetzung von XML-Dateien via XSLT und dem Durchreichen von Daten auch möglich einen XSL:FO-Formatter anzusprechen. Dazu muss das eingehende XML den Content-Type "application/pdf" haben. Dann wird ein Spezialzweig angefaßt, bei dem eine spezielle Java-Klasse aufgerufen wird, die org.mycore.common.fo.MCRFoFormatterInterface implementiert. Im MyCoRe-Kern ist dies eine Klasse, welche den FOP aufruft und das Ergebnis ausliefert. Dazu muss dann eine anwenungspeziefische Klasse implementiert werden, die den gewünschten XSL:FO-Formatter (z.B. Antenna House) aufruft. Konfiguriert wird dies über:

##############################################################################
# XSL-FO Formatter            
##############################################################################

  # Class that implements MCRFoFormatterInterface
  MCR.LayoutService.FoFormatter.class=org.mycore.common.fo.MCRFoFormatterFOP
  # Configuration file for FOP in classpath
  MCR.LayoutService.FoFormatter.FOP.config=myConfigFile
      

Für FOP kann noch eine Konfigurationsdatei im Classpath angegeben werden, die z. B. andere Fonts einsetzt.

Das Zusammenspiel der Servlets mit dem MCRServlet

Als übergeordnetes Servlet mit einigen grundlegenden Funktionalitäten dient die Klasse MCRServlet. Die Hauptaufgabe von MCRServlet ist dabei die Herstellung der Verbindung zur Sessionverwaltung (siehe Abschnitt Die Session-Verwaltung). Das Zusammenspiel der relevanten Klassen ist im Klassendiagramm (Abbildung 2.5) verdeutlicht.

Java-Klassen

Abbildung 2.5: Klassendiagramm Common Servlets

Wie an anderen Stellen im MyCoRe-System auch, kann auf Konfigurationsparameter wie zum Beispiel den Einstellungen für das Logging über das statische Attribut MCRConfiguration zugegriffen werden.

MCRServlet selbst ist direkt von HttpServlet abgeleitet. Sollen andere Servlets im MyCoRe-Softwaresystem die von MCRServlet angebotenen Funktionen automatisch nutzen, so müssen sie von MCRServlet abgeleitet werden. Im Klassendiagramm ist das durch die stellvertretende Klasse MCRAnyOtherServlet angedeutet. Es wird empfohlen, dass die abgeleiteten Servlets die Methoden doGet() und doPost() nicht überschreiben, denn dadurch werden bei einem eingehenden Request auf jeden Fall die Methoden von MCRServlet ausgeführt.

Der Programmablauf innerhalb von MCRServlet ist im folgenden Sequenzdiagramm (siehe Abbildung 2.6) dargestellt. Bei einem eingehenden Request (doGet() oder doPost()) wird zunächst an MVRServlet.doGetPost() delegiert. (Bei dieser Delegation wird ein Parameter mitgeführt, über den feststellbar ist, ob es sich um einen GET- oder POST-Request gehandelt hat.)

Common Servlets

Abbildung 2.6: Sequenzdiagramm Common Servlets

Falls nicht schon aus vorhergehenden Anfragen an das MCRServlet bekannt, werden in doGetPost() die Base-URL und die Servlet-URL des Systems bestimmt. Dabei besteht die Servlet-URL aus der Base-URL und dem angehängten String 'servlets/'. Darauf folgend wird die für diese Session zugehörige Instanz von MCRSession bestimmt. Das Verfahren dazu ist im Ablaufdiagramm (Abbildung 2.7) dargestellt.

Die Session kann bereits durch vorhergehende Anfragen existieren. Falls dies der Fall ist, kann das zugehörige Session-Objekt entweder über eine im HttpServletRequest mitgeführte SessionID identifiziert oder direkt der HttpSession entnommen werden. Existiert noch keine Session, so wird ein neues Session-Objekt über den Aufruf von MCRSessionMgr.getCurrentSession() erzeugt. Nachfolgend wird das Session-Objekt an den aktuellen Thread gebunden und zusätzlich in der HttpSession abgelegt.

Im Sequenzdiagramm gehen wir davon aus, dass die Sitzung neu ist und deswegen ein Session-Objekt über MCRSessionMgr.getCurrentSession() erzeugt werden muss. Schließlich wird eine Instanz von MCRServletJob erzeugt. Diese Klasse ist nichts weiter als ein Container für die aktuellen HttpServletRequest und HttpServletResponse Objekte und hat keine weitere Funktionalität (siehe Klassendiagramm, Abbildung 2.5). (Das Speichern des Session-Objekts in der HttpSession ist notwendig, weil in einer typischen Servlet-Engine mit Thread-Pool Umgebung nicht davon ausgegangen werden darf, dass bei aufeinander folgenden Anfragen aus demselben Kontext auch derselbe Thread zugewiesen wird.)

MCRServlet.doGetPost()

Abbildung 2.7: Ablaufdiagramm für MCRServlet.doGetPost()

An dieser Stelle wird der Programmfluss an das abgeleitete Servlet (in diesem Beispiel MCRAnyOtherServlet) delegiert. Dazu muss das Servlet eine Methode mit der Signatur

public void doGetPost(MCRServletJob job) {}

implementieren. Wie das Sequenzdiagramm beispielhaft zeigt, kann MCRAnyOtherServlet danach gegebenenfalls auf das Session-Objekt und damit auf die Kontextinformationen zugreifen. Der Aufruf an den SessionManager dazu wäre:

MCRSession mcrSession=MCRSessionMgr.getCurrentSession();

Es sei bemerkt, dass dies nicht notwendigerweise genau so durchgeführt werden muss, da wegen der geschilderten Probleme mit threadlocal Variablen in Servlet-Umgebungen das Session-Objekt auch in der HttpSession abgelegt sein muss, könnte man die Kontextinformationen auch aus der übergebenen Instanz von MCRServletJob gewinnen.

Das Login-Servlet und MCRSession

Das LoginServlet, implementiert durch die Klasse MCRLoginServlet, dient zum Anmelden von Benutzern und Benutzerinnen über ein Web-Formular. Die Funktionsweise ist wie folgt: Wie in Abschnitt 3.7.2 empfohlen, überschreibt MCRLoginServlet nicht die von MCRServlet geerbten Standard-Methoden doGet() und doPost(). Meldet sich ein Benutzer oder eine Benutzerin über das MCRLoginServlet an, so wird daher zunächst die Funktionalität von MCRServlet ausgenutzt und die in Abschnitt 3.7.2 beschriebene Verbindung zur Sessionverwaltung herstellt. Wie dort ebenfalls beschrieben, wird der Programmfluss an das Login-Servlet über die Methode MCRLoginServlet.doGetPost() delegiert. Der Ablauf in doGetPost() wird im Diagramm auf Abbildung 2.8 dargestellt und ist selbsterklärend.

MCRServlet.doGetPost()

Abbildung 2.8: Ablaufdiagramm für MCRServlet.doGetPost()

Der resultierende XML Output-Stream muss vom zugehörigen Stylesheet verarbeitet werden und hat die in Abbildung 2.9 gezeigte Syntax.

MCRServlet.doGetPost()

Abbildung 2.9: XML Output des LoginServlets

Bei einer missglückten Anmeldung wird der Grund dafür in Form eines Attributes gespeichert. Das Stylesheet kann dann die entsprechende Meldung ausgeben. Die Gast-User-ID und das Gast-Passwort werden aus einer Konfigurationsdatei gelesen. Die URL schließlich wird dem Http-Request entnommen und sollte dort von der aufrufenden Seite bzw. vom aufrufenden Servlet gesetzt sein. Ist sie nicht gesetzt, so wird die Base-URL des MyCoRe-Systems verwendet.

Generieren von Zip-Dateien

Das Zip-Servlet, implementiert durch die Klasse MCRZipServlet, dient dem Ausliefern der Derivate und der Objektmetadaten als gepackte Zip-Datei. Aus der Konfigurationsdatei mycore.properties.zipper holt sich das Servlet über die Variable MCR.zip.metadata.transformer den Namen des Stylesheets, welches die Metadatentransformation in das gewünschte Auslieferungsformat vornimmt. In DocPortal verwenden wir hierfür Qualified Dublin Core.

Aufrufmöglichkeiten des Servlets:

    $ServletsBaseURL/MCRZipServlet?id=MCRID

    $ServletsBaseURL/MCRZipServlet?id=MCRID/foldername
    

MCRID ist die ID eines Objekts vom Typ <mycoreobject> oder <mycorederivate>. Im Fall von <mycoreobject> werden die Dateien aller dem Objekt zugeordneten Derivate und ein XML-File mit den Metadaten des Objekts zusammengepackt. Im Fall von <mycorederivate> werden alle Dateien des angegebenen Derivates zusammengepackt. Die Option MCRID/foldername ist nur zulässig, wenn MCRID ein Objekt vom Typ <mycorederivate> bezeichnet. Dann wird nur der mit foldername angegebene Ordner des betreffenden Derivats gezippt.

Wer geschützte Inhalte anbietet, sollte das Zip-Servlet erst dann in seine Anwendung integrieren, wenn die Zugriffskontrolle in MyCoRe gewährleistet werden kann. Dies ist momentan (04.2005) noch nicht der Fall, das Zip-Servlet lässt sich mit jeder MCRID aufrufen.

Erweiterung des Commandline-Tools

Dieser Abschnitt beschäftigt sich mit der Struktur des Commandline-Tools und dessen Erweiterung mit eigenen Kommandos. Dem Leser sei vorab empfohlen, den entsprechenden Abschnitt im MyCoRe-UserGuide durchzuarbeiten.

Java-Klassen

Abbildung 2.4: Zusammenhang der Java-Klassen

Das Commandline-Tool ist die Schnittstelle für eine interaktive Arbeit mit dem MyCoRe-System auf Kommandozeilen-Basis. Sie können dieses System ebenfalls dazu verwenden, mittels Skript-Jobs ganze Arbeitsabläufe zu automatisieren. Dies ist besonders bei der Massendatenverarbeitung sehr hilfreich. In DocPortal werden Ihnen schon in den Verzeichnissen unixtools bzw. dostools eine ganze Reihe von hilfreichen Skripts für Unix bzw. MS Windows mitgegeben.

All diese Skripte basieren auf dem Shell-Skript bin/mycore.sh bzw. bin/mycore.cmd, welches im Initialisierungsprozess der Anwendung via ant mit gebaut wird (ant create.unixtools bzw. ant create.dostools). Sollten Sie zu einem späteren Zeitpunkt eventuell einmal *.jar-Dateien in den lib-Verzeichnissen ausgetauscht haben oder sonstige Änderungen hinsichtlich des Java-CLASSPATH durchgeführt haben, so führen Sie für ein Rebuild des MyCoRe-Kommandos ein ant scripts durch.

Die Abbildung 2.4 soll einen Überblick über die Zusammenhänge der einzelnen Java-Klassen im Zusammenhang mit der nutzerseitigen Erweiterung des Commandline-Tools geben.

Es ist relativ einfach, weitere Kommandos hinzuzufügen. In DocPortal sind bereits alle nötigen Muster vorhanden.

  1. Im Verzeichnis ~/docportal/sources/org/mycore/frontend/cli finden Sie eine Java-Klasse MCRMyCommand.java. Diese ist ein Muster, kopieren Sie sie in eine Java-Klasse z.B. MCRTestCommand.java. Die Klasse kann im Package org.mycore.frontend.cli liegen, sie können Sie aber auch in den Bereich tun, zu dem es logisch gehört.
  2. Ersetzen Sie alle MCRMyCommand-String durch MCRTestCommand.
  3. Im Konstruktor werden nun alle neuen Kommandos definiert. Hierzu werden der ArrayList command jeweils zwei weitere Zeilen hinzugefügt. Die erste enthält den Text-String für das Kommando. Stellen, wo Parameter eingefügt werden sollen, sind mit {...} zu markieren, wobei ... eine fortlaufende Nummer beginnend mit 0 ist (siehe Beispielcode). In der zweiten Zeile ist nun der Methodenaufruf anzugeben. Für jeden Parameter ist das Schlüsselwort String anzugeben.
  4. Nun muss das eigentliche Kommando als Methode dieser Kommando-Klasse implementiert werden. Orientieren Sie sich dabei am mitgelieferten Beispiel. (Die Methode convertData sollten Sie in Ihrer Klasse löschen. Ebenso die Definition in der commands-ArrayList.)
  5. Compilieren Sie nun die neue Klasse mit cd ~/docportal; ant jar
  6. Als letztes müssen Sie die Klasse in das System einbinden. Die mit dem MyCoRe-Kern mitgelieferten Kommandos sind bis auf die Basis-Kommandos über die Property-Variable MCR.internal_command_classes in ~/docportal/mycore.properties dem System bekannt gemacht. Für externe Kommandos steht hierfür in der Konfigurationsdatei mycore.properties.application die Variable MCR.external_command_classes zur Verfügung. Hier können Sie eine mit Komma getrennte Liste Ihrer eigenen Kommando-Java-Klassen angeben.
  7. Wenn Sie nun mycore.sh bzw. mycore.cmd starten und DEBUG für den Logger eingeschaltet haben, so sehen Sie Ihre neu integrierten Kommandos.