Runtime-Modelle für Java EE bzw. Jakarta EE

Beim ersten Release des damals noch J2EE genannten Standards war das Betriebsmodell ganz klar so ausgerichtet, dass ein oder einige wenige Application Server als Träger von Enterprise-Applikationen genutzt werden sollten. Wie eine Art Betriebssystem stellten die Server die Infrastruktur – Transaktionen, Persistenz, Kommunikation, Isolation etc. – zur Verfügung, die dann von Anwendungen nach dem Deployment genutzt werden konnte.

Aus organisatorischen Gründen wurden Server aber zunehmend mit nur einer Anwendung betrieben. Hardware-Virtualisierung und leichtgewichtige Server machten es möglich, entsprechend viele Instanzen effektiv betreiben zu können.

Wir können heute also davon ausgehen, dass Server und Anwendung nicht unbedingt scharf voneinander getrennt sind, sonder eher verschiedene Aspekte einer Einheit darstellen. Man hört häufig die Meinung, dass damit das Konzept des Application Servers unbrauchbar geworden ist und moderne Serveranwendungen nur mit dedizierten Frameworks wie Spring Boot aufgebaut werden können. Ich möchte im Folgenden darstellen, dass das so nicht stimmt und JEE-Anwendungen sehr wohl in modernen Betriebsumgebungen ihren Platz haben.

Klassisches Deployment

Das klassische Deployment-Format sind WAR-Files. Ursprünglich mal für Web-Anwendungen gedacht (daher das W) ist dies seit Java EE 6 das General Purpose Deployment Format. Ein WAR-File wird in einen dafür vorgesehen Deployment-Ordner gelegt oder über spezielle Werkzeuge im Server deployt.

Da ein WAR-File nur die kompilierten Anwendungsklassen und – falls nötig – Bibliotheken außerhalb des Standards – enthält, sind die Deployments vergleichsweise klein. Eine Demo-Anwendung, die Sie in https://github.com/GEDOPLAN/jee-runtimes-demo finden, bringt gerade einmal 12 kB als WAR-File auf die Waage. Dabei enthält die Anwendung einen zwar einfachen, aber technisch kompletten Stack aus REST-API, Injektion mittels CDI und Persistenz mit JPA.

Das WAR-File kann auf einen beliebigen Jakarta-EE-Server deployt werden, z. B. auf einen WildFly 24. Der belegt im Vergleich viel Platz auf der Festplatte: ca. 250 MB.

Angenehm ist die Trennung von Anwendung und Infrastruktur. Sämtliche Laufzeit-Container befinden sich im Server, die Anwendung koppelt sich daran nur schwach über Interfaces und Standardklassen. Die Konfiguration von Subsystemen wie Datenbanken (oder Messaging, Mail, …) geschieht im Server. Die Anwendung referenziert die Konfiguration über logische Namen ohne konkrete Kenntnisse von bspw. Passwörtern.

Deployment als Kommando-Parameter

Der klassische Weg umfasst zwei Schritte: Installation eines Servers und Deployment der Anwendung. Manchen ist das zu aufwändig: sie würden einen einfachen Start des Servers inklusive der Anwendung in nur einem Schritt bevorzugen. Das ist mit JEE-Produkten auch recht leicht möglich.

Payara Micro ist ein solches Produkt. Es stellt einen Server in Form eines JAR-Files dar. Es ist nur ca. 77 MB groß. Die zu deployende Anwendung wird beim Start einfach als Parameter mitgegeben:

java -jar payara-micro.jar jee-runtimes-demo.war

Ähnlich funktioniert WildFly Bootable JAR. Hier kann der Server-Anteil sogar an die Bedürfnisse der Anwendung angepasst werden (im Beispiel-Projekt JAX-RS+CDI+JPA). Auch hier wird das Deployment durch einen Startparameter erledigt:

java -jar wildfly-bootable.jar --deployment=jee-runtimes-demo.war

