annotationProcessor("io.micronaut.data:micronaut-data-processor")
Table of Contents
Micronaut for Spring
Extensions to integrate Micronaut and Spring
Version: 5.9.1-SNAPSHOT
1 Introduction
Micronaut uses Ahead of Time (AOT) compilation to pre-compute your applications requirements at compile time. The result of this is significantly lower memory requirements, faster startup time, and reflection free framework infrastructure.
This project consists of various components that make it easier to:
-
Integrate Spring components into a Micronaut application
-
Run Spring applications as Micronaut applications
-
Expose Micronaut Beans to a Spring Application
To achieve this the project provides the ability to use a subset of the Spring Annotation-Based programming model to build Micronaut applications. The goal is not necessarily to provide an alternative runtime for Spring, but instead to enable the ability to build libraries that work with both Spring and Micronaut.
2 Release History
For this project, you can find a list of releases (with release notes) here:
3 Transforming Spring Applications into Micronaut Applications
Micronaut for Spring allows you to use traditional Spring annotations which are mapped to Micronaut annotations at compilation time. This allows you to write an application that can be imported to another Spring or Micronaut application without change.
Unlike traditional runtime reflection based frameworks Micronaut uses Ahead of Time (AOT) compilation, hence there is no runtime overhead to supporting an additional set of annotations (in this case Spring’s annotation programming model).
As part of this project an Example Application is provided that includes no dependencies on Micronaut itself in the source code (only Spring dependencies) but is computed into a Micronaut application at compilation time.
The value in this as follows:
-
You can take the compiled application and include it into another Spring or Micronaut application without change, which is a huge win for library authors.
-
If you have an existing team of Spring developers they can be up and running with Micronaut without learning a new annotation DSL.
-
Existing tooling like IntelliJ IDEA and STS 4.0 "Just Work" with Micronaut
In addition, the guide for Application Class - Spring Boot to Micronaut Framework compares the application class of a Spring Boot application to that of a Micronaut Framework application.
Note that Spring is huge and only a subset of Spring is supported, but enough to build real applications and libraries that work with either Micronaut or Spring. The following documentation covers the annotations and Spring interfaces that are supported.
If an annotation or interface of Spring is not mentioned in this documentation consider it unsupported. |
3.1 Build Configuration
For a build configuration example for Gradle or Maven, see the example project that is part of the guide Run a Spring Boot Application as a Micronaut Application.
3.2 Supported Spring Annotations
The following table summarizes the annotations that Micronaut for Spring supports and the Micronaut annotation that they map to at compilation time:
Spring Annotation | Target Annotation | Notes |
---|---|---|
Example |
||
Example |
||
Example |
||
|
Example |
|
Example |
||
|
Example |
|
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Requires |
||
Requires |
||
Requires |
3.3 Supported Spring Data Annotations
Micronaut Data supports Spring Data annotations. To use them add the following dependency:
<annotationProcessorPaths>
<path>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-processor</artifactId>
</path>
</annotationProcessorPaths>
For Kotlin, add the micronaut-data-processor dependency in kapt or ksp scope, and for Groovy add micronaut-data-processor in compileOnly scope.
|
The following table summarizes the Spring Data annotations that Micronaut Data supports and the Micronaut annotation that they map to at compilation time:
Spring Data Annotation | Micronaut Data Annotation | Notes |
---|---|---|
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
||
Example |
See the guide for Micronaut Data from a Spring Boot Application to learn more. |
3.4 Supported Spring Interfaces
The following Spring interfaces are supported and can be injected into any bean:
Spring Interface |
Adapted Target |
Description |
The Application Environment |
||
For Converting Types |
||
For Publishing Events |
||
The application context |
||
The bean context |
For compatibility the following Aware
interfaces are supported:
Spring Interface |
Description |
For looking up the |
|
For looking up the |
|
For looking up the |
3.5 Supported Spring Events
For compatibility the following ApplicationEvent
instances are supported:
Spring Event |
Description |
Fired when the application context is started |
|
Fired when the application context is shut down |
You can write methods annotated with @EventListener to receive the events in either framework.
3.6 Writing Spring MVC Controllers
You can write Spring MVC controllers that are computed into Micronaut controllers at compilation time. The programming model is largely compatible with Spring Web Reactive.
See the example project that is part of the guide Run a Spring Boot Application as a Micronaut Application for an example Spring Web Reactive applications transformed into a Micronaut application.
Only @RestController
semantics are supported, which is fine for most Microservice use cases. Special support is provided by the micronaut-spring-web
dependency to allowing returning a ResponseEntity.
See the Example application for a demonstration on how to build a Spring MVC application computable to Micronaut. |
The binding semantics as described in the Micronaut documentation and are generally equivalent to how Spring MVC behaves.
The following additional, Spring specific, method argument types are supported:
Type | Notes |
---|---|
For receiving the whole reactive request |
|
|
Requires the |
The HTTP method |
|
With |
The following return types are supported:
Type | Notes |
---|---|
For customizing the response |
|
For sending back only headers |
|
|
A view name when combined with |
Any reactive or POJO return type |
Computed to appropriate JSON response |
The following Spring MVC annotations are supported:
Spring Annotation | Target Annotation | Notes |
---|---|---|
Example |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
No equivalent |
Example: |
|
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
||
Example: |
3.7 Supported Spring Boot Annotations
The following Spring Boot specific annotations are supported:
Spring Boot Annotation | Target Annotation | Notes |
---|---|---|
Example |
||
Maps to |
||
Maps to |
||
Maps to |
||
Maps to |
||
Maps to |
||
Maps to |
||
|
Maps to |
|
Maps to |
With support for @Configuration
and the majority of Spring Boot conditions it is possible to build auto configurations that work with both Spring Boot and Micronaut.
In addition, the following Spring Boot Actuator annotations are supported:
Spring Actuator Boot Annotation | Target Annotation | Notes |
---|---|---|
Example |
||
Example |
||
Example |
||
Example |
||
Example |
What this enables is the ability to write management endpoints that work with both Spring Boot and Micronaut.
3.8 Unsupported Spring Features
As mentioned previously only a subset of Spring is implementated, but enough to build real applications. The question you have to ask yourself coming from Spring is how much Spring do you need?
The following notable features are currently not supported in Micronaut for Spring either and in general if a feature is not documented here consider it unsupported:
-
AspectJ - Spring’s AOP implementation is not supported, you can however use Micronaut AOP which is compilation time and reflection free.
-
Spring Expression Language (SpEL) - SpEL expressions are not supported, property placeholders are, however.
-
The Servlet API - Any reference to the Servlet API is not supported
3.9 Using Micronaut's HTTP Client
Since annotations values are mapped at compilation time, this also impacts the authoring of Micronaut’s compile-time declarative HTTP client.
You can essentially use Spring annotations to a defined a compilation-time HTTP client:
@Client
Implementation/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.spring.web.annotation;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Header;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.http.client.multipart.MultipartBody;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
@Client("/")
public interface GreetingClient {
@GetMapping("/")
String home();
@PostMapping("/request")
@Header(name = "Foo", value = "Bar")
Greeting requestTest(@RequestBody Greeting greeting);
@GetMapping("/withOptVar{/optVar}")
String withOptVar(@PathVariable(required = false) String optVar);
@GetMapping("/greeting{?name}")
Greeting greet(@RequestParam(required = false) String name);
@PostMapping("/greeting")
Greeting greetByPost(@RequestBody Greeting greeting);
@DeleteMapping("/greeting")
HttpResponse<?> deletePost(@RequestHeader(required = false) String myHeader);
@GetMapping("/nested/greeting{?name}")
Greeting nestedGreet(@RequestParam(required = false) String name);
@GetMapping("/greeting-status{?name}")
HttpResponse<Greeting> greetWithStatus(@RequestParam(required = false) String name);
@PostMapping(value = "/multipart-request", consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaType.MULTIPART_FORM_DATA_VALUE)
String multipartRequest(@RequestBody MultipartBody body);
}
This also means you can define a common interface between client and server of a Spring application and compute the client at compilation name.
if you are using low-level HTTP clients see the guide for Building URIs - Spring Boot to Micronaut Framework that compares Spring’s UriComponentsBuilder to Micronaut Framework’s UriBuilder .
|
4 Sharing Libraries between Spring and Micronaut
If you have a lot of existing Spring applications it may be useful to share libraries between Micronaut and Spring.
This is a common requirement if you want to say share common injectable components that can be added to classpath.
If you have this use case you can resolve it by using Spring annotations to define the components using annotations like @configuration, @component and @bean.
For example:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class MyConfiguration {
@Bean
@Primary
public MyBean myBean() {
return new MyBean("default");
}
@Bean("another")
public MyBean anotherBean() {
return new MyBean("another");
}
public static class MyBean {
private final String name;
MyBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
The above configuration, which exposes a bean of type MyBean
, can be imported and used by any Spring application using the @import annotation declared as follows:
@Import
import org.springframework.context.annotation.Import;
@Import(MyConfiguration.class)
class Application {}
You can additionally use the same configuration in a Micronaut application by use the same declaration as above assuming you have correctly configured Micronaut for Spring. See the example project that is part of the guide Run a Spring Boot Application as a Micronaut Application for how to configure Micronaut for Spring.
Micronaut will import all declared beans at compilation time. The only limitation is that ImportBeanDefinitionRegistrar
that require runtime interfaces like BeanClassLoaderAware
will fail to import with a compilation error since import processing happens during compilation with Micronaut. When creating shared components try to avoid defining ImportBeanDefinitionRegistrar
types that depend on one of the following interfaces:
-
BeanClassLoaderAware
-
BeanFactoryAware
-
EnvironmentAware
-
ResourceLoaderAware
5 Using Micronaut Modules with Spring
It may be desirable to use Micronaut modules or libraries from a Spring or Spring Boot application. For example, you may wish to use the Micronaut HTTP Client or Micronaut Data within your Spring application. There are several ways you can integrate Micronaut into a Spring application which are described below.
5.1 Using the Micronaut Spring Boot Starter
The easiest way to use Micronaut inside Spring is to use the Micronaut Spring Boot starter, first include the Micronaut BOM in your Spring Boot application’s build configuration for Gradle:
implementation platform("io.micronaut.platform:micronaut-platform:4.0.0")
annotationProcessor platform("io.micronaut.platform:micronaut-platform:4.0.0")
or Maven:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.micronaut.platform</groupId>
<artifactId>micronaut-platform</artifactId>
<version>4.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
if you prefer not to import the BOM that is also possible, but note you will have to declare dependency versions explicitly. |
Then add the Micronaut annotation processor to your build configuration:
annotationProcessor("io.micronaut:micronaut-inject-java")
<annotationProcessorPaths>
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject-java</artifactId>
</path>
</annotationProcessorPaths>
You will then need to explicitly specify a dependency on a version of the Jakarta Annotations module that uses the jakarta
namespace instead of the javax
namespace (versions 2.0.x and above). This is because the Spring Boot BOM automatically downgrades this module’s version to one that uses the javax
namespace which is incompatible with Micronaut:
annotationProcessor("jakarta.annotation:jakarta.annotation-api:2.1.1")
<annotationProcessorPaths>
<path>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</path>
</annotationProcessorPaths>
implementation("jakarta.annotation:jakarta.annotation-api:2.1.1")
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
Finally, a dependency on micronaut-spring-boot-starter
can be added to the build:
implementation("io.micronaut.spring:micronaut-spring-boot-starter")
<dependency>
<groupId>io.micronaut.spring</groupId>
<artifactId>micronaut-spring-boot-starter</artifactId>
</dependency>
When the Spring Boot application starts app all beans provided by Micronaut will be exposed as Spring Beans as well.
You can control which beans are exposed to Spring by using the @EnableMicronaut annotation on your Application class and specifying a MicronautBeanFilter to include or exclude beans from Micronaut.
|
Using Micronaut Data
Micronaut Data can be used by adding the Micronaut Data annotation processor:
annotationProcessor("io.micronaut.data:micronaut-data-processor")
<annotationProcessorPaths>
<path>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-processor</artifactId>
</path>
</annotationProcessorPaths>
And module you are interested in, for example Micronaut Data JDBC:
implementation("io.micronaut.data:micronaut-data-jdbc")
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-jdbc</artifactId>
</dependency>
However, it is important to note that you will once again need to specify a version of the Jakarta Persistence API that uses the jakarta
namespace instead of the javax
namespace as the Spring Boot BOM forces these to older versions in Spring Boot 2.x:
annotationProcessor("jakarta.persistence:jakarta.persistence-api:3.1.0")
<annotationProcessorPaths>
<path>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</path>
</annotationProcessorPaths>
implementation("jakarta.persistence:jakarta.persistence-api:3.1.0")
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
The annotation processors noted above have different dependency requirements for different language-based projects. For Java add annotation processors in annotationProcessor scope, for Kotlin, add them in kapt or ksp scope, and for Groovy add them in compileOnly scope |
5.2 Using Micronaut Parent Context
You can also use Micronaut for Spring as the parent application context to a regular Spring application.
This has a number of benefits, you can for example define beans using Micronaut and consume any Micronaut beans into a Spring application, resulting in Spring using less memory and having reflection free infrastructure.
You can also use any Micronaut feature from a regular Spring Boot or Spring application including the declaring clients for HTTP and Kafka.
You can also use any compilation time tools from Micronaut with Spring such as Micronaut’s support for Swagger.
The following example shows how to Configure your Spring Boot application with a Micronaut powered parent application context using SpringApplicationBuilder
:
var builder = new SpringApplicationBuilder();
var context = new MicronautApplicationContext();
context.start();
builder.parent(context)
.sources(Application.class)
.build()
.run();
5.3 Using a Bean Post Processor
The MicronautBeanProcessor
class is a BeanFactoryPostProcessor
which will add Micronaut beans to a
Spring Application Context. An instance of MicronautBeanProcessor
should
be added to the Spring Application Context. MicronautBeanProcessor
requires
a constructor parameter which represents a list of the types of
Micronaut beans which should be added to the Spring Application Context. The
processor may be used in any Spring application. As an example, a Grails 3
application could take advantage of MicronautBeanProcessor
to add all the
Micronaut HTTP Client beans to the Spring Application Context with something
like the folowing:
// grails-app/conf/spring/resources.groovy
import io.micronaut.spring.beans.MicronautBeanProcessor
import io.micronaut.http.client.annotation.Client
beans = {
httpClientBeanProcessor MicronautBeanProcessor, Client
}
Multiple types may be specified:
// grails-app/conf/spring/resources.groovy
import io.micronaut.spring.beans.MicronautBeanProcessor
import io.micronaut.http.client.annotation.Client
import com.sample.Widget
beans = {
httpClientBeanProcessor MicronautBeanProcessor, [Client, Widget]
}
In a non-Grails application something similar may be specified using any of Spring’s bean definition styles:
@Configuration
class ByAnnotationTypeConfig {
@Bean
MicronautBeanProcessor beanProcessor() {
new MicronautBeanProcessor(Prototype, Singleton)
}
}
6 Guides
See the following list of guides to learn more about working with Spring in the Micronaut Framework:
7 Repository
You can find the source code of this project in this repository: