MicroProfile Config API
MicroProfile Config API は、異なるソースから構成情報を取得できる単一の API として、アプリケーションで使用できます。
Liberty MicroProfile Config フィーチャーのバージョン 1.1 以降の使用については、 Open Liberty Web サイト を参照してください。
- 複数の構成ソースを単一の構成に結合し、1 つの API でアクセスすることができます。
- 構成プロパティー値は、優先順位の高い値として指定された構成ソースの値でオーバーライドできます。
- 値は、名前付きプロパティー・ファイル、システム環境変数、または Java™ システム・プロパティーに保管できます。
ConfigSource
リソースは、JavaClassLoader
(アプリケーションの現行コンテキストClassLoader
またはユーザー提供のClassLoader
) を使用してロードされます。ConfigSource
インターフェースのユーザー実装環境を登録することで、値を指定できます。- 値は、組み込みまたはカスタム・タイプのコンバーターを使用して、ストリングとして、または特定の Java クラスの型付きオブジェクトとして取得できます。
ConfigSource
実装とConverter
実装は、JavaServiceLoader
パターンを使用してディスカバーできます。- プリミティブ、標準タイプ、またはユーザー提供タイプのいずれの場合でも、構成プロパティー値は、Java CDI (Context and Dependency Injection) を使用して直接注入できます。
構成の注入
MicroProfile Config API は、Java ServiceLoader
configsources
によってロードされるデフォルトの構成ソースおよび構成ソースを収集します。これについては、このトピックで後述します。 Java CDI (Contexts and Dependency Injection) を使用して、構成オブジェクトをアプリケーションに直接注入することができます。
@Inject
Config config;
String appName = config.getValue("APP_NAME", String.class);
単一の構成プロパティー値を注入することも可能です。
@Inject
@ConfigProperty
String PROPERTY_NAME1;
これらのプロパティーは、標準の Java プロパティーと同様に、未加工形式でストリングとして表されます。 システムは構成ソースのデフォルト設定を使用し、classname
の名前から構成プロパティーの名前を取得します。この名前は、最初の文字が小文字で、その後に変数名が付加されます。区切り記号はドットです。 例えば、直前のスニペットが ClassA
というクラス内にある場合、解決されるプロパティー名は classA.PROPERTY_NAME1
です。
@Inject
@ConfigProperty(name="PROPERTY_NAME2")
String propertyTwo;
このコード・スニペットは、必須プロパティー PROPERTY_NAME2 を構成ソースから検索します。 このプロパティーが存在しない場合は DeploymentException がスローされます。
configsources
にもプロパティーが存在しない場合は、defaultValue パラメーターを使用してデフォルト値を割り当てます。@inject
@ConfigProperty(name="myName", defaultValue="Bob")
String name;
このコード・スニペットはプロパティー myName
を構成済み configsources
から検索します。 このプロパティーが未定義の場合は、値 Bob が変数 name に割り当てられます。構成のプログラマチック検索
MicroProfile Config API は、メソッド呼び出しを使用して構成プロパティーを検索するためのインターフェースも提供します。 この検索を行う方法は 2 つあります。デフォルト設定を使用する使いやすい構成プロバイダー・クラスと、完全にカスタマイズ可能な構成ビルダー・クラスです。
ConfigProvider クラス
構成を使用する最も単純な方法は、ConfigProvider
クラスで静的メソッドを使用することです。 この API は、Java ® ServiceLoader
configsources
によってロードされるデフォルトの構成ソースと構成ソースを収集します。
Config config = ConfigProvider.getConfig();
String appName = config.getValue("APP_NAME", String.class);
ConfigBuilder クラス
よりカスタマイズされた方法で構成を作成したいユーザーは、構成ビルダー API を使用して、構成の生成前にさまざまなオプションを設定することができます。 この例では、ビルダー・パターンを使用して、前の例の構成と同等の構成を作成しています。
ConfigBuilder builder = ConfigProviderResolver.getBuilder();
builder.addDefaultSources();
Config config = builder.build();
builder.addDefaultSources()
を呼び出すと、構成を作成するために、ConfigProvider
が使用するのと同じデフォルト・ソースのセットが追加されます。 その他の構成ソースも追加できます。
構成ソース
構成プロパティーは、プロパティー・ファイルや、アプリケーションによって登録されたユーザー・クラス、または Java ServiceLoader
パターンを使用してロードされたユーザー・クラスなど、いくつかの場所から入手できます。
デフォルトのソース
ConfigProvider
インターフェースと異なり、ConfigBuilder
インターフェースは、最初は空の構成プロパティー・ソースのセットを持っています。 デフォルトのソースを追加すると、以下の影響があります。
- プロセス環境変数が構成に含まれます。 Liberty は、ホスト・プロセス環境変数を Java
System.getenv()
メソッドに示し、さらにサーバーの server.env ファイルからプロパティーを追加します。 これにより、これらの変数が MicroProfile Config API で使用可能になります。 System.getProperties()
経由で使用可能な Java システム・プロパティーが構成に含まれています。 Liberty は、サーバーの bootstrap.properties ファイルおよび jvm.options ファイルから Java システム・プロパティーにプロパティーを追加します。resourceName
が META-INF/microprofile-config.propertiesのアプリケーションThreadContextClassLoader
クラスパスからロードされるファイル。 これらのプロパティー・ファイル内では、プロパティーは、標準の Java プロパティー・ファイルで使用されるのと同じ構文を使用して保管されます。 Liberty アプリケーションの場合、 META-INF ディレクトリーの場所は、JAR のルートにあるサブディレクトリー、WAR ファイルの場合は WEB-INF\classes\META-INF\ ディレクトリー、EAR の lib ディレクトリーにある JAR、またはサーバー・レベルの共有ライブラリー JAR のいずれかになります。 使用されるClassLoader
(クラスパス) は、ビルダーのforClassLoader
メソッドを使用して変更できます。
ユーザー提供の ConfigSources
org.eclipse.microprofile.config.spi.ConfigSource
を実装するユーザー・クラスを ConfigBuilder
に登録することができます。 そのようにすると、このユーザー・クラスは、ビルダーが生成する構成に後で組み込まれます。
MySource source = new MySource();
builder.withSources(source);
ConfigSources の Java ServiceLoader ロード
Java ServiceLoader パターンを使用して、カスタム構成ソース・オブジェクトを見つけることもできます。 ConfigSource
インターフェースを実装するユーザー・クラスは、その完全パッケージ修飾クラス名が ${CLASSPATH}/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceという形式のファイルにリストされている場合にロードされます。
コンバーター
MicroProfile Config API は、必要なプロパティー・オブジェクトのタイプを取得する汎化されたメソッドを使用して、プロパティーを Java オブジェクト・タイプとして取得することもできます。 このメソッドは、標準装備またはユーザー提供のコンバーターを持つ任意のタイプに対応できます。 例えば、前述の例のコードは、標準装備のストリング・コンバーターを次のように使用するよう作成することができます。
appName = config.getOptionalValue("APP_NAME", String.class).orElse("MicroDemo");
標準装備コンバーター
MicroProfile Config API には、 boolean
、 Boolean
、 int
、 Integer
、 long
、 Long
、 float
、 Float
、 double
、 Double
、 Duration
、 LocalTime
、 LocalDate
、 LocalDateTime
、 OffsetDateTime
、 OffsetTime
、 Instant
、および URL
の各タイプ用の組み込みコンバーターが含まれています。
これらのタイプの変数は、直接注入することも、汎用化された getValue
呼び出しを使用して取得することもできます。 該当する valueof
、 parse
、またはコンストラクター・メソッドを使用して、単一のストリング・パラメーターを取得することにより、プロパティーのストリング値をタイプに正常に変換できる場合。
カスタム・コンバーター
org.eclipse.microprofile.config.spi.Converter<T>
インターフェースを実装するカスタム・コンバーターは、ConfigBuilder
API を使用することで、構成に登録して使用することができます。
ConfigBuilder builder = ConfigProviderResolver.getBuilder();
builder.addDefaultSources();
Converter<CustomProperty> converter = new MyConverter();
builder.withConverters(converter);
Config config = builder.build();
Optional<CustomProperty> opt = config.getOptionalValue("PROPOBJ", CustomProperty.class);
withConverters
メソッドは、リフレクションを使用してどのタイプのコンバーターが適切かを判別します。 Java Lambda コードは現在、十分なタイプ情報をリフレクション API に提供していないため、カスタム・コンバーターには Converter<T>
インターフェースを明示的に実装するコードが必要です。コンバーターの優先順位
同じタイプに対して複数のコンバーターが存在する場合、使用するコンバーターは @Priority
アノテーションを使用して制御できます。 このメソッドを使用すると、アプリケーションのライフサイクルにおいて、コンバーターの実装を後でオーバーライドすることが可能です。 コンバーターは、優先順位の低い同じタイプの他のコンバーターをオーバーライドします。
import javax.annotation.Priority;
import org.eclipse.microprofile.config.spi.Converter;
@Priority(200)
publicclass StringPrefixConverter implements Converter<String> {
@Override
public String convert(String value) throws IllegalArgumentException {
return"Converted:" + value;
}
}
@Priority
アノテーションを使用していない場合、コンバーターのデフォルト優先順位は 100 です。
Java ServiceLoader によるコンバーターのサポート
Java ServiceLoader パターンを使用して、カスタム・コンバーターのパッケージ修飾クラス名が ${CLASSPATH}/META-INF/services/org.eclipse.microprofile.config.spi.Converterという形式のサービス・ファイルに出現する場合に、カスタム・コンバーターを見つけることもできます。
MicroProfile Config API 実装に組み込まれているデフォルト・コンバーターと、Java ServiceLoader
パターンを使用してディスカバーされたコンバーターの両方を、すべての構成で使用できます。
プロパティー値のオーバーライド
複数の構成ソースが使用される場合、すべてのソースからのプロパティーがまとめて収集され、単一のセットとしてアプリケーションによってアクセスされます。 各構成ソースには序数値が割り当てられます。 1 つのプロパティーが複数のソースに出現する場合、最大序数のソースのプロパティー値が優先され、アプリケーションに返されます。 デフォルトの序数値は以下のとおりです。
- システム・プロパティー - 400
- 環境変数 - 300
- /META-INF/microprofile-config.properties - 100
- カスタム
ConfigSource
オブジェクト -ConfigSource
のgetOrdinal
の結果
config_ordinal
プロパティーを使用してオーバーライドできます。同じプロパティーを提供する 2 つの ConfigSources
が同一の序数を持っている場合、ストリング比較ルールに従って ConfigSources
ID を使用して比較が行われます。
開発ライフサイクルの早い段階で通常設定されるソースには、より低い序数と優先順位が設定されます。 これは、アプリケーションのライフサイクルにおいて後で、例えばアプリケーションのアセンブリーやインストールの際に、既存のプロパティー値をオーバーライドする機能をサポートするためです。
動的プロパティー値
設計が工夫されたマイクロサービス・アプリケーションは個別のアプリケーションの再始動に左右されず可用性を維持しますが、構成値に対する変更についても再始動しなくてもアプリケーションで有効となるのが理想的です。
バージョン 1.4 より前のバージョンの mpConfig フィーチャーでは、登録済みの ConfigSource
オブジェクトによって提供される構成内のプロパティー値は、ConfigSources
が提供する更新値によって更新できます。 ConfigSources
が参照され、値がリフレッシュされる頻度は、 microprofile.config.refresh.rate
Java システム・プロパティーによって制御されます。 使用される単位はミリ秒であり、デフォルト値は 500
です。これは、デフォルトで、ConfigSources
提供の値が、それらの値が寄与する構成に 0.5 秒ほどで取り込まれることを意味します。 microprofile-config.properties ファイルなどの非プログラマチックな構成ソースは、最初の構成作成後に動的に再読み取りされません。
キャッシュされた値を MicroProfile 構成から取得する方法は、 mpConfig-1.4
フィーチャーで変更されました。 詳しくは、 Open Liberty ブログを参照してください。
プロパティーの注入後に値の更新を表示できるようにするには、ConfigValue
オブジェクトを使用できます。 構成プロパティー値と構成プロパティー値の Optional<T>
の両方において、これには getter があり、その getter が呼び出されるたびに現行値が返されます。 例:
@Inject
@ConfigProperty(name="propertyName3")
Provider<MyClass> propertyName3;
MyClass mc = propertyName3.get();
また、ConfigValue
クラスが一般化され、適切なコンバーターが存在すればこれを使用して特定のタイプのプロパティーを取得できることも確認できます。
Config のキャッシング
効率を促進するために、ConfigProvider
は getConfig
メソッドにより返された構成を、その ClassLoader
により識別された特定のアプリケーション (モジュール) 用にキャッシュします。 ConfigBuilder
を使用して構成が生成される場合、その構成オブジェクトはキャッシュされません。 ただし、 org.eclipse.microprofile.config.spi パッケージ内の ConfigProviderResolver
には、Config オブジェクトをキャッシュに入れるために使用できる registerConfig
メソッドと、Config オブジェクトを解放するための releaseConfig
メソッドがあります。
Libertyでの MicroProfile Config の実装について詳しくは、 MicroProfile 構成プロジェクト・サイトを参照してください。