Object Computing, Inc. has released Micronaut 3.0 featuring the removal of a default reactive streams implementation, a change in annotation inheritance, and HTTP compile-time validation. This release was a culmination of work to resolve design faults of the past to make the framework more intuitive and adaptable to future requirements.
Micronaut, the JVM-based full-stack development framework for building modular, easily testable microservices and serverless applications, defined its main mission as reimagining the startup time and memory consumption of applications. The “Micronaut way” relies on the fact that the application startup time and memory consumption aren’t bound to the size of your codebase, resulting in a “monumental leap in startup time, blazing fast throughput, and a minimal memory footprint” as stated on their website.
Previous releases included RxJava2 as a transitive dependency and the default reactive streams used to implement many features within the framework. The release of RxJava3 was the appropriate moment to make a decision: either to upgrade or switch to Project Reactor. The Micronaut team chose the latter due to its functionality, allowing it to maintain state within the reactive flow and broader adoption by the community. The team also recommends that projects currently using RxJava2 switch to Project Reactor. This will lead to fewer classes on the runtime classpath and fewer potential issues with context propagation and reactive type conversion.
The current release changes the way a developer will interact with the annotations. Until now, annotations were inherited from parent interfaces or classes. However, starting with version 3.0, all annotations annotated with @Inherited
will be inherited. Among others, following this change, any annotations related to bean scopes or around/introduction advice will no longer be inherited.
A couple of annotations’ qualified names were changed, either imposed by changes in licenses or the movement of HTTP-related components. In the first case, the javax namespace licensing issues
affected all annotations under javax.annotations
. Namely, with this version, jakarta.annotation.PreDestroy
and jakarta.annotation.PostConstruct
are the recommended alternatives. Also affected are annotations from javax.inject
which were replaced with jakarta.inject
annotations. So, for current uses of javax.inject.Provider
, the recommended alternative is io.micronaut.context.BeanProvider
. In the second case, the HTTP-related components at compile-time have been moved to a new module, io.micronaut:micronaut-http-validation
. This dependency needs to be added to the annotation processor classpath to continue using classes that are validated at compile time.
There are improvements with Micronaut’s Inversion of Control (IoC) mechanism for improved granularity and control. Developers can now qualify an injection of a type by its generic arguments. A class that uses type arguments can be targeted by specifying those generics in the argument type.
@Inject public Vehicle(Engine<V8> engine) { ... }
Beans are now viewed as a super type or interface rather than the type they are. This can be used to prevent an implementation class from being looked up directly and forcing the bean to be looked up by the interface.
@Bean(typed = Engine.class) class V8Engine implements Engine { }
Previously, life cycle methods like @PostConstruct
and @PreDestroy
could not have aspect-oriented programming (AOP) advice applied to them. But now, both constructors and life cycle methods can be intercepted for an AOP advice on those methods.
Another novelty comes in the way server filters are called: they are called exactly once for each request under all conditions. Exceptions are no longer propagated to filters. Instead, the resulting error response is passed through the reactive stream. Previously, server filters could’ve been called multiple times in the case of an exception being thrown.
Other changes come in the GraalVM space where the addition of the @Introspected
annotation also adds the configuration for GraalVM to allow for the reflective usage of the class. That behaviour is not available anymore as, for the vast majority of cases, that is not required. To restore it, add the @ReflectiveAccess
annotation to the class. Another “magic” that was happening under the hood until now was the addition of the src/main/resources
folder to the native image. Users of the Micronaut build plugin will receive the same behaviour while Maven users are now responsible for creating and maintaining the resource configuration.
As with most major version releases, Micronaut 3.0 ships with breaking changes, but also promises an easy upgrade with OpenRewrite, a framework that would change the source code to upgrade an application from Micronaut 2 to Micronaut 3. This can be accomplished with either the Maven or Gradle plugin.
Micronaut was formally introduced in March 2018 by Graeme Rocher, then principal software engineer for Grails and Micronaut product lead at OCI, at the Greach Conference. Micronaut was subsequently open-sourced in late May 2018. Three years after its first GA release, the third version comes as a consolidation release. The team put into practice all the learnings gathered during this period, improving the architecture and offering more flexibility to users in terms of what libraries may be used and what the memory footprint will look like. Also, it aligned its namespace naming to avoid any licensing issues related to the javax
namespace.