2.7. プロパティープレースホルダー
概要
プロパティープレースホルダー機能は、さまざまなコンテキスト (エンドポイント URI や XML DSL 要素の属性など) で文字列を置き換えるために使用できます。プレースホルダーの設定は Java プロパティーファイルに格納されます。この機能は、異なる Apache Camel アプリケーション間で設定を共有したい場合や、特定の設定を一元管理したい場合に役立ちます。
たとえば、以下のルートはリクエストを Web サーバーに送信します。この Web サーバーのホストとポートは、プレースホルダーの {{remote.host}} と {{remote.port}} に置き換えられます。
from("direct:start").to("http://{{remote.host}}:{{remote.port}}");プレースホルダーの値は、以下のように Java プロパティーファイルに定義されています。
# Java properties file remote.host=myserver.com remote.port=8080
プロパティープレースホルダーはエンコーディングオプションをサポートし、UTF-8 などの特定の文字セットを使用して、.properties ファイルの読み取りを可能にします。ただし、デフォルトでは ISO-8859-1 文字セットによる実装になります。
PropertyPlaceholders を使用した Apache Camel では、以下がサポートされます。
- 検索するキーと共にデフォルト値を指定する。
-
すべてのプレースホルダーキーがデフォルト値で構成されていて、それらが使用される場合、
PropertiesComponentを定義する必要がない。 サードパーティー関数を使用してプロパティー値を検索する。これにより、独自のロジックを実装できます。
注記プロパティー値を検索する関数として、標準で OS 環境変数、JVM システムプロパティー、サービス名イディオムの 3 つを提供します。
プロパティーファイル
プロパティー設定は 1 つ以上の Java プロパティーファイルに格納され、標準の Java プロパティーファイル形式に準拠する必要があります。各プロパティー設定は、それぞれ独立した行に Key=Value の形式で表示されます。空白以外の最初の文字が # または ! から始まる行は、コメントとして扱われます。
たとえば、プロパティーファイルは 例2.4「プロパティーファイルの例」 のように内容になります。
例2.4 プロパティーファイルの例
# Property placeholder settings
# (in Java properties file format)
cool.end=mock:result
cool.result=result
cool.concat=mock:{{cool.result}}
cool.start=direct:cool
cool.showid=true
cheese.end=mock:cheese
cheese.quote=Camel rocks
cheese.type=Gouda
bean.foo=foo
bean.bar=barプロパティーの解決
Properties コンポーネントは、ルート定義の中で使用を開始する前に、1 つ以上のプロパティーファイルのロケーションを指定して設定しておく必要があります。以下のいずれかのリゾルバーを使用して、プロパティー値を提供する必要があります。
classpath:PathName,PathName,…- (デフォルト) クラスパス上のロケーションを指定します。PathName は、フォワードスラッシュを使用して区切られたファイルパス名です。
file:PathName,PathName,…- ファイルシステムのロケーションを指定します。PathName はフォワードスラッシュを使用して区切られたファイルパス名です。
ref:BeanID-
レジストリーの
java.util.Propertiesオブジェクトの ID を指定します。 blueprint:BeanID-
cm:property-placeholderBean の ID を指定します。この Bean は、OSGi Blueprint ファイルのコンテキスト内で、OSGi Configuration Admin サービスで定義されたプロパティーにアクセスするために使用されます。詳細は、「OSGi Blueprint プロパティープレースホルダーとの統合」 を参照してください。
たとえば、クラスパス上にある com/fusesource/cheese.properties プロパティーファイルと com/fusesource/bar.properties プロパティーファイルを指定するには、以下のようなロケーション文字列を使用します。
com/fusesource/cheese.properties,com/fusesource/bar.properties
クラスパスリゾルバーはデフォルトで使用されるため、この例では classpath: プレフィックスは省略できます。
システムプロパティーと環境変数を使用したロケーションの指定
ロケーション PathName に Java システムプロパティーおよび O/S 環境変数を埋め込むことができます。
Java システムプロパティーは、${PropertyName} 構文を使用してロケーションリゾルバーに埋め込むことができます。たとえば、Red Hat JBoss Fuse のルートディレクトリーが Java システムプロパティー karaf.home に保存されている場合、以下のようにそのディレクトリー値をファイルの場所に埋め込むことができます。
file:${karaf.home}/etc/foo.properties
O/S 環境変数は、${env:VarName} 構文を使用してロケーションリゾルバーに埋め込むことができます。たとえば、Fuse のルートディレクトリーが環境変数 SMX_HOME に保存されている場合、以下のようにそのディレクトリーの値をファイルロケーションに埋め込むことができます。
file:${env:SMX_HOME}/etc/foo.propertiesProperties コンポーネントの設定
プロパティープレースホルダーの使用を開始する前に、1 つ以上のプロパティーファイルのロケーションを指定して、Properties コンポーネントを設定する必要があります。
Java DSL では、以下のように Properties コンポーネントにプロパティーファイルのロケーションを設定できます。
// Java
import org.apache.camel.component.properties.PropertiesComponent;
...
PropertiesComponent pc = new PropertiesComponent();
pc.setLocation("com/fusesource/cheese.properties,com/fusesource/bar.properties");
context.addComponent("properties", pc);
addComponent() の呼び出しに示されているように、Properties コンポーネントの名前を properties に設定する 必要があります。
XML DSL では、以下のように専用の propertyPlacholder 要素を使用して Properties コンポーネントを設定できます。
<camelContext ...>
<propertyPlaceholder
id="properties"
location="com/fusesource/cheese.properties,com/fusesource/bar.properties"
/>
</camelContext>
Properties コンポーネントの初期化時に見つからない .properties ファイルを、Properties コンポーネントに無視させる場合は、ignoreMissingLocation オプションを true に設定します (通常、.properties ファイルが見つからない場合はエラーが発生します)。
また、Java システムプロパティーまたは O/S 環境変数を使用して、指定されたロケーションが見つからないときに Properties コンポーネントが無視するようにする場合も、ignoreMissingLocation オプションを true に設定することができます。
プレースホルダー構文
Properties コンポーネントは、設定後は (適切なコンテキストで) プレースホルダーを自動的に置き換えます。プレースホルダーの構文は、以下のようにコンテキストによって異なります。
-
エンドポイント URI および Spring XML ファイル: プレースホルダーは
{{Key}}のように指定します。 XML DSL の属性設定時:
xs:string属性は以下の構文で設定します。AttributeName="{{Key}}"
その他の属性タイプ (
xs:intまたはxs:booleanなど) は、以下の構文を使用して設定する必要があります。prop:AttributeName="Key"
propは、http://camel.apache.org/schema/placeholder名前空間に関連付けられています。Java DSL の EIP オプション設定時: Java DSL でエンタープライズ統合パターン (EIP) コマンドにオプションを設定するには、流れるような DSL に以下の
placeholder()句を追加します。.placeholder("OptionName", "Key")-
Simple 言語式: プレースホルダーは
${properties:Key}. のように指定します。
エンドポイント URI 内での置換
ルートの中でエンドポイント URI 文字列が現れると、そのエンドポイント URI を構文解析する最初のステップは、常にプロパティープレースホルダーパーサーを適用することです。プレースホルダーパーサーは、二重かっこ {{Key}} の間に表示されるプロパティー名を自動的に置換します。たとえば、例2.4「プロパティーファイルの例」 に記載されているプロパティー設定では、以下のようにルートを定義できます。
from("{{cool.start}}")
.to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
.to("mock:{{cool.result}}");
デフォルトでは、プレースホルダーパーサーはレジストリーで プロパティー Bean ID を検索し、Properties コンポーネントを検索します。必要であれば、エンドポイント URI でスキーマを明示的に指定できます。たとえば、各エンドポイント URI にプレフィックス properties: を付けて、以下のように同等のルートを定義できます。
from("properties:{{cool.start}}")
.to("properties:log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
.to("properties:mock:{{cool.result}}");
スキーマを明示的に指定する場合、Properties コンポーネントにオプションを指定することもできます。たとえば、プロパティーファイルのロケーションを上書きするために、以下のように location オプションを設定できます。
from("direct:start").to("properties:{{bar.end}}?location=com/mycompany/bar.properties");Spring XML ファイル内での置換
XML DSL で DSL 要素のさまざまな属性を設定するために、プロパティープレースホルダーを使用することもできます。このコンテキストにおいても、プレースホルダー構文には二重かっこ {{Key}} を使用します。たとえば、以下のようにプロパティープレースホルダーを使用して jmxAgent 要素を定義できます。
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" location="org/apache/camel/spring/jmx.properties"/>
<!-- we can use property placeholders when we define the JMX agent -->
<jmxAgent id="agent" registryPort="{{myjmx.port}}"
usePlatformMBeanServer="{{myjmx.usePlatform}}"
createConnector="true"
statisticsLevel="RoutesOnly"
/>
<route>
<from uri="seda:start"/>
<to uri="mock:result"/>
</route>
</camelContext>XML DSL 属性値の置換
xs:string 型の属性値を指定するには、通常のプレースホルダー構文を使用できます (例: <jmxAgent registryPort="{{myjmx.port}}" …>)。しかし、他の型の属性 (例: xs:int や xs:boolean) については、特別な構文 prop:AttributeName="Key" を使用する必要があります。
たとえば、プロパティーファイルで stop.flag プロパティーの値が true に定義されている場合、このプロパティーを使用して以下のように stopOnException ブール値属性を設定できます。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:prop="http://camel.apache.org/schema/placeholder"
... >
<bean id="illegal" class="java.lang.IllegalArgumentException">
<constructor-arg index="0" value="Good grief!"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties"
location="classpath:org/apache/camel/component/properties/myprop.properties"
xmlns="http://camel.apache.org/schema/spring"/>
<route>
<from uri="direct:start"/>
<multicast prop:stopOnException="stop.flag">
<to uri="mock:a"/>
<throwException ref="damn"/>
<to uri="mock:b"/>
</multicast>
</route>
</camelContext>
</beans>
prop プレフィックスは、前述の例の beans 要素に示されるように、Spring ファイルの http://camel.apache.org/schema/placeholder 名前空間に明示的に割り当てられている必要があります。
Java DSL における EIP オプションの置換
Java DSL で EIP コマンドを呼び出す場合は、placeholder("OptionName", "Key") の形式のサブ句を追加することで、プロパティープレースホルダーの値を使用した EIP オプションの設定ができます。
たとえば、プロパティーファイルで stop.flag プロパティーの値が true に定義されている場合、このプロパティーを使用して以下のように Multicast EIP の stopOnException オプションを設定できます。
from("direct:start")
.multicast().placeholder("stopOnException", "stop.flag")
.to("mock:a").throwException(new IllegalAccessException("Damn")).to("mock:b");Simple 言語式内での置換
Simple 言語の式の中でプロパティープレースホルダーを置換することもできますが、この場合プレースホルダーの構文は ${properties:Key} になります。たとえば、以下のようにして Simple 式内の cheese.quote プレースホルダーを置換できます。
from("direct:start")
.transform().simple("Hi ${body} do you think ${properties:cheese.quote}?");
構文 ${properties:Key:DefaultVal} を使用すると、プロパティーのデフォルト値を指定できます。以下に例を示します。
from("direct:start")
.transform().simple("Hi ${body} do you think ${properties:cheese.quote:cheese is good}?");
構文 ${properties-location:Location:Key} を使用して、プロパティーファイルのロケーションをオーバーライドすることもできます。たとえば、com/mycompany/bar.properties プロパティーファイルの設定を使用して、bar.quote プレースホルダーを置き換えるには、以下のように Simple 式を定義します。
from("direct:start")
.transform().simple("Hi ${body}. ${properties-location:com/mycompany/bar.properties:bar.quote}.");XML DSL 内でのプロパティープレースホルダーの使用
以前のリリースでは、 XML DSL のプレースホルダーをサポートするために xs:string 型の属性が使用されていました。たとえば、timeout 属性は xs:int 型になります。したがって、文字列の値をプレースホルダーキーとして設定することはできませんでした。
Apache Camel 2.7 以降、特別なプレースホルダーの名前空間を使用することでそれが可能になりました。以下の例は、その名前空間を使うための prop プレフィックスを示しています。これにより、XML DSL の属性に prop プレフィックスを付けて使用できます。
Multicast において、キー stop を使用してプレースホルダーの値をオプション stopOnException に設定しています。また、プロパティーファイルの中で以下の値を定義しています。
stop=true
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:prop="http://camel.apache.org/schema/placeholder"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
">
<!-- Notice in the declaration above, we have defined the prop prefix as the Camel placeholder namespace -->
<bean id="damn" class="java.lang.IllegalArgumentException">
<constructor-arg index="0" value="Damn"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties"
location="classpath:org/apache/camel/component/properties/myprop.properties"
xmlns="http://camel.apache.org/schema/spring"/>
<route>
<from uri="direct:start"/>
<!-- use prop namespace, to define a property placeholder, which maps to
option stopOnException={{stop}} -->
<multicast prop:stopOnException="stop">
<to uri="mock:a"/>
<throwException ref="damn"/>
<to uri="mock:b"/>
</multicast>
</route>
</camelContext>
</beans>OSGi Blueprint プロパティープレースホルダーとの統合
Red Hat Fuse の OSGi コンテナーにルートをデプロイする場合、Apache Camel プロパティープレースホルダーのメカニズムを Fuse が持つ Blueprint プロパティープレースホルダーのメカニズムと統合できます (実際には、この統合はデフォルトで有効になっています) 。統合のセットアップには、基本的に以下の 2 つの方法があります。
暗黙的な Blueprint の統合
OSGi Blueprint ファイル内で camelContext 要素を定義すると、Apache Camel プロパティープレースホルダーのメカニズムは自動的に Blueprint プロパティープレースホルダーのメカニズムと統合します。つまり、camelContext のスコープ内に現れる Apache Camel 構文に従ったプレースホルダー (例: {{cool.end}}) は、暗黙的に blueprint property placeholder のメカニズムを検索することで解決されます。
たとえば、OSGi Blueprint ファイルで定義された以下のようなルートがあるとします。ルートの最後のエンドポイントは、プロパティープレースホルダー {{result}} で定義されています。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<!-- OSGI blueprint property placeholder -->
<cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint">
<!-- list some properties for this test -->
<cm:default-properties>
<cm:property name="result" value="mock:result"/>
</cm:default-properties>
</cm:property-placeholder>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<!-- in the route we can use {{ }} placeholders which will look up in blueprint,
as Camel will auto detect the OSGi blueprint property placeholder and use it -->
<route>
<from uri="direct:start"/>
<to uri="mock:foo"/>
<to uri="{{result}}"/>
</route>
</camelContext>
</blueprint>
Blueprint プロパティープレースホルダーのメカニズムは、cm:property-placeholder Bean を作成することで初期化されます。上記の例では、cm:property-placeholder Bean は camel.blueprint 永続化 ID に関連付けられています。永続化 ID は、OSGi Configuration Admin サービスから関連するプロパティーのグループを参照する標準的な方法です。つまり、cm:property-placeholder Bean は、camel.blueprint 永続化 ID の下で定義されたすべてのプロパティーへのアクセスを提供します。一部のプロパティーにデフォルト値を指定することもできます (ネストされた cm:property 要素を使用します)。
Blueprint のコンテキストでは、Apache Camel プレースホルダーのメカニズムは Bean レジストリー内の cm:property-placeholder インスタンスを検索します。このインスタンスが見つかると、Apache Camel プレースホルダーのメカニズムと自動的に統合され、{{result}} のようなプレースホルダーは Blueprint プロパティープレースホルダーのメカニズムに対して (この例では myblueprint.placeholder Bean を通して) キーを検索することで解決されます。
デフォルトの Blueprint プレースホルダー構文 (Blueprint プロパティーに直接アクセスする) は ${Key} です。そのため、camelContext 要素の 範囲外 では、使用しなければならないプレースホルダー構文は ${Key} になります。しかし、camelContext 要素の 範囲内 では、使用しなければならないプレースホルダー構文は {{Key}} になります。
明示的な Blueprint の統合
Apache Camel プロパティープレースホルダーのメカニズムがプロパティーを探す場所をさらに制御したい場合は、propertyPlaceholder 要素を定義してリゾルバーのロケーションを明示的に指定できます。
たとえば、以下の Blueprint の設定について考えるとします。この例は、明示的に propertyPlaceholder インスタンスを作成している点が前述の例とは異なっています。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 ">https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<!-- OSGI blueprint property placeholder -->
<cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint">
<!-- list some properties for this test -->
<cm:default-properties>
<cm:property name="result" value="mock:result"/>
</cm:default-properties>
</cm:property-placeholder>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<!-- using Camel properties component and refer to the blueprint property placeholder by its id -->
<propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder"/>
<!-- in the route we can use {{ }} placeholders which will lookup in blueprint -->
<route>
<from uri="direct:start"/>
<to uri="mock:foo"/>
<to uri="{{result}}"/>
</route>
</camelContext>
</blueprint>
前述の例では、propertyPlaceholder 要素は、場所を blueprint:myblueprint.placeholder に設定することにより、使用する cm:property-placeholder Bean を明示的に指定します。つまり、blueprint: リゾルバーは、cm:property-placeholder Bean の ID myblueprint.placeholder を明示的に参照します。
このスタイルによる設定は、Blueprint ファイルに複数の cm:property-placeholder Bean が定義されていて、どれを使用すべきかを指定する必要がある場合に有効です。また、ロケーションをコンマ区切りのリストで指定することで、複数のロケーションからプロパティーを取得することも可能になります。たとえば、cm:property-placeholder Bean とクラスパス上のプロパティーファイル myproperties.properties の両方からプロパティーを検索したい場合、以下のように propertyPlaceholder 要素を定義します。
<propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder,classpath:myproperties.properties"/>
Spring プロパティープレースホルダーとの統合
Spring XML ファイルの XML DSL を使用して Apache Camel アプリケーションを定義している場合、org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer 型の Spring Bean を宣言することで、Apache Camel プロパティープレースホルダーのメカニズムを Spring プロパティープレースホルダーのメカニズムと統合できます。
BridgePropertyPlaceholderConfigurer を定義します。これは、Spring XML ファイルの Apache Camel の propertyPlaceholder 要素と Spring の ctx:property-placeholder 要素の両方を置き換えます。その後、Spring の ${PropName} 構文または Apache Camel の {{PropName}} 構文のいずれかを使用して、設定したプロパティーを参照できます。
たとえば、cheese.properties ファイルからプロパティー設定を読み取るブリッジプロパティープレースホルダーを定義するとします。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Bridge Spring property placeholder with Camel -->
<!-- Do not use <ctx:property-placeholder ... > at the same time -->
<bean id="bridgePropertyPlaceholder"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="location"
value="classpath:org/apache/camel/component/properties/cheese.properties"/>
</bean>
<!-- A bean that uses Spring property placeholder -->
<!-- The ${hi} is a spring property placeholder -->
<bean id="hello" class="org.apache.camel.component.properties.HelloBean">
<property name="greeting" value="${hi}"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<!-- Use Camel's property placeholder {{ }} style -->
<route>
<from uri="direct:{{cool.bar}}"/>
<bean ref="hello"/>
<to uri="{{cool.end}}"/>
</route>
</camelContext>
</beans>
または、Springプロパティーファイルを指すように、BridgePropertyPlaceholderConfigurer の location 属性を設定することもできます。Spring プロパティーファイルの構文は完全にサポートされます。