The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

設定サポートの拡張

1. カスタム ConfigSource

MicroProfile Config で指定されたカスタム ConfigSource を作成することが可能です。

カスタム ConfigSource では、追加の設定値を読み込んで、定義された順序で Config インスタンスに追加することができます。これにより、他のソースからの値をオーバーライドしたり、他の値にフォールバックしたりすることができます。

config sources

カスタム ConfigSource には、 org.eclipse.microprofile.config.spi.ConfigSource または org.eclipse.microprofile.config.spi.ConfigSourceProvider の実装が必要です。それぞれの実装は、 ServiceLoaderメカニズムを介して、 META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource または META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider のファイルで登録する必要があります。

1.1. 例

単純なインメモリ ConfigSource を考えてみましょう。

org.acme.config.InMemoryConfigSource
package org.acme.config;

import org.eclipse.microprofile.config.spi.ConfigSource;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class InMemoryConfigSource implements ConfigSource {
    private static final Map<String, String> configuration = new HashMap<>();

    static {
        configuration.put("my.prop", "1234");
    }

    @Override
    public int getOrdinal() {
        return 275;
    }

    @Override
    public Set<String> getPropertyNames() {
        return configuration.keySet();
    }

    @Override
    public String getValue(final String propertyName) {
        return configuration.get(propertyName);
    }

    @Override
    public String getName() {
        return InMemoryConfigSource.class.getSimpleName();
    }
}

そして以下に登録します。

META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
org.acme.config.InMemoryConfigSource

InMemoryConfigSource は、 275 の序列により、 .env ソースと、 application.properties ソースの間に順序付けられます。

ConfigSource 序列

システムプロパティ

400

システムからの環境変数

300

.env ファイルからの環境変数

295

InMemoryConfigSource

275

/config からの application.properties

260

アプリケーションからの application.properties

250

アプリケーションからの microprofile-config.properties

100

この場合、 InMemoryConfigSource からの my.prop は、設定エンジンが システムプロパティシステムからの環境変数.env ファイルからの環境変数の順に値を見つけられない場合にのみ使用されます。

1.2. ConfigSource初期化

Quarkusアプリケーションの起動時に、 ConfigSource を2回初期化することができます。1回目は STATIC INIT で、2回目は RUNTIME INIT です。

1.2.1. STATIC INIT

Quarkusは静的初期化中にいくつかのサービスを開始しますが、 Config は通常、最初に作成されるものの1つです。特定の状況では、カスタムの ConfigSource を追加できない場合があります。例えば、 ConfigSource がデータベースアクセスのような他のサービスを必要とする場合、この段階では利用できず、鶏と卵の問題が発生してしまいます。このため、カスタム ConfigSource には、この段階で使用しても安全であるとソースをマークするためのアノテーション @io.quarkus.runtime.configuration.StaticInitSafe が必要です。

1.2.1.1. 例

以下だとすると、

org.acme.config.InMemoryConfigSource
package org.acme.config;

import org.eclipse.microprofile.config.spi.ConfigSource;
import io.quarkus.runtime.annotations.StaticInitSafe;

@StaticInitSafe
public class InMemoryConfigSource implements ConfigSource {

}

そして以下に登録します。

META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
org.acme.config.InMemoryConfigSource

InMemoryConfigSource は、 STATIC INIT 中に利用可能になります。

カスタム ConfigSource は、Quarkusの STATIC INIT 中に自動的に追加されません。 @io.quarkus.runtime.configuration.StaticInitSafe のアノテーションを付ける必要があります。

1.2.2. RUNTIME INIT

RUNTIME INIT ステージは、 STATIC INIT の後に起こります。このステージでは、 ConfigSource を再び初期化することができます。この段階では特に制限はなく、期待通りにカスタムソースが Config インスタンスに追加されます。

2. ConfigSourceFactory

ConfigSource を作成するもう一つの方法は、 SmallRye Config io.smallrye.config.ConfigSourceFactory API を使用することです。 SmallRye Configのファクトリーと、 MicroProfile Config で指定されている ConfigSource を作成する標準的な方法との違いは、利用可能な構成にアクセスできるコンテキストを提供するファクトリーの機能です。

io.smallrye.config.ConfigSourceFactory の各実装は、 META-INF/services/io.smallrye.config.ConfigSourceFactory ファイルの ServiceLoaderメカニズムを介して登録する必要があります。

2.1. 例

以下だとすると、

org.acme.config.URLConfigSourceFactory
package org.acme.config;

import java.util.Collections;
import java.util.OptionalInt;

import org.eclipse.microprofile.config.spi.ConfigSource;

import io.smallrye.config.ConfigSourceContext;
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.PropertiesConfigSource;

