vert.x+Scala build with GradleでWebサービス作ってみる

こんにちは、えいやです。

今日はVert.xの検証を始めたのでメモを残します。

## Vert.xとは

NettyベースでMicroService作るのに役立つFWです。

Express.jsとかそういうのに近いのかな。

ノンブロッキングな仕組みの記述を基本とします。

JVM系が主なターゲットですが、多様な言語で開発できます。

http://vertx.io/

## 今回の範囲

Vert.xのコア機能とWebエクステンションを使い、単純な機能のHttpServerをScalaで記述します。

## Vert.x + Scalaを試す理由

前述の通り、Vert.xでは多様な言語でのアプリケーション開発ができます。

今回は、記述が楽で、大規模化に備えて静的型付けで、安定したバージョンが選択でき、普及率がそれなりに高い、JVM系の言語を選択したいので、Scalaでの開発の可能性を調べてみます。

今後の技術動向次第では、まだ見ぬ便利になったJava、またはWebで実績が積まれているバージョンのKotlinあたりが選択肢になる可能性もあります。

あと、小さい規模なことが明白であれば、JVM系ではGroovyが最も良い選択肢かもしれません。

## ビルドにGradleを使う理由

Vert.xでは、前述のとおり多様な言語での開発が可能です。

ScalaプロジェクトであればビルドにはSbtを使うのがデファクトスタンダードだと思いますが、今回は他のJVM系言語も安定してビルドでき、普及率が高く、記述が柔軟であることを理由にGradleを使って検証します。

## Vert.x + Scala の必要ライブラリ

とりあえず、Vert.xのコア機能を試す場合は以下のようにビルドを設定します。

```groovy:build.gradle
plugins {
  id 'application'
  id 'java'
  id 'scala'
}

repositories {
  mavenCentral()
  jcenter()
}

version = '0.1.0-SNAPSHOT'
sourceCompatibility = '1.8'

mainClassName = 'jp.sample.App'

dependencies {
  compile 'io.vertx:vertx-core:3.+'
  compile 'io.vertx:vertx-lang-scala_2.12:3.+'
}
```

applicationプラグインはあとで実行するときに便利なので使っています。

<code>mainClassName = 'jp.sample.App'</code>ではこの後で作る実行可能クラスの名前が指定されています。

## Vert.x コアの機能を試す

とりあえず、一定時間毎に実行されるアクションを作ってみます。

以下のプログラムは、1秒毎に<code>period</code>と表示します。

```scala:src/main/scala/jp/sample/App.scala
package jp.sample

import io.vertx.scala.core.Vertx

object App {
  def main(args : Array[String]) {
    val vertx = Vertx.vertx()
    vertx.setPeriodic(1000,id=>{
      println('period')
    })
  } 
}
```

ビルドおよび実行は以下のコマンドで行います。

```
gradle run
```

# Web機能の追加

Vert.xのコア機能で、簡単なHttpServerを作ることはできますが、便利なエクステンションがあるので入れていきます。

以下を依存ライブラリに加えます。

```groovy
  compile 'io.vertx:vertx-web:3.+'
  compile 'io.vertx:vertx-web-scala_2.12:3+'
```

全体では以下となります。

```groovy:build.gradle
plugins {
  id 'application'
  id 'java'
  id 'scala'
}

repositories {
  mavenCentral()
  jcenter()
}

version = '0.1.0-SNAPSHOT'

sourceCompatibility = '1.8'

mainClassName = 'jp.sample.App'

dependencies {
  compile 'io.vertx:vertx-core:3.+'
  compile 'io.vertx:vertx-lang-scala_2.12:3.+'
  compile 'io.vertx:vertx-web:3.+'
  compile 'io.vertx:vertx-web-scala_2.12:3+'
}
```

# Httpサーバの記述

Web機能で追加されたRouterを使ってHttpServerの振る舞いを記述できます。

以下は、ごく単純なHello Worldレスポンスを返す例です。

```scala:SampleRouter
    val router = Router.router(vertx)
    router.route().handler(context=>{
      val res = context.response()
      res.putHeader("content-type","text/plane")
      res.end("Hello world.")
    })
```

上記のrouterをVert.xのコア機能が提供するHttpServerで使うには以下のようにします。
以下の例ではhttp接続を8080ポートで待ちます。

```
    val srv = vertx.createHttpServer()
    srv.requestHandler(router.accept _).listen(8080)
```

App.scalaの全体は以下のようになります。

```scala:App.scala
package jp.sample

import io.vertx.scala.core.Vertx
import io.vertx.scala.ext.web._

object App {
  def main(args : Array[String]) {
    val vertx = Vertx.vertx()
    val router = Router.router(vertx)
    router.route().handler(context=>{
      val res = context.response()
      res.putHeader("content-type","text/plane")
      res.end("Hello world.")
    })

    val srv = vertx.createHttpServer()
    srv.requestHandler(router.accept _).listen(8080)
  } 
```

HttpServerを起動するには、前述のコマンドと同じです。

止めるにはプロセスをKillしてください。

```
gradle run &
curl http://localhost:8080
```

## ここまでのところ

* Gradleを用いて単純な記述で実行可能なビルドを得られた。
* Vertxを使用したHttpServerの記述方法が分かった。

## これ以降

* データの保存、セッション機能などWebサービスの提供に必要な機能を検証する
* ブロッキングサーバの検証
* 機能の構成単位として提供されているVeticleの仕組みを利用して、APIの提供を検証する

とりあえず、サンプルの実装としてChatでも書こうかと思います。

https://github.com/aya-eiya/vertx-scala-web-prac01