1.2 Upgrading to Micronaut 2.x

This section covers the steps required to upgrade a Micronaut 1.x application to Micronaut 2.x.

Thread Pool Selection Now Manual

If your application does blocking I/O such as communication via JDBC or JPA you should annotate all controllers that interact with these blocking resources with the @ExecuteOn annotation specifying either the default I/O thread pool or a thread pool that you configure an manage to deal with these blocking interactions. For example:

Using @ExecuteOn

  1. import io.micronaut.http.annotation.*;
  2. import io.micronaut.scheduling.TaskExecutors;
  3. import io.micronaut.scheduling.annotation.ExecuteOn;
  4. @Controller("/executeOn/people")
  5. public class PersonController {
  6. private final PersonService personService;
  7. PersonController(
  8. PersonService personService) {
  9. this.personService = personService;
  10. }
  11. @Get("/{name}")
  12. @ExecuteOn(TaskExecutors.IO) (1)
  13. Person byName(String name) {
  14. return personService.findByName(name);
  15. }
  16. }

Using @ExecuteOn

  1. import io.micronaut.http.annotation.*
  2. import io.micronaut.scheduling.TaskExecutors
  3. import io.micronaut.scheduling.annotation.ExecuteOn
  4. @Controller("/executeOn/people")
  5. class PersonController {
  6. private final PersonService personService
  7. PersonController(
  8. PersonService personService) {
  9. this.personService = personService
  10. }
  11. @Get("/{name}")
  12. @ExecuteOn(TaskExecutors.IO) (1)
  13. Person byName(String name) {
  14. return personService.findByName(name)
  15. }
  16. }

Using @ExecuteOn

  1. import io.micronaut.http.annotation.*
  2. import io.micronaut.scheduling.TaskExecutors
  3. import io.micronaut.scheduling.annotation.ExecuteOn
  4. @Controller("/executeOn/people")
  5. class PersonController (private val personService: PersonService) {
  6. @Get("/{name}")
  7. @ExecuteOn(TaskExecutors.IO) (1)
  8. fun byName(name: String): Person {
  9. return personService.findByName(name)
  10. }
  11. }
1The @ExecuteOn annotation is used to execute the operation on the I/O thread pool
If you wish to return to the previous behaviour as defined in Micronaut 1.x you can set micronaut.server.thread-selection to AUTO in configuration.

Compilation Error with classes in io.micronaut.cache package

If your application fails to compile due to missing classes in the io.micronaut.cache you need to add a dependency on a cache implementation, for example the default cache implementation was Caffeine and this can be restored with the following dependency:

  1. implementation("io.micronaut.cache:micronaut-cache-caffeine")
  1. <dependency>
  2. <groupId>io.micronaut.cache</groupId>
  3. <artifactId>micronaut-cache-caffeine</artifactId>
  4. </dependency>

Compilation Error with classes in javax.annotation package

If you application fails to compile referencing classes in the javax.annotation package such as @Nullable and @Nonnull you should update your project to instead import edu.umd.cs.findbugs.annotations from Spot Bugs.

New Group IDs

Some dependencies have new Maven Group IDs so you may need to update your dependency. The following table summarizes changes to group IDs:

Table 1. Updated Maven Group IDs
Previous IDNew ID

io.micronaut.configuration:micronaut-aws-

io.micronaut.aws:micronaut-aws-

io.micronaut.configuration:micronaut-cassandra

io.micronaut.cassandra:micronaut-cassandra

io.micronaut.configuration:micronaut-elasticsearch

io.micronaut.elasticsearch:micronaut-elasticsearch

io.micronaut.configuration:micronaut-flyway

io.micronaut.flyway:micronaut-flyway

io.micronaut.configuration:micronaut-runtime-groovy

io.micronaut.groovy:micronaut-runtime-groovy

io.micronaut.configuration:micronaut-hibernate-validator

io.micronaut.beanvalidation:micronaut-hibernate-validator

io.micronaut.configuration:micronaut-jmx

io.micronaut.jmx:micronaut-jmx

io.micronaut.configuration:micronaut-kafka

io.micronaut.kafka:micronaut-kafka

io.micronaut.configuration:micronaut-liquibase

io.micronaut.liquibase:micronaut-liquibase

io.micronaut.configuration:micronaut-micrometer-

io.micronaut.micrometer:micronaut-micrometer-

io.micronaut.configuration:micronaut-mongo

io.micronaut.mongodb:micronaut-mongo-reactive

io.micronaut.configuration:micronaut-neo4j

io.micronaut.neo4j:micronaut-neo4j

io.micronaut.configuration:micronaut-netflix-

io.micronaut.netflix:micronaut-netflix-

io.micronaut.configuration:micronaut-picocli

io.micronaut.picocli:micronaut-picocli

io.micronaut.configuration:micronaut-rabbitmq

io.micronaut.rabbitmq:micronaut-rabbitmq