Darüber hinaus bietet das zum Build genutzte Plugin sogar einen Development Mode an. Wird die Anwendung mit

mvn wildfly-jar:dev-watch

gestartet, überwacht sie kontinuierlich die Sourcen und deployt Änderungen automatisch.

Quarkus

Die bisherigen Modi nutzen alle ein Standard-WAR-File als Deployment-Einheit. Es ist also – wenn man so will – auch für Payara Micro und WildFly Bootable JAR immer noch ein Server vorhanden, auf den eine Anwendung deployt wird.

Quarkus geht den Weg (wie auch Spring Boot), die Anwendung mit dem Server zu einer ausführbaren Einheit zu verbinden. Die benötigten Serverbestandteile wie REST-, CDI- oder JPA-Implementierung werden im Build als einfache Dependencies eingebunden. Heraus kommt ein JAR-File, das einfach auf der Kommandozeile gestartet werden kann:

java -jar quarkus-app/quarkus-run.jar

Das JAR-File enthält übrigens nicht den gesamten Code der Anwendung, sondern referenziert ihn in dedizierten Unterverzeichnissen für den eigentlichen Anwendungscode und die Infrastruktur. Diese Trennung macht es leichter, bspw. Docker-Images zu erstellen und dabei nicht die eher statische Infrastruktur-Schicht bei jedem Rebuild neu erstellen zu müssen.
Das gesamte Verzeichnis quarkus-app ist für unsere Demo-Anwendung nur ca. 31 MB groß, ist also im Vergleich mit den bisherigen Serverlösungen nochmals erheblich verkleinert.

Quarkus verlegt einige Dinge aus der Laufzeit in die Build-Zeit, wie z. B. Entscheidungen über die Zuordnung von CDI Beans zu Injektionszielen. Damit wird der im Standard beim Anwendungsstart laufende, auf Reflection basierende Container-Start erheblich beschleunigt.

Unsere Demo-Anwendung startet damit in ca. 1,5 s (im Vergleich zu 4,7 s für WildFly Bootable JAR). Wem das immer noch nicht schnell genug ist, kann die Anwendung auch noch in Native Code übersetzen lassen. Dann sind Startzeiten im Millisekunden-Bereich erreichbar.

Auch Quarkus hat einen Development Mode, der ähnlich funktioniert, wie es oben für WildFly Bootable JAR beschrieben ist. Start mit

mvn quarkus:dev

Fazit

Java EE und Jakarta EE sind weit weg von den zunächst schwergewichtigen Serverlösungen der Anfangszeit (seitdem sind ja auch gut 20 Jahre vergangen!).

Wer eine Deployment-Einheit in Form eines WAR-Files bevorzugt, kann sie in einen klassischen Server deployen oder aber mit nur einem Kommando Server und Anwendung zugleich starten.

Es ist jedoch auch möglich, bei unverändertem Anwendungscode eine Anwendung mit eingebetteten Serveranteilen zu bauen, die recht klein ist und äußerst schnell startet.

Wer also heute noch behauptet, Java EE sei für moderne Anwendungen ungeeignet, hat vermutlich einige Jahre der JEE-Entwicklung verschlafen.

Weitere Informationen

Wir versorgen Sie gerne mit weiterem Input:

  • Unser Expertenkreis Java ist eine regelmäßige Vortragsveranstaltung zu allem aus dem Java-Ökosystem. Melden Sie sich kostenfrei an unter https://gedoplan.de/java-events/.
  • In die Tiefe gehen wir in unseren Seminaren, z. B. Power Workshop Jakarta EE oder Microservices mit Quarkus – kompakt, zu finden auf https://gedoplan.de.
  • Zweimal im Jahr finden Sie in unserem Firmenmagazin GEDOPLAN aktuell Fachartikel zu den Themen, die uns bewegen. Fordern Sie die Print-Ausgabe an oder lesen Sie online unter https://gedoplan.de/publikationen/.

Dirk Weil, GEDOPLAN GmbH