Meine JEE-API im Application-Server ist weg - was nun?

Montag, 13.1.2020

JAVA-EE-Header-Blog-Serie_viadee

Im vorherigen Teil der Blogserie wurden konkrete Herausforderungen bei der Migration einer veralteten Anwendung auf Spring betrachtet. In diesem Blogpost sollen wesentliche Teile der Java EE-Spezifikation im Hinblick auf mögliche Zukunftsoptionen betrachtet werden.

Spätestens seit Java EE von Oracle an die Eclipse-Foundation übergeben wurde, steht die Zukunft des Standards auf unsicheren Füßen. Wie wird sich der Standard zukünftig entwickeln? Was ist mit den bestehenden Unternehmens-Systemen, die weiterhin noch auf Application-Servern laufen? Wie wird sich der Support entwickeln? Auf welcher Basis sollen zukünftige Systeme erstellt werden? Die Zukunft altbewährter Java EE-Application-Server erscheint unsicher.

Seit dem ersten Java EE-Standard sind fast 20 Jahre vergangen: Zeit, den Standard gehen zu lassen und sich nach einem stabilen Umfeld für die kritischen Unternehmens-Systeme umzusehen.

Dieser Blogpost beleuchtet wesentliche Teile der Java EE-Spezifikation und zeigt Alternativen und Optionen für die Zukunft auf. Auch der Application-Server als bisheriger Laufzeit-Container und mögliche Alternativen werden in dem Artikel betrachtet. Ist ein großer Application-Server in Zeiten von Cloud-Computing überhaupt noch zeitgemäß?

API

Die erste Frage stellt sich bezüglich der bisherigen Java EE-API: Müssen bestehende Anwendungen nun vollständig umgebaut werden? Kann ich Teile davon außerhalb des Application-Servers weiter verwenden? Was wäre eine Alternative?

Das durch die Übergabe von Java EE an die Eclipse-Foundation entstandene Jakarta EE wird häufig als Nachfolger von Java EE bezeichnet. Die weitere Zukunftssicherheit und der Support für die Technologie müssen sich jedoch erst noch zeigen. Auch geht dieser Übergang nicht ganz ohne Änderungen vor sich: Der bisherige Package-Namespace javax wird im Rahmen von Jakarta EE für eine Weiterentwicklung nicht mehr verwendet werden können. Wenn also ohnehin Änderungen anstehen, liegt es nahe, die möglichen Optionen einmal genauer zu betrachten.

Im Folgenden sollen daher gängige Java EE-APIs betrachtet werden. Dabei stehen zwei grundlegende Optionen im Fokus:

  1. Ich will die API weiterhin verwenden.
  2. Was wäre eine alternative API oder Technologie?

Die erste Option würde bedeuten, Teile der API auch außerhalb und somit unabhängig von einem Application-Server weiter zu nutzen. Die Motivation kann sein, dass die API für den Einsatzzweck weiterhin eine gute Wahl darstellt. Es kann aber auch einfach bedeuten, die Änderungen an bestehenden Teilen eines Systems im Rahmen zu halten.

Die zweite Option betrachtet alternative APIs oder Technologien. Innerhalb des Application-Servers steht zwar durchaus eine Vielzahl an APIs für unterschiedliche Zwecke zur Verfügung, daneben haben sich im Laufe der Zeit aber ernst zu nehmende Alternativen entwickelt.

Die folgende Tabelle listet einige Beispiele für die genannten beiden Optionen auf.

API / Technologie
Ich will das weiter machen!
Gebt mir Alternativen!
Java Servlet Leichtgewichtige Servlet-Container

Servlet-Basiert: Spring Controller

NIO-Server, Reactive Streams

Security Leichtgewichtige Servlet-Container Spring Security / Spring Cloud Security
UI
(JSP / JSF / Expression Language / JSTL)
Leichtgewichtige Servlet-Container - Wenn es zum Übergang sein muss...

Außerhalb von Java: Typescript, LitElements oder Angular

Mit Java: Vaadin

EJB Hier wäre ein Wechsel zur Alternative empfehlenswert. Plain Old Java Objects (POJOs) mit REST für Remote-Beans
CDI Spring-Support für CDI-Annotationen Spring Dependency-Injection
JPA Hibernate als JPA Referenz-Implementierung

JDBC-Templates oder -Repositories

NoSQL

