×

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

MMS Founder
MMS RSS

Article originally posted on InfoQ. Visit InfoQ

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 their 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. I 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 this 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 a 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 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

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.