MicroProfile Config API

この記事は Java EE Advent Calendar 2017 の 8 日目です。昨日予告した MicroProfile Config API についてご紹介します。たぶん半日くらいで覚えられる小さな API ですので、是非この機会に覚えて今後活用してみてください。

さて改めて、MicroProfile 1.1 から新たに Config API が加わりました。これはサービスの構成情報を外部で管理できるようにするための仕組みで、環境に依存する情報やインスタンス固有の情報などをパラメータ化してサービスの実装から分離することが可能になります。

  • サービスが使用するいくつかの情報は実行環境に依存します (例えば開発環境と運用環境)。これらの情報がサービス内部にあると、環境によってビルドを変えなければなりません。これは手間がかかる作業ですし、ビルドのミスで異なる環境向けのビルドを作成してそのままデプロイしてしまう恐れもあります。環境に依存する情報をサービスから分離することで、同一のビルドを様々な環境に適合させるのが容易になります。
  • サービスの構成情報を外部で管理する方法は既に存在します。環境変数、システム・プロパティ、構成ファイル (XML ファイルの場合が多い)、データベースなどが挙げられます。惜しむべくは、これらのデータソースはそれぞれ異なるアクセス方法を用いなければならないということです。特に複数のデータソースを併用する場合、簡単な ID を取得するだけでも煩雑な処理になってしまいます。処理を抽象化してデータソースに依存しない仕組みを用意すれば、構成情報へのアクセスは単純になります。

今回はこの Config API の簡単な使い方についてご紹介したいと思います。Config API は MicroProfile 1.1 以降に対応したランタイムで利用可能です。また、Payara 4.1.2.173 以降では Payara Micro と Payara Server の双方で MicroProfile 1.1 に対応し、Config API も利用できるようになっています。

Config API をはじめよう

では、さっそく Config API に触れてみましょう。今回は Payara Server 4.1.2.174 で動作検証しました。とりあえず Maven の依存関係に以下を追加してください。

<dependency>
  <groupId>org.eclipse.microprofile.config</groupId>
  <artifactId>microprofile-config-api</artifactId>
  <version>1.0</version>
  <scope>provided</scope>
</dependency>

Config API では構成情報を keyvalue のペアで保持します。プロパティや環境変数に似たデータ構造です。Config API では、構成情報のデータソースとして以下のものを規定しています。

  1. システム・プロパティ (ordinal: 400)
  2. 環境変数 (ordinal: 300)
  3. microprofile-config.properties (ordinal: 100)

ordinal の値が大きいほど優先度が高くなります。microprofile-config.properties はクラス・パス上にある META-INF 内に配置します (例: WEB-INF/classes/META-INF/microprofile-config.properties)。構成情報をサービスから分離するという趣旨からは外れますが、いずれのデータソースにも構成情報がなかった場合の既定値を記述する用途としては使用できそうです。

さらに Payara では以下も構成情報のデータソースとして使用できます。

Payara 固有の ConfigSource
SourceOrdinalDescription
domain 110 domain.xml
config 120 server-config etc.
server 130 サーバー
application 140 アプリケーション
module 150 モジュール
cluster 160 Hazelcast クラスタ
jndi 115 JNDI

標準・Payara 拡張を含め、システム・プロパティと環境変数の優先順位が高いことがわかります。おそらく、実際に多用するのもこれらのデータソースでしょう。なお、構成情報のデータソースは独自に実装することも可能で、例えばデータベースから値を取得するようなこともできます。

Config API で構成情報を取得する

1. Config クラスを使用する

Config API は基本的に CDI と組み合わせて使用します。CDI を使用しない方法も採れますが、煩雑になるためおすすめできません。この記事でも CDI を使用しない方法は紹介しません。

まずは基本的な Config クラスを使用する方法です。

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import org.eclipse.microprofile.config.Config;

@RequestScoped
public class ConfigBean {

  @Inject
  private Config config;

  public String getId() {
    return config.getValue("sample.id", String.class);
  }

}

Config クラスは Config API の中心となるクラスです。そのインスタンスをインジェクトして、メソッド getValue を呼び出すことで値を取得できます。この例では、キー sample.id の値を (おそらくシステム・プロパティか環境変数から) 取得します。

getValue メソッドの第 2 引数は戻り値の型です。システム・プロパティや環境変数は文字列の値ですので、ここに String 以外のデータ型を指定することで自動的にパースするような仕組みになっています。対応しているデータ型は Boolean、Integer、Long、Float、Double、Duration、LocalTime、LocalDate、LocalDateTime、OffsetDateTime、OffsetTime、Instant です。

本稿執筆時点での最新版である Config API 1.1 (Payara 4.1.2.174 で対応) では、さらにプリミティブ型 boolean、int、long、float、double にも対応しています。

2. アノテーションを使用する

アノテーションを使用すると、フィールドに対して取得した値を直接設定することができます。

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import org.eclipse.microprofile.config.inject.ConfigProperty;

@RequestScoped
public class ConfigBean {

  @Inject
  @ConfigProperty(name = "sample.name")
  private String name;

  public String getName() {
    return name;
  }

}

単純に値を取得するだけであれば、こちらの方が簡単です。この例では、キー sample.name の値を (おそらくシステム・プロパティか環境変数から) 取得し、フィールド name に設定します。データ型変換はフィールドに値を設定する際に行われます。

まとめに代えて

MicroProfile の Config API は、Java EE が将来的に採用を検討していた Config API を先取りして取り入れたものです。MicroProfile のメンバー (Payara の Ondrej Mihalyi) が Config API のスペックリードに直接接触して使用が今後大きくぶれないことを確認した上で採用に踏み切りました。MicroProfile 発の API としては最初のものとなります。

MicroProfile 1.2 ではさらに 2~3 の仕様を追加し、いずれは Java EE 本体と合流することも視野に入れています。MicroProfile 1.1 以降をサポートするランタイムであれば基本的にどれでも Config API を利用することができます (Payara Micro 4.1.2.174 以降では Java EE 8 の Security API (このアドベントカレンダーでも 3 日目に取り上げています) も先取りしています)。簡単かつ応用範囲が広い API ですので、ぜひお試しください。


明日は @TTakakiyo さんが Servlet 4.0 を取り上げる予定です。私も今から楽しみです。