micronaut入門 with GraalVM

JJUGで取り上げられがちだったmicronautについて簡単なチュートリアル

## micronautについて
[Micronaut公式](https://micronaut.io/)

> モジュール式で簡単にテスト可能なマイクロサービスおよびサーバーレスアプリケーションを構築するための、JVMベースの最新のフルスタックフレームワーク。

ホームページの和訳ですが、非常にわかりやすく説明されてますね。
SpringBootをよりマイクロサービス、サーバーレスに重きを置いた感じですかね。
AWSLambdaなんかにのせられる？らしい

## 事前準備

その前にSDKMANをインストールする

-> % curl -s "https://get.sdkman.io" | bash


そしてmicronautインストール

```bash
-> % sdk install micronaut
```

mnコマンドが使えるようになったら成功です

```bash
-> % mn -V
| Micronaut Version: 1.2.6
| JVM Version: 1.8.0_202
```

## プロジェクト作成
micronautはGraalVMをサポートするオプションがあるので指定したうえでcreate-appする

```bash
-> % mn create-app micronaut-graal --features graal-native-image
# mn create-app プロジェクト名 --features graal-native-image
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/989a8bb0-da4e-7fab-f89d-c7581db1f8b8.png)

こんな感じのプロジェクトができたかと思います
Build.gradleを編集します

```build.gradle
plugins {
    id "com.github.johnrengelman.shadow" version "5.0.0"
    id "application"
    id "net.ltgt.apt-eclipse" version "0.21"
}



version "0.1"
group "micronaut.graal"

repositories {
    mavenCentral()
    maven { url "https://jcenter.bintray.com" }
}

configurations {
    // for dependencies that are needed for development only
    developmentOnly 
}

dependencies {
    annotationProcessor platform("io.micronaut:micronaut-bom:$micronautVersion")
    annotationProcessor "io.micronaut:micronaut-graal"
    annotationProcessor "io.micronaut:micronaut-inject-java"
    annotationProcessor "io.micronaut:micronaut-validation"
    compileOnly "com.oracle.substratevm:svm"
    implementation platform("io.micronaut:micronaut-bom:$micronautVersion")
    implementation "io.micronaut:micronaut-http-client"
    implementation "io.micronaut:micronaut-inject"
    implementation "io.micronaut:micronaut-validation"
    implementation "io.micronaut:micronaut-runtime"
    implementation "io.micronaut:micronaut-http-server-netty"
    runtimeOnly "ch.qos.logback:logback-classic:1.2.3"
    testAnnotationProcessor platform("io.micronaut:micronaut-bom:$micronautVersion")
    testAnnotationProcessor "io.micronaut:micronaut-inject-java"
    testImplementation platform("io.micronaut:micronaut-bom:$micronautVersion")
    testImplementation "org.junit.jupiter:junit-jupiter-api"
    testImplementation "io.micronaut.test:micronaut-test-junit5"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
}

test.classpath += configurations.developmentOnly

mainClassName = "micronaut.graal.Application"
// use JUnit 5 platform
test {
    useJUnitPlatform()
}

shadowJar {
    mergeServiceFiles()
}

run.classpath += configurations.developmentOnly
run.jvmArgs('-noverify', '-XX:TieredStopAtLevel=1', '-Dcom.sun.management.jmxremote')
tasks.withType(JavaCompile){
    options.encoding = "UTF-8"
    options.compilerArgs.add('-parameters')
}

```

次にControllerを作成します

```SampleController.java
package micronaut.graal.controller;

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

@Controller("/hello")
public class SampleController {
    @Get(produces = MediaType.TEXT_PLAIN)
    public String get() {
        return "Hello!";
    }
}
```

native-image.propertiesが作成されていなかった場合には作成する

```native-image.properties
Args = -H:IncludeResources=logback.xml|application.yml\
  -H:Name=example\
  -H:Class=micronaut.graal.Application
```

まずは普通に起動してみる

```bash
-> % ./gradlew run
Starting a Gradle Daemon (subsequent builds will be faster)

> Task :run
17:09:12.835 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 1151ms. Server Running: http://localhost:8080
<=========----> 75% EXECUTING [19s]
> :run
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/5e739e63-9bf8-7196-c15a-55568c37ad18.png)

1151msかかっていますね。SpringBootなどと比べるとこれだけでも結構早いかも

## native-image吐き出し

次にnative-imageを吐き出してみます

```bash
-> % ./docker-build.sh
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/4fe7d006-694e-4180-c273-3c18fdccfa2d.png)

かなり時間かかります。（僕は20分以上かかりました）

続いてnative-imageを実行してみます

```bash
-> % docker run -p 8080:8080 micronaut-graal
08:15:04.502 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 18ms. Server Running: http://95681aa99ad2:8080
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/f90d3612-375c-06a9-86ff-8271f40bc52a.png)

***18ms!!!!!***比べ物にならないくらいはやくなりましたね。

実際に叩けるか試すと

```bash
-> % curl http://localhost:8080/hello
Hello!
```

### Intellijではまりかけるポイント
GraalVMとは関係ないがMicronautアプリケーションをintellij上で動作させる上ではまりかけたポイント

main()を発火させても動かなかった。下記図のように起動オプションを設定すれば動いた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/82decebf-1df1-018c-b083-8a8c1f0e92b1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/3bf1da94-b8fb-e39c-4e77-067ca09ab1d5.png)