MicronautとKotlinでAPIを作ってOpenAPIドキュメントを生成する


はじめに

普段は仕事でRuby + SinatraやNode.js + Expressを利用しているのですが、静的型付け言語で良いWEBフレームワークを調べようと思いSpringBootの記事を探していたところ、デブサミでMicronautについて触れられている場面があったので少し触ってみました

環境

  • macOS Mojave(10.14.2)
  • Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
  • SDKMAN 5.7.3+337
  • Micronaut 1.0.4

環境構築

Java、SDKMANはすでに入っている前提

$ sdk update
$ sdk install micronaut 1.0.4
$ mn create-app my-app --lang kotlin --features swagger-kotlin

micronautをインストールし、micronautのCLIコマンドであるmnでスケルトンを構築します
langオプションで言語、featuresオプションで機能を選択できます
今回はKotlinでOpenAPI(Swagger)のドキュメントも出力しようと思います

$ cd my-app/
$ ./gradlew run
> Task :run
17:50:53.507 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 751ms. Server Running: http://localhost:8080

"./gradlew run"でビルドされ、内包されているhttpサーバが立ち上がります


$ curl http://localhost:8080
{"_links":{"self":{"href":"/","templated":false}},"message":"Page Not Found"}

この時点では何も実装していないのでPage Not Foundとなります

Validator

build.gradleのdependenciesにvalidatorを追加します

my-app/build.gradle
compile "io.micronaut.configuration:micronaut-hibernate-validator"

Controllerを作成します

my-app/src/main/kotlin/my/app/HelloController.kt
package my.app

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.MediaType
import io.micronaut.validation.Validated

import javax.validation.constraints.NotBlank
import javax.validation.constraints.Pattern

@Validated
@Controller("/hello")
class HelloController {

    @Get(
            produces = [MediaType.TEXT_PLAIN],
            uri = "/{name}"
    )
    fun index(@Pattern(regexp = "^t.*") @NotBlank name: String): String {
        return "Hello $name"
    }
}

ビルドし、サーバを立ち上げます

$ ./gradlew run

> Task :run
18:26:06.673 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 772ms. Server Running: http://localhost:8080
<===========--> 85% EXECUTING [7s]
> :run

curlで確認します

$ curl http://localhost:8080/hello/abc
{"_links":{"self":{"href":"/hello/abc","templated":false}},"message":"name: must match \"^t.*\""}

abcだとValidatorで引っかかります

$ curl http://localhost:8080/hello/tomiyan
Hello tomiyan

tomiyanだとValidatorを通ります

OpenAPI

アノテーションで説明を書くとドキュメントを生成できます

my/app/Application.kt
package my.app

import io.micronaut.runtime.Micronaut
import io.swagger.v3.oas.annotations.OpenAPIDefinition
import io.swagger.v3.oas.annotations.info.Contact
import io.swagger.v3.oas.annotations.info.Info
import io.swagger.v3.oas.annotations.info.License

@OpenAPIDefinition(
        info = Info(
                title = "Hello World",
                version = "0.0",
                description = "My API",
                license = License(name = "MIT", url = "https://example.com"),
                contact = Contact(url = "https://example.com", name = "example", email = "[email protected]")
        )
)
object Application {

    @JvmStatic
    fun main(args: Array<String>) {
        Micronaut.build()
                .packages("my.app")
                .mainClass(Application.javaClass)
                .start()
    }
}
$ ./gradlew run

ビルドし、サーバを立ち上げた時点でOpenAPIのYAMLが生成されます

my-app/build/tmp/kapt3/classes/main/META-INF/swagger
openapi: 3.0.1
info:
  title: Hello World
  description: My API
  contact:
    name: example
    url: https://example.com
    email: [email protected]
  license:
    name: MIT
    url: https://example.com
  version: "0.0"
paths:
  /hello/{name}:
    get:
      operationId: index
      parameters:
      - name: name
        in: path
        required: true
        schema:
          minLength: 1
          type: string
          format: ^t.*
      responses:
        default:
          content:
            text/plain:
              schema:
                type: string

Validatorの内容も含めドキュメント化されています
アノテーションを使えばさらに詳細な説明も追加する事が可能です

まとめ

ドキュメントもそこそこあり、簡単なAPIを作るには良さそうですね

参考文献