Spring Bootの設定値が反映されないときの調べ方|設定元とActuator

Spring Bootの設定値を調べる猫のイラスト

application.ymlを書き換えたのに、タイムアウトや接続先が変わらない。そんなときは、同じ設定を何度も編集する前に、設定が読み込まれたか、別の設定元に上書きされたか、アプリがその値を使っているかを分けて調べます。

この記事ではSpring Boot 3.5系を対象に、起動条件と設定ファイルの照合から、Actuatorのenv・configpropsで設定元と束縛結果を追う手順までを説明します。Actuatorの調査では設定情報が露出するため、アクセス範囲を限定してから確認を進めます。

目次

設定値が反映されないときは「読み込み・上書き・利用」を分ける

設定の問題は、次の3段階に分けると原因を絞れます。

段階確認すること主な調査対象
読み込み対象キーを持つ設定元が取り込まれているか設定ファイルの場所、有効profile、起動プロセスの環境変数
上書き同じキーについて、どの設定元が採用されるかPropertySourceの優先順位、env
利用解決された値が設定オブジェクトや処理へ渡っているかconfigprops、Bean登録、利用側のコード

対象キー・期待値・実際の挙動を一つに絞る

この記事では、例としてapp.notification.connection.timeoutを追います。変更したファイルでは2sにしたのに、通知処理の待ち時間が変わらない状況を考えます。

app:
  notification:
    connection:
      timeout: 2s

最初に、対象キー、期待する値、変更した設定元、実際に観察した挙動を記録します。「通知が遅い」という観察だけでは、タイムアウト設定が違うのか、再試行や別の待ち時間があるのかは分かりません。設定の確認結果と処理時間の観察は分けて扱いましょう。

調べているプロセスと変更後の起動状態を確認する

設定元を追う前に、調査先のホスト、ポート、アプリケーションのインスタンス、起動時刻を確認します。ローカルで再起動したつもりでも、別のプロセスや別の配置先へアクセスしていれば、設定変更の結果は判断できません。

jar内の設定を変更した場合は、変更を含む成果物をビルドして起動しているかも確認します。IDEからの起動とjarの起動では、使うクラスパスや起動設定が異なることがあります。

設定ファイルの編集や環境変数の変更だけで、起動済みプロセスの設定が自動的に更新されるとは考えません。動的な再読み込みを導入している場合は、その仕組みの更新条件を別に確認します。

PropertySourceの優先順位から上書き元を探す

SpringのEnvironmentは、複数のPropertySourceから設定値を解決します。同じキーが複数の設定元にあれば、優先される設定元の値が使われます。変更したファイルに正しい値があることと、その値が採用されることは別です。

設定ファイル・環境変数・システムプロパティ・起動引数を照合する

まず、次の代表的な設定元を強い順に照合します。この表は通常起動で調べる候補を抜き出したもので、すべてのPropertySourceを列挙したものではありません。

相対的な優先順位設定元確認箇所
高いコマンドラインオプション--app.notification.connection.timeout=5sなど
↓SPRING_APPLICATION_JSONJSONで渡される対象キー
↓JVMシステムプロパティ-Dapp.notification.connection.timeout=5sなど
↓OS環境変数APP_NOTIFICATION_CONNECTION_TIMEOUTなど
低いConfig Dataapplication.ymlや外部設定ファイルなど

たとえば、ファイルが2sでも、起動時に同じキーを5sとしてコマンドラインへ渡していれば、ファイルだけを編集しても期待値にはなりません。IDEの実行構成では、VMオプションとプログラム引数を別々に確認します。サービスやコンテナでは、起動定義側の指定も照合してください。

SPRING_APPLICATION_JSONやテスト専用の設定も候補に入れる

SPRING_APPLICATION_JSONには、複数の設定がJSON形式でまとめて渡されることがあります。個別の環境変数名だけを探していると、ここに含まれる対象キーを見落とします。内容全体をログへ出すのではなく、管理された設定定義で対象キーの有無を確認します。

テスト実行時だけ違う値になる場合は、テスト用のプロパティ指定、@DynamicPropertySource、@TestPropertySourceなども候補です。Devtoolsを使う開発環境にも別の設定元があります。通常起動の代表表だけで、テストや開発環境の採用値まで決めつけないでください。

独自の@PropertySourceを使っている場合は、追加されるタイミングにも注意します。これはApplicationContextのrefresh時にEnvironmentへ追加されるため、refresh開始前に参照されるlogging.*やspring.main.*の設定には遅すぎます。優先順位だけでなく、「その設定が読まれる時点で存在するか」も確認が必要です。

変更した設定ファイルと環境変数が読み込まれているか調べる

有効profile・外部ファイル・実行ディレクトリを確認する

変更したファイル名と、実際に有効なprofileを照合します。profileを指定する設定そのものが起動引数などで上書きされていないかも確認しましょう。ファイルの存在だけでは、その実行で読み込まれることの証明にはなりません。

