What is it, naokirin?

Micronaut に入門してみよう

結構前から気になりつつ、触ることができていなかった Micronaut に今回入門することができました。

micronaut.io

どんなものかは実際のページを見てもらうと早いと思いますが、以下にざっくりとした紹介を書いてみます。

  • マイクロサービスを見据えたJVM上のフルスタックフレームワーク
  • 単なるHTTPサーバーのフレームワークではなく、クライアント、サーバレスアプリケーションなどにも対応している
  • メモリ消費が少ない
  • 起動が早い
  • 現在は Java、Groovy、Kotlin に対応している(公式では Scalaに対応予定があるとのこと、Clojure は開発できる人がほしいらしい)
  • 対応するモジュールが豊富(RDB、Redis、Kafka、Elasticsearchなどがある )
  • Apache License v2

単なるHTTPサーバーフレームワークと捉えるよりも、マイクロサービス時代のフレームワークとして捉えるのが良さそうです。

今回、試しに実行する際に利用したバージョンを示します。

  • SDKMAN 5.7.3+337
  • Micronaut Version: 1.0.4
  • JVM Version: 1.8.0_181

Micronaut を導入する

SDKMAN をインストールする

Micronaut は SDKMAN を利用してインストールすることが推奨されているようなので、まずは SDKMAN をインストールします。

SDKMAN は JVM系のパッケージマネージャツールです。

sdk というコマンドを利用して、各種ツールのバージョンを含めて管理することができます。

$ curl -s "https://get.sdkman.io" | bash
$ source ~/.sdkman/bin/sdkman-init.sh
$ which sdk

これで SDKMAN のインストールができます。

Micronaut をインストールする

SDKMANをインストールしている場合は、すぐにインストールすることができます。

$ sdk install micronaut

これにより以下のコマンドが利用できるようになっているはずなので、確認をしてみてください。

$ mn --version

Micronaut のプロジェクトを作成する

まずは Micronaut プロジェクトの作成をしてみます。

今回は Kotlinによるプロジェクトを作成します。

$ mn create-app hello-world --features=kotlin

これにより、以下のようなディレクトリ構造を持つプロジェクトが作成されます。

.
├── Dockerfile
├── META-INF/
├── build.gradle
├── gradle/
├── gradle.properties
├── gradlew
├── gradlew.bat
├── micronaut-cli.yml
├── src
│   ├── kotlin
│   │   └── hello
│   │       └── world
│   └── resources
│       ├── application.yml
│       └── logback.xml
└── test
    ├── java
    │   └── hello
    │       └── world
    └── kotlin
        └── hello
            └── world

Dockerfile も生成されるので、gradle の shadow プラグインで jar ファイルをビルドしておけば、すぐにDockerイメージを作成できます。

IntelliJ IDEA で読み込んでみる

残念ながら、現時点では公式に Micronaut に対応した IntelliJ IDEA のプラグインは無いようです。

しかしながら、作成済みのプロジェクトをGradleプロジェクトとして読み込むことでコーディングなどは基本的に IntelliJ IDEA 上で行うことができます。

まずは Import Project を選択します。

f:id:naokirin:20190301234028j:plain

次に先程作成したプロジェクトのディレクトリを選択します。

そして、Gradleプロジェクトとしてインポートをします。

f:id:naokirin:20190301234531p:plain:w300

あとはそのままの設定で進めるとインポートされます。

次回からは普通にプロジェクトを開くことで、IntelliJ IDEAで開発をすることができます。

ただし、IntelliJ IDEA の Preferences から Annotation Processors を有効にしましょう。

f:id:naokirin:20190301235632p:plain:w600

Micronaut を実行してみよう

それではさっそくですが、この何も追加していないプロジェクトを実行してみます。

ですが、IntelliJ IDEA上で Build、その後Dockerの実行ではうまくいきません。理由としては、出力されるディレクトリや対応するjarファイルの形式が異なっていることが原因です。

