Zwei und Zwei ergibt eine neue Generation

Spring Boot 2.2: Die neuen Features in der Übersicht

Michael Simons

© Shutterstock / glamour

Spring Boot 2.2 ist da! Zu den Highlights der neuen Version gehört die Unterstützung für Java 13 und die Aktualisierung zahlreicher Bibliotheken. Michael Simons, Software Engineer bei Neo4j, hat für uns diese und alle weiteren Neuerungen eingehend beleuchtet.

Mehr als anderthalb Jahre nach Erscheinen meines Spring-Boot-Buches erschien nun Spring Boot 2.2.

Achtung! Dieser Artikel entstand bereits Ende August 2019, bis dato ist der fünfte Milestone von Spring Boot 2.2 veröffentlicht worden, Spring Framework 5.2 hat bereits die Release-Candidate-Phase erreicht. Die finale Version erschien Anfang Oktober – pünktlich zur SpringOne Plattform Konferenz.

Nachdem ich während der Veröffentlichung obigen Buches den mehr als umfangreichen Änderungen von Spring Boot 1.5 nach 2.0 quasi hinterher geschrieben habe, hielten sich grundsätzliche Änderungen in Spring Boot 2.1 in überschaubaren Grenzen. In meinen Augen waren das natürlich der Support für das Spring Framework 5.1 und Änderungen in der Default-Bean-Konfiguration: standardmäßig ist es seit Spring Boot 2.1 nicht mehr erlaubt, einmal definierte Beans in weiteren @Configuration-Klassen zu überschreiben.

Im Enterprise-Alltag fiel insbesondere auf, dass die JpaProperties keine Hibernate-spezifischen Einstellungen enthalten. Diese wanderten in HibernateProperties, inklusive neuer Präfixe für entsprechende Konfigurationsdateien. Auch hier hilft das Tooling (org.springframework.boot:spring-boot-properties-migrator).

Welche Java-Version für Spring Boot 2.2?

Spring Boot 2.1 brachte volle Unterstützung für Java 11 mit, blieb aber mit Java 8 kompatibel. Die Release-Kadenz von Java ist nunmehr halbjährlich, wie sieht es mit 2.2 aus? Das Spring-Team bei Pivotal verfolgt die Java Releases und testete den Milestone M5 bereits mit Java 13, im finalen Release ist die Unterstützung von JDK 13 und damit des aktuellen LTS Java Releases enthalten. Es wunderte mich zudem nicht, dass das Spring Framework mit 5.2 eine andere Version als Java 8 als minimale Anforderung hat.

API Experten Dossier 2019

SIND SIE BEREIT FÜR DIE API-REVOLUTION?

In über 30 Seiten beleuchten Experten APIs aus allen Blickwinkeln und teilen ihre Erfahrung, Ideen und Lösungsansätze mit Ihnen.
Sichern Sie sich jetzt kostenlos sieben Fachbeiträge und Interviews zu spannenden Themen wie dem Design, der Entwicklung und der Systemintegration von APIs.

 

Librarys

Jakarta EE

Jakata EE? Ist das nicht ein Artikel über Spring Boot? Natürlich, aber das Spring Framework und damit Spring Boot setzt natürlich auf offene, funktionierte Standards, unter anderem Java EE. Im Mai 2019 wurde bekannt, dass die Java Enterprise Edition (Java EE) nach dem Umzug zur Eclipse Foundation und der Umbenennung zu Jakarta EE noch weitere Aufgaben vor der Brust hat: Eine Einigung hinsichtlich Marken- und Namensrechten konnte nicht gefunden werden, der Name Java ist nicht nur als Java EE schützenwert, sondern auch als Teil der API-Spezifikation. Das heißt, existierende javax-Packages müssen unter dem Jakarta-EE-Mantel eingefroren werden und dürfen nicht weiterentwickelt werden. Weiterentwicklung darf nur unter anderem Namen erfolgen. Finden Änderungen und Erweiterungen statt, muss das Package umbenannt und das API angepasst werden. Bestehende Java-EE-Spezifikationen im javax-Namensraum sind mit zusätzlichen Auflagen verbunden.

