Micronaut is a new open source Java/JVM framework for creating microservice applications. Development is being led by the creators of the Grails framework and is backed by Object Computing. The project is actively working toward its official 1.0 release.
I’ve used Grails in the past for some personal projects and currently work primarily in the JVM ecosystem professionally. So, when I saw the announcement about Micronaut, I decided to give it a try and see what it was all about.
Micronaut’s goals are to provide fast startup times and small memory footprint. Both of which are important for deploying microservices.
Getting Started
To get started building an application, the user guide recommends installing the Micronaut CLI. After completing the installation, you can create a new project with the following command.
mn create-app my-app-name
By default, this creates a Gradle script to build a Java application using Micronaut. You can alternatively specify maven as your build script, and either Java, Groovy, or Kotlin as a programming language. For my examples, I opted to use Groovy. As you look at the generated project structure it will feel very familiar if you have worked with Spring framework before.
To start the application, just run:
./gradlew run
You can also compile the application and run the main method in the Application
class directly using your IDE.
Controllers
Much like in Spring Framework controllers are defined declaratively using the @Controller
annotation. Classes that are annotated with @Controller
or other annotations are automatically detected. Unlike other frameworks, like Spring, that rely on run-time classpath scanning this is done at compile time.
A simple controller looks as follows:
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
@Controller("/api/todo")
class TodoController {
@Get("/{id}")
Todo getTodo(int id) {
//Do something with the id from the URI
}
}
The @Get
annotation is placed onto the method that will handle the GET action for the combined URL in the @Controller
and @Get
annotations. Additional annotations exist for other HTTP methods (POST, PUT, etc.). Path variables are supported in URLs and consist of a placeholder ({id}
in this case) and a matching method parameter. Objects returned from controller methods will automatically be converted to JSON.
Beans
Beans can be defined using annotations on a class. Like with controllers, beans will be found and registered via classpath scanning. There are several different annotations (@Singleton
, @Prototype
, etc.) for creating beans with different scopes. So, for example, I can create a service using the Singleton annotation.
import javax.inject.Singleton
@Singleton
class TodoService {
//Provide some implementation
}
Dependency Injection
Dependency injection is provided using the JSR-330 @Inject
annotation. Unlike other frameworks, Micronaut performs dependency injection at compile time. This avoids the use of reflection/proxies and contributes to faster startup times.
The @Inject
annotation can be used to inject dependencies via constructor injection, field injection, and method parameters.
Extending the controller example from before, we can inject a service as follows:
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import javax.inject.Inject
@Controller("/api/todo")
class TodoController {
TodoService todoService
@Inject
TodoController(TodoService todoService) {
this.todoService = todoService
}
@Get("/{id}")
Todo getTodo(int id) {
//Do something with the id from the URI
}
}
Conclusion
This quick overview just barely scratches the surface of the functionality available already in Micronaut. The user guide is comprehensive and provides a lot of great information for all of the functionality. Developers coming to Micronaut from Spring Framework will find it very familiar.
Considering that the framework hasn’t reached an official 1.0 release yet, it already seems very powerful. I look forward to seeing how it continues to evolve and grow.
Updated 2018-07-30: Thanks to Jim Kleeh for pointing out on Twitter that annotations
are not found via classpath scanning, but instead this happens at compile time.
Top comments (6)
I have to admit, I'm a little confused by the idea of having dependencies injected at compile time. It's like... inverted IoC!
I definitely see how that would be faster than resolving the whole world at startup, and that has to be one of the reasons Grails takes so long to get rolling.
Plus ça change... It's time for the pendulum to swing the other way again.
Quick note: if you already use sdkman to manage versions of tools you use (grails, jdk, etc), you can install micronaut trivially with
Thank you for the introduction!
Dependency injection at compile time is definitely a different concept if you are used to the way Spring Framework (and others) handle it at run-time. I don't know that I would say it is "inverted IoC". The framework is still in control, but the framework now extends to compile time and does the hard work of weaving your code together up front. That way it doesn't have to be done at startup.
Thanks for the comments!
When Spring (and other frameworks) started, they touted Dependency Injection and Inversion of Control as this new amazing thing (which it was, at the time). If you now resolve dependencies at compile time, it feels like it's the opposite of that, and what IoC was trying to get around at the time.
It looks like it uses a different approach to hook up dependencies at compile time, so that it's not a massive mess to change one implementation of a service for another, but it's still a bit amusing to see how paradigms shift over the years.
I'm keeping an eye out for integration between Mironaut and Grails, which I hear may happen with a Micronaut profile for Grails. crossing fingers
Great intro. I was trying to find the time to try Micronaut, but I never managed to do it...until I ran into your post. Thanks, it was the kick in the butt I needed :) and it really took little time to do create simple app. I'm continuing the experimentation now with their kafka support.
Glad I was able to inspire you to give it a try!
You can also create a project using the command
To see all available archetypes run: