1.2 Upgrading to Micronaut 3.x
This section covers the steps required to upgrade a Micronaut 2.x application to Micronaut 3.0.0.
The sections below go into more detail, but at a high level the process generally involves:
updating versions
updating annotations
choosing a Reactive implementation
adjusting code affected by breaking changes
Typically, upgrading should be straightforward, but it’s possible to save yourself some work with OpenRewrite, an automated refactoring tool that you can use to make many of the required upgrade changes.
Automating Upgrades with OpenRewrite
OpenRewrite works with Micronaut applications written in Java, but OpenRewrite doesn’t currently support Kotlin or Groovy. Like any automated tool it does much of the work for you, but be sure to review the resulting changes and manually make any changes that aren’t supported by OpenRewrite, for example converting from RxJava2 to Reactor.
If you will be using OpenRewrite, don’t make any upgrade changes yet that would cause your application not to compile, for example updating the Micronaut version to 3.x. This would cause application classes that use javax.inject annotations like @Singleton or RxJava2 classes like io.reactivex.Flowable to not compile since those dependencies are no longer included by default. Instead, use OpenRewrite to do the initial work and just do the steps yourself that aren’t possible or practical to automate. |
Adding OpenRewrite support to your build is easy, it just requires adding the Gradle or Maven plugin and configuring the plugin to use the Micronaut upgrade recipe.
See the Gradle feature diff or the Maven feature diff to see the required build script changes.
Once you’ve made the build script changes, you can “dry-run” the Micronaut upgrade recipe to see what changes would be made.
For Gradle, run
$ ./gradlew rewriteDryRun
and view the diff report generated in build/reports/rewrite/rewrite.patch
and for Maven, run
$ ./mvnw rewrite:dryRun
and view the diff report generated in target/site/rewrite/rewrite.patch
.
Then you can run the recipe for real, letting OpenRewrite update your code.
For Gradle, run
$ ./gradlew rewriteRun
and for Maven, run
$ ./mvnw rewrite:run
Once the changes have been made, you could remove the plugin, but it’s fine to leave it since OpenRewrite doesn’t run automatically, only when you run one of its commands. And there are many more recipes available beyond the Micronaut upgrade recipe that you might want to include to automate other code changes.
The plugin includes another command to list all recipes currently in the classpath (in this case the core recipes plus those added by the rewrite-micronaut
module).
For Gradle, run
$ ./gradlew rewriteDiscover
and for Maven, run
$ ./mvnw rewrite:discover
and the available recipes and styles will be output to the console. Check out the OpenRewrite documentation for more information and to see the many other available recipes available.
Version Update
If you use Gradle, update the micronautVersion
property in gradle.properties
, e.g.
gradle.properties
micronautVersion=3.0.0
If you use Maven, update the parent POM version and micronaut.version
property in pom.xml
, e.g.
pom.xml
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.0.0</version>
</parent>
<properties>
...
<micronaut.version>3.0.0</micronaut.version>
...
</properties>
Build Plugin Update
If you use the Micronaut Gradle plugin, update the version to 2.0.3
id("io.micronaut.application") version "2.0.3"
For Maven users the plugin version is updated automatically when you update the Micronaut version.
Inject Annotations
The javax.inject
annotations are no longer a transitive dependency. Micronaut now ships with the Jakarta inject annotations. Either replace all javax.inject
imports with jakarta.inject
, or add a dependency on javax-inject
to continue using the older annotations:
implementation("javax.inject:javax.inject:1")
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
Any code that relied on the javax.inject
annotations being present in the annotation metadata will still work as expected, however any code that interacts with them must be changed to no longer reference the annotation classes themselves. Static variables in the AnnotationUtil class (e.g. AnnotationUtil.INJECT
, AnnotationUtil.SINGLETON
, etc.) should be used in place of the annotation classes when working with annotation metadata.
Nullability Annotations
Micronaut now only comes with its own set of annotations to declare nullability. The findbugs, javax, and jetbrains annotations are all still supported, however you must add a dependency to use them. Either switch to the Micronaut @Nullable / @NonNull annotations or add a dependency for the annotation library you wish to use.
RxJava2
Micronaut no longer ships any reactive implementation as a default in any of our modules or core libraries. Upgrading to Micronaut 3 requires choosing which reactive streams implementation to use, and then adding the relevant dependency.
For those already using RxJava3 or Project Reactor, there should be no changes required to upgrade to Micronaut 3. If you use RxJava2 and wish to continue using it, you must add a dependency:
implementation("io.micronaut.rxjava2:micronaut-rxjava2")
<dependency>
<groupId>io.micronaut.rxjava2</groupId>
<artifactId>micronaut-rxjava2</artifactId>
</dependency>
In addition, if any of the Rx
HTTP client interfaces were used, a dependency must be added and the imports must be updated.
implementation("io.micronaut.rxjava2:micronaut-rxjava2-http-client")
<dependency>
<groupId>io.micronaut.rxjava2</groupId>
<artifactId>micronaut-rxjava2-http-client</artifactId>
</dependency>
Old | New |
---|---|
io.micronaut.http.client.RxHttpClient | io.micronaut.rxjava2.http.client.RxHttpClient |
io.micronaut.http.client.RxProxyHttpClient | io.micronaut.rxjava2.http.client.proxy.RxProxyHttpClient |
io.micronaut.http.client.RxStreamingHttpClient | io.micronaut.rxjava2.http.client.RxStreamingHttpClient |
io.micronaut.http.client.sse.RxSseClient | io.micronaut.rxjava2.http.client.sse.RxSseClient |
io.micronaut.websocket.RxWebSocketClient | io.micronaut.rxjava2.http.client.websockets.RxWebSocketClient |
If the Netty based server implementation is being used, an additional dependency must be added:
implementation("io.micronaut.rxjava2:micronaut-rxjava2-http-server-netty")
<dependency>
<groupId>io.micronaut.rxjava2</groupId>
<artifactId>micronaut-rxjava2-http-server-netty</artifactId>
</dependency>
We recommend switching to Project Reactor as that is the implementation used internally by Micronaut. Adding a dependency to RxJava2 will result in both implementations in the runtime classpath of your application. |
Breaking Changes
Review the section on Breaking Changes and update your affected application code.