LoginSignup
5
1

More than 1 year has passed since last update.

Micronaut 3を使ってみる

Last updated at Posted at 2021-12-03

What's?

TIS Advent Calendar 2021に参加ということで。

2年ほど前にMicronaut 1.0で遊んでいたことがあるのですが、気づくと3.0を超えていたので、この機会に久しぶりに触ってみようかなと。

Micronautとは、フルスタックのマイクロサービスやサーバーレスに向くと謳われているフレームワークです。

環境

今回の環境はこちらです。

$ java --version
openjdk 11.0.11 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 11.0.11, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-91-generic", arch: "amd64", family: "unix"

CLIのインストールとプロジェクトの作成

まずは、MicronautのCLIをインストールします。

SDKMANを使って行います。

$ sdk install micronaut

現在のMicronautのバージョンは、3.2.0です。

$ mn --version
Micronaut Version: 3.2.0

そのまま続けて、プロジェクトを作成します。ビルドツールは、Mavenにしました。

$ mn create-app hello-micronaut3 --build maven

プロジェクト内に移動。

$ cd hello-micronaut3

こんな感じの構成になっています。

$ tree
.
├── README.md
├── micronaut-cli.yml
├── mvnw
├── mvnw.bat
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── hello
    │   │       └── micronaut3
    │   │           └── Application.java
    │   └── resources
    │       ├── application.yml
    │       └── logback.xml
    └── test
        └── java
            └── hello
                └── micronaut3
                    └── HelloMicronaut3Test.java

10 directories, 9 files

含まれているJavaソースコードと

src/main/java/hello/micronaut3/Application.java
package hello.micronaut3;

import io.micronaut.runtime.Micronaut;

public class Application {

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

pom.xml

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>hello.micronaut3</groupId>
  <artifactId>hello-micronaut3</artifactId>
  <version>0.1</version>
  <packaging>${packaging}</packaging>

  <parent>
    <groupId>io.micronaut</groupId>
    <artifactId>micronaut-parent</artifactId>
    <version>3.2.0</version>
  </parent>

  <properties>
    <packaging>jar</packaging>
    <jdk.version>11</jdk.version>
    <release.version>11</release.version>
    <micronaut.version>3.2.0</micronaut.version>
    <exec.mainClass>hello.micronaut3.Application</exec.mainClass>
    <micronaut.runtime>netty</micronaut.runtime>
  </properties>

  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
    </repository>
  </repositories>

  <dependencies>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-inject</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-validation</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut.test</groupId>
      <artifactId>micronaut-test-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-http-client</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-http-server-netty</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-runtime</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>io.micronaut.build</groupId>
        <artifactId>micronaut-maven-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <!-- Uncomment to enable incremental compilation -->
          <!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->

          <annotationProcessorPaths combine.children="append">
            <path>
              <groupId>io.micronaut</groupId>
              <artifactId>micronaut-http-validation</artifactId>
              <version>${micronaut.version}</version>
            </path>
          </annotationProcessorPaths>
          <compilerArgs>
            <arg>-Amicronaut.processing.group=hello.micronaut3</arg>
            <arg>-Amicronaut.processing.module=hello-micronaut3</arg>
          </compilerArgs>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

アプリケーションを書いてみる

こちらを見ながら、簡単なアプリケーションを作ってみましょう。

Creating a Server Application

DIも使っておきます。

Inversion of Control

Controllerの作成。

src/main/java/hello/micronaut3/HelloController.java
package hello.micronaut3;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Inject;

@Controller("/hello")
public class HelloController {
    @Inject
    MessageService messageService;

    @Get(produces = MediaType.TEXT_PLAIN)
    public String index() {
        return messageService.get();
    }
}

Beanの作成。

src/main/java/hello/micronaut3/MessageService.java
package hello.micronaut3;

import jakarta.inject.Singleton;

@Singleton
public class MessageService {
    public String get() {
        return "Hello Micronaut 3!!";
    }
}

Micronaut Maven Pluginで起動。

$ mvn mn:run

こんな感じのバナーが表示されます。

