SpringBootのMultiple Moduleの構成で、Moduleごとにapplication.ymlを設置する

エキサイト株式会社メディア事業部エンジニアの佐々木です。SpringBootのMulti Module構成を採用して、各プロダクトごとにモノリポでモジュラーモノリス構成を敷いています。各モジュールごとに設定ファイルを置きたいことがあります。普通にやるとハマるんですが、割と簡単な方法で解決できるのでご紹介します。

前提

openjdk 17.0.5 2022-10-18 LTS
OpenJDK Runtime Environment GraalVM 22.3.0 (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode, sharing)
  • Gradle
------------------------------------------------------------
Gradle 7.6
------------------------------------------------------------

Build time:   2022-11-25 13:35:10 UTC
Revision:     daece9dbc5b79370cc8e4fd6fe4b2cd400e150a8

Kotlin:       1.7.10
Groovy:       3.0.13
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.5 (BellSoft 17.0.5+8-LTS)
OS:           Mac OS X 12.5 aarch64
  • SpringBoot
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.1)

ディレクトリツリー

マルチモジュール構成のディレクトリツリーはこのような感じです。

├── service
│   └── src
│       ├── main
│       │   ├── java
│       │   │   ├── com
│       │   │   │   └── example
│       │   │   └── jp
│       │   │       └── co
│       │   │           └── excite
│       │   │               └── example
│       │   │                   └── Config.java
│       │   └── resources
│       │       └── application.yml
└── web-front
    └── src
        ├── main
        │   ├── java
        │   │   └── jp
        │   │       └── co
        │   │           └── excite
        │   │               └── example
        │   │                   ├── ExampleApplication.java
        │   │                   └── controller
        │   │                       └── RootController.java
        │   └── resources
        │       └── application.yml

web-frontとserviceアプリケーションがあります。起動アプリケーションは、web-frontになります。サービスに必要な主要な設定はweb-frontのapplication.ymlにあるんですが、service層固有の設定はservice層内のapplication.ymlに書きたいところです。

application.ymlは1度しか読まれない

SpringBootの仕様として、jarファイル内にあるapplication.yml (or application.properties) が優先されるみたいです。SpringBootの外部の設定ファイルの仕様 つまり、同名の設定ファイルだと起動アプリケーションの application.yml が優先されてしまうので、service層のapplication.ymlは別名にする必要があります。

マルチモジュール構成でのapplication.ymlの有効化

それでは、service層でも、固有の設定をapplication.ymlに書けるように変更していきます。

  1. application.ymlの名前変更

ファイル構成はこのようになります。変更点は、service層のapplication.ymlが、application-service.ymlになっています。

├── service
│   └── src
│       ├── main
│       │   ├── java
│       │   │   ├── com
│       │   │   │   └── example
│       │   │   └── jp
│       │   │       └── co
│       │   │           └── excite
│       │   │               └── example
│       │   │                   └── Config.java
│       │   └── resources
│       │       └── application-service.yml
└── web-front
    └── src
        ├── main
        │   ├── java
        │   │   └── jp
        │   │       └── co
        │   │           └── excite
        │   │               └── example
        │   │                   ├── ExampleApplication.java
        │   │                   └── controller
        │   │                       └── RootController.java
        │   └── resources
        │       └── application.yml

ファイル名を変更することで、設定ファイル名の重複を回避します。

  1. 起動アプリケーションのapplication.ymlの修正

起動アプリケーションのapplication.ymlに下記を追加します。

spring:
  profiles:
    include:
      - service

これを追加することで、SpringBootは起動時にapplication-service.ymlを探しに言ってくれるようになります。

実行

では実行してみましょう。

application-service.ymlには下記のような設定を書いておきます。

service:
  id: 1234
  name: service

読み出し用のJavaConfigは下記のように記述します。

@Component
@ConfigurationProperties("service")
@Data
public class Config {
    private Integer id;
    private String name;
}

参考までに、Rootコンロトーラは下記のように記述します。

@RestController
@RequestMapping("/")
@RequiredArgsConstructor
public class RootController {

    private final Config config;

    @GetMapping
    public Object index(){
        return config;
    }
}

では、起動してリクエストしてみます。

$ ./gradlew web-front:bootRun

$ curl http://localhost:8080/

{"id":1234,"name":"service"}

application-service.ymlに書いてある設定が読み出せています。

まとめ

これで、MultiModule構成でもModule固有のapplication.ymlが使えるようになりました。命名等に気をつける必要がある、起動アプリケーションの設定ファイルで指定する必要があるなど、いくつかポイントはありますが、無事に分離できました。

ただし、SpringBootのフレームワーク的には、application.ymlは1つであることが望ましい記述があるので、参考程度としてください。

最後に

エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。

カジュアル面談はこちらになります! meety.net

募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com