3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SpringAdvent Calendar 2022

Day 4

SpringBoot2.4からの設定ファイル処理方法

Posted at

概要

SpringBoot2.4以降、設定ファイル(application.ymlの類)の処理方法がガラッと変わっている。1

SpringBoot2.x系を使っている分には、2.3以前の処理方法をonにするオプション(spring.config.use-legacy-processing)を利用できるが、SpringBoot3に追随する場合は左記のオプションは使えないので、新しい処理方法への適応が必須である。2

ここではこのSpringBoot2.4で入った設定ファイルの処理方法変更の背景、変更内容、spring-cloudへの影響を記述する。

設定ファイル処理方法の変更が入った背景

そもそもこのような変更が必要となった背景はSpring公式のこのブログに記載されている。
要約すると、KubernetesのConfigMapの設定読み取りに対応しつつ、従来の方法も提供し続けたいが、2.3以前の設定ファイルを処理するクラスであるConfigFileApplicationListenerを使い続けるのは厳しいため、新たな仕組みへと刷新することにした、という内容であった。

KubernetesのConfigMapの設定読み取りに対応しつつ

ここについてもう少し詳しく記述すると、Kubernetesにおいてはファイルのディレクトリをキーとし、ファイルの内容を値とする設定方法があり、SpringBoot2.4以降はその読み取りに対応できるようになっている。

従来の方法と新しい設定方法を比較してみる。
従来のapplication.ymlから下記のような設定値を読み取ることができる。

myapp:
  username: nannany
  password: dolphins

ファイルのディレクトリをキーとし、ファイルの内容を値とする設定で同様のことをしようとした場合、下記のようなディレクトリ構造をしていて、usernameファイルの中にnannanyという値、passwordファイルの中にdolphinsという値が含まれている、というイメージである。3

/etc
└── config
    └── myapp
        ├── username
        └── password

SpringBoot2.4以降では、上記のどちらからも設定を取得することができるようになっている。

どんな変更が入っている?

入った変更は下記ページがよくまとまっている。

  • application.propertiesでも#---を使ったら1つのファイルを論理的に分割することができるようになった
    • application.ymlでは---を使って以前から分割できていた
  • spring.config.activate.on-profileでactivateなprofileを切り替えることができるようになった
    • spring.profiles.activeとの共存に関しては、論理的に分割された別の範囲で共存することは可能。論理的にも一緒の部分で共存することは不可
これはエラーにならない
test=value
spring.profiles.active=local
#---
spring.config.activate.on-profile=dev
test=overridden value
これはエラーになる
test=value
#---
spring.config.activate.on-profile=dev
spring.profiles.active=local # will fail
test=overridden value
  • 複数のprofileを1つのグループにまとめることができるようになった
こんな感じ
spring.profiles.group.prod=proddb,prodmq,prodmetrics
  • spring.config.importで読み取るべき設定ファイルの指定、kubernetes likeな設定値の読み取りができるようになった
    • 肝の機能と思われる
    • 複数のキーバリューが設定してある設定ファイルから設定読み取りができる
    • ディレクトリをキー、ファイル内容をバリューとした設定からの読み取りができる
複数のキーバリューが設定してある設定ファイルから設定読み取りができる
spring.config.import=file:/etc/config/myconfig.yaml
ディレクトリをキー、ファイル内容をバリューとした設定からの読み取りができる
spring.config.import=optional:configtree:/etc/config/
  • クラウドプラットフォームによってアクティブにするか切り替えられるspring.config.activate.on-cloud-platformが用意された
    • kubernetesだけでなく、cloudfoundry、heroku、sap、azureappserviceが(おそらく)デフォルトで指定できる4
こんな感じで、k8sならこうやって設定値を読み取る、と指定できる
spring.config.activate.on-cloud-platform=kubernetes
spring.config.import=configtree:/etc/config
  • 2.3以前の処理方法を継続したい人のためにspring.config.use-legacy-processingオプションが用意された

spring-cloudへの影響

spring-cloud側でもこの変更の影響を受けていて、例えばspring-cloud-commons内のConfigDataMissingEnvironmentPostProcessor.javaでは下記のようにspring.config.importが設定されていないと落ちることがある。5

ConfigDataMissingEnvironmentPostProcessor.java
	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		if (!shouldProcessEnvironment(environment)) {
			return;
		}
		List<Object> property = getConfigImports(environment);
		if (property == null || property.isEmpty()) {
			throw new ImportException("No spring.config.import set", false);
		}
		if (!property.stream().anyMatch(impt -> ((String) impt).contains(getPrefix()))) {
			throw new ImportException("spring.config.import missing " + getPrefix(), true);
		}
	}

私自身、SpringBootとspring-cloudのバージョンを上げた際に、ユニットテストが上記のエラー分岐に入るようになって下記のエラーメッセージに直面した。

Caused by: org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor$ImportException: No spring.config.import set

ユニットテストであったので、spring-cloud-configを無効にすべくspring.cloud.config.enabled=falseにして対処することができた。

(直面した事象ベースで記述しており、ここ以外にもspring-cloudへの影響はあると思う)

まとめ

SpringBoot2.4で大きく変更の入った設定ファイルの処理方法について、変更の背景・変更内容・spring-cloudへの影響(の一例)を記述した。

雑感として、SpringBootのドキュメントは色々あって本当に充実しているなぁと感じる一方、spring-cloud側はもうちょっと変更の影響をガイドする何かがあっても良いのでは、と思った。 -> ちゃんとみたらあった
https://spring.pleiades.io/spring-cloud-config/docs/current/reference/html/#config-data-import

追加で面白そうだと感じたのは、ここ に書いてあるのだが、spring.config.import設定ファイル読み込みはプラガブルで、ConfigDataLocationResolverConfigDataLoaderを実装すれば独自のサポートが可能らしい。
実際、spring-cloud-config-clientでは、下記のようにconfigserverなる文字列を利用した独自の指定が可能となっている。

spring.config.import=optional:configserver:http://myconfigserver.com

参考

  1. SpringBoot2.4のリリースノート

  2. 公式のブログでもこの点について言及されている

  3. このページに具体的な方法が書いてある

  4. CloudPlatform.java。このコードに出てくるものを列挙した

  5. ConfigDataMissingEnvironmentPostProcessor.javaのソースコード

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?