ちなみに、 ./gradlew build をすると build/libs 以下に対応する jar ファイルが生成されるので、以下の変更は不要となります。IntelliJ IDEA 上である程度進めたい人向けになります。もう少し良い方法があるかもしれませんが、一旦可能な方法として記載しておきます。

IntelliJ IDEA 上でビルド、Dockerコンテナで実行する

まずは IntelliJ IDEA上では、Gradleのツールウィンドウを利用してビルドしましょう。

View −> Tool Windows -> Gradle を選択します。するとウィンドウが開きます。

下記画面の階層にある build コマンドを選びます。

f:id:naokirin:20190302005507p:plain:w300

すると、 build/libs/hello-world-0.1.jar が生成されます。これは単一のjarファイルとして実行可能なようになっています。

ちなみに2回目以降は、Gradleのツールウィンドウ上部で実行できるようになるので、簡単になります。

次にDockerイメージのビルドを行うのですが、最初に生成された Dockerfile は build/libs/hello-world-0.1-all.jar を対象としています。これは、GradleのShadowプラグインの 5.0.0からの変更なので、おそらく今後生成されるDockerfileが修正されるとは思います。

残念ながら現状はそうなっているので、Dockerfile内の以下の行の変更を行います。

- COPY build/libs/*-all.jar hello-world.jar
+ COPY build/libs/*.jar hello-world.jar

- の方を削除して、 + の方を追加します。これにより、Dockerで実行できるところまで進められます。

それでは早速実行してみます。

$ docker build . -t hello-world-micronaut && docker run --rm -it -p 8080:8080 hello-world-micronaut

これで、http://localhost:8080 にアクセスします。

{"_links":{"self":{"href":"/","templated":false}},"message":"Page Not Found"}

まだページがないので、JSON形式で "Page Not Found" が返ってきます。

Controller を追加してみよう

それでは、Controller を追加して、レスポンスを返すようにしてみましょう。

まずはコマンドで Controller のソースファイルを生成しましょう。

$ mn create-controller helloController 

src/main/kotlin/hello/world/HelloController.ktsrc/test/kotlin/hello/world/HelloControllerTest.kt が生成されます。

見ての通り、前者はアプリケーション側のファイル、後者はテストコード用のファイルです。

今回はテストコード側には触れずに、アプリケーション側だけを触ります。

実はこの時点でも、 http://localhost:8080/hello に正常にアクセスすることができるようになっているのですが、レスポンスとして 200 を返すだけなので、プレーンテキストを返してみましょう。

今回は、 localhost:8080/hello/hogehoge にアクセスしたら、 Hello, hogehoge と返ってくるようにしましょう。

// src/main/kotlin/hello/world/HelloController.kt

package hello.world

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

@Controller("/")
class HelloController {

    @Get("/hello/{name}")
    fun hello(name: String): String {
        return "Hello, $name"
    }
}

ソースコードを変更したら、 ビルド、Dockerイメージのビルド、コンテナの実行の順に行いましょう。ちなみに、開発の手間を抑えるために IntelliJIDEA 上の Gradle のウィンドウで application 以下の run を実行することでも確認することができます。

また、 jarファイルを直接実行したり、 gradlew run するなどでも動かすことができます。

f:id:naokirin:20190302013749p:plain:w400

アノテーションによってかなり直感的にコードを書くことができるようになっているため、説明がなくてもどのような挙動になっているかわかるかと思います。

まとめ

正直、導入やIntelliJ IDEAでの利用部分のほうが多くなってしまいました。

まだ IDEの対応が手厚いといった状況ではないのと、多くのフレームワークで導入されているような自動リロードがないあたりは、他のフレームワークからの移行の際にはネックになるかもしれません。

しかし軽量な部分などはかなり面白いところであったり、サーバー、クライアント、サーバーレスなアプリケーションを同一フレームワークで開発できるのも魅力として今後より際立ってくるかもしれません。

まだまだ始めたばかりなので、評価できるほど深く利用できていませんが、これまでにない方向性で作られているので、今後何らかの有名な開発で利用された実績が出たりすると状況が変わるかもしれませんね。