 __  __ _                                  _   
|  \/  (_) ___ _ __ ___  _ __   __ _ _   _| |_ 
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
| |  | | | (__| | | (_) | | | | (_| | |_| | |_ 
|_|  |_|_|\___|_|  \___/|_| |_|\__,_|\__,_|\__|
  Micronaut (v3.2.0)

17:13:26.550 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 974ms. Server Running: http://localhost:8080

確認。

$ curl localhost:8080/hello
Hello Micronaut 3!!

OKですね。

次は、パッケージングしてJARファイルを作成しましょう。

$ mvn package

起動。

$ java -jar target/hello-micronaut3-0.1.jar
 __  __ _                                  _   
|  \/  (_) ___ _ __ ___  _ __   __ _ _   _| |_ 
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
| |  | | | (__| | | (_) | | | | (_| | |_| | |_ 
|_|  |_|_|\___|_|  \___/|_| |_|\__,_|\__,_|\__|
  Micronaut (v3.2.0)

17:14:18.344 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 957ms. Server Running: http://localhost:8080

っていうか、起動速いですね。

Startup completed in 957ms.

結果は同じなので、割愛。

ネイティブイメージを作成する

最後に、このアプリケーションをネイティブイメージにしたいと思います。

Microservices as GraalVM native images

GraalVMをインストールせずにDockerを使ってビルドする方法もあるようですが、今回はGraalVMをインストールしてビルドすることにします。

GraalVMもSDKMANでインストール。native-imageツールもインストールしておきます。

$ sdk install java 21.3.0.r11-grl
$ sdk install java 21.3.0.r11-grl
$ gu install native-image

GraalVMとnative-imageツールがインストールされました。

$ java --version
openjdk 11.0.13 2021-10-19
OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05)
OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05, mixed mode, sharing)


$ native-image --version
GraalVM 21.3.0 Java 11 CE (Java Version 11.0.13+7-jvmci-21.3-b05)

-Dpackaging=native-imageを指定して、パッケージング。

$ mvn package -Dpackaging=native-image

だいぶ時間がかかりますが、なんとか完了します。

[hello-micronaut3:208224]    classlist:   4,339.55 ms,  0.96 GB
[hello-micronaut3:208224]        (cap):     802.08 ms,  0.96 GB
[hello-micronaut3:208224]        setup:   3,730.72 ms,  0.96 GB
Warning: class initialization of class io.micronaut.http.server.$CoroutineHelper$Definition failed with exception java.lang.NoClassDefFoundError: kotlin/coroutines/CoroutineContext. This class will be initialized at run time because option --allow-incomplete-classpath is used for image building. Use the option --initialize-at-run-time=io.micronaut.http.server.$CoroutineHelper$Definition to explicitly request delayed initialization of this class.
[hello-micronaut3:208224]     (clinit):   2,268.13 ms,  3.58 GB
[hello-micronaut3:208224]   (typeflow):  15,282.40 ms,  3.58 GB
[hello-micronaut3:208224]    (objects): 140,670.17 ms,  3.58 GB
[hello-micronaut3:208224]   (features):  25,422.79 ms,  3.58 GB
[hello-micronaut3:208224]     analysis: 192,424.77 ms,  3.58 GB
[hello-micronaut3:208224]     universe:  20,954.42 ms,  3.58 GB
[hello-micronaut3:208224]      (parse):   5,223.66 ms,  3.61 GB
[hello-micronaut3:208224]     (inline):  18,816.18 ms,  3.48 GB
[hello-micronaut3:208224]    (compile):  99,596.81 ms,  3.71 GB
[hello-micronaut3:208224]      compile: 141,904.16 ms,  3.71 GB
[hello-micronaut3:208224]        image:  15,093.41 ms,  3.71 GB
[hello-micronaut3:208224]        write:   3,054.96 ms,  3.71 GB
[hello-micronaut3:208224]      [total]: 382,040.97 ms,  3.71 GB
# Printing build artifacts to: /path/to/target/hello-micronaut3.build_artifacts.txt
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  06:27 min
[INFO] Finished at: 2021-12-03T17:21:50+09:00
[INFO] ------------------------------------------------------------------------

ネイティブイメージができあがりました。

$ file target/hello-micronaut3 
target/hello-micronaut3: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ceca748796f73559894e78c43bb90f0de66038a1, for GNU/Linux 3.2.0, with debug_info, not stripped

起動。

$ ./target/hello-micronaut3 
 __  __ _                                  _   
|  \/  (_) ___ _ __ ___  _ __   __ _ _   _| |_ 
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
| |  | | | (__| | | (_) | | | | (_| | |_| | |_ 
|_|  |_|_|\___|_|  \___/|_| |_|\__,_|\__,_|\__|
  Micronaut (v3.2.0)

17:22:42.238 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 63ms. Server Running: http://localhost:8080

起動速度がめちゃくちゃ速くなりました。

Startup completed in 63ms.

動作確認。

$ curl localhost:8080/hello
Hello Micronaut 3!!

補足

GraalVMをインストールせずとも、Dockerを使うとネイティブイメージを作れるようです。

$ mvn package -Dpackaging=docker-native -Pgraalvm

この場合、GraalVMのアーティファクトをダウンロードしてきます。

[INFO] ---------------------------[ docker-native ]----------------------------
Downloading from central: https://repo.maven.apache.org/maven2/org/graalvm/sdk/graal-sdk/21.3.0/graal-sdk-21.3.0.pom
Downloaded from central: https://repo.maven.apache.org/maven2/org/graalvm/sdk/graal-sdk/21.3.0/graal-sdk-21.3.0.pom (1.4 kB at 340 B/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/graalvm/nativeimage/svm/21.3.0/svm-21.3.0.pom
Downloaded from central: https://repo.maven.apache.org/maven2/org/graalvm/nativeimage/svm/21.3.0/svm-21.3.0.pom (1.9 kB at 8.3 kB/s)
...

こんなディレクトリツリーになります。

$ tree $HOME/.m2/repository/org/graalvm -d
$HOME/.m2/repository/org/graalvm
├── buildtools
│   ├── junit-platform-native
│   │   └── 0.9.7.1
│   ├── native-maven-plugin
│   │   └── 0.9.7.1
│   └── utils
│       └── 0.9.7.1
├── compiler
│   └── compiler
│       └── 21.3.0
├── nativeimage
│   ├── objectfile
│   │   └── 21.3.0
│   ├── pointsto
│   │   └── 21.3.0
│   └── svm
│       └── 21.3.0
├── sdk
│   └── graal-sdk
│       └── 21.3.0
└── truffle
    └── truffle-api
        └── 21.3.0

23 directories

が、手元の環境の事情で、Dockerイメージを使ってビルドする最中に失敗してしまうので…。

回避方法はまた別途探そうかなと思います。

こんなところで?

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1