Für alles nach Jakarta EE 8 besteht als realistische Möglichkeit nur, schnellstmöglich alle Spezifikationen und APIs von javax zu jakarta zu portieren. Genau das passiert und Spring Boot bzw. das Spring Framework ziehen an dieser Stelle mit: Soweit möglich werden Jakarta-EE-Spezifikationen eingesetzt, die bereits portiert sind. Stand heute sind das Jakarta Mail und Jakarta EL.

Allgemeine Betrachtungen

Die ursprünglichen Ziele Spring Boots (einfache Konfigurierbarkeit von Spring-Framework-Anwendungen und Erstellung ausführbarer Anwendungen) werden meiner Meinung nach immer mehr von Dependency-Management „überschattet“. Spring Boot ist enorm erfolgreich, unter anderem weil es viele Abhängigkeiten im Kontext des Spring-Ökosystems konfiguriert. Umgekehrt rückt der Erfolg Spring Boots in den Fokus von Herstellern, die möchten, dass ihr Produkt möglichst gut in der Plattform funktioniert.

Die Liste gemanagter Dependencies wächst und wächst und mit ihr die Menge der Librarys, die bei einem Versionssprung ebenfalls aktualisiert werden müssen. Hervorgehoben werden in der Regel das Spring Framework selbst, Spring Security, Hibernate und JUnit. Spring Boot 2.1 machte den Spring auf Hibernate 5.3, Spring Boot 2.2 setzt auf Hibernate 5.4. In den Release Notes fallen insbesondere AssertJ 3.12 und Hamcrest 2.1 mit Breaking Changes auf, weitere erwähnenswerte Upgrades sind:

  • Artemis 2.7
  • Elasticsearch 6.7.2
  • Hazelcast 3.12
  • Jedis 3.1
  • Jersey 2.29
  • Kafka 2.2
  • Kotlin 1.3.31
  • Lombok 1.18.8
  • Netty 4.1.36
  • Solr 8.0
  • Tomcat 9.0.19

Die Liste aktualisierter Spring-eigener Module ist ähnlich umfangreich:

  • Spring AMQP
  • Spring Batch
  • Spring Data Moore
  • Spring Framework
  • Spring HATEOAS
  • Spring Integration
  • Spring Kafka
  • Spring Security
  • Spring Session Corn
  • Reactor Dysprosium

In den meisten Fällen hängt Spring Boot von diesen Projekten hinsichtlich Autokonfiguration und ähnlichem ab. Teilweise bestehen aber auch umgekehrte Abhängigkeiten, meistens über das Spring Framework selbst. Natürlich bringen die einzelnen Spring-Projekte wieder Abhängigkeiten mit sich, die Liste der zu lesenden Changelogs wird gefühlt immer größer.

Ich vertrete nach wie vor die Meinung, dass Spring Boot die vernünftigste Lösung ist, im Jahr 2019 ein neues Spring-Projekt aufzusetzen, aber die Form des Projektes gilt es zu überdenken: Multi-Module-Projekte haben sich für mich als ausgesprochen schwierig erwiesen und zwar hinsichtlich der Wartbarkeit. Soll in einem Module, beispielsweise dem Datenbank-Layer – und das gilt unabhängig davon, ob dieser JPA heißt oder es sich um das von mir gepflegte Spring Data Neo4j bzw. deas Neo4j-OGM-Modul handelt –, nur Spring Data aktualisiert werden, so bedeutet dies, dass ich damit auch das Spring Framework aktualisieren muss und damit alle Abhängigkeiten auf vom Framework unterstützte Versionen heben muss. Ein oftmals erheblicher Aufwand, der zwar geleistet werden kann, aber mit der Größe der Anwendungen und der Anzahl der Module wächst. Hier einen vernünftigen Architekturschnitt zu finden, ist wichtiger denn je.

Performance

Neue Frameworks wie Micronaut und Quarkus, die – frei von über 15 Jahren Entwicklung – verschiedene Aspekte eines Anwendungsframeworks neu denken konnten und tatsächlich auf Microservices fokussiert sind, haben das Java-Umfeld in den letzten Monaten aufgewirbelt. Zusammen mit der GraalVM, die es – neben vielen anderen coolen Dingen – erlaubt, native Binarys aus Java-Programmen zu erzeugen, rücken so Dinge wie Startup-Zeit und auch Speicherverbrauch noch weiter in den Fokus.

Spring Boot und das Spring Framework adressieren in den Versionen 2.2 und 5.2 viele dieser Punkte. Die eingebaute automatische Konfiguration (siehe dazu einen meiner Vorträge) verwendet nun keine Proxys mehr und Injection Points werden nur dann tatsächlich angewandt, wenn ein ensprechendes Bean erzeugt wird.

Gerade Quarkus hat durch Anpassungen in Hibernate extrem viel Performance gewinnen können. Gleiches gilt für Spring-Anwendungen: Hibernates Entity Scanning wird in Spring Boot 2.2 gar nicht mehr genutzt, sondern nur noch die von Spring bereitgestellte Persistence Unit. Dies ist im Übrigen ein Ansatz, den wir mit unserem Next-generation Spring-Data-Modul für Neo4j ebenfalls verfolgen. Wer mehr darüber lesen möchte, sollte mal in den Blog Post von Gerrit Meier schauen: Welcome SDN/RX.

Eine Opt-in-Verbesserung ist die Möglichkeit, alle Beans lazy zu initialisieren. Durch Setzen von spring.main.lazy-initialization auf true wird das Feature eingeschaltet. Der Start kann schneller sein, der erste HTTP Request wird hingegen langsamer sein. Weiterhin fallen einige mögliche Fehler erst nach der vollständigen Initialisierung und nicht bereits beim Start auf. Funktionen wie Tomcats MBean Registry, die zwar nützlich sind, aber oft nicht genutzt werden, sind per Default abgeschaltet. Das reduziert Speicherverbrauch.

Erweitertes, reaktives Programmiermodell

Reaktive Transaktionen

Die Spring Data Stores MongoDB und Redis unterstützen nun seit einiger Zeit reaktive Programmierung. Mit R2DBC, dem reactive relational database access, sowie serverseitigen reaktiven Transaktionen innerhalb der Graphendatenbank Neo4j 4.0 und auch in MongoDB wurde der Ruf nach applikationsseitigem Support für reaktive Transaktionen unüberhörbar laut. Mark Paluch schrieb bereits im Mai über das zu diesem Zeitpunkt im Spring Framework veröffentliche Feature: Reactive Transactions with Spring.

Es geht bei diesem Feature eben nicht um modulspezifische Lösungen wie .inTransaction oder ähnliches, sondern um die Unterstützung des bekannten deklarativen Ansatzes (@Transactional) sowie ein Pendant zum TransactionTemplate. Spring 5.2 bietet ab 5.2 M2 ein SPI für ReactiveTransactionManager an. Auf Basis dieses APIs kann @Transactional auf alle Methoden angewandt werden, die reaktive Datentypen (Flux<> und Mono<>) zurückgeben. Der TransactionalOperator ist das Pendant zum TransactionTemplate.

Reaktive Transaktionen speichern ihre Resourcen – Status der Transaktion und anderes – nicht in einem ThreadLocal, sondern im Kontext von Project Reaktor. Das ist insofern erwähnenswert, da es bedeutet, das reaktive Transaktionen mit Spring nur mit reaktiven Datentypen aus Project Reactor, nicht aber mit RX Java 2 funktionieren, obwohl RX Java 2 weiterhin von Spring unterstützt wird. Deklarative, reaktive Transaktionen sowie der TransactionalOperator werden von folgenden Spring-Data-Modulen unterstützt:

  • R2DBC mit Spring Data R2DBC ab 1.0 M2
  • MongoDB mit Spring Data MongoDB ab 2.2 M4
  • Neo4j 4.0 mit Spring Data Neo4j RX ab 1.0.0-beta01

SDN/RX wurde Ende August von Gerrit Meier öffentlich vorgestellt: Welcome SDN⚡️RX. Dieser englische Post von Mark Paluch ist in diesem Zusammenhang wärmstens zu empfehlen: Reactive Relational Database Transactions.

