【SpringBoot】マルチプロジェクト構成のプロジェクトを作成する

SpringBootでのマルチプロジェクト構成を試してみたので備忘録として記事にします。

実際のプロジェクトではDDDの実現等のために書くレイヤーをサブプロジェクトとして構成したりすると思いますが、今回はシンプルにSpring Intilizrで作成した最小構成のプロジェクトを使用します。(設定を入れるのが面倒くさかったのでDB系の依存も追加していません。)

環境

SpringBoot: v2.5.0

Gradle: v7.0.2

Kotlin: v1.4.10

サンプルコードのリポジトリ

今回使用したサンプルは以下のリポジトリに配置しています。

https://github.com/i-shinya/multiproject-sample

マルチプロジェクト構成のプロジェクトを作成する

以下のような構成となるようにしていきます。

.
|-- build.gradle.kts
|-- multi-master //親プロジェクト
|   |-- build.gradle.kts
|   `-- src
|-- multi-sub // 子プロジェクト
|   |-- build.gradle.kts
|   `-- src
`-- settings.gradle.kts

Spring Initializrでプロジェクトのベースを作成する

とりあえずSpring Initializrを使って以下のような構成でプロジェクトを作成。

WebとConfiguration Processorだけ依存に入れています。(Configuration Processorは最小であればいらなかったのですが、癖で入れていました。)

generateしてダウンロードされるzipを解凍してこちらを使います。

マルチプロジェクトの親プロジェクトの設定

まずはマルチプロジェクトの親プロジェクトの設定を行います。

マルチプロジェクトの親プロジェクトを追加

ディレクトリ作成

まずは親プロジェクトのディレクトリを作成します。今回はmulti-masterというディレクトリ名にしました。こちらのディレクトリにSpring Initializrで元々作成されたsrcディレクトリを移動します。

build.gradle.ktsを追加

そしてmuti-masterディレクトリに新規でbuild.gradle.ktsを追加して以下のように記述してください。

plugins {
	id("org.springframework.boot")
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-web:2.4.4")
}

動作確認用のコントローラーを追加

適当に動作確認用のコントローラーを追加しました。

package com.multiproject.controller

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/sample")
class SampleController {

    @GetMapping("/sample")
    fun sample(): String {
        return "sample controller access."
    }
}

ルートプロジェクトの設定を修正

settings.gradle.ktsを修正

プロジェクトのルートディレクトリのsettings.gradle.ktsを以下のように修正します。

rootProject.name = "multiproject"
include(
    ":multi-master"
)

build.gradle.ktsを修正

プロジェクトのルートディレクトリのbuild.gradle.ktsを以下のように修正します。(設定内容はプロジェクトに合わせて適宜修正してください)

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
	id("org.springframework.boot") version "2.5.0"
	id("io.spring.dependency-management") version "1.0.11.RELEASE"
	kotlin("jvm") version "1.5.10"
	kotlin("plugin.spring") version "1.5.10"
}

group = "com.multiproject"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

configurations {
	compileOnly {
		extendsFrom(configurations.annotationProcessor.get())
	}
}

allprojects {
	repositories {
		mavenCentral()
	}
}

subprojects {
	apply {
		// 以下を参照し追加
		// https://github.com/gradle/kotlin-dsl-samples/issues/1268
		plugin("java")

		plugin("kotlin")
		plugin("io.spring.dependency-management")
		plugin("org.jetbrains.kotlin.jvm")
		plugin("org.jetbrains.kotlin.plugin.spring")
	}

	dependencies {
		implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.2")
		implementation("org.jetbrains.kotlin:kotlin-reflect:1.5.0-M1")
		implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.0-M1")
		annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:2.4.4")
		testImplementation("org.springframework.boot:spring-boot-starter-test:2.4.4")
	}

	tasks.withType<KotlinCompile> {
		kotlinOptions {
			freeCompilerArgs = listOf("-Xjsr305=strict")
			jvmTarget = "11"
		}
	}

	tasks.withType<Test> {
		useJUnitPlatform()
	}
}

ここまでで一旦動作確認します。アプリケーションを起動してコントローラーへアクセスできればOKです。

このセクションの修正内容は以下コミットで確認できます。

https://github.com/i-shinya/multiproject-sample/commit/3f8d0e859668a47e2bd826caaa0560224b66df6c

マルチプロジェクトの子プロジェクトの設定

次に子プロジェクト側の設定も入れていきます。

マルチプロジェクトの子プロジェクトを追加

ディレクトリ作成

子プロジェクトのディレクトリを作成します。今回はmulti-subというディレクトリ名にしました。

build.gradle.ktsを追加

そしてmuti-masterディレクトリに新規でbuild.gradle.ktsを追加して以下のように記述してください。

dependencies {
	implementation("org.springframework.boot:spring-boot-starter:2.4.4")
}

動作確認用のサービスクラスを追加

muti-masterディレクトリにsrc/main/kotlin/com/multiproject/serviceの階層でディレクトリを作成し、適当に動作確認用のサービスクラスを追加しました。

package com.multiproject.service

import org.springframework.stereotype.Service

@Service
class SampleService {
    fun sample(): String {
        return "sub hello world."
    }
}

ルートプロジェクトの設定を修正

settings.gradle.ktsを修正

プロジェクトのルートディレクトリのsettings.gradle.ktsに親プロジェクトの時と同様に記載を修正します。

rootProject.name = "multiproject"
include(
    ":multi-master",
    ":multi-sub"
)

親プロジェクトの設定を修正

build.gradle.ktsを修正

親プロジェクトのbuild.gradle.ktsに子プロジェクトへの依存を追加します。

plugins {
	id("org.springframework.boot")
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-web:2.4.4")
	implementation(project(":multi-sub")) // この行を追加
}

子プロジェクトの処理を呼び出す

親プロジェクト側に実装した動作確認用のコントローラーから子プロジェクトの処理を呼び出すよう以下のように記載を修正しました。

package com.multiproject.controller

import com.multiproject.service.SampleService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/sample")
class SampleController(
    private val sampleService: SampleService
) {

    @GetMapping("/sample")
    fun sample(): String {
        return sampleService.sample()
    }
}

これで設定は完了です。コントローラーにアクセスして正しく値が返ってくればOKです。

このセクションの修正内容は以下コミットで確認できます。

https://github.com/i-shinya/multiproject-sample/commit/083d73cf96da72babf231ad849fe3020df29e8dc

 

参考

https://qiita.com/YutaSaito1991/items/049412205340c98c67c6

https://qiita.com/BooookStore/items/695b199a5d13f633a2dc