Upgrade auf Micronaut 3.x
Im August ist die Major-Version 3.0 des Micronaut Framework's erschienen. Da exensio für Kunden bereits mehrere Applikationen mit Micronaut erstellt hat und ständig weiterentwickelt, ist der Upgrade des Frameworks entsprechend relevant. Dieser Blogpost gibt die Erfahrungen beim Upgrade von zwei Produktiv-Applikationen wider.
Für die Version 3.0 existiert vorbildlicherweise ein separates Kapitel im Userguide zum Thema Upgrade, das vor einer anstehenden Migration durchgearbeitet werden sollte.
Micronaut setzt auf das Werkzeug OpenRewrite. Dieses Tool eignet sich für automatisierte Source-Code Refactorings und Migrationen von Frameworks. Die Einbindung von OpenRewrite erfolgt über gradle bzw. maven und die Ausführung durch Aufruf der entsprechenden Tasks. Vor der Durchführung sollten alle Änderungen des Projektes in die Versionsverwaltung eingecheckt sein.
Mit gradle wird die Migration über folgenden Aufruf angestoßen:
./gradlew rewriteRun
Nach der Ausführung sind einige Source-Dateien des Projektes geändert und teilweise migriert. Die vorgenommenen Änderungen sollten gegen die Versionsverwaltung abgeglichen werden. Hier sind dann zum Beispiel geänderte Importe oder Annotationen zu sehen. OpenRewrite kann allerdings nur einen ersten Vorschlag erstellen und das Projekt muss nach der Migration entsprechend verifiziert und bei Bedarf händisch angepasst werden.
Bei unseren Migrationen mussten wir in drei Bereichen tätig werden:
- Durch die Verwendung von Java 17 ist OpenRewrite bei der Ausführung abgebrochen. Dies konnte durch Setzen von JVM-Optionen behoben werden. Das Problem wurde auch schon auf Stack Overflow beschrieben.
- Die Abhängigkeiten in der Datei build.gradle bzw. pom.xml mussten überarbeitet werden. Nach der Ausführung von OpenRewrite war eine Kompilierung nicht möglich, da einige Importe nicht gefunden wurden. Beispielhaft sei hier die Nutzung von Transaktionen über die Annotation @Transactional erwähnt.
Die entsprechenden Klassen sind jetzt in einer Jakarta Bibliothek zu finden, die explizit zu referenzieren ist.implementation("jakarta.transaction:jakarta.transaction-api:2.0.0")
- Im Bereich Security wird in unseren Projekten für die Authentifizierung ein eigener AuthenticationProvider genutzt, der bisher mit der Klasse io.micronaut.security.authentication.UserDetails arbeitete. Diese Klasse steht ab der Version 3.0 nicht mehr zur Verfügung und der AuthenticationProvider musste angepasst werden.
Fazit
OpenRewrite bietet für den "ersten Wurf" einer Migration eine exzellente Ausgangsbasis und erspart viel Arbeit. Da jedes Projekt anders aufgebaut ist und andere Funktionalitäten hat, müssen Details projektspezifisch nachgearbeitet werden. Durch Hinweise im Migration-Guide oder JavaDoc-Kommentare des Framework-Codes findet man nach unserer Erfahrung schnell Hilfe, um voranzukommen.