BT

The Road to Micronaut 1.0: A JVM-Based Full-Stack Framework

| by Michael Redlich Follow 16 Followers on Oct 19, 2018. Estimated reading time: 7 minutes |

A year in the making, the road to Micronaut 1.0 has accelerated within the past three weeks as Object Computing (OCI) published release candidates RC1, RC2 and RC3. Formerly known as Project Particle, Micronaut is a full-stack JVM-based framework for creating microservice-based, cloud-native and serverless applications that can be written in Java, Groovy, and Kotlin.

Micronaut was introduced earlier this year by Graeme Rocher, principal software engineer and Grails and Micronaut product lead at OCI, at the Greach Conference. Micronaut was subsequently open-sourced in late May.

New features in all three release candidates include: GraalVM native image support; compile-time support for Swagger (OpenAPI); compile-time validation; and mapping annotations at compile-time. Micronaut Test 1.0 RC1, Micronaut's testing framework, was also released in RC3.

Micronaut uses dependency injection and Ahead-of-Time (AOT) compilation. As defined on the website:

Reflection-based IoC frameworks load and cache reflection data for every single field, method, and constructor in your code, whereas with Micronaut, your application startup time and memory consumption are not bound to the size of your codebase.

Built on top of Netty, Micronaut ships with its own non-blocking web server. Designed to reduce memory consumption, Micronaut reactive clients can be built declaratively and are implemented at compile-time.

Profiles

Micronaut includes several built-in profiles that generate skeleton, yet working, applications as a building block for developing web or command line applications. Each profile consists of a template and additional commands specific to that profile. For example, create-app initiates the service profile that includes additional commands for building controller (create-controller) and client (create-client) classes that may not be available in other profiles.

Getting Started

After downloading and installing Micronaut, applications are created via the command line or the Micronaut shell. Inspired by the familiar command line interface in Grails, Micronaut follows the same concept for creating applications. Consider the following command:

    
$ mn create-app org.redlich.demo
    

As shown below, this will create a Java application and Gradle project under a root folder named demo and the package name, org.redlich.

Notice the inclusion of a test directory structure, a Dockerfile, and YAML configuration files. The micronaut-cli.yml file provides specific information about the project:

    
profile: service
defaultPackage: org.redlich
---
testFramework: junit
sourceLanguage: java
    

The generated Java source file, Application.java, launches a Micronaut server:

    
package org.redlich;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class);
        }
    }
    

To build and run this initial application:

    
$ ./gradlew run
    

To add a controller to the above project:

    
$ mn create-controller HelloController
    

As shown below, the files, HelloController.java and HelloControllerTest.java, are added to the project.

In the generated HelloController.java file, notice how the endpoint in the @Controller annotation is named "/hello" based on the name of the controller, HelloController.

    
package org.redlich;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.HttpStatus;

@Controller("/hello")
public class HelloController {

    @Get("/")
    public HttpStatus index() {
        return HttpStatus.OK;
        }
    }
    

Java and Gradle are the default language and build tool. To generate Groovy and Kotlin applications:

    
$ mn create-app org.redlich.demo --lang groovy
$ mn create-app org.redlich.demo --lang kotlin
    

There is also support for generating a Maven project:

    
$ mn create-app org.redlich.service --build maven
$ ./mvnw compile exec:exec
    

In Part 1 of this Micronaut tutorial, Sergio del Amo Caballero, software engineer at OCI, demonstrates how to create three microservices in three languages: Java, Groovy, and Kotlin.

Rocher spoke to InfoQ about this latest release.

InfoQ: What inspired OCI to develop this new microservices framework?

Graeme Rocher: The technology landscape has changed drastically over the past few years, in particular if you look at systems like Docker, Kubernetes and the Serverless movement they are really optimised for low memory Microservices and applications that have low overhead when it comes to cold starts. The result of this is that languages like Go and Node are getting significant traction on those platforms over Java due superior cold start performance and memory consumption. A good question to ask yourself, is given the technology choices available to the Docker and Kubernetes teams, why choose Go over Java to implement those platforms? In my opinion, the answer is simple: if they had written those technology stacks in Java, with the technology choices available today, we would all need a supercomputer for a laptop to run them locally.

The reasons for this are varied; on the one hand you have the language level limitations. The JVM is an amazing technological achievement, but for short lived operations like Serverless functions the optimisations it provides are often lost, yet you still have to drag along this entire JVM to run your application. Projects like GraalVM have the potential to resolve these limitations by allowing Java applications to be compiled to a native image, but frankly framework designers have a large role to play when it comes to making Java applications more efficient.

At the framework level, traditional JVM frameworks (like Spring and Java/Jakarta EE) are over 10 years old, from an era when everyone was deploying Monolithic applications, and are primarily built around the use of reflection and runtime analysis of annotations. The issue with this approach is that due to a variety of issues from type erasure, to a limited annotation API, to the relative slowness of reflective logic it makes it nearly impossible to build a Java framework that includes both ultra fast startup and low memory consumption. The burden placed on the framework runtime is enormous. If you look at what Spring does at runtime it is quite remarkable, from literally parsing your byte code with ASM to produce annotation metadata, to aggressively caching reflection information to avoid the inevitable slow down repeatedly reading it would cause. There exists a irreconcilable conflict between the need to cache all of this runtime produced information and the goal to achieve fast startup and low memory consumption.

We believe Micronaut is the basis for a framework for the future, by resolving this tension by eliminating all use of reflection and producing all annotation metadata, proxies and framework infrastructure at compilation time through a set of annotation processors and AST transformations that perform Ahead-of-Time (AOT) compilation. What this allows Micronaut to achieve is blazing fast startup time, low memory consumption and crucially improved compatibility with GraalVM native image.

Of course the Java ecosystem is huge with massive projects based on Java like Spring, Kafka, Cassandra, Hadoop, Grails etc. and a rich language ecosystem with Groovy, Scala, Kotlin, Java, Clojure etc. so it is not all about low memory footprint Microservices and Serverless applications and there are many, many workloads that still benefit massively from the JVM and the JIT. However, even for those workloads we believe that Micronaut has a lot to offer, by simply being more efficient than other frameworks, both in terms of startup time and memory consumption.

InfoQ: Are there plans to include Scala and/or Clojure as supporting JVM-based languages in Micronaut?

