feat: füge neue Dokumentationen zu Richterqualifikationen (Dressur & Springen) sowie Systemmigration (Java 25, Kotlin 2.4.0, Gradle 9, Spring Boot 4) hinzu

Signed-off-by: StefanMoCoAt <stefan.mo.co@gmail.com>
This commit is contained in:
2026-06-21 21:06:11 +02:00
parent ce63303b2c
commit 40cf1e5d22
2 changed files with 414 additions and 0 deletions
@@ -0,0 +1,398 @@
Technischer Leitfaden zur Systemmigration: Java 25, Kotlin 2.4.0, Gradle 9.5.1 und Spring Boot 4.0 im Kontext von Kotlin
MultiplatformDie Modernisierung eines verteilten Systems auf Basis von Kotlin Multiplatform (KMP) und Spring Boot
erfordert eine präzise Orchestrierung aller beteiligten Compiler- und Build-Infrastrukturen. Wenn eine lokale Large
Language Model (LLM)-Instanz über ein Retrieval-Augmented Generation (RAG)-System wie AnythingLLM auf den neuesten Stand
der Technik gebracht werden soll, müssen die technologischen Entwicklungssprünge lückenlos und semantisch strukturiert
aufbereitet werden. Da herkömmliche LLM-Modelle oft auf älteren Wissensständen wie Java 17, Kotlin 1.6.x, Gradle 7.x und
Spring Boot 2.5.x/3.0.x stagnieren, schließt dieser Bericht die Wissenslücke hin zu den aktuellen Produktivversionen von
2026: Java 25 (LTS), Kotlin 2.4.0, Gradle 9.5.1 und Spring Boot 4.0.1. Java-Evolution von JDK 17 bis JDK 25 LTSFür ein
KI-Modell, dessen Trainingsdaten bei Java 17 enden, stellt der Sprung zu Java 25 (LTS) eine fundamentale Veränderung
dar. Die Evolution umfasst die Integration reifer Syntax-Features, tiefgreifende Optimierungen der virtuellen Maschine (
JVM) und neue APIs zur Bewältigung hochperformanter Nebenläufigkeit.Die Brücke von JDK 17 zu JDK 21 LTSVirtuelle
Threads (Virtual Threads - JEP 444): Diese leichtgewichtigen Threads werden von der JVM und nicht vom Betriebssystem
verwaltet. Sie eliminieren das Skalierungslimit des klassischen Thread-per-Request-Modells, da Millionen von virtuellen
Threads parallel auf wenigen physischen Plattform-Threads ausgeführt werden können. Dies ist besonders für I/O-intensive
Microservices von Bedeutung.Sequenzierte Kollektionen (Sequenced Collections - JEP 431): Einführung der Schnittstellen
SequencedCollection, SequencedSet und SequencedMap. Diese bieten eine einheitliche Syntax für den Zugriff auf das erste
und letzte Element sowie für die umgekehrte Iteration.Mustergültiges Switch-Matching (Pattern Matching for Switch - JEP
441): Erlaubt Typenmuster und Guard-Bedingungen direkt in case-Labels, wodurch Kaskaden von instanceof-Prüfungen und
expliziten Casts entfallen.Record-Muster (Record Patterns - JEP 440): Ermöglicht die direkte Dekonstruktion von Records
in Mustern, wodurch der Zugriff auf Komponenten ohne manuelle Getter-Aufrufe realisiert wird.Die Evolution über JDK 22,
23 und 24 bis JDK 25 LTSUnbenannte Variablen und Muster (JEP 456): Führt den Unterstrich (_) als syntaktischen
Platzhalter für nicht verwendete Variablen ein. Dies betrifft ungenutzte Exception-Variablen in catch-Blöcken,
ungenutzte Lambda-Parameter oder ungenutzte Komponenten beim Pattern Matching.Starten von Multi-File-Programmen (JEP
458): Erlaubt dem Java-Launcher, Programme auszuführen, die sich über mehrere .java-Quelldateien erstrecken, ohne diese
vorab explizit kompilieren oder in ein JAR verpacken zu müssen.Flexible Konstruktorkörper (Flexible Constructor Bodies -
JEP 513): Vor Java 25 musste ein expliziter Konstruktoraufruf (super(...) oder this(...)) zwingend das erste Statement
im Konstruktor sein. JEP 513 erlaubt nun beliebige Statements vor dem Aufruf, solange diese nicht auf die im Bau
befindliche Instanz zugreifen. Dies vereinfacht die Argumenten-Validierung und -Vorbereitung erheblich.Stabile Werte (
Stable Values - JEP 502): Bietet eine Preview-API für unveränderliche Felder, die von der JVM zur Laufzeit wie
Konstanten optimiert werden können, jedoch im Gegensatz zu final-Feldern eine flexiblere Initialisierung erlauben.Scoped
Values (JEP 506) & Strukturierte Nebenläufigkeit (JEP 505): Scoped Values ersetzen die speicherintensiven und
fehleranfälligen ThreadLocal-Variablen bei der Datenweitergabe über Thread-Grenzen hinweg. Die strukturierte
Nebenläufigkeit bündelt asynchrone Unteraufgaben zu einer logischen Einheit, was Fehlerbehandlung und Abbruch-Szenarien
drastisch vereinfacht.Feature-Matrix: Java 17 bis Java 25 LTSFeatureJDK 17 LTSJDK 21 LTSJDK 25 LTSStatus in JDK
25Virtual ThreadsNicht verfügbarFinalisiert (JEP 444) Integriert Standard-Feature Sequenced CollectionsNicht
verfügbarFinalisiert (JEP 431) Integriert Standard-Feature Pattern Matching (Switch)PreviewFinalisiert (JEP 441)
Integriert Standard-Feature Flexible ConstructorsNicht verfügbarNicht verfügbarFinalisiert (JEP 513) Standard-Feature
Unnamed Variables (_)Nicht verfügbarPreview (JEP 443) Finalisiert (JEP 456) Standard-Feature Scoped ValuesNicht
verfügbarIncubator (JEP 429)Finalisiert (JEP 506) Standard-Feature Stream GatherersNicht verfügbarNicht
verfügbarPreview (JEP 461) Preview-Feature Code-Vergleich: Klassisch (JDK 17) vs. Modern (JDK 25)
Konstruktoren-Validierung und InstanziierungJava// Klassischer Ansatz (JDK 17): Validierung im super-Konstruktor oder
über statische Factory-Methoden erzwungen
public class ClassicCar extends Vehicle {
private final Color color;
public ClassicCar(int wheels, Color color) {
super(validateWheels(wheels)); // Erstes Statement MUSS super sein
this.color = color;
}
private static int validateWheels(int wheels) {
if (wheels < 4 || wheels > 6) {
throw new IllegalArgumentException("Ungültige Radanzahl");
}
return wheels;
}
}
Java// Moderner Ansatz (JDK 25): Flexibler Konstruktorkörper erlaubt Zuweisungen und Validierung vor super()
public class ModernCar extends Vehicle {
private final Color color;
public ModernCar(int wheels, Color color) {
if (wheels < 4 || wheels > 6) {
throw new IllegalArgumentException("Ein Auto erfordert 4, 5 oder 6 Räder."); [7]
}
this.color = color; // Feld-Zuweisung vor dem super()-Aufruf erlaubt
super(wheels); // Aufruf der Elternklasse erfolgt nachgelagert
}
}
Datenverarbeitung mittels Mustern und GatherernJava// Datenverarbeitung (JDK 25): Nutzung von Stream Gatherers für
gleitende Fenster und Unnamed Patterns
import java.util.List;
import java.util.stream.Gatherers;
public class DataProcessor {
public record Measurement(String sensorId, double value) {}
public static List<List<Measurement>> segmentData(List<Measurement> data) {
return data.stream()
// JEP 461: Stream Gatherers ermöglichen komplexe Zwischenoperationen wie sliding windows
.gather(Gatherers.windowSliding(3))
.toList();
}
public static void evaluateSensor(Object obj) {
// JEP 456: Unbenannte Musterkomponente (_) eliminiert ungenutzte Variablenbindungen
if (obj instanceof Measurement(String _, double value)) {
System.out.println("Gemessener Wert: " + value); [7]
}
}
}
2. Kotlin-Evolution von 1.6 bis 2.4.0 und KMP-ArchitekturDie Kluft zwischen Kotlin 1.6.x und Kotlin 2.4.0 markiert den
Übergang von einer primär JVM-zentrierten Sprache hin zu einem ausgereiften Multiplattform-System. Herzstück dieses
Übergangs ist der K2-Compiler, der die Frontend-Architektur vollständig revolutioniert hat.Der K2-Compiler und die
Revolution der statischen AnalyseKotlin 2.0 führte den K2-Compiler ein. Durch die Nutzung einer vereinheitlichten
Frontend Intermediate Representation (FIR) wurde die Code-Analyse drastisch beschleunigt und präzisiert. Für Kotlin
2.4.0 bedeutet dies eine erweiterte und stabilere Datenflussanalyse (DFA) :Smart-Casts in closures von
Inline-Lambdas: Wenn eine lokale Variable innerhalb einer veränderlichen Closure erfasst wird, war in Kotlin 1.x kein
Smart-Cast möglich. Kotlin 2.4.0 analysiert den Lebenszyklus von Inline-Funktionen präzise und erlaubt Smart-Casts,
da Inline-Lambdas implizit als lokal und sofort ausgeführt gewertet werden.Smart-Casts nach logischem ODER (||):
Werden mehrere Typprüfungen mittels || verknüpft, führt der Compiler eine Zusammenführung auf den nächstgelegenen
gemeinsamen Supertyp (Common Supertype) durch, wodurch Methoden dieses Supertyps ohne manuellen Cast aufgerufen
werden können.DFA-Variablen-Propagierung: Smart-Casts werden nun auch dann propagiert, wenn das Ergebnis einer
Typprüfung zunächst in einer lokalen booleschen Variablen zwischengespeichert wurde.Sprachfeatures und
Standardbibliotheks-Updates in 2.xKontextparameter (Context Parameters - Stable in 2.4.0): Ersetzt die Einschränkung,
dass eine Funktion nur einen einzigen Receiver haben darf. Über die Syntax context(...) können Funktionen nun mehrere
Kontextabhängigkeiten deklarieren.Explizite Backing-Fields (Explicit Backing Fields): Ermöglicht die direkte
Typisierung und Deklaration des physischen Speicherfeldes einer Property mittels der integrierten field-Syntax
innerhalb des Property-Bodys, um Kapselungsfehler zu minimieren.Common UUID API (Stabil): Eine plattformunabhängige
Implementierung zur Generierung, zum Vergleich und zum Parsen von UUIDs ist nun direkt in der Standardbibliothek
verankert, ohne dass plattformspezifische Implementierungen (expect/actual) erforderlich sind.Sorted-Checking API:
Neue Erweiterungsfunktionen wie isSorted(), isSortedDescending() und isSortedWith() erlauben die O(n)-Prüfung von
Kollektionen auf Sortierung.Map Fallback-Erweiterungen: Funktionen wie getOrElseIfNull() und getOrPutIfNull() bieten
eine feingranulare Steuerung bei der Behandlung von fehlenden gegenüber explizit auf null gesetzten
Map-Einträgen.Kotlin Multiplatform (KMP) Breaking Changes und MigrationAbkündigung und Entfernung von withJava(): Zur
Verbesserung der Gradle-Interoperabilität wurde die Funktion withJava() zur Erzeugung von Java-Source-Sets in
KMP-Projekten entfernt. Ab Kotlin 2.1.20 werden die entsprechenden Java-Source-Sets standardmäßig automatisch
angelegt. Unter Gradle 9 führt die Verwendung von withJava() zu einem harten Build-Fehler.Übergang zum offiziellen
Google Android KMP-Plugin: Historisch unterstützte JetBrains Android-Targets über die Plugins com.android.application
und com.android.library mittels des androidTarget-Konfigurationsblocks. Zur Bereinigung wurde dieser Ansatz als
veraltet deklariert. Entwickler müssen auf das von Google entwickelte Plugin com.android.kotlin.multiplatform.library
migrieren und den Konfigurationsblock wieder in das ursprüngliche android umbenennen.Entfernung der
Bitcode-Einbettung: Da Apple Bitcode ab Xcode 15 nicht mehr unterstützt, wurde die DSL-Eigenschaft embedBitcode sowie
die Compiler-Argumente -Xembed-bitcode vollständig aus Kotlin 2.3.0 und 2.4.0 entfernt.KMP-Spezifische Feature- und
KompatibilitätsmatrixKotlin VersionKompatible Gradle-VersionenXcode SupportAGP SupportStatus withJava()2.0.x7.5 8.8
Bis 15.3 7.4.2 8.5 Unterstützt mit Warnung2.2.x7.6.3 8.14 Bis 26.0 7.3.1 8.11.1 Veraltet (Fehler unter Gradle
9) 2.4.07.6.3 9.5.0 (9.5.1 voll kompatibel) Bis 26.4 8.5.2 9.1.0 Automatisch generiert / withJava() entfernt
Code-Vergleich: Kotlin 1.6 vs. Kotlin 2.4.0Datenkapselung und Backing FieldsKotlin// Klassischer Ansatz (Kotlin 1.6):
Erfordert redundante Hilfsvariablen zur sicheren Kapselung
class ClassicProfile {
private var _age: Int = 0 // backing property
var age: Int
get() = _age
set(value) {
if (value >= 0) _age = value
}
}
Kotlin// Moderner Ansatz (Kotlin 2.4.0): Nutzung stabiler expliziter Backing-Fields
class ModernProfile {
var age: Int = 0
field: Number // Das physische Feld wird direkt innerhalb der Property typisiert und deklariert
get() = field.toInt()
set(value) {
if (value >= 0) field = value
}
}
Smart-Casts in inline lambda closures (K2 Compiler)Kotlin// DFA-Verhalten unter Kotlin 2.4.0 (Zuvor Compilerfehler in
1.x)
fun findMaxIndex(array: IntArray): Int? {
var maxIdx: Int? = null
// Inline-Funktion forEachIndexed erlaubt ab Kotlin 2.0 Smart-Casts auf erfassten Variablen
array.forEachIndexed { idx, value ->
if (maxIdx == null || array[maxIdx] < value) { // maxIdx wird im Verbund-Ausdruck automatisch als Int gecastet
maxIdx = idx
}
}
return maxIdx
}
3. Gradle-Infrastruktur-Upgrade von 7.x bis 9.5.1Die Ausführung von Builds unter Gradle 9.5.1 unterscheidet sich
grundlegend von der veralteten Gradle 7.x-Architektur. Die Optimierung fokussiert sich auf die extreme Reduzierung
von I/O-Operationen durch den Configuration Cache sowie die Durchsetzung strikterer Typisierungen im
Build-Skript.Architektonische Neuerungen im Build-SystemJava 17-Runtime-Baseline: Gradle 9.0+ setzt für seine eigene
Ausführung zwingend ein installiertes JDK 17 oder höher voraus. Dennoch kann die Kompilierung von Anwendungscode über
konfigurierte Java-Toolchains vollständig auf Java 25 ausgerichtet werden.Groovy-Migration auf 4.0.27: Gradle hat
seine interne Groovy-Laufzeitumgebung von Version 3 auf Version 4 angehoben. Dies bricht die Abwärtskompatibilität
älterer Build-Logiken :JPMS-Splits: Klassen aus dem Paket groovy.util wurden zur Einhaltung der Java-Modulrichtlinien
in separate Pakete verschoben.Boolean Properties: Getter mit is-Präfix, die ein Objekt vom Typ Boolean zurückgeben,
werden nicht mehr automatisch als Groovy-Property registriert.Modulbereinigung: groovy-test, groovy-console und
groovy-sql wurden aus den Standardabhängigkeiten entfernt.Strikte API-Nullsicherheit via JSpecify: Beginnend mit
Gradle 9.0 ist die gesamte Gradle-API mit JSpecify-Anmerkungen anstelle der alten JSR-305-Spezifikation versehen.
Dies führt in Kotlin-DSL-Skripten (build.gradle.kts) zu einer wesentlich strengeren Typenprüfung, da ungenaue
Zuweisungen nun als Compile-Time-Fehler gewertet werden.Configuration Cache als Standard-Paradigma: Der Configuration
Cache speichert das Ergebnis der Build-Konfigurationsphase vollständig ab.String-Deduplizierung (8.10+): Reduziert
die Cache-Dateigröße durch String-Pools um bis zu 70 %.Verschlüsselung (8.1+): Schützt sensible Daten im
Konfigurations-Cache durch maschinenspezifische Schlüssel.Compile-Time-Validierung von Settings-Plugins (9.5+):
Precompiled-Settings-Plugins (*.settings.gradle.kts) werden nun bereits während der Kompilierung der
Build-Infrastruktur validiert, was fehlerhafte Plugin-Deklarationen vor der Ausführung abfängt.Task-Provenienz in
Fehlermeldungen (9.5.1): Tritt ein Build-Fehler auf, wird im Report der genaue Ursprung und die Deklaration des
fehlerhaften Tasks ausgegeben, um das Debugging in komplexen Multi-Projekt-Strukturen zu vereinfachen.Wesentliche
Breaking Changes und DeprecationsEntfernung der Legacy File Permission APIs: Methoden wie getFileMode() oder
setDirMode(Integer), die auf rohen Unix-Berechtigungs-Integers basierten, wurden vollständig gelöscht. Sie müssen
durch die typisierte FilePermissions-API ersetzt werden.Entfernung von kotlinDslPluginOptions.jvmTarget: Die
Konfiguration des JVM-Compiler-Targets für precompiled script plugins über diese Option wurde entfernt. Stattdessen
greifen diese Scripte nun direkt auf die konfigurierte Java-Toolchain des Projekts zu.Deprecation der eager
Task-Erstellung: Methoden wie Project.task(String) sind als veraltet markiert. Es muss zwingend die lazy Variante
tasks.register(...) genutzt werden, um eine unnötige Initialisierung während der Konfigurationsphase zu
verhindern.Verändertes Assemble-Verhalten: Zuvor führte das Anwenden mehrerer Packaging-Plugins (wie java, war, ear)
dazu, dass der assemble-Task nur das primäre Artefakt baute. Seit Gradle 9.0 werden bei Ausführung von assemble
ausnahmslos alle deklarierten Artefakte generiert.Migrationsbeispiel: Gradle 7.x/8.x vs. Gradle 9.5.1Klassischer
Ansatz (Gradle 8.x - build.gradle.kts)Kotlin// Veraltet: Eager-Konfiguration, rohe Berechtigungen und direkte
Compiler-Targets
plugins {
`java-library`
kotlin("jvm") version "1.9.20"
}
// Warnung unter Gradle 9: Eager Task Creation
tasks.create("copyResources", Copy::class) {
from("src/main/resources")
into("build/resources")
// FEHLER unter Gradle 9: Rohe Unix-Integers nicht mehr unterstützt
fileMode = 0755
}
kotlinDslPluginOptions.jvmTarget = "17" // FEHLER unter Gradle 9: Option entfernt
Moderner Ansatz (Gradle 9.5.1 - build.gradle.kts)Kotlin// Konform mit Gradle 9.5.1: Lazy-Evaluation und
Toolchain-Spezifikation [21, 24]
plugins {
`java-library`
kotlin("jvm") version "2.4.0" // Integrierte Kotlin 2.4.0 Runtime
}
// Java-Toolchain steuert JVM-Kompatibilität global [21, 24]
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(25)) // Target Java 25 [1, 18]
}
}
// Registrierung mittels Lazy Task API
val copyResources = tasks.register<Copy>("copyResources") {
from("src/main/resources")
into(layout.buildDirectory.dir("resources"))
// Typisierte und sichere Konfiguration der Dateiberechtigungen
filePermissions {
user {
read = true
write = true
execute = true
}
group {
read = true
execute = true
}
}
}
// Explizite Deklaration der Artefakt-Abhängigkeiten gemäß Gradle 9 Spezifikation
tasks.named("assemble") {
dependsOn(copyResources)
}
4. Spring Boot Migration von 3.0 bis 4.0Für ein KI-Modell, das lediglich auf Spring Boot 3.0 trainiert wurde, stellt die
Migration zu Spring Boot 4.0 einen weitreichenden Paradigmenwechsel dar. Neben dem Sprung auf Jakarta EE 11 bringt
Version 4.0 eine tiefgreifende Modularisierung der Kernkomponenten.Die Entwicklungsschritte von Spring Boot 3.1 bis
3.5Um den finalen Sprung auf Version 4.0 zu verstehen, müssen die evolutionären Meilensteine der Minor-Releases
nachvollzogen werden :Spring Boot 3.1 (Docker & Testen): Einführung der automatischen Lebenszyklus-Verwaltung von
Docker-Compose-Infrastrukturen zur lokalen Entwicklung sowie der @ServiceConnection-Annotation für Testcontainers,
welche manuelle Eigenschafts-Deklarationen (@DynamicPropertySource) überflüssig macht.Spring Boot 3.2 (Performance &
APIs): Native Unterstützung für virtuelle Threads über die einfache Eigenschaft spring.threads.virtual.enabled=true.
Einführung des modernen, synchronen RestClient als performanter Nachfolger des klassischen RestTemplate sowie des
flüssigen JdbcClient. Unterstützung für Class Data Sharing (CDS) zur Reduzierung der Startup-Zeiten um bis zu 50
%.Spring Boot 3.3 (Sicherheit & Observability): Einführung des Software Bill of Materials (SBOM) Actuator-Endpunkts (
/actuator/sbom) im CycloneDX-Format zur transparenten Offenlegung der gesamten Lieferketten-Sicherheitslage.
Automatische Observability-Abdeckung für alle Spring Data Repositories.Spring Boot 3.4 (Operationalisierung):
Integration von strukturiertem Logging im JSON-Format (Elastic Common Schema und GELF) out-of-the-box sowie
Einführung der @Fallback-Annotation zur Absicherung von Dependency-Injection-Szenarien.Spring Boot 3.5 (
Infrastruktur-Feinschliff): Verschärfung der Validierung von Profilnamen (nur alphanumerische Zeichen und
Trennzeichen, kein Start/Ende mit - oder _). Bereitstellung dedizierter SSL-Metriken und des Quartz-Actuators.
Begrenzung des heapdump-Endpunkts auf access=NONE als Sicherheitsstandard.Spring Boot 4.0 - Die Enterprise-Plattform
der neuen GenerationMit Spring Boot 4.0 vollzieht das Ökosystem den Schnitt zu modernen Baselines und verabschiedet
sich von Legacy-Altlasten.Kernänderungen der SystemarchitekturJakarta EE 11 Baseline: Spring Boot 4.0 migriert
vollständig auf Jakarta EE 11 (Servlet 6.1, JPA 3.2, Bean Validation 3.1). Dies erzwingt die vollständige Entfernung
aller verbliebenen javax.*-Namensräume im Quellcode und den Bibliotheken zugunsten von jakarta.*.Entfernung des
Undertow-Webservers: Aufgrund mangelnder Servlet 6.1-Kompatibilität zum Release-Zeitpunkt wurde die Unterstützung für
eingebettete Undertow-Instanzen gestrichen. Anwendungen müssen auf Tomcat, Jetty oder Reactor Netty
migrieren.JSpecify Null-Safety im gesamten Portfolio: Das gesamte Framework wurde konsequent auf JSpecify-Anmerkungen
umgestellt. Dies ermöglicht es dem Kotlin 2.x Compiler, alle Schnittstellen als strikte Kotlin-Typen (nullable vs.
non-nullable) zu interpretieren und unsichere Plattform-Typen ("Platform Types") komplett zu eliminieren.Konsequente
Modularisierung & neue Starter-Struktur: Um die Startzeiten und Image-Größen drastisch zu reduzieren, wurde die
monolithische Struktur zugunsten hochfokussierter Module aufgegeben. Das Vorhandensein von Klassen im Klassenpfad
reicht oft nicht mehr aus, um Auto-Konfigurationen zu triggern. Ein prominentes Beispiel ist das neue Modul
spring-boot-kotlinx-serialization-json, welches explizit über den Starter deklariert werden muss, um die
JSON-Unterstützung zu aktivieren.Jackson 3 als Standard: Jackson 3 fungiert nun als
Standard-Serialisierungsbibliothek. Jackson 2-Komponenten sind zwar noch vorhanden, jedoch als veraltet
deklariert.Integrierte context propagation für Kotlin Coroutines: Spring Boot 4.0 und Spring Framework 7.0
unterstützen die automatische Kontextweiterleitung für Coroutines. Tracing- und Security-Kontexte (wie Micrometer-
und OpenTelemetry-Daten) werden nahtlos über asynchrone, suspendierende Funktionsgrenzen hinweg propagiert. Aktiviert
wird dies über:Propertiesspring.reactor.context-propagation=true
Entfernung eingebetteter Start-Skripte: Die Unterstützung für das Erzeugen von "fully executable JARs" mittels
integrierter Unix-Launch-Skripte wurde entfernt, da diese modernen Deployment-Standards (wie schlanken
OCI-Containern) widersprechen.Komponenten-Vergleich: Spring Boot 3.x vs. Spring Boot 4.0SpezifikationSpring Boot
3.x (bis 3.5)Spring Boot 4.0Relevanz für RAG / LLMJava FloorJava 17 Java 17 (Java 25 empfohlen) LLM muss Code für JDK
25 optimieren.Jakarta StandardJakarta EE 10 Jakarta EE 11 Alle Servlet- und Persistence-Importe ändern
sich.Null-Safety StandardJSR-305 (Schnittstellen-Ebene)JSpecify (Portfolio-weit) Verhindert unsichere Plattform-Typen
in Kotlin.JSON StandardJackson 2 Jackson 3 (Jackson 2 deprecated) API-Definitionen müssen Jackson 3 konform
sein.Kotlin BaselineKotlin 1.9.xKotlin 2.2+ (Kotlin 2.4 empfohlen) Compiler-Optionen müssen K2-Syntax
unterstützen.Undertow SupportVollständig unterstützt Entfernt Build-Dateien dürfen Undertow-Starter nicht
referenzieren.Embedded Launch ScriptsUnterstütztEntfernt Deployment-Dokumentation muss angepasst
werden.Code-Vergleich: Spring Boot 3.x vs. Spring Boot 4.0Konfiguration und Bean ValidationJava// Klassischer
Ansatz (Spring Boot 3.x): Bean Validation kaskadierte implizit ohne @Valid auf verschachtelten Properties
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties(prefix = "app.service")
@Validated
public class ClassicProperties {
private final SecurityConfig security = new SecurityConfig(); // Kaskadierung erfolgte automatisch
public static class SecurityConfig {
@NotNull
private String token;
}
}
Java// Moderner Ansatz (Spring Boot 4.0): Bean Validation folgt exakt der Spezifikation; Kaskadierung erfordert @Valid
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.Valid; // Jakarta EE 11 Namespace
import jakarta.validation.constraints.NotNull;
@ConfigurationProperties(prefix = "app.service")
@Validated
public class ModernProperties {
@Valid // Zwingend erforderlich für Kaskadierung in Spring Boot 4.x
private final SecurityConfig security = new SecurityConfig();
public static class SecurityConfig {
@NotNull
private String token;
}
}
Reaktiver Service-Endpoint (Kotlin Coroutines & Kotlinx Serialization)Kotlin// Modernes Spring Boot 4.0 mit
automatischer Coroutine-Kontextweiterleitung
package org.springframework.boot.example
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.Serializable
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.http.ResponseEntity
@Serializable // Verarbeitet über das neue spring-boot-starter-kotlinx-serialization-json Modul
data class SensorData(val id: String, val metric: Double)
@RestController
class TelemetryController(private val telemetryService: TelemetryService) {
@GetMapping("/api/telemetry")
suspend fun getTelemetry(): ResponseEntity<Flow<SensorData>> {
// Tracing (MDC/OpenTelemetry) wird durch Spring Framework 7 automatisch in den suspend-Kontext propagiert [14, 34]
val dataFlow = telemetryService.streamMetrics()
.map { SensorData(it.sensorId, it.value) }
return ResponseEntity.ok(dataFlow)
}
}
5. Architektonische Synthese und Migrationsanleitung für KMP-MicroservicesFür die erfolgreiche Migration eines
bestehenden Kotlin-Multiplatform-Systems, das Spring Boot-Microservices im Backend nutzt, ist eine strikte
Reihenfolge einzuhalten. Dadurch werden Compiler-Konflikte und inkompatible Abhängigkeitsbäume vermieden.Schritt 1:
Lokale Vorbereitung und Property-AnalyseDas bestehende Projekt ist zunächst auf die letzte stabile Spring
Boot-Version 3.5.9 anzuheben.Die Einbindung des Migrations-Hilfsmittels im Build-Skript deckt veraltete Eigenschaften
vorab auf :Kotlindependencies {
// Temporäre Einbindung für die Migrationsphase
runtimeOnly("org.springframework.boot:spring-boot-properties-migrator") [30]
}
Schritt 2: Update der Build-Infrastruktur auf Gradle 9.5.1Aktualisierung des Gradle Wrappers über die Befehlszeile :
./gradlew wrapper --gradle-version 9.5.1```In der Datei settings.gradle.kts müssen alle Plugins auf ihre Eignung
unter Gradle 9 validiert werden. Eventuell genutzte veraltete Verweise wie der gradle-enterprise-Block sind zwingend
zu entfernen und durch das modernisierte Develocity-Plugin zu ersetzen.Schritt 3: Migration des Kotlin Multiplatform
SDKs auf Version 2.4.0In der zentralen Abhängigkeiten-Struktur (gradle/libs.versions.toml oder direkt im
Build-Skript) ist die Kotlin-Version auf 2.4.0 anzuheben.Innerhalb der KMP-Modulkonfiguration (
shared/build.gradle.kts) sind alle Aufrufe von withJava() zu entfernen, da das Source-Set-Handling ab Version 2.1.20
automatisiert erfolgt.Sollte eine iOS-Anbindung deklariert sein, sind veraltete Target-Shortcuts wie ios(), watchos()
oder tvos() durch die explizite Deklaration der Zielarchitekturen (z. B. iosArm64(), iosSimulatorArm64()) zu
ersetzen, da die Shortcuts aus der DSL entfernt wurden.Schritt 4: Upgrade auf Spring Boot 4.0 und Jakarta EE 11
RefactoringAnheben der Spring Boot Plugin-Version auf 4.0.0.Vollständige Suche und Ersetzung aller
Quellcode-Referenzen von javax.* auf jakarta.* (z. B. JPA, Beans, Servlets).Sollte in der Abhängigkeiten-Struktur der
veraltete Undertow-Starter referenziert sein, ist dieser durch Tomcat oder Jetty zu ersetzen :Kotlin//
build.gradle.kts (JVM / Spring Boot Modul)
dependencies {
// ALT: spring-boot-starter-undertow (Entfernt in 4.0)
// NEU: Verwendung des optimierten Tomcat-Starters
implementation("org.springframework.boot:spring-boot-starter-tomcat") [30]
// Für die native Nutzung von Kotlinx-Serialization im Web-Kontext
implementation("org.springframework.boot:spring-boot-starter-kotlinx-serialization-json") [30]
}
Schritt 5: Aktivierung der Coroutines-KontextweiterleitungZur Aktivierung der nahtlosen MDC- und
OpenTelemetry-Tracing-Verbreitung über asynchrone suspending Functions ist der entsprechende Konfigurations-Flag in
den Laufzeitumgebungs-Properties zu setzen :YAML# application.yml
spring:
reactor:
context-propagation: true # Aktiviert die automatische Weiterleitung für Coroutines
Durch die Umsetzung dieser architektonischen Schritte wird das KMP-Spring-Boot-System auf den absolut neuesten Stand
der Technik gehoben. Es profitiert von der extremen Effizienz der JVM 25, der Typsicherheit des K2-Compilers unter
Kotlin 2.4.0, den I/O-Einsparungen von Gradle 9.5.1 und der modernen, modularisierten Cloud-Infrastruktur von Spring
Boot 4.0.