コンテンツにスキップ

application-modules プロジェクトの設定⚓︎

application-modules プロジェクトで必要な設定を解説します。 application-modules プロジェクトには、境界付けられたコンテキスト単位に分割されたモジュールを配置します。

1
2
3
4
5
application-modules/
 └ src/main/java/{ プロジェクトのグループ名 }/applicationmodules
   ├ xxcontext --------------------------------- Xx コンテキストのルートパッケージ 
   ├ yycontext --------------------------------- Yy コンテキストのルートパッケージ
   └ shared ------------------------------------ 複数のコンテキスト間で共有するパッケージ

なお、システム共通機能は system-common プロジェクトに配置し、 application-modules プロジェクトには含めません。

依存ライブラリの設定⚓︎

application-modules プロジェクトには、データアクセス処理やモジュラーモノリスアーキテクチャの実装に必要なライブラリを追加します。 データアクセス処理の実装に AlesInfiny Maia OSS Edition で推奨する MyBatis を利用する場合には、 mybatis-spring-boot-starter を利用することを推奨します。 application-modules プロジェクトで利用を推奨するライブラリは以下の通りです。

  • spring-boot-transaction: Spring Boot アプリケーションでトランザクションを管理するスターター
  • spring-modulith-bom: Spring Modulith の依存関係を管理するための BOM
  • spring-modulith-starter-core: モジュラーモノリスアーキテクチャを実装するためのスターター
  • spring-modulith-starter-test: モジュラーモノリスアーキテクチャのテストを実装するためのスターター
  • mybatis-spring-boot-starter: MyBatis と Spring Boot を統合するためのスターター
  • mybatis-spring-boot-starter-test: MyBatis と Spring Boot を統合したアプリケーションをテストするためのスターター
application-modules/build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
dependencies {
  implementation platform("org.springframework.modulith:spring-modulith-bom:x.x.x")
  implementation 'org.springframework.boot:spring-boot-transaction'
  implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:x.x.x'

  compileOnly 'org.springframework.modulith:spring-modulith-starter-core'

  testImplementation 'org.springframework.modulith:spring-modulith-starter-test'
  testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:x.x.x'
}

データアクセス処理の実装に MyBatis 以外を利用する場合、適切なライブラリに切り替えてください。

各依存ライブラリのバージョンの参照先

依存プロジェクトの設定⚓︎

application-modules プロジェクトは system-common を参照しています。 そのため、 build.gradle で以下のように他のプロジェクトを依存関係に含めます。

application-modules/build.gradle
1
2
3
dependencies {
  implementation project(':system-common')
}

ロギングライブラリの除外設定⚓︎

依存関係に記載している org.mybatis.spring.boot:mybatis-spring-boot-starter ライブラリは、デフォルトで Logback 用のライブラリである org.springframework.boot:spring-boot-starter-logging が推移的依存で追加されます。

AlesInfiny Maia OSS Edition では、ロギングライブラリとして Apache Log4j 2 (以降 log4j2 )を使用します。 そのため、以下のようにデフォルトのロギングライブラリを依存関係から除外する設定を記述します。

spring-boot-starter-logging の除外設定
1
2
3
4
5
configurations {
 all {
  exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
 }
}

プロジェクトのビルド方法の設定⚓︎

application-modules プロジェクトは単体で動作せず、他プロジェクトからライブラリとして呼び出します。 呼び出し可能な Jar ファイルで出力する必要がないため以下を設定します。

application-modules/build.gradle
1
2
3
4
5
6
7
bootJar {
  enabled = false
}

jar {
  enabled = true
}

不要な設定やファイルの削除⚓︎

こちら で、 Java のバージョンと使用するテストフレームワークを集約管理しています。 そのため、 Toolchain の設定と test タスクに関するブロックを削除します。

application-modules/build.gradle
1
2
3
4
5
6
7
8
9
java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(x)
  }
}

tasks.named('test') {
  useJUnitPlatform()
}

また、併せて不要なファイルを削除します。 application-modules プロジェクトの src 以下にある、 ApplicationModulesApplication.java と ApplicationModulesApplicationTests.java を削除してください。 さらに、 application-modules プロジェクトはライブラリとして利用するサブプロジェクトであるため、 src/main/resources にある application.properties も削除してください。

ここまでを実行した後に、適切にビルドが実行できるかを確認します。 依存ライブラリを追加したため、 依存ライブラリのバージョン固定 で作成したロックファイルをビルドの前に更新します。 ターミナルを用いてルートプロジェクト直下で以下を実行してください。

application-modules プロジェクトのビルド
1
2
./gradlew allDependencies --write-locks
./gradlew application-modules:build
ここまでの手順を実行した際の application-modules/build.gradle の例
application-modules/build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
plugins {
  id 'java'
  id 'org.springframework.boot' version 'x.x.x'
  id 'io.spring.dependency-management' version 'x.x.x'
}

group = 'プロジェクトのグループ名'
version = 'x.x.x-SNAPSHOT'
description = 'プロジェクトの説明'

repositories {
  mavenCentral()
}

dependencies {
  implementation platform("org.springframework.modulith:spring-modulith-bom:x.x.x")
  implementation 'org.springframework.boot:spring-boot-transaction'
  implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:x.x.x'

  implementation project(':system-common')

  compileOnly 'org.springframework.modulith:spring-modulith-starter-core'

  testImplementation 'org.springframework.modulith:spring-modulith-starter-test'
  testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:x.x.x'
  // その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}

configurations {
  all {
    exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
  }
}

bootJar {
  enabled = false
}

jar {
  enabled = true
}

モジュールの追加⚓︎

application-modules プロジェクトに、境界付けられたコンテキスト単位のモジュールを追加する手順を解説します。 モジュールは、 Spring Modulith のアプリケーションモジュールとして定義します。 アプリケーションモジュールとして定義することで、モジュール間の依存関係を Spring Modulith で検証できます。 アプリケーションモジュールの詳細は、Spring Modulith のリファレンスドキュメント を参照してください。

モジュールのパッケージ作成⚓︎

{ プロジェクトのグループ名 }.applicationmodules パッケージの直下に、モジュールごとのパッケージを作成します。 ここで作成したパッケージが、モジュールのルートパッケージです。 ルートパッケージの直下には、他のモジュールへ公開する型のみを配置します。 公開しない型は internal パッケージ配下に配置します。

1
2
3
4
5
application-modules/
 └ src/main/java/{ プロジェクトのグループ名 }/applicationmodules
   └ xxcontext --------------------------------- Xxコンテキストのルートパッケージ
     ├ package-info.java ----------------------- モジュールを定義するファイル
     └ internal -------------------------------- 他のモジュールへ公開しない型を配置するパッケージ

package-info.java の配置⚓︎

モジュールのルートパッケージ直下に package-info.java を配置し、 @ApplicationModule アノテーションを付与します。 このアノテーションは、依存ライブラリの設定 で追加した spring-modulith-starter-core に含まれます。

xxcontext/package-info.java
1
2
3
4
5
6
7
8
@ApplicationModule(
    displayName = "Xx コンテキスト",
    allowedDependencies = { "shared" },
    type = Type.CLOSED)
package com.example.applicationmodules.xxcontext;

import org.springframework.modulith.ApplicationModule;
import org.springframework.modulith.ApplicationModule.Type;

主な属性は以下の通りです。

  • displayName: モジュールの表示名です。省略した場合はルートパッケージ名を使用します。
  • allowedDependencies: 依存を許可するモジュールを指定します。省略した場合はすべてのモジュールへの依存を許可します。すべてのモジュールへの依存を禁止する場合は、空の配列を指定します。
  • type: モジュールの公開範囲を指定します。指定できる値は オープンモジュールとクローズドモジュールの指定 を参照してください。

オープンモジュールとクローズドモジュールの指定⚓︎

type 属性には、モジュールをオープンモジュールとクローズドモジュールのどちらとするかを指定します。 それぞれの違いは以下の通りです。

  • クローズドモジュール( Type.CLOSED ): 既定値です。他のモジュールから参照できる型は、ルートパッケージ直下の型だけです。
  • オープンモジュール( Type.OPEN ): サブパッケージに配置した型を含め、すべての型を他のモジュールから参照できます。

モジュールは、原則としてクローズドモジュールとし、内部実装を他のモジュールから隠蔽します。 複数のモジュールから共有する shared パッケージのように、サブパッケージの型も公開する場合は、オープンモジュールとします。

shared/package-info.java
1
2
3
4
5
6
7
@ApplicationModule(
    displayName = "共有モジュール",
    type = Type.OPEN)
package com.example.applicationmodules.shared;

import org.springframework.modulith.ApplicationModule;
import org.springframework.modulith.ApplicationModule.Type;

オープンモジュールの利用

オープンモジュールは内部実装を隠蔽できないため、モジュール間の結合度が高くなりやすくなります。 オープンモジュールとして定義するモジュールは、必要最小限にとどめてください。

モジュール間の依存関係を検証するテストの追加⚓︎

allowedDependencies によるモジュール間の依存関係の宣言は、あくまで宣言にすぎず、それだけでは違反を検知できません。 実際に宣言どおりの依存関係が守られていることを検証するテストクラスを、 application-modules プロジェクトに追加します。

1
2
3
application-modules/
 └ src/test/java/{ プロジェクトのグループ名 }/applicationmodules
   └ ModularityTests.java -------------------------- モジュール間の依存関係を検証するテストクラス
applicationmodules/ModularityTests.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.applicationmodules;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.modulith.core.ApplicationModules;
import org.springframework.modulith.docs.Documenter;

class ModularityTests {

  static final ApplicationModules modules =
      ApplicationModules.of(ModularityTests.class.getPackageName());

  @Test
  @DisplayName("コンテキスト間の依存関係が正しいことを検証する")
  void verifiesModularStructure() {
    modules.verify();
  }

  @Test
  @DisplayName("モジュール構造のドキュメントを生成する")
  void writesDocumentationSnippets() {
    new Documenter(modules).writeDocumentation();
  }
}

ApplicationModules.of() には、モジュールを配置した applicationmodules パッケージを指定します。 このパッケージ配下にある xxcontext や yycontext などのモジュールをまとめて 1 つの ApplicationModules として扱うため、モジュールごとにテストクラスを作成する必要はありません。

  • modules.verify(): モジュール間の依存関係を検証します。 allowedDependencies で許可していないモジュールへの依存や、クローズドモジュールの internal パッケージ配下の型への参照があった場合、このメソッドが例外をスローし、テストが失敗します。
  • new Documenter(modules).writeDocumentation(): モジュール構造を表す図( PlantUML )や文書を build フォルダー配下に自動生成します。モジュール構成を可視化したい場合に活用してください。

このテストクラスを配置することで、モジュール間の不正な依存を CI で検知できるようになります。 modules.verify() の検証内容の詳細は、アプリケーションモジュール構造の検証 を参照してください。

MyBatis の設定⚓︎

MyBatis を利用する場合、 @Configuration を付与した設定クラスを作成し、 ConfigurationCustomizer を Bean 登録することで MyBatis の設定をプログラム的に行います。 以下は、データベースのカラム名(スネークケース)と Java のプロパティ名(キャメルケース)を自動的にマッピングする設定の例です。

MyBatisConfig.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.example.applicationmodules", annotationClass = Mapper.class)
public class MyBatisConfig {

  /**
   * MyBatis の設定をカスタマイズします。
   *
   * @return カスタマイズされた MyBatis 設定。
   */
  @Bean
  ConfigurationCustomizer mybatisConfigurationCustomizer() {
    return configuration -> {
      configuration.setMapUnderscoreToCamelCase(true);
    };
  }
}

その他に設定できる項目については、MyBatis のリファレンスドキュメント(設定) を参照してください。

MyBatis Generator によるコードの自動生成⚓︎

MyBatis Generator は、 MyBatis を使用する際に、データベースのテーブルからテーブルエンティティやマッパーインターフェース、 SQL マッピングファイルを自動的に生成するツールです。

具体的な設定方法については、こちら を参照してください。

メッセージ管理の設定⚓︎

application-modules プロジェクトで管理する業務メッセージの設定方法については、こちら を参照してください。