Spring bootでapplication.propertiesの設定値を起動時に変更する方法

新型コロナの影響が徐々に職場にも出始めていていつ出社停止になるかドキドキしています。

そんな中、久しぶりに丸一日ハマったので記録しておくことにしました。
しかも理解できればとても単純な話でかなり凹んでます。
おそらくJavaやってる人からすれば初歩的すぎてWebに公開するまでもないようなことなのかもしれません。。


## やりたいこと
* アプリケーション起動時に設定ファイルを読み込んで値を設定したい。

こんな簡単なことに8h。


## ハマったポイント
* classes/application.propertiesを書き換えても値が反映されない。

## 事象再現

https://github.com/t-o-z/configuration-demo

Readmeの通りにセットアップして、

```
docker run config-demo
```

するとapplication.propertiesに含まれている

```
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.4.RELEASE)

2020-02-27 09:51:15.557  INFO 7 --- [           main] c.z.c.ConfigurationDemoApplication       : Starting ConfigurationDemoApplication v0.0.1-SNAPSHOT on 6c889b4a8ada with PID 7 (/usr/src/myapp/configuration-demo-0.0.1-SNAPSHOT.jar started by root in /usr/src/myapp)
2020-02-27 09:51:15.566  INFO 7 --- [           main] c.z.c.ConfigurationDemoApplication       : No active profile set, falling back to default profiles: default
2020-02-27 09:51:16.918  INFO 7 --- [           main] c.z.c.ConfigurationDemoApplication       : Started ConfigurationDemoApplication in 2.482 seconds (JVM running for 3.809)
key1-value
```

が表示されます。

classes配下のapplication.propertiesを

```
sample.key1=key1-value1
```

と書き換えて、再度実行しても、

```
user:configuration-demo user$ docker run config-demo

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.4.RELEASE)

2020-02-27 09:58:45.004  INFO 6 --- [           main] c.z.c.ConfigurationDemoApplication       : Starting ConfigurationDemoApplication v0.0.1-SNAPSHOT on 9999dad12dac with PID 6 (/usr/src/myapp/configuration-demo-0.0.1-SNAPSHOT.jar started by root in /usr/src/myapp)
2020-02-27 09:58:45.014  INFO 6 --- [           main] c.z.c.ConfigurationDemoApplication       : No active profile set, falling back to default profiles: default
2020-02-27 09:58:46.425  INFO 6 --- [           main] c.z.c.ConfigurationDemoApplication       : Started ConfigurationDemoApplication in 2.564 seconds (JVM running for 3.881)
key1-value
```

となり反映されません。。

いろいろ試しました。

* **classes/config**にapplication.properties置いてみたり
    * https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
* 設定読み込みの方法を変えてみたり
    * https://qiita.com/kazuki43zoo/items/0ce92fce6d6f3b7bf8eb
* 起動時にプロパティを直接InputStreamから取得して上書きしてみたり
    * (すみません。参考にしていたURL見失いました。)


対策を調べても、

* 環境ごとの設定ファイルを用意する
    * https://www.baeldung.com/spring-profiles
* コマンドライン引数で書き換える
    * https://stackoverflow.com/questions/37052857/spring-overriding-one-application-property-from-command-line
* Hot(Live) Reloadを使用する
    * https://www.baeldung.com/spring-reloading-properties

とかいろいろあるのですが、純粋に1ファイルだけってもしかしてできないの？ってくらい情報がありませんでした。最後のHot Reloadなんかはこれやるためだけにサーバ立ち上げるとか。



# 結論

**/configにコピーする！**

もう試行錯誤のところで太字にしちゃってますが、

```
classes/config
```

じゃダメなんです。

```
/config
```

を新しく作成してその中にclasses/application.propertiesを配置します。

<img width="446" alt="target 2020-02-27 19-21-35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274988/276b5fba-4cc7-9d0e-17e7-5392397734fa.png">



```
sample.key1=modify
```

と変更してDockerを起動（COPYなので再build必要）すると。

```
Otsuka:configuration-demo otsukatakuya$ docker run config-demo

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.4.RELEASE)

2020-02-27 10:54:32.393  INFO 6 --- [           main] c.z.c.ConfigurationDemoApplication       : Starting ConfigurationDemoApplication v0.0.1-SNAPSHOT on c43d6b28259a with PID 6 (/usr/src/myapp/configuration-demo-0.0.1-SNAPSHOT.jar started by root in /usr/src/myapp)
2020-02-27 10:54:32.403  INFO 6 --- [           main] c.z.c.ConfigurationDemoApplication       : No active profile set, falling back to default profiles: default
2020-02-27 10:54:33.804  INFO 6 --- [           main] c.z.c.ConfigurationDemoApplication       : Started ConfigurationDemoApplication in 2.474 seconds (JVM running for 3.59)
modify
```

## どこに書いてある？

https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config

Spring bootの公式リファレンスに記載がありました。


> SpringApplication loads properties from application.properties files in the following locations and adds them to the Spring Environment:


> 1. A /config subdirectory of the current directory

> 2. The current directory

> 3. A classpath /config package

> 4. The classpath root

> The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).


1を試しているつもりが最初に3を試してできないとなっていたのです。。
おそらくクラスパスはjarに含まれているからそちらと競合してしまう？

pom.xmlに除外設定を書いて、buildに含めない方法を提案している方もいたのですが、追加するだけで良いよ！って簡潔に書いている記事が少なくて勉強になりました。