Der erste Teil dieser Artikelreihe betrachtete den grundlegenden Aufbau des Geronimo Application Server. Neben der Administration und Installation des Servers wurde seine Verwendung als J2EE konformer Application Server vorgestellt. Ein Schwerpunkt lag im Deployment von Java EE-Anwendungsarchiven sowie der grundsätzlichen Architektur des Servers. Der Geronimo arbeitet wie gezeigt konfigurationsbasiert. Geronimo-Serverbestandteile werden in gleicher Weise wie eigene Anwendungen als Konfigurationen innerhalb des Servers verwaltet. Über die im Server enthaltenen Konfigurationen wird dessen Funktionsumfang bestimmt. Die Erstellung einer Serverdistribution beschränkt sich auf die Zusammenstellung von Konfigurationen, über die der vollständige Funktionsumfang definiert wird. Der Aufwand zur Herstellung einer auf Geronimo basierenden Distribution wird durch die zur Verfügung gestellten Werkzeuge sowie die zugrunde liegende Apache Software Licence gering gehalten und stellt ein reizvolles Einsatzgebiet für den Geronimo dar. In der Versionsverwaltung der Apache Software Foundation stehen bereits verschiedene Serverdistributionen zur Verfügung:
- Java EE Jetty - Java EE-konformer Server mit einem vorkonfigurierten Jetty-Web-Container
- Java EE Tomcat - Java EE-konformer Server mit einem vorkonfigurierten Tomcat-Web-Container
- Minimal Tomcat - Distribution mit reiner Web-Container-Unterstützung
- Web JMS Tomcat Server - Distribution mit Web-Container und JMS-Unterstützung
- Java EE Installer - selbstextrahierendes Installer-Archiv, mit dem ein Java EE-konformer Server installiert werden kann. Bei der Installation kann der Funktionsumfang des Servers angegeben werden.
- reiner Java EE Web-Container mit prozesseigener Datenbank
- EAI-Server aus JMS-Implementierung, Datenbank und Routing Engine
- Web Service Engine zur generischen Bereitstellung vorhandener Dienste innerhalb einer serviceorientierten Architektur
- Server mit Funktionalität für Spring Deployment
- Portalserver aus JSR 168 konformem Portlet-Container und Content Management System
Der Bauplan
Die Konfektionierung einer Distribution funktioniert nach dem Baukastenprinzip. Dadurch ist es möglich, aus einfachen Bausteinen komplexe Strukturen aufzubauen. Im ersten Schritt werden die einfachen Bausteine gefertigt. In diesem Bild entspricht ein Baustein einer Geronimo-Konfiguration. Benötigte Dienste und Funktionen der optimierten Serverumgebung sowie die zu integrierenden Anwendungen müssen hierzu als Konfigurationen erstellt werden. Größe und Umfang eines Bausteins sind vom Entwickler hierbei selbst zu bestimmen. Indem man z.B. eine Datenbank-Anbindung in Form einer eigenständigen Konfiguration definiert, erhält man eine kleine, leicht wiederverwendbare Einheit. Wird die gleiche Datenbank-Anbindung in eine komplexere Konfiguration integriert, ergibt sich ein größerer Baustein, der sich durch einen größeren Funktionsumfang auszeichnen kann. Im zweiten Schritt der Konfektionierung werden die Bausteine zur endgültigen Produktdistribution zusammengestellt. Art und Herkunft der Bausteine spielen für den Prozess des Zusammensetzens keine Rolle. Im folgenden Abschnitt wird die Herstellung eigener Bausteine demonstriert. Zuerst wird ein eigener Dienst für eine optimierte Serverumgebung vorgestellt. Als zweiter Baustein dient eine Java EE-konforme Anwendung. Beide Bausteine werden im Anschluss zusammen mit weiteren Konfigurationen zu einem eigenen Geronimo-basierten Produkt zusammengestellt.Der eigene Baustein
Im ersten Artikel wurde die Basisarchitektur des Geronimo behandelt. Grundlegendes Element bilden dabei die GBeans. Sie sind die kleinste verwaltbare Einheit innerhalb des Servers. Ein eigener Dienst wird deshalb auch durch mindestens eine GBean in den Server integriert. Aufgabe der GBean ist die Definition und Bereitstellung der administrativen und konfigurativen Schnittstelle zwischen dem Dienst und dem Application Server. Der Geronimo-Kernel unterscheidet dabei nicht zwischen Java EE-Application-Komponente oder einem proprietären Dienst. Die GBeans einer Konfiguration werden innerhalb des Servers im ConfigStore gespeichert. Er stellt in unserer Metapher den Baukasten zur Aufbewahrung der Bausteine dar (siehe Kasten ConfigStore).
|
Die eigentliche Implementierung eines eigenen Dienstes kann ohne spezielle Berücksichtigung des Application Server erfolgen. Die Integration wird dann nachträglich durch die Bereitstellung einer oder mehrerer GBeans durchgeführt. An dieser Stelle setzt unser Beispiel der Entwicklung und Integration einer GBean an. Die Verwaltungsschnittstelle zwischen Geronimo und Dienst ist möglichst simpel durch ein String-Feld serviceName repräsentiert. Die einzige zu erfüllende Aufgabe des GBeans ist die Implementierung der Methode getGBeanInfo(), die ein GBeanInfo -Objekt zur Beschreibung der Schnittstelle zurückgibt. Statt das Metadaten-Objekt selbst zu erzeugen, kann mit der Klasse GBeanInfoBuilder eine Implementierung des Builder Patterns[3] zur Vereinfachung der Objektinitialisierung eingesetzt werden. Die GBean des Beispiels nutzt zusätzlich noch die Möglichkeit, einen eigenen Dienst mit Signalen aus dem Lebenszyklusmanagement des Application Server zu versorgen. Dazu wird das Interface GBeanLifeCycle mit den Methoden doStart() , doStop() und doFail() implementiert (Listing 1).
Listing 1
GBean Beispiel
public class BeispielGBean implements GBeanLifecycle {private String serviceName;public String getServiceName() {return serviceName;}public void setServiceName(String serviceName) {this.name = serviceName;}public static final GBeanInfo GBEAN_INFO;static {GBeanInfoBuilder builder = new GBeanInfoBuilder(BeispielGBean.class);builder.addAttribute("serviceName", String.class, true);GBEAN_INFO = builder.getBeanInfo();}public static GBeanInfo getGBeanInfo() {return GBEAN_INFO;}public void doStart() throws Exception {System.out.println("doStart ");}public void doStop() throws Exception {System.out.println("doStop ");}public void doFail() {}}
Listing 2
Deployment-Plan des GBean-Beispiels
<?xml version="1.0"?><configuration xmlns="http://geronimo.apache.org/xml/ns/deployment-1.0"configId="de/oio/gbean-sample/1.0"><dependency><groupId>de.oio.geronimo</groupId><artifactId>gBeanBeispiel</artifactId><version>1.0-SNAPSHOT</version></dependency><gbean name="OIOSample" class="de.oio.geronimo.SampleGBean"><attribute name="serviceName">Kristian</attribute></gbean></configuration>
|
Zur Fertigstellung des ersten Bausteins muss noch das CAR-Archiv angelegt werden. Zu diesem Zweck kann das Maven-basierte Packaging-Plug-in genutzt werden. In der Geronimo-Version 1.0 handelt es sich um ein Plug-in für Maven 1, welches in der Version 1.1 durch ein Plug-in für Maven 2 erweitert wird. Eine alternative Werkzeugunterstützung durch Ant ist in Planung. Ein Deployment zur Laufzeit wäre eine grundsätzliche Alternative bei der Erstellung der CAR-Archive. Allerdings muss dafür eine bereits existierende Geronimo-Distribution gestartet werden. Daher wird hier nicht weiter auf diese Möglichkeit eingegangen. Befindet sich die GBean-Implementierung in einem Maven 1-basierten Projekt kann durch Aufnahme des folgenden XML-Ausschnitts aus Listing 3 das Packaging-Plug-in nach der Übersetzung des Projektes aufgerufen werden. Die resultierende CAR-Datei wird automatisch in das Maven Repository kopiert.
<project default="default"><goal name="default"><attainGoal name="car:install"/></goal></project>
Der Java EE-Baustein
Beim Deployment eines Java EE-Archivs wird ebenfalls eine Konfiguration angelegt. Diese wird auch durch den ConfigStore in Form einer CAR-Datei abgelegt. Im Bereich des Standard-Deployments waren wir nicht näher auf dieses Serverspezifikum eingegangen. Der Deployment-Plan unterscheidet sich vom Deployment-Plan des vorherigen Bausteins durch ein anderes Wurzelelement application . Innerhalb der Deployment-Pläne können gleiche Umgebungskonfigurationen von GBeans durch Elemente der gleichen Namensräume identisch deklariert werden. Auch hier unterscheidet der Server nicht zwischen GBeans aus Java EE-Archiven und speziellen Geronimo-Services. Der Aufbau des Plans ist an einen Java EE-Standard-Deployment-Deskriptor angelehnt. Mithilfe des Attributs configId wird wieder ein Name zur eindeutigen Identifikation der späteren Bausteins definiert. Im Beispiel handelt es sich um ein EAR-Archiv ear-sample-1.0-SNAPSHOT.ear, in welchem eine Webapplikation als web-sample-1.0-SNAPSHOT.war abgelegt ist (Listing 3).Listing 3
Deployment-Plan für ein EAR -Archiv
<?xml version="1.0" encoding="UTF-8"?><application xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-1.0"configId="de.oio/geronimo/application/1.0/car"><module><web>web-sample-1.0-SNAPSHOT.war</web><web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.0" configId="Web"></web-app></module></application>
<dependency><groupId>de.oio.geronimo</groupId><artifactId>ear-sample</artifactId><version>1.0-SNAPSHOT</version><type>ear</type></dependency>
Stein auf Stein ...
Das Zusammensetzen der einzelnen Bausteine kann mittels des Maven Geronimo Assembly Plug-in erfolgen. Das Plug-in wird ebenfalls innerhalb des Geronimo-Projektes zur Konfektionierung der angebotenen Serverdistributionen eingesetzt. Jede Serverdistribution sollte als separates Maven-Projekt angelegt werden. In der entsprechenden project.xml -Datei müssen sämtliche benötigten Bausteine als Abhängigkeiten eingetragen werden. Dies erstreckt sich vom Geronimo-Kernel bis zu den Start und Stopp-Skripten des Servers. Eigene Anwendungen müssen in diesem Zusammenhang ebenfalls angegeben werden. Einen Ausschnitt der Datei zeigt der folgende Quellcode. In diesem Beispiel wird Jetty als Konfiguration mit in den Server aufgenommen. Die CAR Datei aus dem Maven Repository wird durch das Assembly-Plug-in in den ConfigStore installiert und steht somit im Server zur Verfügung.<dependency><groupId>geronimo</groupId><artifactId>jetty</artifactId><type>car</type><version>1.2-SNAPSHOT</version><properties><geronimo.assemble>install</geronimo.assemble></properties></dependency>...
<project default="default"><goal name="default" prereqs="assemble:install"/></project>
Der Meisterbrief
In der bisher beschriebenen Produktdistribution werden Java EE-Anwendungsarchive in der Standardimplementierung des ConfigStore abgelegt. Verschiedene Anforderungen an die Softwareverteilung eines Produktes lassen sich mit diesem Standardmechanismus nicht abbilden. Die Architektur des Servers erlaubt allerdings den Austausch der ConfigStore-Implementierung zur Realisierung unterschiedlichster Distributionsszenarien. Folgende Szenarien sind z.B. denkbar:- zentraler Distributionsserver
- zentraler Lizenzierungsmechanismus auf Basis von Anwendungskomponenten
- Farming von geclusterten Applikationen
- Verschlüsselung der Anwendungsarchive
Eigener Baukasten
Neben den normalen Anforderungen an ein GBean muss der eigene ConfigStore das Interface org.apache.geronimo.kernel.config. ConfigurationStore implementieren. Das Interface enthält Methoden zum Installieren, Laden, Suchen und Deinstallieren von Konfigurationen. Diese werden hierbei über ihre eindeutige c onfigId adressiert und in Form von ConfigurationData -Objekten übergeben. Für die Ablage der Konfiguration können ConfigurationData -Objekte über Geronimo-Hilfsklassen recht einfach serialisiert werden.ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);GBeanData configurationGBeanData = ExecutableConfigurationUtil.getConfigurationGBeanData(configurationData);configurationGBeanData.writeExternal(oos);byte[] bites = baos.toByteArray();//Speicherung mit eventueller Verschlüsselung
GBeanInfoBuilder infoFactory =GBeanInfoBuilder.createStatic(AlternativeConfigStoreImpl.class,"ConfigurationStore");
|
Der Dependency-Injection-Mechanismus für GBeans innerhalb des Geronimo unterstützt neben einer festen Referenzangabe zu einem einzelnen GBean auch die Definition einer Referenz zu einer Menge von GBeans. Über diesen Mechanismus kann ein GBean Interesse an weiteren GBeans anmelden. Wird ein entsprechendes GBean gestartet bzw. wieder gestoppt, wird eine Referenz über Dependency Injection gesetzt. Die Angabe des Ziel-Bean erfolgt über ein Namensmuster, das Teile der ObjectNameGroup benthalten kann. Die Angabe von *:j2eeType=WebModule,* stellt z.B. eine Referenzangabe zu allen GBeans mit einem j2eeType -Webmodul dar. Auf diese Weise kann sich der Web-Container über neu installierte Webmodule informieren lassen und entsprechend darauf reagieren. Eine direkte Referenz zwischen Installationsmechanismus und Ausführungsumgebung ist nicht nötig. In der Standardkonfiguration des Geronimo verwaltet der ConfigurationManager auf diese Weise alle ConfigStore-Instanzen. Er lässt sich über den Start bzw. das Stoppen aller GBeans, die den Typ ConfigurationStore besitzen, informieren (Listing 4). Durch die oben gezeigte Java EE-Typ-Angabe beim Erstellen des GBeanData -Objektes innerhalb der eigenen ConfigStore-Implementierung besitzt das GBean den Typ ConfigurationStore . Beim Start des Bean wird der ConfigurationManager entsprechend darüber informiert. Eine weitere Anmeldung des ConfigStore ist nicht erforderlich.
Listing 4
Deployment-Plan - Ausschnitt für ConfigurationManager
<!-- Configuration Manager service --><gbean name="ConfigurationManager"class="org.apache.geronimo.kernel.config.EditableConfigurationManagerImpl"><reference name="Stores"><gbean-name>*:j2eeType=ConfigurationStore,*</gbean-name></reference><reference name="AttributeStore"><name>AttributeManager</name></reference><reference name="PersistentConfigurationList"><type>AttributeStore</type><name>AttributeManager</name></reference></gbean>
Richtfest
Damit das eigene ConfigStore GBean im Server zum Einsatz kommen kann, muss eine eigene Konfiguration für den Store erstellt werden. Hierzu kann wieder das Geronimo Maven 1 Packaging Plug-in genutzt werden. Der Deployment-Plan ist in Listing 5 dargestellt. Die Konfiguration kann anschließend über ein eigenes Assemblieren des Servers genutzt werden. Eine Anpassung der bestehenden Serverkonfigurationen ist nicht nötig.Listing 5
Deployment-Plan für eigenen ConfigStore
<configurationxmlns="http://geronimo.apache.org/xml/ns/deployment-1.0"configId="de.oio.geronimo/alternative-configStore-config/1.0-SNAPSHOT/car"domain="geronimo.server"server="geronimo"><gbean name="AlternativeConfigStore"class="de.oio.geronimo.config.AlternativeConfigStoreImpl"></gbean></configuration>
Der Einzug
Innerhalb des Geronimo werden alle ConfigStores als Targets verwaltet. Dieser Begriff stammt aus der Java EE-Application-Deployment-Spezifikation und bezeichnet zur Verfügung stehende Installationsziele. Mit dem Geronimo-eigenen Kommandozeilenwerkzeug deploy lassen sich diese Targets eines Servers ausgeben. Die Ausführung von deploy.bat list-targets liefert im Beispiel:Available Targets:geronimo.server:J2EEApplication=null,J2EEModule=geronimo/j2ee-system/1.2-SNAPSHOT/car,J2EEServer=geronimo,j2eeType=ConfigurationStore,name=Localgeronimo.server:J2EEApplication=null,J2EEModule=<b>de.oio.geronimo/alternative-configStore-config/1.0-SNAPSHOT/car</b>,J2EEServer=geronimo,j2eeType=ConfigurationStore,name=AlternativeConfigStore
deploy.bat list-modules geronimo.server:J2EEApplication=null,J2EEModule=de.oio.geronimo/alternative-configStore-config/1.0-SNAPSHOT/car,J2EEServer=geronimo,j2eeType=ConfigurationStore,name=AlternativeConfigStore
Nach dem Bau ist vor dem Bau
Die integrationsorientierte Softwarearchitektur des Geronimo erleichtert die Erstellung einer eigenen Serverdistribution. Der unter www.javamagazin.de/geronimo bereitgestellte Java Magazin Application Server kann als Basis für ein eigenes Produktes eingesetzt werden. Viel Spaß beim "Heimwerken"!Christian Dedek und Kristian Köhler beschäftigen sich bei Orientation in Objects mit der Architektur, Entwicklung und Beratung von Java EE-Applikationen. Kontakt: geronimo@oio.de .
Links & Literatur
- [1] www.oio.de/public/geronimo/jm-artikel
- [2] www-306.ibm.com/software/de/websphere/was-ce.html
- [3] Erich Gamma et al.: Entwurfsmuster, Addison-Wesley, 1996, 119 ff.




