weblog

技術的なメモ置き場。

Micronaut + Kotlin + Doma を試す

MicronautでDomaを試したときのメモ。

環境は以下の通り。

Micronautアプリの用意

適当なディレクトリにKotlinのMicronautアプリを作成する。

$ mn create-app -f kotlin -i

build.gradleの設定

PostgreSQL

以下の設定を追加する。

dependencies {
    // 省略
    runtimeOnly "org.postgresql:postgresql:42.2.6"
}

Doma

Domaの公式ドキュメントを参考に、build.gradleに以下の設定を追加する。

doma.readthedocs.io

dependencies {
    // 省略
    implementation "org.seasar.doma:doma:2.25.1"
    kapt "org.seasar.doma:doma:2.25.1"
}

kapt {
    arguments {
        arg("doma.resources.dir", compileKotlin.destinationDir)
    }
}

task copyDomaResources(type: Sync)  {
    from sourceSets.main.resources.srcDirs
    into compileKotlin.destinationDir
    include 'doma.compile.config'
    include 'META-INF/**/*.sql'
    include 'META-INF/**/*.script'
}

compileKotlin {
    dependsOn copyDomaResources
}

データベースの設定

PostgreSQL Tutorialが用意しているサンプルデータを利用する。

www.postgresqltutorial.com

今回はCountryテーブルを検索する処理を作成する。

CREATE TABLE country
(
    country_id integer default nextval('public.country_country_id_seq'::regclass) not null
        constraint country_pkey
            primary key,
    country varchar(50) not null,
    last_update timestamp default now() not null
);

Configクラスの作成

object DomaConfig : Config {

    private val dialect = PostgresDialect()

    private val dataSource = LocalTransactionDataSource(
            "jdbc:postgresql://localhost:5432/dvdrental", "postgres", "password")

    private val transactionManager = LocalTransactionManager(
            dataSource.getLocalTransaction(jdbcLogger))

    override fun getDialect() = dialect

    override fun getDataSource() = dataSource

    override fun getTransactionManager() = transactionManager

    override fun getNaming() = Naming.SNAKE_LOWER_CASE
}

Entityクラスの作成

@Entity(immutable = true)
data class Country(
        val countryId: Int,
        val country: String,
        val lastUpdate: LocalDateTime
)

Daoクラスの作成

AnnotateWithでSIngletonを追加することで、DAOクラスをDIできるようにする。

@Dao(config = DomaConfig::class)
@AnnotateWith(annotations = [
    Annotation(target= AnnotationTarget.CLASS, type = Singleton::class)
])
interface CountryDao {
    @Select
    fun findAll(): List<Country>
}

SQLファイル src/main/resources/META-INF/Daoのパッケージ/CountryDao/findAll.sql を作成する。

SELECT * FROM country;

Controllerクラスの作成

@Controller
class CountryController(
        private val countryDao: CountryDao
) {

    @Get
    fun findAll(): List<Country> {
        val tm = DomaConfig.transactionManager
        return tm.required(Supplier {
            countryDao.findAll()
        })
    }
}

動作確認

Micronautアプリを起動し、データベースアクセスさせる。

curl http://localhost:8080 -i
HTTP/1.1 200 OK
Date: Sun, 8 Sep 2019 12:19:58 GMT
content-type: application/json
content-length: 7516
connection: keep-alive

[{"countryId":1,"country":"Afghanistan","lastUpdate":[2006,2,15,9,44]},{"countryId":2,"country":"Algeria","lastUpdate":[2006,2,15,9,44]},{"countryId":3,"country":"American Samoa","lastUpdate":[2006,2,15,9,44]},{"countryId":4,"country":"Angola","lastUpdate":[2006,2,15,9,44]},{"countryId":5,"country":"Anguilla","lastUpdate":[2006,2,15,9,44]},{"countryId":6,"country":"Argentina","lastUpdate":[2006,2,15,9,44]},{"countryId":7,"country":"Armenia","lastUpdate":[2006,2,15,9,44]},{"countryId":8,"country":"Australia","lastUpdate":[2006,2,15,9,44]},{"countryId":9,"country":"Austria","lastUpdate":[2006,2,15,9,44]},{"countryId":10,"country":"Azerbaijan","lastUpdate":[2006,2,15,9,44]},{"countryId":11,"country":"Bahrain","lastUpdate":[2006,2,15,9,44]},{"countryId":12,"country":"Bangladesh","lastUpdate":
省略

後日HikariCPを使って検証したい。

godotenvで環境変数を扱う

godotenvを使用することで、外部ファイルに定義した環境変数Golangで扱うことができる。

github.com

使用方法

インストール

go get github.com/joho/godotenv

.envファイルの作成

プロジェクトルートに .env ファイルを作成する。

SOME_TOKEN=xxxxx

YAML形式でもOK。

SOME_TOKEN: xxxxx

プロジェクトルート以外にも環境変数を定義した任意のファイルを指定できる。ファイル名も任意。

godotenv.Load("path/to/file")

実装例

import (
    "github.com/joho/godotenv"
    "log"
    "os"
)

func main() {
    // .envから環境変数を読み込む
    err := godotenv.Load()
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    token := os.Getenv("SOME_TOKEN")
    
     // omit..
}

mapで読み込むことも可能。

var myEnv map[string]string
myEnv, _ = godotenv.Read()
token := myEnv["SOME_TOKEN"]

改訂2版 みんなのGo言語

改訂2版 みんなのGo言語

Micronautでバリデーション

MicronautでPostされたデータをバリデーションする。


環境

  • Kotlin 1.3.21
  • Micronaut 1.1.3

build.gradleに以下を追加する。

dependencies {
    ...
    compile 'io.micronaut.configuration:micronaut-hibernate-validator'
    ...
}

Postデータを受け取るFormクラスを作成する。 各パラメータにアノテーションで実施したいバリデーションを指定する。 Kotlinの場合 @field: が必要。

data class ValidationForm(
    @field:NotNull
    val name: String,

    @field:Max(10)
    val age: Int
)

Controllerクラスを作成する。 クラスレベルに @Validated を付与する必要がある。

@Validated
@Controller("/validation")
class ValidationController {

    @Post("/")
    fun index(@Body @Valid form: ValidationForm): HttpStatus {
        return HttpStatus.OK
    }
}

アプリを起動してバリデーションを試す。

$ curl -X POST -H "Content-Type: application/json" -d '{"name":"hoge", "age":"100"}' localhost:8080/validation/
> {"_links":{"self":{"href":"/validation/","templated":false}},"message":"form.age: must be less than or equal to 10"}