外部ファイルを使う場合は、jarの配置場所とプロセスの実行ディレクトリを区別します。相対パスの指す先が想定と違えば、編集したファイルとは別のファイルを参照する原因になります。IDE、サービス、コンテナそれぞれの起動条件を確認してください。

設定の配置やprofileの分け方を見直す場合は、予防設計を扱う次の記事が参考になります。

config.location・additional-location・importの指定を追う

設定ファイルが見つからない場合は、読み込み場所を変更する指定を確認します。特に次の2つは役割が異なります。

設定役割診断時の着眼点
spring.config.locationデフォルトの検索場所を置き換える従来の場所も引き続き検索されると思い込んでいないか
spring.config.additional-location検索場所を追加する追加場所の設定が既定の設定を上書きしていないか

これらは設定ファイルの探索に使われるため、環境変数、JVMシステムプロパティ、起動引数など、起動の早い段階で利用できる指定を確認します。

spring.config.importがある場合は、現在のファイルだけで調査を止めず、取り込み先にも対象キーがないか追います。読み込み先、profile、各設定元の優先関係を並べ、最終的には後述するenvで実際の供給元と照合します。

環境変数の名前と起動プロセスへの受け渡しを確認する

例のキーなら、環境変数の確認対象はAPP_NOTIFICATION_CONNECTION_TIMEOUTです。設定ファイル側のキーと、起動定義に書いた環境変数名を対応させて確認します。

次に、その変数がアプリケーションを起動したプロセスへ渡っているかを調べます。手元のターミナルで設定されていても、そこから起動していないIDEやサービスに同じ値が渡るとは限りません。コンテナでは、ホスト側の変数とコンテナ内へ渡す指定も分けて確認します。

調査のために環境変数をすべて表示・保存する必要はありません。起動定義と対象キーに絞り、秘密情報をログや問い合わせ資料へ残さないようにします。

Actuatorの診断前に情報の公開範囲を限定する

Actuatorのenvとconfigpropsは設定調査に役立ちますが、設定キーやファイルパスなどの運用情報も扱います。調査の入口を作る前に、誰がどの経路からアクセスできるかを確認してください。

env/configpropsのアクセス・公開・認証を確認する

Spring Boot 3.5では、HTTPで既定公開されるActuatorエンドポイントはhealthだけです。envとconfigpropsをHTTPで調査するには、エンドポイントのaccessで必要な操作が許可され、HTTP exposureにも含まれている必要があります。

さらに、公開された経路への認証・認可とネットワーク制御を確認します。exposureへ名前を追加する操作は、運用担当者だけにアクセスを許可する設定の代わりにはなりません。既存のSecurityFilterChainやプロキシを含め、許可された担当者が到達でき、許可されていない利用者は到達できない構成にします。

調査のために全Actuatorエンドポイントを一括公開しないでください。必要なエンドポイントだけを対象にし、公開先、利用者、調査期間を限定します。

公開設計の考え方を補足する記事は次のとおりです。リンク先の設定例はSpring Boot 4.1向けなので、本記事の3.5系へ設定名やJavaのimportをそのまま転用せず、対象版の資料と照合してください。

値の表示設定とレスポンスの保存・共有範囲を確認する

envとconfigpropsの値は、既定で完全にサニタイズされます。値の表示を制御するのは、management.endpoint.env.show-valuesとmanagement.endpoint.configprops.show-valuesです。

neverは値を表示せず、alwaysは認可の有無で表示対象を限定しません。when-authorizedは認可された利用者への表示を扱いますが、HTTPの認証状態や各エンドポイントのroles設定を合わせて確認する必要があります。独自のSanitizingFunctionがある場合は、そのサニタイズ条件も別に作用します。

まずは値を伏せた状態で設定元を追い、実値の確認が必要な場合だけ、担当者の権限と表示条件を確認します。値が見えないことを理由にshow-values=alwaysへ切り替える進め方は避けましょう。

マスキングされていても、キー名、内部の構成、ファイルパスなどは共有に適さない場合があります。レスポンス全体をチケットやチャットへ貼らず、必要な情報だけを抽出し、保存先、閲覧権限、保存期間も管理します。

env/configpropsで設定元と束縛結果を追う

アクセス範囲を限定できたら、まずenvでEnvironmentの解決結果を確認し、次にconfigpropsで設定オブジェクトへの束縛結果を照合します。ここでは標準のベースパスを使った確認先を示します。実際の管理ポートやベースパスに合わせて読み替えてください。

envで対象キーのPropertySourceとoriginを確認する

envはConfigurableEnvironmentのプロパティとPropertySourceを確認するためのエンドポイントです。対象キーを絞る場合は、次のGET経路を使います。

/actuator/env/app.notification.connection.timeout

確認するのは、対象キーが解決されているか、どのsourceが採用されているか、各PropertySourceに同じキーがあるかです。originが提供されていれば、ファイル名や位置など、入力元を絞る手掛かりになります。ただし、すべての設定元でoriginが得られるわけではありません。

