1. Overview
In this tutorial, weβre going to compare Micronaut and Spring Boot. Spring Boot is a part of the popular Spring framework used for getting Spring applications up and running quickly. Micronaut is a JVM-based framework created to address some of the weaknesses of Spring/Spring Boot.
Weβll compare the two frameworks in several areas. First, weβll compare the ease of creating a new application, language support, and other configuration options. Then weβll look at two simple REST applications. Finally, weβll compare the code and measure performance differences.
2. Features
In the following sections, weβll break down several features in the two frameworks.
2.1. Setup
First, weβll compare the ease of getting a new application up and running in the two frameworks.
Both Micronaut and Spring Boot offer multiple convenient methods for creating new applications. For example, we can create a new application using either framework with a command-line interface. Alternatively, we could use the Spring Initializr for Spring Boot or a similar tool for Micronaut called Launch.
In terms of IDE support, we can use Spring Boot plugins for most popular IDEs, including its flavor of Eclipse, the Eclipse Spring Tools Suite. We have a Micronaut plugin available to us if weβre using IntelliJ.
2.2. Language Support
As we turn to language support, weβll find that itβs nearly identical for Spring Boot and Micronaut. For both frameworks, we can choose between Java, Groovy, or Kotlin. If we choose Java, both frameworks support Java 8, 11, and 17. Additionally, we can use either Gradle or Maven with both frameworks.
2.3. Servlet Container
Using Spring Boot, our application will use Tomcat by default. However, we can configure Spring Boot to use either Jetty or Undertow as well.
Our Micronaut applications will, by default, run on a Netty-based HTTP Server. However, we can choose to switch our application to run on Tomcat, Jetty, or Undertow.
2.4. Properties Configuration
For Spring Boot, we can define our properties in application.properties or application.yml. We can use the application-{env}.properties convention to provide different properties for different environments. Additionally, we can override these applications file provided properties using system properties, environment variables, or JNDI attributes.
We can use application.properties, application.yml, and application.json for our properties files in Micronaut. We can also use the same convention for supplying environment-specific properties files. If we need to override any properties, we can use system properties or environment variables.
2.5. Messaging Support
If weβre using messaging with Spring Boot, we have Active MQ, Artemis, Rabbit MQ, and Apache Kafka available to us.
On the Micronaut side, we have Apache Kafka, Rabbit MQ, and Nats.io as options.
2.6. Security
Spring Boot offers five authorization strategies: basic, form login, JWT, SAML, and LDAP. If weβre using Micronaut, we have the same options minus the SAML.
Both frameworks provide us with OAuth2 support.
In terms of actually applying the security, both frameworks allow us to use annotations to secure methods.
2.7. Management and Monitoring
Both frameworks provide us with the ability to monitor various metrics and statistics in our applications. We can define custom endpoints in both frameworks. We also can configure endpoint security in both frameworks.
However, the Spring Boot actuator provides several more built-in endpoints than Micronaut.
2.8. Template Languages
We can create complete full-stack applications with both frameworks, using provided template languages to render the front-end.
For Spring Boot, our choices are Thymeleaf, Apache Freemarker, Mustache, and Groovy. We can also use JSP, although the practice is discouraged.
We have a few more options available in Micronaut: Thymeleaf, Handlebars, Apache Velocity, Apache Freemarker, Rocker, Soy/Closure, and Pebbles.
2.9. Cloud Support
Spring Boot applications rely on third-party libraries for many cloud-specific features.
Micronaut is natively designed for cloud microservices. Cloud concepts that Micronaut will natively handle for us include distributed configuration, service discovery, client-side load balancing, distributed tracing, and serverless functions.
3. The Code
Now that weβve compared some basic features in the two frameworks, letβs create and compare two applications. To keep things simple, weβll create a simple REST API that solves basic arithmetic problems. Our service layer will consist of a class that actually does the math for us. Our controller class will contain an endpoint for addition, subtraction, multiplication, and division.
Before we dig into the code, letβs consider a significant difference between Spring Boot and Micronaut. Although the two frameworks provide dependency injection, they go about it differently. Our Spring Boot application handles dependency injection at runtime using reflection and proxies. In contrast, our Micronaut application builds dependency injection data when itβs compiled.
3.1. The Spring Boot Application
First, letβs define a class in our Spring Boot application called ArithmeticService:
@Service
public class ArithmeticService {
public float add(float number1, float number2) {
return number1 + number2;
}
public float subtract(float number1, float number2) {
return number1 - number2;
}
public float multiply(float number1, float number2) {
return number1 * number2;
}
public float divide(float number1, float number2) {
if (number2 == 0) {
throw new IllegalArgumentException("'number2' cannot be zero");
}
return number1 / number2;
}
}
Next, letβs create our REST controller:
@RestController
@RequestMapping("/math")
public class ArithmeticController {
@Autowired
private ArithmeticService arithmeticService;
@GetMapping("/sum/{number1}/{number2}")
public float getSum(@PathVariable("number1") float number1, @PathVariable("number2") float number2) {
return arithmeticService.add(number1, number2);
}
@GetMapping("/subtract/{number1}/{number2}")
public float getDifference(@PathVariable("number1") float number1, @PathVariable("number2") float number2) {
return arithmeticService.subtract(number1, number2);
}
@GetMapping("/multiply/{number1}/{number2}")
public float getMultiplication(@PathVariable("number1") float number1, @PathVariable("number2") float number2) {
return arithmeticService.multiply(number1, number2);
}
@GetMapping("/divide/{number1}/{number2}")
public float getDivision(@PathVariable("number1") float number1, @PathVariable("number2") float number2) {
return arithmeticService.divide(number1, number2);
}
}
Our controller has an endpoint for each of the four arithmetic functions.
3.2. The Micronaut Application
Now, letβs create the service layer of our Micronaut application:
@Singleton
public class ArithmeticService {
// implementation identical to the Spring Boot service layer
}
Next, weβll write our REST controller with the same four endpoints as the Spring Boot applications:
@Controller("/math")
public class ArithmeticController {
@Inject
private ArithmeticService arithmeticService;
@Get("/sum/{number1}/{number2}")
public float getSum(float number1, float number2) {
return arithmeticService.add(number1, number2);
}
@Get("/subtract/{number1}/{number2}")
public float getDifference(float number1, float number2) {
return arithmeticService.subtract(number1, number2);
}
@Get("/multiply/{number1}/{number2}")
public float getMultiplication(float number1, float number2) {
return arithmeticService.multiply(number1, number2);
}
@Get("/divide/{number1}/{number2}")
public float getDivision(float number1, float number2) {
return arithmeticService.divide(number1, number2);
}
}
We can see a lot of similarities between our very simple example applications. In terms of differences, we see that Micronaut takes advantage of Javaβs annotations for injection whereas Spring Boot has its own. Additionally, our Micronaut REST endpoints donβt require any special annotations on the path variables passed into the methods.
3.3. Basic Performance Comparison
Micronaut advertises fast start-up times, so letβs compare our two applications.
First, letβs fire up the Spring Boot application and see how long it takes:
[main] INFO c.b.m.v.s.CompareApplication - Started CompareApplication in 3.179 seconds (JVM running for 4.164)
Next, letβs see how quickly our Micronaut application starts:
21:22:49.267 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1278ms. Server Running: http://localhost:57535
We can see that our Spring Boot application starts up in just over three seconds and a little over one second in Micronaut.
Now that weβve looked at start-up time, letβs exercise our APIs a bit and then check some basic memory statistics. Weβll use the default memory settings when we start our applications.
Weβll start with the Spring Boot application. First, letβs call each of the four arithmetic endpoints and then pull our memory endpoint:
Initial: 0.25 GB
Used: 0.02 GB
Max: 4.00 GB
Committed: 0.06 GB
Next, letβs run through the same exercise with our Micronaut application:
Initial: 0.25 GB
Used: 0.01 GB
Max: 4.00 GB
Committed: 0.03 GB
In this limited example, both our applications use little memory, but the Micronaut uses about half as much as the Spring Boot application.
4. Comparison
There is no single βbestβ framework for all applications. The best choice will depend on the specific requirements of the application and the preferences of the developers.
However, the following table can provide some information that may be helpful in making a decision:
| Features | Micronaut | Spring Boot |
|---|---|---|
| Size | Smaller JAR files | Larger JAR Files |
| Actuator | No support | Yes, which provides health checks, metrics, and more |
| Build time | Faster | Slower |
| Startup time | Faster build time | Slower build time |
| Performance | Much better than Spring boot | OK |
| Native image | Yes | No default support |
| Auto Configuration | Less | More |
| Starter dependencies | Fewer starter dependencies | More starter dependencies |
| Dependency injection | Annotation-based | Property-based |
| Community | Smaller community | Larger community |
| Documentation | Good documentation | Excellent documentation |
5. Conclusion
In this article, we compared Spring Boot with Micronaut. First, we started with an overview of what the two frameworks are. Then, we went through several features and compared the options. Finally, we pitted two simple example applications against each other. We took a look at the code for both applications and then looked at start-up and memory performance.
