Creating your first Micronaut Graal application

Learn how to create a Hello World Micronaut Graal application.

Authors: Iván López, Sergio del Amo

Micronaut Version: 1.1.0.M1

1 Getting Started

In this guide we are going to create a Micronaut application with Graal support.

1.1 What you will need

To complete this guide, you will need the following:

  • Some time on your hands

  • A decent text editor or IDE

  • JDK 1.8 or greater installed with JAVA_HOME configured appropriately

1.2 Solution

We recommend you to follow the instructions in the next sections and create the app step by step. However, you can go right to the completed example.

or

Then, cd into the complete folder which you will find in the root project of the downloaded/cloned project.

2 Writing the App

Create an app using the Micronaut Command Line Interface.

mn create-app example.micronaut.complete --features=graal-native-image

The previous command creates a micronaut app with the default package example.micronaut in a folder named complete and with support for Graal.

If you are using Java or Kotlin and IntelliJ IDEA make sure you have enabled annotation processing.

annotationprocessorsintellij

3 Service

Create a POJO Conference.java:

src/main/java/example/micronaut/Conference.java
package example.micronaut;

public class Conference {
    private String name;

    public Conference(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Create a Service:

src/main/java/example/micronaut/ConferenceService.java
package example.micronaut;

import javax.inject.Singleton;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

@Singleton (1)
public class ConferenceService {

    private static final List<Conference> CONFERENCES = Arrays.asList(
            new Conference("Greach"),
            new Conference("GR8Conf EU"),
            new Conference("Micronaut Summit"),
            new Conference("Devoxx Belgium"),
            new Conference("Oracle Code One"),
            new Conference("CommitConf"),
            new Conference("Codemotion Madrid")
    );

    public Conference randomConf() { (2)
        return CONFERENCES.get(new Random().nextInt(CONFERENCES.size()));
    }
}
1 Use javax.inject.Singleton to designate a class a a singleton.
2 Return a random conference.

4 Controller

Create a Controller with a method that returns a Conference. Micronaut will convert it automatically to JSON in the response:

src/main/java/example/micronaut/ConferenceController.java
package example.micronaut;

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

@Controller("/conferences") (1)
public class ConferenceController {

    private final ConferenceService conferenceService;

    public ConferenceController(ConferenceService conferenceService) { (2)
        this.conferenceService = conferenceService;
    }

    @Get("/random") (3)
    public Conference randomConf() { (4)
        return conferenceService.randomConf();
    }
}
1 The class is defined as a controller with the @Controller annotation mapped to the path /conferences.
2 Constructor injection
3 The @Get annotation is used to map the index method to all requests that use an HTTP GET
4 Return a Conference.

5 Adding Graal support

GraalVM is a new universal virtual machine from Oracle that supports a polyglot runtime environment and the ability to compile Java applications down to native machine code.

Any Micronaut application can be run using the GraalVM JVM, however special support has been added to Micronaut to support running Micronaut applications using GraalVM’s nativeimage tool.

Use of GraalVM’s nativeimage tool is only supported in Java or Kotlin projects. Groovy relies heavily on reflection which is only partially supported by GraalVM.

5.1 Creating Graal native image

When we created the application we used the graal-native-image feature. This feature adds four important items:

  • A MicronautSubstitutions.java file needed to recompute Netty and Caffeine’s use of Unsafe.

  • svm and graal dependencies in build.gradle:

build.gradle
compileOnly "com.oracle.substratevm:svm"
runtime "io.micronaut:micronaut-graal"
  • A Dockerfile which can be used to construct the native image executing docker-build.sh

  • A build-native-image.sh script to build the native image outside Docker.

Creating native image inside Docker

With this approach you only need to have Docker installed because it will download the required images, if necessary.

The provided Dockerfile is a multi-stage dockerfile which builds the project in three steps:

  1. A Gradle or Maven image will build the project

  2. A GraalVM official image will build the native image

  3. A typical dockerfile structure will build the final image which is smaller due to layering

Building Graal native image
$ ./docker-build.sh

The previous command will create the image complete:latest. To execute it:

Executing the native image
$ docker run --network host complete
10:29:46.845 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 12ms. Server Running: http://nobita:8080

We can see that the application starts in only 12ms.

We use the option --network host to use the same network as the host and expose automatically all the ports

Creating native image outside Docker

For this approach you need to use Linux or Mac. As this moment GraalVM is not supported on Windows.
Building Graal native image
$ sdk use java 1.0.0-rc-12-grl
$ ./build-native-image.sh

The previous commmand will create a native executable called complete.

Sending a request

Start the application either using Docker or the native executable. You can run a few cURL requests to test the application:

complete $ time curl localhost:8080/conferences/random
{"name":"Oracle Code One"}
real    0m0.016s
user    0m0.005s
sys     0m0.004s

complete $ time curl localhost:8080/conferences/random
{"name":"GR8Conf EU"}
real    0m0.014s
user    0m0.005s
sys     0m0.004s

6 Next steps

Read more about Graal Support inside Micronaut.