Nach mehr als fünf Jahren ist mit Jakarta EE 10 das erste neue Featurerelease des Java-Enterprise-Standards erschienen. Viele neue oder überarbeitete Spezifikationen trimmen das Schwergewicht auf Schlankheit, Parallelisierung und Microservices. Mit einem Vierteljahr Verzögerung ist im September Jakarta EE 10 erschienen. Es ist seit fünf Jahren der erste Java- Enterprise-Standard, der neue Features bringt. Die Ziele sind dabei hochgesteckt: „Building an Open Source Ecosystem for Cloud Native Enterprise Java“, so zu lesen auf der Homepage des Projekts. Das ist auch zwingend notwendig, soll es in Zeiten von Containern, Cloud-native und Co. bestehen.
Um zu verstehen, welchen hohen Stellenwert das aktuelle Jakarta-EE-Release in der mittlerweile zwanzig Jahre währenden Historie des Java-Enterprise-Standards innehat, hilft ein kurzer Blick zurück: Das letzte echte Featurerelease für Java Enterprise gab es mit Java EE 8 im August 2017. Damals wurden unter anderem eine eigenständige Security-API, JSON-Binding und ein JAX-RS-Reactive-Client eingeführt. Die folgenden beiden Releases Jakarta EE 8 und Jakarta EE 9 brachten zunächst keine weiteren neuen Features, sondern wurden lediglich dazu verwendet, den Umzug weg von Oracle hin zur Eclipse Foundation zu realisieren und damit einhergehend die Namespaces von javax.* auf jakarta.* zu migrieren. Auch der Sprung auf die vor Jakarta EE 10 aktuelle Version 9.1 ist lediglich als Maintenance Release zu verstehen, das zwar die Unterstützung von Java SE 11 mit sich brachte, aber keine neuen Features.
Technisch ist also das bis dato aktuelle Jakarta EE 9.1 auf dem Stand von vor fünf Jahren. Dies ist der Grund, warum das jetzige Release 10 so sehnsüchtig erwartet wurde. Im Vordergrund steht dabei die Frage, ob man in Zukunft auch in hochdynamischen Umgebungen wie der Cloud noch auf den Enterprise-Java-Standard setzen kann. CDI Lite und das Core Profile sollen in der neuen Version die Grundlage schaffen, Jakarta-EE-Services zukünftig ohne den Ballast eines Application-Servers schlank in einer Cloud-nativen Umgebung zu betreiben.
Bereits mit CDI 2.0 und somit als Teil von Java EE 8 wurde die CDI-Spezifikation (Contexts and Dependency Injection) in die Bereiche Core CDI, CDI in Java SE und CDI in Java EE unterteilt. Während der Bereich Core CDI die grundlegende Funktionsweise von CDI spezifiziert, definieren die anderen beiden Bereiche zusätzliche Features für die jeweiligen Umgebungen Java SE und Java EE.
Die neue Spezifikation CDI 4.0 geht noch einen Schritt weiter. Mit der Einführung von CDI Lite und CDI Full wird Core CDI weiter unterteilt. Während CDI Full als Basis für Anwendungsserver dient, kommt CDI Lite immer dann zur Anwendung, wenn es darum geht, ein schmales Runnable beispielsweise in Form eines Microservice zu erzeugen.
Damit stellt sich die Frage, warum es überhaupt noch CDI Full gibt. Der eben skizzierte Optimierungsschritt setzt den Verzicht auf Reflection zur Laufzeit voraus, was einige Restriktionen mit sich bringt. So darf eine auf CDI Lite aufsetzende Anwendung keine passivierbaren Scopes (Session und Conversation) anbieten. Auch Decorator- und Specializes-Annotationen sind tabu. Viel schwerer ins Gewicht fallen dürfte aber für die meisten Anwendungsfälle, dass in CDI Lite auch der Mechanismus der CDI Portable Extensions fehlt. Mit dessen Hilfe lässt sich auf einfache Art und Weise die Funktionalität des CDI-Containers via Drag-and-drop erweitern.
Fairerweise soll nicht unterschlagen werden, dass es für die Portable Extensions in CDI Lite ein Pendant namens Build Compatible Extension gibt. Es ist davon auszugehen, dass es viele der aktuell in der JEE-Community etablierten Portable Extensions künftig ebenso in Form von Build Compatible Extensions geben wird.
Die CDI-Lite-API ist für sich genommen bereits spannend, spielt aber ihre volle Stärke erst im Zusammenspiel mit einer weiteren Neuerung der Jakarta-EE-10-Spezifikation aus: dem Core Profile. Das neue Profile ist bewusst deutlich schlanker gehalten als die beiden bisherigen Varianten Full Profile und Web Profile und hat nur sieben APIs: Jakarta Annotations 2.1, Jakarta CDI 4.0 Lite, Jakarta Dependency Injection 2.0, Jakarta Interceptors 2.1, Jakarta JSON Processing 2.1, Jakarta JSON Binding 3.0 und Jakarta RESTful Web Services 3.1. Damit ist es besonders gut zum Entwickeln von Headless-Anwendungen wie Microservices geeignet.
Dank der geringen Größe des resultierenden Artefakts und der verkürzten Start-up-Phase durch die Anwendung der Compile-Time-Optimierung via CDI Lite entstehen Programme für hochdynamische und automatisch skalierende Systeme wie Cloud-native und Kubernetes-Anwendungen.
Bei einem genaueren Blick auf die APIs des Core Profile fällt auf, dass sie nahezu identisch mit den Jakarta-EE-APIs des Eclipse MicroProfile sind. Das kommt nicht von ungefähr: Es ist ein erklärtes Ziel beider Spezifikationen, dass zukünftige Versionen des Eclipse MicroProfile auf der aktuellen Version des Jakarta EE Core Profile aufsetzen sollen. Das führt zu mehr Kompatibilität zwischen beiden. Zu den weiteren Kandidaten für eine künftige Kompatibilität mit dem Jakarta EE Core Profile gehören Helidon, Quarkus und Micronaut.
Die Möglichkeit, einzelne Funktionen gezielt asynchron und somit non-blocking auszuführen, ist ein wichtiger Baustein zeitgemäßer Softwarearchitekturen. In Jakarta-EE-Anwendungen ließ sich das bisher deklarativ nur innerhalb von EJBs (Enterprise Java Beans) realisieren. Außerhalb davon musste man dagegen auf den ManagedExecutorService zurückgreifen und den asynchronen Task manuell anstoßen.
Die aktuelle Version 3.0 der Concurrency-API ermöglicht nun auch CDI-Beans, einzelne Methoden deklarativ als asynchron zu markieren und damit gezielt nebenläufig ablaufen zu lassen. Dazu dient die neue Annotation @Asynchronous aus dem Package jakarta.enterprise. concurrent. Achtung: Das Package ja karta.enterprise.ejb enthält eine Annotation mit demselben Namen. Als optionaler Parameter dient der zu nutzende Threadpool.
Anders als die beiden bisherigen Ansätze, die lediglich Methoden unterstützen, die das 2004 mit Java 5 eingeführte und somit in die Jahre gekommene Future zurückgeben, erlaubt die neue @Asynchronous-Annotation Methoden mit den Rückgabewerten Completion Stage und CallableFuture. Asynchrone Tasks können auf die Weise aneinandergereiht ausgeführt und ihre Rückgabewerte automatisch an die Folgetasks übergeben werden. Zusätzlich wird eine sinnvolle Fehlerbehandlung in dem nicht immer ganz trivialen asynchronen Kontext ermöglicht (Codebeispiel siehe Listing 1).
Die neue Annotation ist ausschließlich für den Einsatz im Kontext von CDI Managed Beans gedacht. Die Spezifikation erwähnt explizit, dass sie nicht innerhalb einer EJB zum Einsatz kommen darf und dass mit ihr annotierte Methoden nicht zusätzlich mit der gleichnamigen Annotation aus der MicroProfile-Fault-Tolerance-API versehen sein dürfen.
Dass die Concurrency-API bisher dem Jakarta EE Full Profile zugeordnet war, hat immer wieder zu Diskussionen geführt. Es war nicht nachvollziehbar, warum Anwendungen für das Web Profile die gezielte asynchrone Ausführung von Tasks nicht nutzen sollten. Mit der aktuellen Version 3.0 wechselt die API in das Web Profile.
Auch Jakarta JPA 3.1 bringt einige interessante Neuerungen mit sich. Künftig lassen sich UUIDs als Basistypen verwenden und können somit unter anderem als Primärschlüssel inklusive passender ID-Generator-Strategie dienen (Listing 2). Zwar erlaubten bisher sowohl Hibernate als auch EclipseLink das Vorgehen über proprietäre Ergänzungen, aber es war nicht via JPA-Spezifikation standardisiert.
Die JPA Query Language und Criteria- API bringen ebenfalls Ergänzungen mit. Mit EXTRACT lassen sich numerische Teile eines Datums YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE und SECOND extrahieren. Die neuen Datumsfunktionen LOCAL DATE, LOCAL TIME, LOCAL DATE TIME erlauben das Handling von Local-Date-und -Time-Klassen aus dem java.time- Package. Die numerischen Funktionen bringen als Erweiterungen die selbsterklärenden Funktionen CEILING, EXP, FLOOR, LN, POWER, ROUND und SIGN mit.
Zur Authentisierung über Drittanbieter wie Google, Facebook oder Twitter bringt die Jakarta-Security-API 3.0 einen neuen Authentifizierungsmechanismus auf Basis von OpenID Connect. Grundlage dafür ist der OpenID Connect Authorization Code Flow, der wiederum Teil der OpenID-Connect-Core-Spezifikation ist.
Listing 3 zeigt eine annotierte CDI-Bean zum Aktivieren der OpenID-Connect-Authentifizierung. Die für den Provider benötigten Metadaten finden sich in den Parametern der Annotation. Das Beispiel setzt dafür auf die Unified Expression Language.
Ist ein Log-in über den OpenID Connect Provider erfolgreich, wird automatisch eine Credential-Instanz erzeugt, die das vom Provider zurückgelieferte Token erhält. Dass dieses valide ist, stellt ein für OpenID Connect spezifischer Identity Store sicher. Da der OpenID Connect Provider keine Kenntnis über die Rollen und Gruppen aufseiten des Clients hat, lässt sich ein anwendungsspezifisches Mapping angeben. Die resultierenden Gruppen finden sich später in einer Instanz der Klasse CredentialValidation Result wieder. Der neue Mechanismus ist neben der reinen Authentifizierung dafür zuständig, das Ablaufen des Tokens zu überwachen und gegebenenfalls über RefreshToken automatisch ein neues Token anzufordern.
JAX-RS spezifiziert seit der 2008 veröffentlichten Version 1.0 Java SE als eine von mehreren Ablaufumgebungen für eine JAX-RS-basierte Anwendung. Leider hat die Spezifikation sich bisher darüber ausgeschwiegen, wie genau das zugehörige Bootstrapping auszusehen hat. Daher hat jeder Hersteller seine eigene proprietäre Lösung implementiert, um vom Applikationsserver unabhängige (Micro-) Services oder Runnables zu realisieren.
Mit der Version 3.1 standardisiert JAX-RS nun das Bootstrapping einer JAX-RS-Serveranwendung innerhalb von Java SE. Zwar sind die proprietären Lösungen weiterhin als Alternative erlaubt, aber der standardisierte Weg ist explizit der empfohlene, um für die Zukunft einen potenziellen Vendor Lock-in zu umgehen. Für einen einfachen Microservice-Endpunkt, der an Port 8080 lauschen soll, könnte ein Bootstrapping wie in Listing 4 aussehen.
Die Spezifikation Jakarta RESTful Web Services 3.1 bringt eine weitere erwähnenswerte Neuerung: das Handling von Multipart/Form-Data-Media-Type-Requests. Obwohl RESTful Web Services eine der populärsten APIs aus Jakarta EE ist, fehlte das Format merkwürdigerweise bisher. Entwicklerinnen und Entwickler waren gezwungen, auf ein mit @Multi PartConfig annotiertes Servlet zurückzugreifen, das immerhin seit Servlet-API 3.0 und somit Java EE 6 (2009) verfügbar ist. Alternativ mussten sie eine proprietäre Library nutzen.
Die neue Umsetzung sieht vor, dass Anwendungen in der @Consumes-Annotation signalisieren, dass sie einen Multipart-Request erwarten. Für den Zugriff auf die einzelnen Teile der Anfrage bietet die API zwei Optionen: Entweder lassen sich Anwendungen eine Liste von EntityPart-Objekten übergeben oder sie übergeben die Teile des Multipart-Request als einzelne Parameter und adressieren sie über deren Namen. Listing 5 zeigt die Methodendeklaration für beide Varianten.
Obwohl viele Anwendungen mittlerweile ein JavaScript-Frontend mit Frameworks wie Angular, React oder Vue.js nutzen, ist JSF nach wie vor weit verbreitet. Zum einen, weil es in den letzten zehn bis zwanzig Jahren Einzug in viele Enterprise-Anwendungen gehalten hat und dort weiterhin existiert. Zum anderen aber auch, weil nach wie vor etliche Jakarta-EE-Neuentwicklungen im Frontend auf JSF setzen, da für viele Developer im Java- Enterprise-Umfeld JSF einfacher zu verstehen und zu handhaben ist als seine JavaScript-basierten Alternativen. Daher wartet JSF ebenfalls mit einem Update der Spezifikation auf.
Die wohl auffälligste Änderung ist der Name: Ab sofort heißt die Spezifikation nicht mehr Java oder Jakarta Server Faces, sondern Jakarta Faces oder kurz Faces. Das ist der generellen Umbenennung von Java in Jakarta geschuldet und hilft außerdem dabei, sich des Kürzels JSF zu entledigen.
Neu ist eine API zum rein Java-basierten Aufbau von Facelets. In der Faces- Community gab es schon immer Vertreter des hundertprozentig Java-basierten Ansatzes. Eine von Facelet abgeleitete Klasse muss lediglich die @View-Annotation tragen und die gewünschten Lifecycle-Methoden implementieren. Listing 6 zeigt den Aufbau einer einfachen View mit der neuen API.
Derzeit ist die API noch minimalistisch gehalten. Abhängig von der Akzeptanz innerhalb der Faces-Community gibt es aber Pläne, sie weiter auszubauen. Mit der Annotation @ClientWindowScopes existiert ein neuer Managed Scope, der denjenigen, die DeltaSpike genutzt haben, bekannt sein dürfte. Der Scope ist in etwa vergleichbar mit @FlowScoped, ist aber nicht auf dedizierte Seiten begrenzt. Stattdessen startet er mit dem automatischen Erstellen einer jfwid zum Identifizieren des aktuellen Window und existiert so lange, wie die ID als Request-Parameter an die Folgeseiten weitergegeben wird.
Interessant sind nicht nur die Neuerungen, sondern auch, was künftig nicht mehr dazugehört. An erster Stelle ist dabei die Anbindung an Java beziehungsweise Jakarta Server Pages als View- Technik zu nennen. JSPs sind bereits seit JSF 2.0, das 2009 erschienen ist, als überholt (deprecated) markiert, da ihr Lebenszyklus nicht gut zum Lifecycle von Jakarta Faces passt. Die Herausnahme aus der Spezifikation ist somit nur konsequent. Ebenfalls entfernt wurden die proprietären JSF Managed Beans, die seit JSF 2.3 als deprecated markiert sind. In der Praxis haben die meisten Projekte sie vermutlich seit Jahren durch CDI Managed Beans ersetzt.
Wer sich in den vergangenen Monaten mit den Vorgängen innerhalb der Jakarta- Community auseinandergesetzt hat, wird in der Aufzählung der Jakarta-EE-APIs die eine oder andere Spezifikation vermissen. Neben den offiziellen Spezifikationen der drei Profiles existieren einige weitere Seitenprojekte, die es aus unterschiedlichen Gründen noch nicht in die Spezifikation geschafft haben, aber heiße Anwärter für spätere Versionen sind.
Vorneweg steht die Jakarta-Config- API, die das Verwalten und Bereitstellen von Konfigurationsinformationen vereinheitlichten soll. Die API ist stark an die gleichnamige API aus dem MicroProfile angelehnt, soll sie aber nach aktuellem Stand nicht ersetzen. Ursprünglich sollte die erste Version als Bestandteil von Jakarta EE 10 erscheinen, aber die Spezifikation brachte es innerhalb des recht strengen Zeitplans nicht zur Fertigstellung.
Ebenfalls nicht in das aktuelle Release geschafft hat es die Jakarta-NoSQL-Spezifikation, die eine API zum einfachen und standardisierten Zugriff auf NoSQL-Datenbanken bietet. Die Spezifikation ist nach wie vor „under construction“ und sicherlich ein heißer Kandidat für eins der kommenden Jakarta-EE-Releases. Weitere Kandidaten in der Warteschlange sind Jakarta Data, Jakarta MVC und Jakarta RPC.
Deutlich mehr als die Hälfte der in Jakarta EE 10 eingebetteten Spezifikationen bringen ein Major oder zumindest ein Minor Update mit. Auffällig dabei ist, dass viele der Neuerungen und Änderungen darauf setzen, Jakarta EE aus der Ecke der schwergewichtigen Enterprise- Anwendungen zu bewegen. Cloud-native ist auch für Jakarta EE die Zukunft. Dank Core Profile, CDI Lite und SE Bootstrapping lassen sich mit dem Java-Enterprise-Standard schlanke und schnell startende Services erstellen. Bisher waren dafür proprietäre Frameworks wie Helidon, Quarkus oder Micronaut erforderlich.
Die notwendige Security in der verteilten Welt liefert die neue Integration des OpenID Connect Flows in der Security-API. Aspekte wie Distributed Tracing, Health Checks, Metriken, Fault Tolerance oder Security Context Propagation fehlen bewusst in der Spezifikation. Hier setzt das Jakarta-Team auf das gute Zusammenspiel mit den APIs des ebenfalls bei der Eclipse-Community beheimateten MicroProfile.
Das Release bringt nicht nur viele Neuerungen mit, sondern räumt einige Altlasten auf. Unter anderem hat das Team die lange obsolet gewordenen EJB Entity Beans entsorgt. Damit können neue Projekte besser im Jakarta-EE-Ökosystem Fuß fassen, wovon die gesamte Community profitiert, da die Auswahl der Provider steigt.
Details zur Veröffentlichung finden sich in der Releaseankündigung bei der Eclipse Foundation (siehe ix.de/zx89). Wer Jakarta EE 10 ausprobieren möchte, findet in Eclipse GlassFish 7.0 M8, Payara 6 Alpha 4 und WildFly 27 Alpha 5 drei Implementierungen des neuen Standards. (ulw@ix.de)
Quellen
Releaseseite Jakarta EE 10: ix.de/zx89
iX 11/2022 S. 84
Um zu verstehen, welchen hohen Stellenwert das aktuelle Jakarta-EE-Release in der mittlerweile zwanzig Jahre währenden Historie des Java-Enterprise-Standards innehat, hilft ein kurzer Blick zurück: Das letzte echte Featurerelease für Java Enterprise gab es mit Java EE 8 im August 2017. Damals wurden unter anderem eine eigenständige Security-API, JSON-Binding und ein JAX-RS-Reactive-Client eingeführt. Die folgenden beiden Releases Jakarta EE 8 und Jakarta EE 9 brachten zunächst keine weiteren neuen Features, sondern wurden lediglich dazu verwendet, den Umzug weg von Oracle hin zur Eclipse Foundation zu realisieren und damit einhergehend die Namespaces von javax.* auf jakarta.* zu migrieren. Auch der Sprung auf die vor Jakarta EE 10 aktuelle Version 9.1 ist lediglich als Maintenance Release zu verstehen, das zwar die Unterstützung von Java SE 11 mit sich brachte, aber keine neuen Features.
Technisch ist also das bis dato aktuelle Jakarta EE 9.1 auf dem Stand von vor fünf Jahren. Dies ist der Grund, warum das jetzige Release 10 so sehnsüchtig erwartet wurde. Im Vordergrund steht dabei die Frage, ob man in Zukunft auch in hochdynamischen Umgebungen wie der Cloud noch auf den Enterprise-Java-Standard setzen kann. CDI Lite und das Core Profile sollen in der neuen Version die Grundlage schaffen, Jakarta-EE-Services zukünftig ohne den Ballast eines Application-Servers schlank in einer Cloud-nativen Umgebung zu betreiben.
Bereits mit CDI 2.0 und somit als Teil von Java EE 8 wurde die CDI-Spezifikation (Contexts and Dependency Injection) in die Bereiche Core CDI, CDI in Java SE und CDI in Java EE unterteilt. Während der Bereich Core CDI die grundlegende Funktionsweise von CDI spezifiziert, definieren die anderen beiden Bereiche zusätzliche Features für die jeweiligen Umgebungen Java SE und Java EE.
Die neue Spezifikation CDI 4.0 geht noch einen Schritt weiter. Mit der Einführung von CDI Lite und CDI Full wird Core CDI weiter unterteilt. Während CDI Full als Basis für Anwendungsserver dient, kommt CDI Lite immer dann zur Anwendung, wenn es darum geht, ein schmales Runnable beispielsweise in Form eines Microservice zu erzeugen.
Damit stellt sich die Frage, warum es überhaupt noch CDI Full gibt. Der eben skizzierte Optimierungsschritt setzt den Verzicht auf Reflection zur Laufzeit voraus, was einige Restriktionen mit sich bringt. So darf eine auf CDI Lite aufsetzende Anwendung keine passivierbaren Scopes (Session und Conversation) anbieten. Auch Decorator- und Specializes-Annotationen sind tabu. Viel schwerer ins Gewicht fallen dürfte aber für die meisten Anwendungsfälle, dass in CDI Lite auch der Mechanismus der CDI Portable Extensions fehlt. Mit dessen Hilfe lässt sich auf einfache Art und Weise die Funktionalität des CDI-Containers via Drag-and-drop erweitern.
Fairerweise soll nicht unterschlagen werden, dass es für die Portable Extensions in CDI Lite ein Pendant namens Build Compatible Extension gibt. Es ist davon auszugehen, dass es viele der aktuell in der JEE-Community etablierten Portable Extensions künftig ebenso in Form von Build Compatible Extensions geben wird.
Die CDI-Lite-API ist für sich genommen bereits spannend, spielt aber ihre volle Stärke erst im Zusammenspiel mit einer weiteren Neuerung der Jakarta-EE-10-Spezifikation aus: dem Core Profile. Das neue Profile ist bewusst deutlich schlanker gehalten als die beiden bisherigen Varianten Full Profile und Web Profile und hat nur sieben APIs: Jakarta Annotations 2.1, Jakarta CDI 4.0 Lite, Jakarta Dependency Injection 2.0, Jakarta Interceptors 2.1, Jakarta JSON Processing 2.1, Jakarta JSON Binding 3.0 und Jakarta RESTful Web Services 3.1. Damit ist es besonders gut zum Entwickeln von Headless-Anwendungen wie Microservices geeignet.
Dank der geringen Größe des resultierenden Artefakts und der verkürzten Start-up-Phase durch die Anwendung der Compile-Time-Optimierung via CDI Lite entstehen Programme für hochdynamische und automatisch skalierende Systeme wie Cloud-native und Kubernetes-Anwendungen.
Bei einem genaueren Blick auf die APIs des Core Profile fällt auf, dass sie nahezu identisch mit den Jakarta-EE-APIs des Eclipse MicroProfile sind. Das kommt nicht von ungefähr: Es ist ein erklärtes Ziel beider Spezifikationen, dass zukünftige Versionen des Eclipse MicroProfile auf der aktuellen Version des Jakarta EE Core Profile aufsetzen sollen. Das führt zu mehr Kompatibilität zwischen beiden. Zu den weiteren Kandidaten für eine künftige Kompatibilität mit dem Jakarta EE Core Profile gehören Helidon, Quarkus und Micronaut.
Die Möglichkeit, einzelne Funktionen gezielt asynchron und somit non-blocking auszuführen, ist ein wichtiger Baustein zeitgemäßer Softwarearchitekturen. In Jakarta-EE-Anwendungen ließ sich das bisher deklarativ nur innerhalb von EJBs (Enterprise Java Beans) realisieren. Außerhalb davon musste man dagegen auf den ManagedExecutorService zurückgreifen und den asynchronen Task manuell anstoßen.
Die aktuelle Version 3.0 der Concurrency-API ermöglicht nun auch CDI-Beans, einzelne Methoden deklarativ als asynchron zu markieren und damit gezielt nebenläufig ablaufen zu lassen. Dazu dient die neue Annotation @Asynchronous aus dem Package jakarta.enterprise. concurrent. Achtung: Das Package ja karta.enterprise.ejb enthält eine Annotation mit demselben Namen. Als optionaler Parameter dient der zu nutzende Threadpool.
Anders als die beiden bisherigen Ansätze, die lediglich Methoden unterstützen, die das 2004 mit Java 5 eingeführte und somit in die Jahre gekommene Future zurückgeben, erlaubt die neue @Asynchronous-Annotation Methoden mit den Rückgabewerten Completion Stage und CallableFuture. Asynchrone Tasks können auf die Weise aneinandergereiht ausgeführt und ihre Rückgabewerte automatisch an die Folgetasks übergeben werden. Zusätzlich wird eine sinnvolle Fehlerbehandlung in dem nicht immer ganz trivialen asynchronen Kontext ermöglicht (Codebeispiel siehe Listing 1).
Die neue Annotation ist ausschließlich für den Einsatz im Kontext von CDI Managed Beans gedacht. Die Spezifikation erwähnt explizit, dass sie nicht innerhalb einer EJB zum Einsatz kommen darf und dass mit ihr annotierte Methoden nicht zusätzlich mit der gleichnamigen Annotation aus der MicroProfile-Fault-Tolerance-API versehen sein dürfen.
Dass die Concurrency-API bisher dem Jakarta EE Full Profile zugeordnet war, hat immer wieder zu Diskussionen geführt. Es war nicht nachvollziehbar, warum Anwendungen für das Web Profile die gezielte asynchrone Ausführung von Tasks nicht nutzen sollten. Mit der aktuellen Version 3.0 wechselt die API in das Web Profile.
Auch Jakarta JPA 3.1 bringt einige interessante Neuerungen mit sich. Künftig lassen sich UUIDs als Basistypen verwenden und können somit unter anderem als Primärschlüssel inklusive passender ID-Generator-Strategie dienen (Listing 2). Zwar erlaubten bisher sowohl Hibernate als auch EclipseLink das Vorgehen über proprietäre Ergänzungen, aber es war nicht via JPA-Spezifikation standardisiert.
Die JPA Query Language und Criteria- API bringen ebenfalls Ergänzungen mit. Mit EXTRACT lassen sich numerische Teile eines Datums YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE und SECOND extrahieren. Die neuen Datumsfunktionen LOCAL DATE, LOCAL TIME, LOCAL DATE TIME erlauben das Handling von Local-Date-und -Time-Klassen aus dem java.time- Package. Die numerischen Funktionen bringen als Erweiterungen die selbsterklärenden Funktionen CEILING, EXP, FLOOR, LN, POWER, ROUND und SIGN mit.
Zur Authentisierung über Drittanbieter wie Google, Facebook oder Twitter bringt die Jakarta-Security-API 3.0 einen neuen Authentifizierungsmechanismus auf Basis von OpenID Connect. Grundlage dafür ist der OpenID Connect Authorization Code Flow, der wiederum Teil der OpenID-Connect-Core-Spezifikation ist.
Listing 3 zeigt eine annotierte CDI-Bean zum Aktivieren der OpenID-Connect-Authentifizierung. Die für den Provider benötigten Metadaten finden sich in den Parametern der Annotation. Das Beispiel setzt dafür auf die Unified Expression Language.
Ist ein Log-in über den OpenID Connect Provider erfolgreich, wird automatisch eine Credential-Instanz erzeugt, die das vom Provider zurückgelieferte Token erhält. Dass dieses valide ist, stellt ein für OpenID Connect spezifischer Identity Store sicher. Da der OpenID Connect Provider keine Kenntnis über die Rollen und Gruppen aufseiten des Clients hat, lässt sich ein anwendungsspezifisches Mapping angeben. Die resultierenden Gruppen finden sich später in einer Instanz der Klasse CredentialValidation Result wieder. Der neue Mechanismus ist neben der reinen Authentifizierung dafür zuständig, das Ablaufen des Tokens zu überwachen und gegebenenfalls über RefreshToken automatisch ein neues Token anzufordern.
JAX-RS spezifiziert seit der 2008 veröffentlichten Version 1.0 Java SE als eine von mehreren Ablaufumgebungen für eine JAX-RS-basierte Anwendung. Leider hat die Spezifikation sich bisher darüber ausgeschwiegen, wie genau das zugehörige Bootstrapping auszusehen hat. Daher hat jeder Hersteller seine eigene proprietäre Lösung implementiert, um vom Applikationsserver unabhängige (Micro-) Services oder Runnables zu realisieren.
Mit der Version 3.1 standardisiert JAX-RS nun das Bootstrapping einer JAX-RS-Serveranwendung innerhalb von Java SE. Zwar sind die proprietären Lösungen weiterhin als Alternative erlaubt, aber der standardisierte Weg ist explizit der empfohlene, um für die Zukunft einen potenziellen Vendor Lock-in zu umgehen. Für einen einfachen Microservice-Endpunkt, der an Port 8080 lauschen soll, könnte ein Bootstrapping wie in Listing 4 aussehen.
Die Spezifikation Jakarta RESTful Web Services 3.1 bringt eine weitere erwähnenswerte Neuerung: das Handling von Multipart/Form-Data-Media-Type-Requests. Obwohl RESTful Web Services eine der populärsten APIs aus Jakarta EE ist, fehlte das Format merkwürdigerweise bisher. Entwicklerinnen und Entwickler waren gezwungen, auf ein mit @Multi PartConfig annotiertes Servlet zurückzugreifen, das immerhin seit Servlet-API 3.0 und somit Java EE 6 (2009) verfügbar ist. Alternativ mussten sie eine proprietäre Library nutzen.
Die neue Umsetzung sieht vor, dass Anwendungen in der @Consumes-Annotation signalisieren, dass sie einen Multipart-Request erwarten. Für den Zugriff auf die einzelnen Teile der Anfrage bietet die API zwei Optionen: Entweder lassen sich Anwendungen eine Liste von EntityPart-Objekten übergeben oder sie übergeben die Teile des Multipart-Request als einzelne Parameter und adressieren sie über deren Namen. Listing 5 zeigt die Methodendeklaration für beide Varianten.
Obwohl viele Anwendungen mittlerweile ein JavaScript-Frontend mit Frameworks wie Angular, React oder Vue.js nutzen, ist JSF nach wie vor weit verbreitet. Zum einen, weil es in den letzten zehn bis zwanzig Jahren Einzug in viele Enterprise-Anwendungen gehalten hat und dort weiterhin existiert. Zum anderen aber auch, weil nach wie vor etliche Jakarta-EE-Neuentwicklungen im Frontend auf JSF setzen, da für viele Developer im Java- Enterprise-Umfeld JSF einfacher zu verstehen und zu handhaben ist als seine JavaScript-basierten Alternativen. Daher wartet JSF ebenfalls mit einem Update der Spezifikation auf.
Die wohl auffälligste Änderung ist der Name: Ab sofort heißt die Spezifikation nicht mehr Java oder Jakarta Server Faces, sondern Jakarta Faces oder kurz Faces. Das ist der generellen Umbenennung von Java in Jakarta geschuldet und hilft außerdem dabei, sich des Kürzels JSF zu entledigen.
Neu ist eine API zum rein Java-basierten Aufbau von Facelets. In der Faces- Community gab es schon immer Vertreter des hundertprozentig Java-basierten Ansatzes. Eine von Facelet abgeleitete Klasse muss lediglich die @View-Annotation tragen und die gewünschten Lifecycle-Methoden implementieren. Listing 6 zeigt den Aufbau einer einfachen View mit der neuen API.
Derzeit ist die API noch minimalistisch gehalten. Abhängig von der Akzeptanz innerhalb der Faces-Community gibt es aber Pläne, sie weiter auszubauen. Mit der Annotation @ClientWindowScopes existiert ein neuer Managed Scope, der denjenigen, die DeltaSpike genutzt haben, bekannt sein dürfte. Der Scope ist in etwa vergleichbar mit @FlowScoped, ist aber nicht auf dedizierte Seiten begrenzt. Stattdessen startet er mit dem automatischen Erstellen einer jfwid zum Identifizieren des aktuellen Window und existiert so lange, wie die ID als Request-Parameter an die Folgeseiten weitergegeben wird.
Interessant sind nicht nur die Neuerungen, sondern auch, was künftig nicht mehr dazugehört. An erster Stelle ist dabei die Anbindung an Java beziehungsweise Jakarta Server Pages als View- Technik zu nennen. JSPs sind bereits seit JSF 2.0, das 2009 erschienen ist, als überholt (deprecated) markiert, da ihr Lebenszyklus nicht gut zum Lifecycle von Jakarta Faces passt. Die Herausnahme aus der Spezifikation ist somit nur konsequent. Ebenfalls entfernt wurden die proprietären JSF Managed Beans, die seit JSF 2.3 als deprecated markiert sind. In der Praxis haben die meisten Projekte sie vermutlich seit Jahren durch CDI Managed Beans ersetzt.
Wer sich in den vergangenen Monaten mit den Vorgängen innerhalb der Jakarta- Community auseinandergesetzt hat, wird in der Aufzählung der Jakarta-EE-APIs die eine oder andere Spezifikation vermissen. Neben den offiziellen Spezifikationen der drei Profiles existieren einige weitere Seitenprojekte, die es aus unterschiedlichen Gründen noch nicht in die Spezifikation geschafft haben, aber heiße Anwärter für spätere Versionen sind.
Vorneweg steht die Jakarta-Config- API, die das Verwalten und Bereitstellen von Konfigurationsinformationen vereinheitlichten soll. Die API ist stark an die gleichnamige API aus dem MicroProfile angelehnt, soll sie aber nach aktuellem Stand nicht ersetzen. Ursprünglich sollte die erste Version als Bestandteil von Jakarta EE 10 erscheinen, aber die Spezifikation brachte es innerhalb des recht strengen Zeitplans nicht zur Fertigstellung.
Ebenfalls nicht in das aktuelle Release geschafft hat es die Jakarta-NoSQL-Spezifikation, die eine API zum einfachen und standardisierten Zugriff auf NoSQL-Datenbanken bietet. Die Spezifikation ist nach wie vor „under construction“ und sicherlich ein heißer Kandidat für eins der kommenden Jakarta-EE-Releases. Weitere Kandidaten in der Warteschlange sind Jakarta Data, Jakarta MVC und Jakarta RPC.
Deutlich mehr als die Hälfte der in Jakarta EE 10 eingebetteten Spezifikationen bringen ein Major oder zumindest ein Minor Update mit. Auffällig dabei ist, dass viele der Neuerungen und Änderungen darauf setzen, Jakarta EE aus der Ecke der schwergewichtigen Enterprise- Anwendungen zu bewegen. Cloud-native ist auch für Jakarta EE die Zukunft. Dank Core Profile, CDI Lite und SE Bootstrapping lassen sich mit dem Java-Enterprise-Standard schlanke und schnell startende Services erstellen. Bisher waren dafür proprietäre Frameworks wie Helidon, Quarkus oder Micronaut erforderlich.
Die notwendige Security in der verteilten Welt liefert die neue Integration des OpenID Connect Flows in der Security-API. Aspekte wie Distributed Tracing, Health Checks, Metriken, Fault Tolerance oder Security Context Propagation fehlen bewusst in der Spezifikation. Hier setzt das Jakarta-Team auf das gute Zusammenspiel mit den APIs des ebenfalls bei der Eclipse-Community beheimateten MicroProfile.
Das Release bringt nicht nur viele Neuerungen mit, sondern räumt einige Altlasten auf. Unter anderem hat das Team die lange obsolet gewordenen EJB Entity Beans entsorgt. Damit können neue Projekte besser im Jakarta-EE-Ökosystem Fuß fassen, wovon die gesamte Community profitiert, da die Auswahl der Provider steigt.
Details zur Veröffentlichung finden sich in der Releaseankündigung bei der Eclipse Foundation (siehe ix.de/zx89). Wer Jakarta EE 10 ausprobieren möchte, findet in Eclipse GlassFish 7.0 M8, Payara 6 Alpha 4 und WildFly 27 Alpha 5 drei Implementierungen des neuen Standards. (ulw@ix.de)
Quellen
Releaseseite Jakarta EE 10: ix.de/zx89
iX 11/2022 S. 84