Damit die MIR Anwendung verwendet werden kann, wird diese in einem Servlet Webcontainer bereitgestellt. Doch wie funktioniert das genau? Wie bilden MyCoRe Komponenten, Anwendungskomponenten und eigene MIR Plugins eine Einheit? Was passiert im Hintergrund um dieses Konstrukt zu verbinden und zu starten? Welche Mechanismen gibt MyCoRe dem Entwickler an die Hand um den Startvorgang zu beeinflussen, und was muss beachtet werden, wenn der ServletContainer beendet wird? Diese Themen sollen hier im Detail erklärt werden. Weitehin wird die Ladereihenfolge der Komponenten und Module erläutert.
Um zu verstehen wie die Initialisierung beginnt ist es zunächst notwendig die Situation aus dem Blickwinkel
des Servlet Webcontainers vorzunehmen. Für diesen ist das MIR Webarchiv einfach nur eine Kollektion aus
Komponenten der Servlet Spezifikation (Servlets, Filter, Listener) und anderen Resourcen. Damit diese Servlet
Komponenten mit dem Webcontainer kommunizieren können wird eine Schnittstelle benötigt. Diese Schnittstelle
wird mit dem ServletContext und seinem Set an Methoden zur Verfügung gestellt.
Seit Servlet Spezifikation 3.0 bietet die Servlet API das ServletContainerInitializer
Interface an.
Mittels
eigener Implementierung kann die Startphase der Webanwendung individualisiert werden. Genau an dieser Stelle
setzt das mycore-base
an. Die Initialisierung von MyCoRe beginnt innerhalb der onStart Methode.
Dieser Methode
wird als Parameter der ServletContext mitgegeben. Auf diese Weise können programmatisch Servlets, Filter sowie
Listener ergänzt werden. Genau dieser Mechanismus wird sich bei den vielen MyCoRe Kern Komponenenten/
Anwendungskomponenten aber auch zusätzlichen Komponenten von MIR (siehe eigene JAR) zu nutzen gemacht.
Die Klasse MCRServletContainerInitializer
implementiert das ServletContainerInitializer
Interface. Wie zuvor
erwähnt wird diese Klasse ausgehend von der Servlet 3.0 Spezifikation als Initialisierungsklasse genutzt.
MyCoRe
erweitert diesen Mechanismus. Für MyCoRe ist diese Klasse nicht nur Servlet bezogen, sondern der Startpunkt
für
eine Reihe verschiedener
Initialisierungsvorgänge mit unterschiedlichen Kontexten.
MyCoRe bietet Entwicklern mit dem AutoExecutable Interface die Möglichkeit den Startup Vorgang zu
beeinflussen.
Um einen eigenen Startup Handler zu schreiben, muss die Klasse nur das AutoExecutable Interface implementieren
und innerhalb der mycore.properties
mittels MCR.Startup.Class
bekanntgemacht werden.
Im Folgenden werden die Methoden des AutoExecutable Interface erläutert:
Mithilfe einer Priorität wird die Ausführungsreihenfolge der eigenen Klasse innerhalb des Startup Vorgangs
definiert. MyCoRe selbst verfügt über eine Vielzahl von AutoExecutables, also Klassen die das AutoExecutable
Interface implementieren. Diese Vielzahl wird mithilfe der Priorität nach Wichtigkeit sortiert. Als Beispiel
soll hier die MCRJPABootstrapper
Klasse genannt werden. Diese initialisiert die Schnittstelle
zwischen Anwendung
und Datenbank. Falls also ein AutoExecutable mittels JPA Datenbankzugriff benötigt, kann dieser erst nach
erfolgreichem durchlaufen des MCRJPABootstrappers stattfinden. Als vordefinierter Wert gilt eine Priorität von
0.
Der Rückgabewert gibt dem AutoExecutable einen sprechenden Namen und wird derzeit für Logging Zwecke verwendet.
Über die startup Methode wird die benötigte Initialisierungslogik ausgeführt.
Dieses
einfache Beispiel kann als Grundlage für den eigenen StartupHandler genommen werden. Für die
Einrichtung des zugehörigen Plugins wird an dieser Stelle an die Dokumentation
Eigene MIR Plugins einbinden
verwiesen.
Um das Beispiel in den MyCoRe Initialisierungsvorgang zu integrieren ist es notwendig das zuvor genannte
MCR.Startup.Class
Property zu setzen.
Die folgende Zeile in den mycore.properties
erweitert den bisherigen Startup Mechanismus:
MCR.Startup.Class=%MCR.Startup.Class%, custom.mycore.CustomStartupHandler
Der MyCoRe Shutdown Mechanismus wird eingeleitet, sobald alle Servlets und Filter gemäß Servlet Lifecycle
zerstört wurden. In der Regel ist dies der Fall, sobald der Webserver beendet werden soll.
MyCoRe bietet dem Entwickler mit dem Closeable
Interface eine Möglichkeit, seine eigenen Klassen
innerhalb des Shutdown Vorgangs zu beenden.
Die Implementierung des zentralen MyCoRe Shutdown Vorgangs befindet sich innerhalb der
MCRShutdownHandler
Klasse.
Diese Klasse beinhaltet eine Menge registrierter Closeables (also Klassen die das Closeable Interface
implementieren) und führt diese zum beschriebenen Zeitpunkt aus.
Die Klasse ermöglicht es mit der addCloseable(Closeable) und removeCloseable(Closeable)Methode benötigte
Closeables zu
registrieren sowie zu entfernen. Ein Closeable muss sich also eigenverantwortlich beim
MCRShutdownHandler
melden.
MyCoRe benutzt an verschiedenen Stellen Closeables. Es macht immer dann Sinn eine Klasse mittels Closeable Interface zu implementieren, wenn Abhängigkeiten im Spiel sind. Beispiele hierfür sind JMX sowie JPA. Innerhalb der JMX Ebene betrifft dies MBeans. Sobald der Webserver beendet wird, macht es Sinn diese aus der MBean Server Registry zu entfernen um somit ggf. abhängigen MBeans, JMX Agenten sowie anderen Anwendungen mitzuteilen, dass bestimmte Ressourcen nicht mehr verfügbar sind.
Diese Methode wird als erste innerhalb des MyCoRe Shutdown Prozesses aufgerufen. Hier kann eine Vorbereitung
für den eigentlichen close()
Vorgang stattfinden. Eine Beispielimplementierung findet sich
innerhalb der
MCRSolrIndexer
Klasse. Hier wird innerhalb der prepareClose()
Methode der eigentliche Shutdown Prozess für die
beteiligten Solr Services initialisiert. Dieser Stil ist vergleichbar mit einem asynchronen Aufruf. Innerhalb
der close()
Methode wird somit versucht auf die eigentliche Terminierungsantwort zu reagieren.
Ein anderes Beispiel sind Objekte im Zusammenhang mit Datenbankverbindungen. Bevor Verbindungen zur Datenbank
aufgrund des JPA Shutdowns (MCRJPAShutdownProcessor) nicht mehr möglich sind, könnten an dieser Stelle noch
Datenbankzugriffe stattfinden.
Mithilfe der close() Methode wird einer Klasse die das Closeable Interface implementiert die Möglichkeit eines
geordneten und sauberen Shutdown Prozesses im MyCoRe Umfeld ermöglicht. Diese Methode wird für das jeweilige
Closeable nach der prepareClose()
Methode aufgerufen. Vorrangig sollten hier wie im vorherigen
Abschnitt bereits
beschrieben Abhängigkeiten sauber geschlossen werden.
Mittels Priorität ist es möglich die Closeables in einer Ausführungsreihenfolge zu sortieren. Ein Closeable mit einem höhreren Wert wird vor einem Closeable mit geringeren Wert geschlossen. Jedes Closeable besitzt eine definierte Standardpriorität.
Für die Gestaltung komplexer Anwendungen mit mehreren Subanwendungen und Mandanten ist es erforderlich, festzulegen,
in welcher Reihenfole Klassen und Ressourcen gefunden und eingebunden werden. Hierfür werden im Startup-Prozess Maifest-Informationen
der eingebundnen *.jar
-Dateien ausgewertet. Die Reihenfolge des Überladens ist dabei :
*.jar
-Dateien der Anwendung - diese habe eine Priorität von 0 aufwärts, wobei zu
dieser Priorität noch ein Offset von 100 hinzugerechnet wird, um MyCoRe-Komponenten vorher einzuordnen.Bei gleichen Prioritäten kann die Reihenfolge der Integration nicht vorhergesagt werden. Die reihenfolgeabhängige Integration der Ressourcen bezieht sich auf die Properties der Anwendung und die definierten I18N-Werte.
Die Festlegung in den Manifest-Dateien kann beispielsweise mittels Maven wie folgend realisiert werden :
|
|