JMS Spring Messaging JMS Apache Kafka (für ausgewählte Einsatzszenarien)
JAX-RS RESTEasy REST mit Spring
JAX-WS Apache Axis2 oder Apache CXF SOAP mit Spring

Weitergehende inforMationen
Für viele der Probleme finden sich Optionen im Spring-Ökosystem. Eine genauere Betrachtung des Spring-Ökosystems als Alternative zu Java EE stellt Tobias Voß in seinem Blogpost vor.

Java Servlet & Security

Die Servlet-Spezifikation ist eines der älteren Teile der Java EE-API und bietet auch die Basis für andere Frameworks wie beispielsweise die in Spring verwendeten Controller. Schaut man sich die API genauer an, sieht man ihr das Alter teilweise durchaus an: So werden bei einigen Methoden noch Java Enumerations geliefert (siehe zum Beispiel die Klasse ServletRequest).

Ich will das weitermachen!

Als leichtgewichtige Alternative zu einem kompletten Application-Server würden sich hier sogenannte Servlet-Container wie der Apache Tomcat oder Jetty anbieten. In diese kann weiterhin ein Deployment bestehender WAR-File auf Basis der Servlet-API erfolgen. Vor dem Hintergrund der Anpassungen im javax-Namensraum ist aber hier ebenfalls mit zukünftigen Änderungen zu rechnen.

Gebt mir Alternativen!

Mit den Controllern aus Spring MVC steht auch eine alternative API zur Verfügung: Dabei werden gleichzeitig viele Funktionen wie Datenkonvertierung und komfortables Exception-Handling aus dem Spring-Kontext mit angeboten. Dabei basiert dies zwar auf dem Servlet-Standard, abstrahiert jedoch an vielen Stellen. Damit reduziert sich einerseits die Auswirkung von zukünftigen Änderungen am Standard. Auf der anderen Seite bietet es die Grundlage, sich schnell in die neue API einzufinden.

Auch steht mit Spring Security ein komfortables Framework zur Authentifizierung und Autorisierung zur Verfügung. Im Gegensatz zum Security-Support im Java EE-Standard besteht hier auch die Option, in einer Anwendung problemlos mehrere unterschiedliche Authentifizierungs-Mechanismen zu betreiben. Neben klassischen Sessions stehen darüber hinaus auch andere Optionen wie beispielsweise OAuth2 oder Java Web Token (JWT) zur Verfügung.

Weitergehende inforMationen

In unserer zweiteiligen Blogreihe "Microservices mit OAuth2 absichern" stellen wir die Verwendung von Spring Security mit OAuth2 im Kontext von Microservices anhand praktischer Beispiele vor.

 

Technologisch weiter entfernte Alternativen wären hier NIO-Server wie Netty. Diese zeichnen sich durch ein Non-Blocking-IO und potenziell höheren Durchsatz aus, was jedoch auf Kosten anderer Programmiermodelle geht. In diesem Kontext wären auch Reactive Streams beispielsweise durch Spring Webflux zu nennen.

User Interface (UI)

Im klassischen Java EE-Stack wurden UIs mit Java Server Pages (JSP) und der Java Standard Tag Library (JSTL) oder Java Server Faces (JSF) erstellt. Dabei werden die Seiten auf dem Server dynamisch erzeugt und an den Browser ausgeliefert. Formulareingaben werden via Request an den Server gesendet, was dieser in der Regel mit einer neuen Seite beantwortet. Aspekte moderner Webanwendungen, wie das Laden und Senden von Daten im Hintergrund, stehen dabei nicht im Fokus und werden in der Regel durch JavaScript-Bibliotheken mit diesen Seiten ausgeliefert.

Die folgende Grafik verdeutlicht diesen klassischen Ablauf:

klassischerAblauf-1

Der Browser als Client fordert die Webseite vom Server an. Nach einer Bearbeitung auf der Seite werden die Daten an den Server gesendet. Dieser beantwortet die Anfrage mit einer neuen Webseite. Die Steuerung des Ablaufs geht dabei primär vom Server aus. Ein Nachladen von Daten oder eine Speicherung im Hintergrund ist dabei erst einmal nicht vorgesehen.

Ich will das weitermachen!

Mit leichtgewichtigeren Servlet-Containern wie dem Apache Tomcat oder Jetty besteht weiterhin die Möglichkeit, diesen Weg zu verfolgen. Dabei ist dieser Weg aber auch hier mit den bereits zu Servlets im Allgemeinen genannten Problemen behaftet.

Gebt mir Alternativen!

Eine moderne Alternative wäre die komplett unabhängige Entwicklung einer Webanwendung mit TypeScript und Angluar oder LitElements als Single Page Application (SPA). Damit bewegen wir uns zwar nicht mehr im Sprach-Umfeld von Java, haben mit TypeScript aber eine moderne Sprache, welche direkt in JavaScript transpiliert und im Browser läuft. Angular stellt als Framework dazu einen umfangreichen Rahmen für die Webentwicklung zur Verfügung. Auf Basis des neuen W3C-Standards zu Web Components bietet LitElements eine leichtgewichtige Option, einfache und wiederverwendbare Komponenten für die Webentwicklung zu erstellen.

Weitergehende inforMationen
Christian Siebmanns zeigt in seinem Blogbeitrag "Eigene Komponenten mit Web Components" genauer, wie sich eigene Komponenten mit dem Web-Components-Standard entwickeln lassen.

Die Anbindung an das Java Backend erfolgt dabei via REST. Dafür steht beispielsweise mit den Rest-Controllern im Spring-Framework eine komfortable API zur Implementierung zur Verfügung. Damit erfolgt auch eine stärkere Entkopplung von Frontend und Server.

Bei einer SPA fordert der Browser zunächst auch die SPA vom Server an. Nach einer Bearbeitung wird die Seite jedoch nicht verlassen, sondern die Daten werden im Hintergrund an den Server gesendet. Innerhalb der SPA kann zwar dennoch eine andere Seite angezeigt werden, diese Steuerung erfolgt jedoch durch die SPA selber und nicht durch den Server. Darüber hinaus können die Daten durchaus auch öfter an den Server übertragen werden: So könnte beispielsweise nach der Erfassung kritischer Eingabefelder bereits im Hintergrund eine fachliche Prüfung der Daten im Server erfolgen, während der Anwender parallel weitere Daten in der SPA erfasst. Die folgende Grafik stellt den Ablauf mit einer SPA noch einmal exemplarisch dar:

Ablauf-mit-einer-SPA

Insbesondere für Frontends zur reinen Anzeige und Bearbeitung von Datensätzen steht mit Vaadin eine Alternative zur Verfügung, welche eine einfache Erstellung solcher Masken erlaubt. Insbesondere ist zu erwähnen, dass dabei weiterhin in Java entwickelt werden kann.

Allerdings bringt dieser Ansatz Nachteile mit sich: Vaadin besitzt, im Gegensatz zur standardisierten zustandslosen Kommunikation mit REST-Services, ein eigenes und zustandsbehaftetes Protokoll zur Kommunikation zwischen Client und Server. Gerade bei der Skalierung oder zum Einsatz in der Cloud mit Container-Technologien kann dieser zustandsbehaftete Ansatz problematisch werden.

Enterprise Java Beans (EJB) & Context Dependency Injection (CDI)

Ich will das weitermachen!

Im Fall von CDI werden die entsprechenden Annotationen wie beispielsweise @Inject auch direkt von Spring unterstützt. Bei EJBs wäre ein Wechsel zu einer Alternative zu überdenken.

Gebt mir Alternativen!

Als Alternative zu EJBs lässt sich die damit realisierte Logik von lokalen EJBs relativ einfach in Form von Spring Beans abbilden. Für Remote Beans wäre ein möglicher Ansatz, die Logik via REST anzubinden. Dies würde zusätzlich die Schnittstelle für zukünftige Aufrufe aus gänzlich anderen Technologien bzw. Systemen öffnen.

Die Verwaltung des Lifecycle der Spring Beans sowie eine eventuell notwendige Dependency Injection übernimmt dabei ebenfalls Spring. Wie eingangs beschrieben, werden dabei auch die CDI Annotationen von Spring direkt unterstützt.

Weitergehende inforMationen

An dieser Stelle wird es Zeit, sich von Teilen der Java EE-API zu verabschieden. Was bedeutet das und wie kann so etwas funktionieren? Dazu stellt Pia Diedam in ihrem Blogpost Herausforderungen und praktische Erfahrungen bei der Migration einer Java EE-Anwendung auf Spring vor.

 

Java Persistence API (JPA)

Ich will das weitermachen!

JPA steht nicht nur ausschließlich in einem vollständigen Application-Server zur Verfügung. Vielmehr steht mit Hibernate ORM eine Implementierung zur Verfügung, mit welcher die JPA-Spezifikation auch außerhalb eines Application-Servers genutzt werden kann. Bei Hibernate handelt es sich darüber hinaus um die Referenz-Implementierung des JPA-Standards.