Rocher: Micronaut is already built with multiple languages in mind, and in fact we support Java, Kotlin and Groovy today by creating a common AST produced for each language. We have plans to at some point to add Scala support through a Scala compiler plugin (see https://github.com/micronaut-projects/micronaut-core/issues/675), although if there are folks in the Scala community who wish to help accelerate that we would love to hear from them. Clojure is an interesting one, we would certainly need input from the Clojure community on how that could be made to happen.

InfoQ: Since GraalVM supports non-JVM-based languages, would it be possible to one day build Micronaut applications with languages supported by GraalVM?

Rocher: I can certainly imagine it enabling sidecars and easier integrations with other languages into a Micronaut application.

InfoQ: When do you anticipate a GA release of Micronaut?

Rocher: Micronaut 1.0 GA will be released on the 23rd of October.

InfoQ: What's on the horizon for Micronaut, especially after the GA release?

Rocher: Micronaut 1.0 is all about establishing a stable baseline to build on. Since Micronaut uses AOT compilation the pre-compiled metadata format needs a stable 1.0 release. Once 1.0 we plan to build integration with a lot more technologies such as RabbitMQ, Kubernetes, GRPC, GraphQL etc.

Resources

Rate this Article

Adoption Stage
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? by Jakob Jenkov

How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? I am not trying to be condescending here - just trying to figure out what it is about these other platforms that did not address the itch Micronaut is scratching.

I am myself working on a distributed systems toolkit - albeit it is not desgined for microservices or HTTP-like communication etc. etc. so we had to write it ourselves.

Re: How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? by Graeme Rocher

Hi Jakob,

The Java framework world is divided into frameworks that take an opinionated approach (Spring Boot, Grails, Jakarta EE) using an annotation-driven model and those that take an unopinionated approach (Ratpack, Netty, Vert.x etc.) where you have to piece together your application from various components manually.

Whilst it is true some aspects of Micronaut can be achieved with Ratpack/Vert.x etc by manually configuring components yourself, the popularity of Spring Boot, Grails etc. in the Java community is testament to the fact that developers overwhelmingly prefer a framework to have opinions and don't want to have to manually figure out how to setup MongoDB, or how to integrate service discovery or how to achieve retry and failover etc.

The problem is today's frameworks that feature out-of-the-box experiences come with the performance and memory consumption compromises I mentioned in the article. Micronaut is trying to provide the opinionated, out-of-the-box, annotation-driven experience you get with Spring Boot and Grails that is the most popular with the vast majority of Java developers today, but the memory consumption and startup performance of the piece it together yourself toolkits like Netty, Vert.x, Ratpack etc.

Re: How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? by Jakob Jenkov

Hi Graeme, thank you for your elaboration. Could you provide an example of a "feature" / "aspect" that you have done different than Spring, so I can understand in what way Micronaut is different? I understand that it *is* different - and within the realms of memory consumption etc. but not how.

Regarding opiniated / unopiniated frameworks, I think they appeal to different types of developers. I now have 20 years of experience. In my first 5-8 years I loved frameworks like Spring. However, as I gained more experience, I felt I needed a framework's "opinion" less and less. Now I avoid them. What is your take on this?

Re: How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? by Graeme Rocher

The primary difference is that Spring/Jakarta EE/MicroProfile etc. performs DI, AOP and Configuration Management at runtime using reflection, Micronaut does it at compile time. You can see a more detailed explanation here: objectcomputing.com/news/2018/10/08/micronaut-1...

Regarding opiniated / unopinionated frameworks, the diversity available in the Java ecosystem is great, you have a range of frameworks appealing to a range of tastes and use cases. It is certainly true that as you gain experience you are more capable of stepping outside opinions, however IMO you and developers like you are most certainly in the minority when you look at framework adoption / marketshare stats. Java developers as a whole overwhelmingly prefer annotation-based, opinionated frameworks.

As for myself I regard myself as a pretty experienced developer and most certainly see the value in frameworks like Spring and Jakarta EE. Sure you could roll your own framework, and some developers go down that path, but you will inevitably end up repeated tried and tested patterns already available.

Re: How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? by abhishek manocha

Opinions are good. Or rather right opinions are good.
It is the fundamental principles underlying "convention over configuration" or the design patterns lets say. It builds on knowledge built overtime and hence helps in not reinventing the wheel.

The hard part is to get the opinions right.

Re: How is Micronaut different from e.g. Ratpack, Netty or Vert.x ? by Jakob Jenkov

Hi Graeme, thanks again! ... this time I think it is I that has to clarify a bit :-)

I don't think that using "no frameworks" and writing everything myself is the solution. There is no reason to implement my own JSON parser, DI container etc. when there are excellent implementations available, that does everything I need.

The types of frameworks I tend to avoid are those that try to be a "one-stop-solution" for all kinds of different problems. Quite often some of these solutions are not good enough for what you need, and you need to introduce another solution, or work around the solution the framework provides etc. In many cases I would have preferred "no solution".

I liked Spring when it was primarily a DI container that helped you integrate many different toolkits into a coherent application. Then Spring tried to come bundled with solutions for everything under the sun - most of which weren't that great. Now you have the fight on every team about whether to "do it the Spring way", or "use your common sense" - constantly having to debate whether you really think you are smarter than the Spring team or not.

I agree, many developers tend to prefer this one-stop-solution type of frameworks, that seem to have a solution for every problem they might encounter.
My attitude is definitely not mainstream.

Anyways, this was never an argument against Micronaut. I like small toolkits - not big all-encompassing frameworks. I guess I was just trying to figure out in which category Micronaut fits, and how it is different from other players in that category :-)

Open source development takes a lot of work. I have great respect for anyone taking that on. Best of luck with Micronaut and any other open source project you are working on!

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

6 Discuss
BT