たとえば、編集したファイルに対象キーが見つかっても、採用元が別のPropertySourceなら、先に上書き元を調べます。originがない場合は、source名と起動定義を照合して候補を絞ります。

envで期待する値が解決されていても、アプリケーションがその値を使って動作している証明にはなりません。設定オブジェクトへの束縛と利用側の処理を続けて確認します。

configpropsで対象の設定オブジェクトと入力情報を照合する

configpropsは、@ConfigurationPropertiesのBeanに関する情報を確認するエンドポイントです。標準の確認先は次のとおりです。

/actuator/configprops

対象のprefixとBeanを見つけ、propertiesの情報を確認します。inputsには、束縛に使われた入力値やoriginが記録される場合があるため、Environment側で調べた設定元と照合できます。レスポンスは設定全体の情報を含み得るので、閲覧と保存の範囲を広げないようにしてください。

この例なら、app.notificationをprefixとする設定Beanと、そのconnection.timeoutに注目します。文字列としての入力と、Durationなどへ変換されたプロパティは表現が異なることがあるため、見た目の文字列だけで不一致と判断しません。

configpropsは@Valueを含む全設定の一覧ではありません。対象が@Valueで注入されている場合や、独自コードで読み込まれている場合は、その注入先や読み込み処理を確認します。

値が伏せられている場合と設定が存在しない場合を区別する

値がマスクされていることと、対象キーやBeanが存在しないことは別です。まずキー、source、prefix、Beanの情報があるかを見て、表示制限によって実値だけが見えない状態なのかを切り分けます。

エンドポイント自体へアクセスできない場合も、設定キーの欠落とは判断できません。access、HTTP exposure、認証・認可、管理ポート、ベースパスを先に確認します。Actuatorを利用できない環境では、起動定義と設定配置の照合から進め、調査のためだけに設定値を全量出力する実装を追加しないようにしましょう。

診断結果から修正箇所を決めて再確認する

設定が見つからない・別の供給元が採用される場合

Environmentに対象キーが見つからない場合は、読み込み側へ戻ります。キーの綴り、ファイルの配置、有効profile、検索場所の指定、import先、プロセスへ渡る環境変数を確認します。

一方、対象キーはあるものの別のsourceが採用されている場合は、その供給元を修正します。起動引数が原因なら、ファイルに同じ値を追記しても解決しません。上書きが不要なら指定を取り除き、必要な上書きなら、その設定元の値を意図した内容へ変更します。

調査中に新しい場所へ同じキーを追加し続けると、次回の採用理由がさらに追いにくくなります。どの設定元が値を管理するかを決めて修正してください。

Environmentの値と束縛結果・アプリの挙動が違う場合

Environmentの解決結果が期待どおりなら、次は設定の受け取り方を調べます。@ConfigurationPropertiesでは、prefix、Bean登録、プロパティの対応、型変換を確認します。利用側がSpring管理のBeanを受け取らず、自分で生成した別のオブジェクトを使っていないかも確認しましょう。

束縛の仕組みや設定クラスの登録方法は、次の記事で詳しく説明しています。

束縛結果まで期待どおりなら、値を使う処理へ進みます。例のタイムアウトなら、対象のクライアントへその値を渡しているか、別の既定値で置き換えていないか、初期化時に作成したクライアントが以前の値を保持していないかを確認します。

また、処理全体の待ち時間には、再試行や複数段階の通信なども関係します。設定値が2sだから処理全体も必ず2秒で終了する、と結び付けず、何に適用するタイムアウトなのかを利用ライブラリ側の仕様と照合します。

一か所ずつ修正し、再確認後に診断用の公開設定を戻す

修正は一か所ずつ行い、必要な再ビルドや再起動をしたうえで、同じ対象キーを確認します。採用されたsource、確認できる入力元、設定オブジェクトの情報、実際の挙動を順に照合すると、どの修正で解消したかを記録できます。

解消後は、一時的に追加したHTTP exposureや値の表示設定、ネットワークの許可を通常運用の状態へ戻します。診断用のログや保存レスポンスも、保持の必要性と閲覧権限を見直してください。

まとめ

Spring Bootの設定値が反映されないときは、対象キーを一つに絞り、起動プロセスの確認、設定の読み込み、PropertySourceによる上書き、束縛と利用の順に調べます。ファイルに期待値があることだけでは、その実行で採用されているとは判断できません。

ActuatorのenvはEnvironmentの解決結果と設定元を、configpropsは@ConfigurationPropertiesのBean情報を追う手掛かりになります。両者の役割を分け、必要に応じて利用側のコードまで確認しましょう。

調査中も公開範囲は必要最小限にし、値の全量表示やレスポンスの不用意な共有を避けます。原因となる設定元を一か所ずつ修正し、再確認後に診断用の公開設定を戻すところまでを手順に含めてください。

参考資料

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次