すきま風

勉強したことのメモとか

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

要旨

Gradleマルチプロジェクトの勉強用です。Spring Boot2, Kotlin, Gradleを使ったシンプルなレイヤーアーキのサンプルです。
クリーンアーキテクチャの記事はこちら

ソフトウェアバージョン

software version
OS MacOS Mojave
Spring Boot 2.1.5
Java 1.8.0_192-b12
Kotlin 1.3.31
Gradle 5.2.1

モジュール概要

module description
demo-web controller
demo-application use caseを記述する
demo-domain domain層
demo-infra infra層 DBや外部Apiとの通信
demo-env 設定ファイル置き場。なくても良い

プロジェクト構成

demo
├── demo-application
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo.application.usecase
├── demo-domain
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo.domain
├── demo-env
│   ├── build.gradle
│   └── src.main.resources
├── demo-infra
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo.infra
├── demo-web
│   ├── build.gradle
│   └── src.main.kotlin.com.example.demo
│                                   └── web
│                                   └── DemoApplication.kt
├── build.gradle
└── settings.gradle

コード

settings.gradle

pluginManagement {
    repositories {
        gradlePluginPortal()
    }
}
rootProject.name = 'demo'

// moduleの追加
include ':demo-application', ':demo-web', ':demo-domain', ':demo-env', ':demo-infra'

build.gradle

import org.springframework.boot.gradle.plugin.SpringBootPlugin

buildscript {
    // プロジェクトのライブラリのバージョン管理を行う場所
    ext.versions = [
        'coroutine': '1.2.1',
    ]

    // dependency-management 内でのバージョンをoverride
    // https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/235
    ext['kotlin.version'] = '1.3.31'
}

plugins {
    id 'org.springframework.boot' version '2.1.5.RELEASE' apply false
    id 'org.jetbrains.kotlin.jvm' version '1.3.31'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.3.31'
}

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

repositories {
    mavenCentral()
}

dependencies {
}

subprojects {
    apply plugin: 'kotlin'
    apply plugin: 'org.jetbrains.kotlin.plugin.spring'
    apply plugin: 'io.spring.dependency-management'

    dependencyManagement {
        imports {
            mavenBom SpringBootPlugin.BOM_COORDINATES
            // 以下と大体同じ。versionの指定が不要
            // mavenBom "org.springframework.boot:spring-boot-dependencies:2.1.5"
        }
    }

    sourceCompatibility = '1.8'
    targetCompatibility = '1.8'

    repositories {
        mavenCentral()
    }

    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.jetbrains.kotlin:kotlin-test"
        testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
    }

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

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

demo-web#build.gradle

apply plugin: 'org.springframework.boot'

// springBoot でもOK
bootJar {
    mainClassName = 'com.example.demo.DemoApplicationKt'
}

dependencies {
    implementation project(':demo-application')
    implementation project(':demo-env')
    implementation project(':demo-infra')
    implementation project(':demo-domain')

    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'

    // Spring MVCを使うならこっち
    // implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
}

demo-application#build.gradle

dependencies {
    implementation project(':demo-domain')

    implementation 'org.springframework.boot:spring-boot-starter'
}

demo-domain#build.gradle

// 最小構成なので今は空ファイル

demo-infra#build.gradle

dependencies {
    implementation project(':demo-domain')

    implementation 'org.springframework.boot:spring-boot-starter'
}

demo-env#build.gradle

// 空ファイル

demo-web#DemoApplication.kt

package com.example.demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

解説

Spring Bootのライブラリのバージョンはio.spring.dependency-managementを使ってMaven BOMを利用します。今回のようなマルチプロジェクト構成だと実際のSpring Boot Applicationはdemo-webだけになるので id 'org.springframework.boot' version '2.1.5.RELEASE' apply falseと指定してapply plugin: 'org.springframework.boot' をweb層のbuild.gradleに記述しています。詳細はこちら

また、domain層はspring bootに依存したくないためspring-boot-starterを入れていません。

参考サイト

Spring Boot Gradle Plugin Reference Guide

Compiler Plugins - Kotlin Programming Language