MicronautでHelloWorld
Micronautとは
Grailsの開発チームが新たに作成しているJVMベースのマイクロサービスのためのフルスタックフレームワークです。 Micronaut 大きな特徴としては、Springベースではない、起動が早い、Java、Apache Groovy、Kotlinでコードを書ける、などが有ります。 もちろん他にも素敵な機能が満載なのですが、私の理解が追いついていません。興味の有る方は是非公式サイトをご覧ください。
Grailsの開発チームが開発を主導しているようなので、今後Grailsの開発よりこのMicronautの方によりリソースが割かれるのかな。。。?という暗い思いも有りますが、何はともあれ先ずは触ってみようということでHelloWorldを書いてみました。
インストール
SDKMANですでにインストールできるので当然SDKMANでインストールします!
[koji:micronaut]$ sdk list micronaut
================================================================================
Available Micronaut Versions
================================================================================
1.0.0.M1
[koji:micronaut]$ sdk install micronaut
Downloading: micronaut 1.0.0.M1
In progress...
######################################################################## 100,0%
Installing: micronaut 1.0.0.M1
Done installing!
Setting micronaut 1.0.0.M1 as default.
[koji:micronaut]$
これでMicronautのインストールは完了です。
すでにMicronautのCLI用コマンドであるmn
が利用できるようになっています。
[koji:micronaut]$ mn help
Usage (optionals marked with *):'
mn [target] [arguments]*'
| Examples:
$ mn create-app my-app
| Language support for Groovy and/or Kotlin can be enabled with the corresponding feature::
$ mn create-app my-groovy-app -features=groovy
$ mn create-app my-kotlin-app -features=kotlin
| Available Commands (type mn help 'command-name' for more info):
| Command Name Command Description
----------------------------------------------------------------------------------------------------
create-app Creates an application
create-federation Creates a federation of services
create-function Creates a serverless function application
create-profile Creates a profile
help Prints help information for a specific command
list-profiles Lists the available profiles
profile-info Display information about a given profile
| Detailed usage with help [command]
[koji:micronaut]$
Hello World
では早速Hello Worldしてみます。
Micronautアプリケーションの作成
先ほど利用できるようになったmn
コマンドを使ってMicronautアプリケーションを作成します。
[koji:micronaut]$ mn create-app hello-world
| Application created at /home/koji/work/micronaut/hello-world
[koji:micronaut]$
Micronautの起動
作成したMicronautアプリケーションのディレクトリに移動して、gradlew run
を実行するだけです。
初回起動時は、ライブラリのダウンロードが入るので時間がかかるのでしばし待ちます。
[koji:micronaut]$ cd hello-world
[koji:hello-world]$ ./gradlew run
> Task :run
10:25:38.657 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1239ms. Server Running: http://localhost:24419
メッセージ−通り、http://localhost:24419
にアクセスすればMicronautoが起動していることが確認できます。
ブラウザでアクセスすると
{"_links":{"self":{"href":"/","templated":false}},"message":"Page Not Found"}
というメッセージが表示され、ちゃんと、Micronautが起動していることが確認できます。
起動ポートの指定
デフォルトでは毎回空いているポートをMicronautが勝手に探してランダムに使うようです。
ポートを固定したい場合は、src/main/resources/application.yml
に以下の用にポートを指定するようにします。
micronaut:
application:
name: hello-world
server: # この2行を追加
port: 8080
独自のコントローラ
以下のファイルを作成します。
src/main/groovy/hello/world/HelloController.java
※Micronautアプリケーション名にハイフンを入れてしまったので、パッケージ名的にハイフンが使えないため、以下のようにhello.world
というパッケージになっています。
package hello.world;
import io.micronaut.http.annotation.*;
@Controller("/hello")
public class HelloController {
@Get("/")
public String index() {
return "Hello World";
}
}
これで一旦Micronautを終了して再度起動すれば、http://localhost:8080/hello
でこのHelloWorldにアクセスできます。
余計な設定ファイルなどを書く必要がなくてとってもシンプルで良いですね!
なお、上記のように単純に文字列をreturnした場合、JSONとしてクライアントに返されます。
[koji:~]$ curl -D - http://localhost:8080/hello
HTTP/1.1 200 OK
content-type: application/json
content-length: 11
Hello World%
[koji:~]$
Groovyを利用する
さて、Micronautoは公式でJava、Apache Groovy、Kotlinで利用できるよ!と謳っています。 ということで実際に今回Apache Groovyも利用できるようにしてみました。
build.gradleの修正
長いので、追加した部分の前後を抜粋です。
なお、サンプルリポジトリのbuild.gradle
からApache Groovyに関する記述を全て抜き出してきているので、不要なものも含まれているかもしれません。
version "0.1"
group "hello.world"
apply plugin:"io.spring.dependency-management"
apply plugin:"com.github.johnrengelman.shadow"
apply plugin:"application"
apply plugin:"java"
apply plugin:"net.ltgt.apt-eclipse"
apply plugin:"net.ltgt.apt-idea"
apply plugin:"groovy" // これを追加
...省略...
dependencies {
annotationProcessor "io.micronaut:inject-java"
compile "io.micronaut:http-client"
compile "io.micronaut:http-server-netty"
compile "io.micronaut:inject"
compile "io.micronaut:runtime"
compileOnly "io.micronaut:inject-java"
runtime "ch.qos.logback:logback-classic:1.2.3"
testCompile "junit:junit:4.12"
testCompile "io.micronaut:inject-java"
// 以下を追加
compile "io.micronaut:runtime-groovy"
compileOnly "io.micronaut:inject-groovy"
testCompile "io.micronaut:inject-groovy"
testCompile("org.spockframework:spock-core:1.1-groovy-2.4") {
exclude module: 'groovy-all'
}
}
コントローラを作成する
これでApache GroovyをMicronautで利用する準備が整いました。 Apache Groovy用のControllerを作成します。
src/main/groovy/hello/world/HelloGroovyController.groovy
package hello.world
import io.micronaut.http.annotation.*
@Controller("/hello-groovy")
class HelloGroovyController {
@Get("/")
def index() {
"Hello Groovy (version:${GroovySystem.version})"
}
}
これで一旦Micronautを終了して再度起動すれば、http://localhost:8080/hello-groovy
でこのHelloWorldにアクセスできます。
ちなみに、実際にURLにアクセスすれば分かりますが、Micronautが利用しているApache Groovyのバージョンは現時点では2.5.0-rc-3
となっています。
これまた簡単にコントローラを作成できました。さすがApache Groovy!
Kotlinを利用する
さて、どんどん勢いを増しているKotlinでも試してみます。
build.gradleの修正
buildscript {
...省略...
dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:2.0.4"
classpath "io.spring.gradle:dependency-management-plugin:1.0.5.RELEASE"
classpath "net.ltgt.gradle:gradle-apt-plugin:0.15"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" // Added for Kotlin
}
}
...省略...
apply plugin:"net.ltgt.apt-idea"
apply plugin:"groovy" // Addef for Groovy
apply plugin: "kotlin" // Added for Kotlin
apply plugin: 'kotlin-kapt' // Added for Kotlin
...省略...
dependencies {
...省略...
// Added for Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
kapt "io.micronaut:inject-java:$projectVersion"
kaptTest "io.micronaut:inject-java:$projectVersion"
}
...省略...
// Added for Kotlin
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
gradle.propertiesの作成
build.gradle
が有るディレクトリに、gradle.properties
を作成してKotlin等のバージョンを指定します。
projectVersion=1.0.0-SNAPSHOT
kotlinVersion=1.2.30
spekVersion=1.1.5
junitVersion=5.1.0
コントローラを作成する
後は普通にKotlinコードを書くだけです!
src/main/kotlin/hello/world/HelloKotlinController.kt
package hello.world
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
@Controller("/hello-kotlin")
class HelloKotlinController {
@Get("/")
fun index(): String {
return "Hello Kotlin"
}
}
これで一旦Micronautを終了して再度起動すれば、http://localhost:8080/hello-kotlin
でこのHelloWorldにアクセスできます。
何の問題もなくJava、ApacheGroovyそしてKotlinが同じMicronautインスタンスで利用できました!これは素敵ですね!
ユニットテスト
みんな大好きユニットテスト!
ということで、今回はSpockを使って、1ファイルのテストでJavaとApache Groovy、Kotlinのコントローラをテストしてみます。
Spockに必要なライブラリも、すでに上記のGroovyを利用する
の部分でbuild.gradle
に追加しているので、他に必要なものはありません。
実際にテストを用意するだけです!
Unitテストは、src/main
配下に設置します。今回はSpock(Groovy)で、テスト対象と同じパッケージでテストを作成しますので、src/test/groovy/hello/world/MyTestSpec.groovy
というファイルを作成します。
中身は以下です。
package hello.world
import io.micronaut.context.ApplicationContext
import io.micronaut.runtime.server.EmbeddedServer
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification
class MyTestSpec extends Specification {
@Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)
void "Test for Java code"() {
setup:
HelloController client = embeddedServer.applicationContext.getBean(HelloController)
expect:
client.index() == "Hello World"
}
void "Test for Groovy code"() {
setup:
// このUnitテスト自体はGroovyなので当然以下のようにdefで変数宣言OK
def client = embeddedServer.applicationContext.getBean(HelloGroovyController)
expect:
client.index() == "Hello Groovy (version:2.5.0-rc-3)"
}
void "Test for Kotlin code"() {
setup:
def client = embeddedServer.applicationContext.getBean(HelloKotlinController)
expect:
client.index() == "Hello Kotlin"
}
}
テストを実行するのも簡単で、./gradlew test
でOKです。
これでなんとこの1ファイルのみで問題なくJavaとApache Groovy、そしてKotlinのコードをテストすることが出来ました!非常にお手軽です。
普通ならテスト対象のクラスごとにテストファイルを作るべきですが、Micronautがいかに綺麗にこれらを統合して簡単に扱えるようにしてくれているかが伺えますね。
開発時の自動リロードについて
モダンなJVM系フレームワークなら、ソースの変更を自動で検知して、コンパイル&リロードしてくれる仕組みが有ります。 が、現状Micronautにはそのような仕組みは用意されていないようです。 Add support for live reloadingに要望は出されているのでそのうち機能が追加されるかもしれませんが、開発者の方が、「Micronautの起動は高速なので、IDEで開発して常にIDEの中でUnitテストを走らせる事ができるよ。」とコメントしているので、実際のところはこの自動リロード機能は重要視していないようです。 確かにMicronaut自体がMicroframeworkを謳っていますし、もうUnitテストが必須、という時代なのでそのアプローチのほうが正しいのかもしれないですね。
感想
まだHelloWorld程度なので何が優れているのか、という点を語るほどの理解には達していません。 が、Springベースじゃない点と、最初からJava、Apache Groovy、Kotlinに対応しているよ、と明言している点などが、なんだか好きな物使って開発すればいいじゃん!楽しくやろうぜ!と言っているように感じられました。 その牧歌的な空気感が、私がApache Groovyが大好きな理由と絶妙にマッチしていて、なんだかMicronautも好きになれそうな気がします。 もちろん、標準でServerlessに対応するための機能などが用意されているなど、モダンで先進的な機能も有りますので、今後もMicronautを試してその魅力の発見、発信をしていきたいと思います。
公開日:2018/05/30