すきま風

勉強したことのメモとか

Spring Boot2 × Kotlin × Gradle5でクリーンアーキテクチャのアプリケーションを構築する

要旨

Gradleの勉強。クリーンアーキテクチャを実装してみます。
この記事ではgradleについて記述します。実際のコードについては次回記事を参照ください。
元ネタはSpring IO 2019で紹介されていたこちら
以前書いたレイヤーアーキテクチャのサンプルはこちら
kotlin-dslで書き直したものはこちら
gRPCを導入する際に書き直したものはこちら


下のサンプルほど新しいです

ソフトウェアバージョン

software version
OS MacOS Mojave
Spring Boot 2.2.0.M5
Java Corretto-11.0.4.11.1
Kotlin 1.3.50
Gradle 5.6.1

モジュール概要

module description
adapters port。api, persistence, web
application use case
configuration 設定ファイルと起動アプリケーション
domain domainレイヤー

プロジェクト構成

demo
├── adapters
│   ├── build.gradle
│   ├── api
│   │   ├── build.gradle
│   │   └── src.main.kotlin.com.example.demo.api
│   ├── persistence
│   │   ├── build.gradle
│   │   └── src.main.kotlin.com.example.demo.persistence
│   └── web
│       ├── build.gradle
│       └── src.main.kotlin.com.example.demo.web
├── application
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo
│                                   ├── port
│                                   └── service
├── configuration
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo
│                                   └── DemoApplication.kt
├── domain
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo.domain
├── build.gradle
└── settings.gradle

依存ライブラリ

リアクティブプログラミング勉強用にspring-boot-starter-webflux, spring-data-r2dbc を設定しています。

コード

settings.gradle

Spring Boot 2.2 を使えるようにmaven repositoryを追加
pluginManagement {
    repositories {
        gradlePluginPortal()
        maven { url 'https://repo.spring.io/snapshot' }
        maven { url 'https://repo.spring.io/milestone' }
    }
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == 'org.springframework.boot') {
                useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
            }
        }
    }
}
rootProject.name = 'demo'

include ':domain', ':configuration', ':adapters:web', ':adapters:api', ':adapters:persistence', ':application'

adapters.api.build.gradle (api用の実装)

dependencies {
    implementation project(':application')
    implementation project(':domain')

    implementation "org.springframework.boot:spring-boot-starter-webflux:${versions.springBoot}"
    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9'
}

adapters.persistence.build.gradle (DB用の実装)

dependencies {
    implementation project(':application')
    implementation project(':domain')

    implementation 'org.springframework.data:spring-data-r2dbc:1.0.0.M2'
    implementation 'io.r2dbc:r2dbc-pool:0.8.0.M8'
    implementation "org.springframework:spring-jdbc:${versions.spring}"
    implementation "org.springframework.boot:spring-boot-starter:${versions.springBoot}"
    implementation 'com.github.jasync-sql:jasync-r2dbc-mysql:1.0.1'
}

adapters.web.build.gradle (Controller用の実装)

dependencies {
    implementation project(':application')
    implementation project(':domain')

    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9'
    implementation "org.springframework.boot:spring-boot-starter-webflux:${versions.springBoot}"
}

application.build.gradle (use case層)

dependencies {
    implementation project(':domain')

    implementation "org.springframework.boot:spring-boot-starter:${versions.springBoot}"
}

configuration.build.gradle (Spring Boot起動ファイルを置くところ)

apply plugin: 'org.springframework.boot'

springBoot {
    mainClassName = 'com.example.demo.DemoApplicationKt'
}

dependencies {
    implementation project(':application')
    implementation project(':domain')
    implementation project(':adapters:web')
    implementation project(':adapters:api')
    implementation project(':adapters:persistence')

    implementation "org.springframework.boot:spring-boot-starter-webflux:${versions.springBoot}"
    implementation 'org.springframework.data:spring-data-r2dbc:1.0.0.M2'
}

build.gradle

buildscript {
    ext.versions = [
        'coroutine': '1.3.0',
        'junitJupiter': '5.5.1',
        'junitPlatform': '1.5.1',
        'kotlin': '1.3.50',
        'spring': '5.2.0.M2',
        'springBoot': '2.2.0.M5'
    ]
}

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.2.0.M5' apply false
    id 'org.jetbrains.kotlin.jvm' version '1.3.50'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.3.50'
    id 'org.jetbrains.kotlin.plugin.jpa' version '1.3.50'
}

allprojects {
    group = 'com.example'
    version = '0.0.1-SNAPSHOT'
}

repositories {
    mavenCentral()
}

dependencies {
}

subprojects {
    apply plugin: 'kotlin'
    apply plugin: 'org.jetbrains.kotlin.plugin.spring'

    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8

    repositories {
        mavenCentral()
        maven { url "http://repo.spring.io/libs-milestone" }
        maven { url "http://repo.spring.io/libs-snapshot" }
    }

    dependencies {
        implementation 'org.jetbrains.kotlin:kotlin-reflect'
        implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutine}"
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-reactor:${versions.coroutine}"
        testImplementation "org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}"
        testImplementation "org.junit.jupiter:junit-jupiter-params:${versions.junitJupiter}"
        testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${versions.junitJupiter}"
    }

    compileKotlin {
        kotlinOptions {
            freeCompilerArgs = ['-Xjsr305=strict']
            jvmTarget = "1.8"
        }
    }

    compileTestKotlin {
        kotlinOptions {
            freeCompilerArgs = ['-Xjsr305=strict']
            jvmTarget = "1.8"
        }
    }

    test {
        useJUnitPlatform()
    }
}

元ネタのmaven projectをgradle projectにしてみた。ただそれだけの記事でした。