算譜王におれはなる!!!!

偏りはあると思うけど情報技術全般についてマイペースに書くよ。

Kotlin Developers Meetup #jkug でSpring Fuの紹介LTをしたよ〜

JetBrainsのDeveloper AdvocacyであるHadi HaririさんがGoogle for Mobile I/O RECAP 2018のために来日するということで、 Hadiさんはもとより、Googleさんにもご協力いただき日本Kotlinユーザグループによるイベントを6/27に開催しました。

kotlin.connpass.com

僕自身はあまり運営を手伝えなかったのですが、ライトニングトークをしてきました。 下にあるのがそのスライドです。

Spring Fuという、Springの新しいプロジェクトを使って、GraalVMの上で動かしたいという旨の発表でした。

Spring Fu

Spring Fuは、Kotlin向けのマイクロ・フレームワークで、Sparkや、Spring 5のFunctional Bean Registrationを思わせるAPIが提供されています。 始めるのは簡単です。 公式ドキュメントから、プロジェクトの雛形がダウンロードできます。 入手したzipファイルを展開して、それをIntelliJ IDEAなどのエディタで開けば、開発を始められます。

f:id:ngsw_taro:20180630120430p:plain

初期状態のまま./gradlew bootRunするとHelloWorld Webアプリケーションが起動するので、http://localhost:8080をブラウザで開くと「Hello world!」と表示されます。

公式ドキュメントを参考に、DI機能を試してみます。

package com.example

import org.springframework.fu.application
import org.springframework.fu.module.webflux.netty.netty
import org.springframework.fu.module.webflux.webflux
import org.springframework.fu.ref

class HelloService {
    fun hello(): String = "Hello world!"
}

val app = application {
    // bean登録
    bean<HelloService>()

    webflux {
        server(netty(8080)) {
            routes {
                // beanのインジェクション
                val helloService = ref<HelloService>()

                GET("/") {
                    val body = helloService.hello()
                    ok().syncBody(body)
                }
            }
        }
    }
}

fun main(args: Array<String>) = app.run(await = true)

これ、うまく行きそうなんですが、アプリケーションを起動しようとすると失敗します。 そのときに吐かれる例外メッセージはこんな感じです。

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webHandler': Unexpected exception during bean creation; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property context has not been initialized

lateinit付きの遅延初期化されるプロパティcontextが、初期化されていないのにアクセスがあったようです。 丁寧に調査してから、修正してプルリクエストを送りたいところですが、さしあたり、次のコードでこの問題を回避できます。

package com.example

import org.springframework.fu.application
import org.springframework.fu.module.webflux.netty.netty
import org.springframework.fu.module.webflux.webflux
import org.springframework.fu.ref

class HelloService {
    fun hello(): String = "Hello world!"
}

val app = application {
    // bean登録
    bean<HelloService>()

    webflux {
        server(netty(8080)) {
            routes {
                // ↓の1行を追加する
                this.context = this@server.context

                // beanのインジェクション
                val helloService = ref<HelloService>()

                GET("/") {
                    val body = helloService.hello()
                    ok().syncBody(body)
                }
            }
        }
    }
}

fun main(args: Array<String>) = app.run(await = true)

GraalVM

これはオマケなんですが、Spring Fuで作ったWebアプリケーションをGraalVMで動かしてみたいと思いました。 特にAOTコンパイラで、ネイティブの実行バイナリを作って、それを動かせたらすごいなぁと考えていました。

GraalVMには、Community Edition(CE)とEnterprise Edition(EE)の2つのバージョンが提供されていて、今回はCEを使いました。 CEは現在のところ、Linux上でしか動作せず、Macで直接動かすことはできないようです。 そこで、rayyildiz/graalvmというDockerイメージを使いました。 また、GraalVMのAOTコンパイルを行うコマンドnative-imageが依存するパッケージをインストールする必要があります。 gcczlib1g-devです。

結論から言うと、Spring FuアプリケーションをAOTコンパイルすることはできませんでした。 コンパイルに失敗します。 試してから気づいたのですが、Spring Fuのissueとしてすでに登録がありました。

github.com

Hadiさんと食事行ってきました

Hadiさんと山本ユースケさんと食事に行ってきました!

Kotlin Fest 2018

やります!!!詳細は近日発表予定です!!!!