public class URLConfigSourceFactory implements ConfigSourceFactory {
    @Override
    public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context) {
        final ConfigValue value = context.getValue("config.url");
        if (value == null || value.getValue() == null) {
            return Collections.emptyList();
        }

        try {
            return Collections.singletonList(new PropertiesConfigSource(new URL(value.getValue())));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public OptionalInt getPriority() {
        return OptionalInt.of(290);
    }
}

そして以下に登録します。

META-INF/services/io.smallrye.config.ConfigSourceFactory
org.acme.config.URLConfigSourceFactory

io.smallrye.config.ConfigSourceFactory を実装することで、 Iterable<ConfigSource> getConfigSources(ConfigSourceContext context) メソッドを介して ConfigSource のリストを提供することができます。また、 ConfigSourceFactory は、 OptionalInt getPriority() メソッドをオーバーライドすることで、優先度を割り当てることができます。優先度の値は、複数の io.smallrye.config.ConfigSourceFactory をソートするために使用されます(見つかった場合)。

io.smallrye.config.ConfigSourceFactory の優先順位は、 ConfigSource の序列には影響しません。これらは独立してソートされます。

ファクトリーの初期化中、提供された ConfigSourceContext は、メソッド ConfigValue getValue(String name) を呼び出すことができます。このメソッドは、 Config インスタンスによってすでに初期化されたすべての ConfigSource`の設定名を検索します。これには、 `ConfigSourceFactory で定義されたものよりも低い序列のソースが含まれます。 ConfigSourceFactory によって提供された ConfigSource リストは、優先順位の低い ConfigSourceFactory によって生成された他のソースを構成するためには考慮されません。

3. カスタム Converter

MicroProfile Configで指定されたカスタム Converter 型を作成することが可能です。

カスタム Converter には、 org.eclipse.microprofile.config.spi.Converter<T> の実装が必要です。それぞれの実装は、 META-INF/services/org.eclipse.microprofile.config.spi.Converter ファイルの ServiceLoaderメカニズムによる登録が必要です。以下だとすると、

package org.acme.config;

public class MicroProfileCustomValue {

    private final int number;

    public MicroProfileCustomValue(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }
}

対応するコンバータは以下のようになります。

package org.acme.config;

import org.eclipse.microprofile.config.spi.Converter;

public class MicroProfileCustomValueConverter implements Converter<MicroProfileCustomValue> {

    @Override
    public MicroProfileCustomValue convert(String value) {
        return new MicroProfileCustomValue(Integer.parseInt(value));
    }
}
カスタム・コンバータ・クラスは public でなければならず、 public コンストラクタは引数なしでなければならず、 abstract であってはなりません。

カスタムコンフィグレーションタイプは、設定値を自動的に変換します。

@ConfigProperty(name = "configuration.value.name")
MicroProfileCustomValue value;

3.1. コンバーターの優先順位

javax.annotation.Priority アノテーションは、 Converter の優先順位を上書きし、コンバータの優先順位を変更して実行順序を微調整します。デフォルトでは、 Converter@Priority が指定されていない場合、コンバーターは 100 の優先順位で登録されます。以下の場合、

package org.acme.config;

import javax.annotation.Priority;
import org.eclipse.microprofile.config.spi.Converter;

@Priority(150)
public class MyCustomConverter implements Converter<MicroProfileCustomValue> {

    @Override
    public MicroProfileCustomValue convert(String value) {

        final int secretNumber;
        if (value.startsFrom("OBF:")) {
            secretNumber = Integer.parseInt(SecretDecoder.decode(value));
        } else {
            secretNumber = Integer.parseInt(value);
        }

        return new MicroProfileCustomValue(secretNumber);
    }
}

同値の型 ( MicroProfileCustomValue)を変換し、優先度が 150 であるため、デフォルトの優先度が 100 である MicroProfileCustomValueConverter の代わりに使用されます。

すべてのQuarkusコアコンバーターは、 200 の優先値を使用しています。Quarkus特有のコンバーターをオーバーライドするには、優先度の値を 200 よりも高くする必要があります。

4. 設定インターセプター

SmallRye Configは、設定値の解決をフックするインターセプターチェーンを提供します。これは、 プロファイルプロパティExpressionsのような機能を実装するのに便利で、また、設定値がどこから読み込まれたかを調べるためのロギングにも役立ちます。

インターセプターは、 io.smallrye.config.ConfigSourceInterceptor の実装が必要です。それぞれの実装は、 META-INF/services/io.smallrye.config.ConfigSourceInterceptor ファイルの ServiceLoaderメカニズムを介して登録する必要があります。

io.smallrye.config.ConfigSourceInterceptor は、メソッド ConfigValue getValue(ConfigSourceInterceptorContext context, String name) で設定名の解決をインターセプトすることができます。 ConfigSourceInterceptorContext は、インターセプター・チェーンを進めるために使用されます。このチェーンは、 io.smallrye.config.ConfigValue のインスタンスを返すことで短絡させることができます。 ConfigValue オブジェクトは、キー名、値、コンフィグソースのオリジン、序列に関する情報を保持しています。

インターセプターチェーンは、設定値の変換が行われる前に適用されます。

インターセプターは、 io.smallrye.config.ConfigSourceInterceptorFactory の実装で作成することもできます。それぞれの実装は、ServiceLoaderメカニズムを介して、 META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory ファイルで 登録が必要です。

ConfigSourceInterceptorFactory は、(インターセプターの設定や設定値の取得に使用できるように)現在のチェーンにアクセスし、インターセプターを初期化し、優先度を設定することができます。

4.1. 例

org.acme.config.LoggingConfigSourceInterceptor
package org.acme.config;

import javax.annotation.Priority;

import io.smallrye.config.ConfigSourceInterceptor;
import io.smallrye.config.ConfigLogging;

@Priority(Priorities.LIBRARY + 200)
public class LoggingConfigSourceInterceptor implements ConfigSourceInterceptor {
    private static final long serialVersionUID = 367246512037404779L;

    @Override
    public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) {
        ConfigValue configValue = doLocked(() -> context.proceed(name));
        if (configValue != null) {
            ConfigLogging.log.lookup(configValue.getName(), configValue.getLocation(), configValue.getValue());
        } else {
            ConfigLogging.log.notFound(name);
        }
        return configValue;
    }
}

そして以下に登録します。

META-INF/services/io.smallrye.config.ConfigSourceInterceptor
org.acme.config.LoggingConfigSourceInterceptor

LoggingConfigSourceInterceptor ログは、提供されたログプラットフォームで設定名を検索します。ログ情報には、設定名と値、設定ソースの出所と場所(存在する場合)が含まれます。