Reaktive Transaktionen sind ein bemerkenswertes Feature, aber weder einfach in der Erstellung, noch einfach in der Benutzung, auch wenn der deklarative Ansatz das Gegenteil suggeriert. Ich selbst bin gespannt, welchen Anklang es – gerade im relationalen Enterprise-Umfeld – findet und mit welchen Erwartungshaltungen es eingesetzt werden wird.

RSocket Server

RSocket ist ein binäres Protokoll auf Anwendungsebene, das die Semantik von reaktiven Datenströmen über binäre Transportprotokolle wie TCP und WebSocket implementiert. RSocket ermöglicht verschiedene Formen reaktiver Programmierung:

  • Request/Response (stream of one)
  • Request/Rtream (stream of many)
  • Fire and Forget (no response)
  • Channel (bi-directional streams)

RSocket wird direkt vom Messaging Modul des Spring Frameworks unterstützt, sowohl auf Server- als auch auf Client-Site. Durch spezielle @Controller, die @MessageMapping einsetzen, kann es analog zu HTTP-Controllern genutzt werden, ohne dass ein neues Paradigma für die Programmierung erlernt werden müsste. Spring Boot 2.2 wird dies mit automatischer Konfiguration unterstützen.

Wichtige Aspekte hier sind, in welcher Art und Weise Payloads serialisiert und wieder deserialisiert werden. Es stehen CBOR und JSON zur Verfügung. Der Server benötigt entweder einen aktiven WebFlux-Server oder eine explizite Konfiguration eines eingebetteten RSocket-Servers. Ebenfalls neu ist ein RSocketRequester, der innerhalb von Services genutzt werden kann, um mit RSocket-Servern zu kommunizieren.

Weitere erwähnenswerte Features

Freemarker, eine Template-Sprache, ermöglicht die Nutzung von .ftl und .ftlh. In .ftl-Dateien wird HTML in interpolierten Blöcken (${}) per Default nicht escaped. Das ist unsicher und .ftlh-Dateien drehen das Verhalten entsprechend um. Spring Boot 2.2 wird .fthlh als Default-Erweiterung für Freemarker-Dateien verwenden. Konstruktor-Injection ist kein neues Feature, der Support für @DefaultValue, @DateTimeFormat und andere hingegen schon.

Nach langer Zeit ist Spring HATEOAS endlich aus der Alpha heraus und in Version 1 veröffentlicht worden. Spring Boot 2.2 wird Spring HATEOAS vollumfänglich unterstützen. Neo4j 3.4+ hat hingegen nicht nur vollständigen Support für alle wichtigen Java 8 Datums- und Zeittypen, sondern auch für räumliche Datentypen. Spring Boot 2.2 konfiguriert OGM nun entsprechend, falls die notwendigen Abhängigkeiten auf dem Klassenpfad sind. Ebenso wurde die eingebettete Variante von Neo4j in das Dependency-Management mit aufgenommen. Dies vereinfacht das Testen von Neo4j-Anwendungen.

Zu guter Letzt wurden die Konfigurationseigenschaften logging.file und logging.path als „deprecated“ markiert und sinnvollerweise durch logging.file.name beziehungsweise logging.file.path ersetzt.

Übersicht der verfügbaren Changelogs

Grundlage für den Artikel sind – abgesehen von eigener Arbeit – die öffentlich verfügbaren CHangelogs. Ich kann nur empfehlen, die entsprechenden Wiki-Pages auf GitHub zu verfolgen, um für ein Upgrade gewappnet zu sein. Ebenso möchte ich die Empfehlung des Spring-Teams wiederholen: Ein Upgrade sollte in Phasen erfolgen. Falls die Anwendung noch auf Spring Boot 2.0 basiert, sollte zuerst auf 2.1, dann auf 2.2 aktualisiert werden.

Geschrieben von
Michael Simons
Michael Simons
Michael ist Vater, Ehemann, Radfahrer und Java Champion. Er ist Autor des ersten deutschen Buchs über Spring Boot 2 und Spring 5. Michael arbeitet im Spring Data Team bei Neo4j. Als Mitgründer und Leiter der EuregJUG in Aachen ist Michael seit langem in der Community-Arbeit engagiert.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
4000
  Subscribe  
Benachrichtige mich zu: