Spring Boot 設定値(Configuration Properties)入力をガッツリ支援する

# 前置き

デモ用アプリはGithubで公開しています。[コチラ](https://github.com/kyosuke-yamagata/test-properties)。

# モチベーション

Spring Bootを用いて共通部品を作る際に
Configuration Properties経由で、設定値(Key Value)を入力して貰いたいケース多々あり。

チーム内で「"設定する"作業の負荷、もう少し減らせないだろうか」議論が持ち上がったので
(=DX:Developer Experienceを向上したい)
役に立ちそうな情報を纏めると共に、解法を1つメモしておくもの。

# ペルソナ(=開発者)戸惑い体験の列挙

1. 設定する(Developing)時点
  - Key上位階層名は知っているけど、細部は忘れてしまったケース。
  - 何のValueが設定OKか覚えていないケース。
    - 結局、割込み（別資料を確認する等）が生じる。
1. App Running時点
  - [防げる範疇であれば]アプリがコケて戸惑う。
  - [コケた際、反射的に]ミスした箇所どこか？思索し始める。
1. 稼働(App Running)成功　～テスト実施後
  - [標準出力 or ログ点検後]設定値が効いていなかったことを突き止める。
  - [標準出力 or ログ点検後]Value入力の不備を突き止める。タイプmiss等。
1. 各フェーズ共通
  - 開発者の習熟度に関わらず、戸惑い体験そのものは発生し得る。
  - 習熟度が高いほど、体験が及ぼす心的負担感は軽減する。（…筈だが、モノと状況にも依る）
  - さらっと書いた「テスト実施後」が曲者。  
    実時間の多く掛かるCAPFや、関係チーム多くなりがちな総合テスト後とかだと悲惨。

# 主題：設定値の入力をガッツリ支援する

デモ用アプリはGithubで公開しています。[コチラ](https://github.com/kyosuke-yamagata/test-properties)。

具体的な実装も興味あれば、ページ下部「デモ用アプリ解説+おまけ」まで通読ください。

# 前提
- 今回は「特定Key名に対して、Valueが数パターンに限定される」最も基本的なパターンを取り扱う。
   - とはいえ応用すれば、支援する幅を広げること可能。
- 特定Key名に対するValueの設定バリエーションは、POJOなEnumクラスとして事前に定義する。
   - 「ValueがEnumじゃないと役に立たない」訳ではない。デモの判り易さを優先したもの。
- 想定エディタはSTSとする。
   - 他エディタ、例えばIntelliJ IDEA等でも利用できる様子だが、動作は未確認。

# デモ

### STSでの編集

- ファイル`application.properties` を開く。
   - 今回デモで入力したい、対象キー名は`test-app.colors`とする。
   - `test-app.colors`に設定可能なValueとして、事前にEnum型のColorを定義してある。
     - 同Enum型は`RED,BLUE,GREEN ` の3つしか取らない。

- エディタで`test-app.`と入力。
   - 「`colors` というキー名が、配下に在りますよ」とサジェストしてくれる。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/e6579c3a-159c-63e4-6183-b535c65ccf35.png)

- `colors`をクリックして再度Ctrl+Spaceキーを押下。
   - 「設定可能なValueは`blue,green,red` の3つです」とサジェストしてくれる。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/c6877c90-bf7e-8a84-3663-808fde52e2ea.png)

- `blue`をクリック+加えて`,`を入力。
  再度Ctrl+Spaceキー押下。
   - 再び「設定可能なValueは`blue,green,red` の3つです」とサジェストしてくれる。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/3498fee7-e829-d35c-7b86-082c41626d21.png)

- 今回デモとしては以下Valueを設定し終える。Ctrl+Sでファイル保存。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/23de8754-35b0-e501-ff22-c8ef3dee72ae.png)

### アプリ稼働確認

- アプリを起動する。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/eeb81f6e-74b1-94ff-ee00-13058ccaa187.png)

- 起動が完了したら、`http://localhost:8080/testProps`　にアクセス。
  - 先ほど設定した`test-app.colors`のValueが表示される。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/b9c66159-2dff-98b3-3975-d6972ca3089a.png)

- ちなみに`test-app.colors=red`のみ設定した場合は以下。

![red.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/cdd253f9-0aed-a3be-b80c-910b3c55ed24.png)

# デモ用アプリ解説+おまけ

- 設定値の入力を支援する為に、"spring-boot-configuration-processor"を利用。
  - 同モジュールがアプリ内のBean情報を解析して、コード補完用メタデータを自動生成してくれる。
  - pom.xmlにdependency定義の上でプロジェクトBuildすると都度、メタデータも生成してくれる。
    - メタデータはJSON形式。直接ファイル弄ることも可能。
      - とはいえメンテ負荷が高まるので、可能な限り自動生成に頼る方が、筋が良い。

- 自動生成されたメタデータ抜粋。

```target\classes\META-INF\spring-configuration-metadata.json
{
  "groups": [
    {
      "name": "test-app",
      "type": "com.example.demo.ConfigurationMetadataStudyForCollectionProps",
      "sourceType": "com.example.demo.ConfigurationMetadataStudyForCollectionProps"
    }
  ],
  "properties": [
    {
      "name": "test-app.colors",
      "type": "java.util.List<com.example.demo.Color>",
      "sourceType": "com.example.demo.ConfigurationMetadataStudyForCollectionProps"
    },
  ],
  "hints": []
}
```

- 例えば`test-app.colors=red,gray`と設定してしまった(=認めていないValueを含めた)場合には  
  まずSTS上では警告が出る。 

![warn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/97268714-2163-8410-db81-3d2ccbfb4046.png)

- 無視してアプリ稼働しても結局、アプリ起動シーケンスでコケる。

![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32882/f9deacfc-c065-ede8-a077-3aac864ba93c.png)

# 参考リンク

* propertiesとメタデータ  

> https://spring.pleiades.io/spring-boot/docs/2.1.3.RELEASE/reference/html/configuration-metadata.html

* 独自メタデータ作成  

> https://spring.pleiades.io/spring-boot/docs/2.1.3.RELEASE/reference/html/configuration-metadata.html#configuration-metadata-annotation-processor

* 参考にさせて頂いたQiita記事

> https://qiita.com/rubytomato@github/items/abbf0ee15662a7252bd8