Gebt mir Alternativen!

Vielleicht reicht aber auch ein relativ einfacher Zugriff auf die Datenbank? Dann wäre vielleicht eine Verwendung von einfachem JDBC denkbar. Dazu stellt Spring eine Implementierung im Spring-Ökosystem bereit, welche der klassischen JDBC-Schnittstelle einigen Komfort hinzufügt: Unter anderem bietet Spring hier mit einem sogenannten JDBC-Template eine API an, welche einen gewissen Komfort beim Mapping von JDBC-Records in Java-Objekte bietet. Gleichzeitig bleibt aber der Vorteil der vollen Kontrolle über die verwendeten SQL-Statements erhalten.

Wenn das nicht ausreicht, besteht mit Spring Data JDBC eine Option, Repositories auf Basis von JDBC im Sinne des Domain Driven Design zu definieren.

Eine weitere Alternative stellen NoSQL-Datenbanken dar: Sollen mit JPA sehr unterschiedlich strukturierte Daten abgespeichert werden, kann dies zu eher abstrakten Datenmodellen führen. Auch hier bietet Spring Data entsprechende Implementierungen an, mit welchen sich vergleichsweise einfach NoSQL-Datenbanken anbinden lassen.

Java Messaging Service (JMS)

Ich will das weitermachen!

Die aus dem Application-Server bisher angesprochene JMS-Infrastruktur kann auch außerhalb des Application-Servers weiter verwendet werden. Der eigentliche Anwendungscode muss jedoch gewisse Anpassungen erfahren: Hier steht beispielsweise im Spring-Ökosystem eine Implementierung bereit, welche die Anbindung von JMS-Queues oder -Topics sehr komfortabel via JMS-Templates erlaubt. Auch ist es möglich, über die Annotation @JmsListener eine Spring Bean als Äquivalent einer Message Driven Bean zu implementieren.

Gebt mir Alternativen!

Für gewisse Szenarien bietet sich auch Apache Kafka als Alternative an: wenn es darum geht, viele Daten zu transportieren und dabei ggf. auch noch zu transformieren. Als vollständige Alternative zu JMS für jedes Einsatzszenario kann Kafka jedoch nicht gesehen werden. Darüber hinaus muss auch beachtet werden, dass ein System-Setup mit Kafka komplexer als ein einfaches JMS-Setup ist, da für den Betrieb zusätzlich noch Apache Zookeeper benötigt wird.

JAX-RS & JAX-WS

Generell muss hier zwischen der Schnittstellen-Technologie selber und deren möglicher Implementierung unterschieden werden: Bei REST und SOAP handelt es sich um Marktstandards, unabhängig der Java-EE-API. Somit bestand in Bezug auf die Schnittstellen-Technologie auch mit Java-EE bisher kein Lock-In. Für die Umsetzung solcher Schnittstellen stehen mit JAX-RS (REST) und JAX-WS (SOAP) APIs zur Verfügung, welche im Folgenden kurz betrachtet werden sollen.

Ich will das weitermachen!

JAX-RS und JAX-WS können auch außerhalb eines Application-Servers sehr gut angeboten werden. So existiert mit RestEasy eine mögliche Implementierung für JAX-RS. Ab Version 6 war eine JAX-WS-Implementierung auch in der Java-Standard-Edition verfügbar. Mit Java 11 ist diese zwar wieder entfallen, steht jedoch weiterhin gesondert bereit. Mit Apache Axis2 oder CXF stehen darüber hinaus weitere Alternativen zur Verfügung, um außerhalb des Spring-Ökosystems SOAP-Webservices zu implementieren.

Weitergehende inforMationen

Die mit dem Entfallen der JAX-WS-Implementierung verbundenen Probleme und mögliche Lösungen stellen wir in unserem Blogpost JAXB und SOAP in Java 11 vor.

 

Gebt mir Alternativen!

Für eine Umsetzung von REST-Schnittstellen bietet Spring mit REST-Controllern und REST-Templates alternative Optionen zur einfachen Umsetzung und Anbindung der Schnittstellen.

Wird bereits Spring eingesetzt, so steht auch mit Spring-WS eine API bereit, um SOAP-Webservices zu implementieren. Dabei stellt sich jedoch die Frage, ob SOAP für die Schnittstelle zwingend notwendig ist: Vielfach ist der SOAP-Overhead gar nicht notwendig und die Schnittstelle lässt sich wesentlich einfacher als REST-Schnittstelle umsetzen.