io.micronaut.configuration:micronaut-redis

io.micronaut.redis:micronaut-redis

io.micronaut.configuration:micronaut-rss

io.micronaut.rss:micronaut-rss

io.micronaut.configuration:micronaut-itunespodcast

io.micronaut.rss:micronaut-itunespodcast

io.micronaut:micronaut-security-

io.micronaut.security:micronaut-security-

io.micronaut.configuration:micronaut-views-

io.micronaut.views:micronaut-views-

AWS Module Changes

The AWS functionality (including support for AWS ParameterStore, AWS Route53 and AWS Lambda Function Client) has been moved out of the Micronaut core therefore if you need AWS related functionality you should use the necessary module.

Table 2. Updated AWS Modules
PackageNew Dependency

io.micronaut.function.client.aws

io.micronaut.aws:micronaut-function-client-aws

io.micronaut.discovery.aws.parameterstore

io.micronaut.aws:micronaut-aws-parameter-store

io.micronaut.discovery.aws.route53

io.micronaut.aws:micronaut-aws-route53

Kubernetes Discovery Service deprecation

The class io.micronaut.discovery.kubernetes.KubernetesDiscoveryClient, that was deprecated in Micronaut 1.2, has now been removed from Micronaut 2.0. The replacement is the new Micronaut Kubernetes module, with an improved support for running Micronaut applications in a Kubernetes cluster, including support for Kubernetes’ ConfigMaps, Secrets and more.

To use the new module, you need to add the following dependency:

  1. implementation("io.micronaut.kubernetes:micronaut-kubernetes-discovery-client")
  1. <dependency>
  2. <groupId>io.micronaut.kubernetes</groupId>
  3. <artifactId>micronaut-kubernetes-discovery-client</artifactId>
  4. </dependency>

Transaction Management

For Micronaut 2.0, we recommend you to use the native Micronaut-based transaction management instead of other alternatives such as Spring Transaction Management.

You will use Java EE 7 javax.transaction.Transactional annotation and io.micronaut.transaction.annotation.ReadOnly to mark your transaction demarcations.

To use those annotations, you have to include the micronaut-data-processor dependency in your annotation processor configuration:

  1. annotationProcessor("io.micronaut.data:micronaut-data-processor")
  1. <dependency>
  2. <groupId>io.micronaut.data</groupId>
  3. <artifactId>micronaut-data-processor</artifactId>
  4. </dependency>

If you use Hibernate/JPA, you will need to add as well:

  1. implementation("io.micronaut.data:micronaut-data-hibernate-jpa")
  1. <dependency>
  2. <groupId>io.micronaut.data</groupId>
  3. <artifactId>micronaut-data-hibernate-jpa</artifactId>
  4. </dependency>

Then, code such as:

  1. import io.micronaut.spring.tx.annotation.Transactional;
  2. ...
  3. ..
  4. .
  5. @Singleton
  6. public class GenreRepositoryImpl implements GenreRepository {
  7. ...
  8. ..
  9. .
  10. @Transactional(readOnly = true)
  11. public Optional<Genre> findById(@NotNull Long id) {
  12. ...
  13. ..
  14. }
  15. @Transactional
  16. public Genre save(@NotBlank String name) {
  17. ...
  18. ..
  19. }
  20. }

becomes:

  1. import javax.transaction.Transactional;
  2. import io.micronaut.transaction.annotation.ReadOnly;
  3. ...
  4. ..
  5. .
  6. @Singleton
  7. public class GenreRepositoryImpl implements GenreRepository {
  8. ...
  9. ..
  10. .
  11. @ReadOnly
  12. public Optional<Genre> findById(@NotNull Long id) {
  13. ...
  14. ..
  15. }
  16. @Transactional
  17. public Genre save(@NotBlank String name) {
  18. ...
  19. ..
  20. }
  21. }

Micronaut 2 for Groovy Users

Micronaut 2 defaults to Groovy 3 and Spock 2 both of which include significant changes at the language and testing framework level.

Some features of Micronaut 2 for Groovy users are currently in preview status including GORM 7.1 and Spock 2 support as these frameworks do not yet have stable releases.

In the case of Spock 2 the most important change is that Spock 2 deprecates support for JUnit 4 and the associated JUnit 4 test runner and replaces it with JUnit 5 Platform.

In the case of a Gradle build this change means that when upgrading to Micronaut 2 with Spock 2 you may find your tests don’t execute at all which can give you the false sense of security that the upgrade was successful.

To ensure your Spock 2 tests run in a Micronaut 2 Gradle build you must add the following configuration to your build.gradle to enable JUnit 5 platform:

Using JUnit Platform

  1. test {
  2. useJUnitPlatform()
  3. }

With this configuration is place your Spock 2 tests will execute correctly.

Other Breaking Changes

If the above cases don’t cover your use case see the section on Breaking Changes for a list of other changes that are regarded as breaking in this release.