Weitere Aspekte

Wurden bisher im Application-Server mit der J2EE Connector Architecture (JCA) andere Systeme integriert, so bietet sich hier Apache Camel als Alternative an. Damit steht eine API zur Verfügung, welche es erlaubt, unterschiedliche Schnittstellen-Technologien mit einer einheitlichen Philosophie zu verwenden. Darüber hinaus bildet Camel die von Hohpe und Woolf beschriebenen Enterprise Integration Patterns als Lösungsbausteine für die gängigen Probleme bei der Systemintegration sehr nahe ab.

Weitergehende inforMationen

Gerne vermitteln wir in unserem Seminar zu Camel und EIP die Grundlagen für eine erfolgreiche Migration.


Laufzeitcontainer

Fällt der bisherige Application-Server als Laufzeitcontainer weg, stellt sich die Frage, wohin ein Deployment nun erfolgt. Wird ein Servlet-Container in Gestalt eines Tomcat oder Jetty verwendet, kann weiterhin ein Deployment des altbekannten WAR-Files erfolgen. Was aber, wenn der Servlet-Container mit der Anwendung ausgeliefert wird, wie es Spring Boot mit einem Embedded Servlet-Container anbietet? Was passiert, wenn es später etwas ganz anderes als ein Netty ist? Erfolgt das Deployment überhaupt noch auf einen monolithischen Application-Server(-Cluster)?

Gerade wenn es um die (Teil-)Modernisierung eines bestehenden Monolithen geht oder dieser um neue Aspekte ergänzt werden soll, kann es sinnvoll sein, diese kleineren Einheiten als Microservices zu betreiben. Damit würden Stück für Stück Teile aus dem bisherigen Monolithen herausgelöst, bis dieser vollständig abgelöst ist.

Damit steigen die Menge der Deployment-Einheiten und die möglichen Technologien der Ziel-Plattformen potenziell an. Wenn es dann noch darum geht, die Entwicklung und Produktion möglichst gleich zu halten, bietet sich ein Deployment als Docker-Image an: Dabei wird die eigentliche Anwendung in ein einheitliches Image verpackt, welches alle notwendigen Laufzeit-Komponenten (inklusive der Java-Runtime) enthält. Dieses kann dann lokal auf dem Entwickler-Rechner, aber auch in Produktion ausgeführt werden.

Weitergehende inforMationen

Interessiert an Containern, die nicht am Hochseehafen stehen? Unser Seminar zu Docker und Kubernetes verschafft die ersten Erfahrungen und Grundlagen für Entscheidungen und eine Migration.


Fazit

Auch wenn die Java EE-API im Application-Server einer ungewissen Zukunft entgegensieht, stehen für Java-Anwendungen im Enterprise-Umfeld weiterhin viele alternative APIs zur Verfügung. Insbesondere das Spring-Ökosystem stellt dabei Alternativen in einer einheitlichen Philosophie zur Verfügung. Durch die Etablierung am Markt und eine breite Community steht damit eine echte Alternative zur Verfügung.


 

Dieser Beitrag ist Teil einer Serie

Teil 1: Java EE ist tot – es lebe Spring (Boot)!
Teil 2: Im Griff der Würgefeige: Herausforderungen bei der Spring Migration
Teil 3: Meine JEE-API im Application-Server ist weg - was nun?
Teil 4: Weg von Java EE - so gelingt die Migration


zurück zur Blogübersicht

Diese Beiträge könnten Sie ebenfalls interessieren

Keinen Beitrag verpassen – viadee Blog abonnieren

Jetzt Blog abonnieren!

Kommentare

Michael Twelkemeier

Michael Twelkemeier

Michael Twelkemeier ist Senior-Berater bei der viadee. Er berät Kunden im Finanzdienstleistungs-Umfeld in Fragen der IT-Architektur und Systemintegration bei der Umsetzung individueller Softwaresysteme mit einem Schwerpunkt auf Java-basierte Enterprise-Anwendungen.

Er ist Leiter des Kompetenzbereichs Java / Software-Architektur und teilt seine Erfahrungen als Autor und Speaker u.a. auf dem NAVIGATE Kongress.

Michael Twelkemeier bei Xing Michael Twelkemeier bei LinkedIn