2.6. メッセージコンテンツの変換

概要

Apache Camel は、メッセージコンテンツを変換するためのさまざまなアプローチをサポートしています。Apache Camel は、メッセージコンテンツを変更するためのシンプルなネイティブ API に加えて、いくつかの異なるサードパーティーライブラリーや変換のための標準とのインテグレーションをサポートしています。

2.6.1. シンプルなメッセージ変換

概要

Java DSL にはビルトインの API があり、送受信メッセージのシンプルな変換を実行できます。たとえば、例2.1「受信メッセージのシンプルな変換」 に示すルールは、受信メッセージのボディー部の末尾にテキスト World! を追加します。

例2.1 受信メッセージのシンプルな変換

from("SourceURL").setBody(body().append(" World!")).to("TargetURL");

ここで、setBody() コマンドは受信メッセージボディーのコンテンツを置き換えます。

シンプルな変換の API

以下の API クラスを使用して、ルーターのルールによってメッセージコンテンツのシンプルな変換を実行できます。

  • org.apache.camel.model.ProcessorDefinition
  • org.apache.camel.builder.Builder
  • org.apache.camel.builder.ValueBuilder

ProcessorDefinition クラス

org.apache.camel.model.ProcessorDefinition クラスは、ルーターのルールに直接挿入できる DSL コマンドを定義しています (例: 例2.1「受信メッセージのシンプルな変換」setBody() コマンド)。表2.5「ProcessorDefinition クラスの変換メソッド」 は、メッセージコンテンツの変換に関係のある ProcessorDefinition のメソッドを示しています。

表2.5 ProcessorDefinition クラスの変換メソッド

メソッド説明

Type convertBodyTo(Class type)

IN メッセージのボディーを指定の型に変換します。

Type removeFaultHeader(String name)

FAULT メッセージのヘッダーを削除するプロセッサーを追加します。

Type removeHeader(String name)

IN メッセージ上のヘッダーを削除するプロセッサーを追加します。

Type removeProperty(String name)

エクスチェンジプロパティーを削除するプロセッサーを追加します。

ExpressionClause<ProcessorDefinition<Type>> setBody()

IN メッセージのボディーをセットするプロセッサーを追加します。

Type setFaultBody(Expression expression)

FAULT メッセージのボディーをセットするプロセッサーを追加します。

Type setFaultHeader(String name, Expression expression)

FAULT メッセージにヘッダーをセットするプロセッサーを追加します。

ExpressionClause<ProcessorDefinition<Type>> setHeader(String name)

IN メッセージにヘッダーをセットするプロセッサーを追加します。

Type setHeader(String name, Expression expression)

IN メッセージにヘッダーをセットするプロセッサーを追加します。

ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name)

OUT メッセージにヘッダーをセットするプロセッサーを追加します。

Type setOutHeader(String name, Expression expression)

OUT メッセージにヘッダーをセットするプロセッサーを追加します。

ExpressionClause<ProcessorDefinition<Type>> setProperty(String name)

エクスチェンジプロパティーをセットするプロセッサーを追加します。

Type setProperty(String name, Expression expression)

エクスチェンジプロパティーをセットするプロセッサーを追加します。

ExpressionClause<ProcessorDefinition<Type>> transform()

OUT メッセージのボディーをセットするプロセッサーを追加します。

Type transform(Expression expression)

OUT メッセージのボディーをセットするプロセッサーを追加します。

Builder クラス

org.apache.camel.builder.Builder クラスは、式または述語が想定される文脈でのメッセージコンテンツへのアクセスを提供します。つまり、Builder のメソッドは通常 DSL コマンドの 引数 の中で呼び出されます (例: 例2.1「受信メッセージのシンプルな変換」body() コマンド)。表2.6「Builder クラスのメソッド」 では、Builder クラスで利用可能な static メソッドをまとめています。

表2.6 Builder クラスのメソッド

メソッド説明

static <E extends Exchange> ValueBuilder<E> body()

エクスチェンジのインバウンドボディーに対する述語および値ビルダーを返します。

static <E extends Exchange,T> ValueBuilder<E> bodyAs(Class<T> type)

インバウンドメッセージのボディーを特定の型として、それに対する述語および値ビルダーを返します。

static <E extends Exchange> ValueBuilder<E> constant(Object value)

定数式を返します。

static <E extends Exchange> ValueBuilder<E> faultBody()

エクスチェンジのフォールトボディーに対する述語および値ビルダーを返します。

static <E extends Exchange,T> ValueBuilder<E> faultBodyAs(Class<T> type)

フォールトメッセージのボディーを特定の型として、それに対する述語および値ビルダーを返します。

static <E extends Exchange> ValueBuilder<E> header(String name)

エクスチェンジのヘッダーに対する述語および値ビルダーを返します。

static <E extends Exchange> ValueBuilder<E> outBody()

エクスチェンジのアウトバウンドボディーに対する述語および値ビルダーを返します。

static <E extends Exchange> ValueBuilder<E> outBodyAs(Class<T> type)

アウトバウンドメッセージのボディーを特定の型として、それに対する述語および値ビルダーを返します。

static ValueBuilder property(String name)

エクスチェンジのプロパティーに対する述語および値ビルダーを返します。

static ValueBuilder regexReplaceAll(Expression content, String regex, Expression replacement)

正規表現のすべての出現箇所を、指定した置換文字列で置き換える式を返します。

static ValueBuilder regexReplaceAll(Expression content, String regex, String replacement)

正規表現のすべての出現箇所を、指定した置換文字列で置き換える式を返します。

static ValueBuilder sendTo(String uri)

指定したエンドポイント URI にエクスチェンジを送信する式を返します。

static <E extends Exchange> ValueBuilder<E> systemProperty(String name)

指定のシステムプロパティーの式を返します。

static <E extends Exchange> ValueBuilder<E> systemProperty(String name, String defaultValue)

指定のシステムプロパティーの式を返します。

ValueBuilder クラス

org.apache.camel.builder.ValueBuilder クラスを使用すると、Builder メソッドによって返される値を変更できます。つまり、 ValueBuilder のメソッドは、メッセージコンテンツを変更するシンプルな方法を提供します。表2.7「ValueBuilder クラスの変更メソッド」 では、ValueBuilder クラスで利用可能なメソッドをまとめています。この表では、呼び出された値を変更するために使用されるメソッドのみが示されています (詳細は API Reference ドキュメントを参照してください) 。

表2.7 ValueBuilder クラスの変更メソッド

メソッド説明

ValueBuilder<E> append(Object value)

指定された値をこの式の文字列評価に追加します。

Predicate contains(Object value)

左辺の式に右辺の式の値が含まれた述語を作成します。

ValueBuilder<E> convertTo(Class type)

登録された型コンバーターを使用して、現在の値を指定の型に変換します。

ValueBuilder<E> convertToString()

登録された型コンバーターを使用して、現在の値を String に変換します。

Predicate endsWith(Object value)

 

<T> T evaluate(Exchange exchange, Class<T> type)

 

Predicate in(Object…​ values)

 

Predicate in(Predicate…​ predicates)

 

Predicate isEqualTo(Object value)

現在の値が指定の value 引数と等しい場合、true を返します。

Predicate isGreaterThan(Object value)

現在の値が指定の value 引数よりも大きい場合、true を返します。

Predicate isGreaterThanOrEqualTo(Object value)

現在の値が指定の value 引数より大きい場合、true を返します。

Predicate isInstanceOf(Class type)

現在の値が指定の型のインスタンスである場合、true を返します。

Predicate isLessThan(Object value)

現在の値が指定の value 引数未満の場合、true を返します。

Predicate isLessThanOrEqualTo(Object value)

現在の値が指定の value 引数以下である場合、true を返します。

Predicate isNotEqualTo(Object value)

現在の値が指定の value 引数と等しくない場合、true を返します。

Predicate isNotNull()

現在の値が null でない場合、true を返します。

Predicate isNull()

現在の値が null の場合、true を返します。

Predicate matches(Expression expression)

 

Predicate not(Predicate predicate)

述語の引数を否定にします。

ValueBuilder prepend(Object value)

この式の文字列評価を指定された値に追加します。

Predicate regex(String regex)

 

ValueBuilder<E> regexReplaceAll(String regex, Expression<E> replacement)

正規表現のすべての出現箇所を、指定した置換文字列で置き換えます。

ValueBuilder<E> regexReplaceAll(String regex, String replacement)

正規表現のすべての出現箇所を、指定した置換文字列で置き換えます。

ValueBuilder<E> regexTokenize(String regex)

指定の正規表現を使用してこの式の文字列変換をトークン化します。

ValueBuilder sort(Comparator comparator)

指定されたコンパレーターを使用して現在の値をソートします。

Predicate startsWith(Object value)

現在の値が value 引数の文字列値と一致する場合、true を返します。

ValueBuilder<E> tokenize()

コンマのトークン区切り文字を使用してこの式の文字列変換をトークン化します。

ValueBuilder<E> tokenize(String token)

指定のトークン区切り文字を使用してこの式の文字列変換をトークン化します。

2.6.2. マーシャリングとアンマーシャリング

Java DSL コマンド

以下のコマンドを使用して、低レベルのメッセージ形式と高レベルのメッセージ形式の間で変換を行うことができます。

  • marshal()  - 高レベルのデータフォーマットを低レベルのデータフォーマットに変換します。
  • unmarshal() - 低レベルのデータフォーマットを高レベルのデータフォーマットに変換します。

データ形式

Apache Camel は、以下のデータフォーマットのマーシャリングおよびアンマーシャリングをサポートします。

  • Java シリアライゼーション
  • JAXB
  • XMLBeans
  • XStream

Java シリアライゼーション

Java オブジェクトをバイナリーデータの Blob に変換できるようにします。このデータフォーマットでは、アンマーシャリングはバイナリー Blob を Java オブジェクトに変換し、マーシャリングは Java オブジェクトをバイナリー Blob に変換します。たとえば、エンドポイント SourceURL からシリアライズされた Java オブジェクトを読み込み、これを Java オブジェクトに変換するには、以下のようなルールを使用します。

from("SourceURL").unmarshal().serialization()
.<FurtherProcessing>.to("TargetURL");

または、Spring XML では以下の通りです。

<camelContext id="serialization" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <serialization/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

JAXB

XML スキーマ型と Java 型間のマッピングを提供します (https://jaxb.dev.java.net/ を参照してください)。JAXB では、アンマーシャリングは XML データ型を Java オブジェクトに変換し、マーシャリングは Java オブジェクトを XML データ型に変換します。JAXB データフォーマットを使用する前に、JAXB コンパイラーを使用して XML スキーマをコンパイルし、スキーマの XML データ型を表す Java クラスを生成する必要があります。これはスキーマの バインディング と呼ばれます。スキーマをバインドした後に、以下のようなコードを使用して XML データを Java オブジェクトにアンマーシャリングするルールを定義します。

org.apache.camel.spi.DataFormat jaxb = new org.apache.camel.converter.jaxb.JaxbDataFormat("GeneratedPackageName");

from("SourceURL").unmarshal(jaxb)
.<FurtherProcessing>.to("TargetURL");

GeneratedPackagename は JAXB コンパイラーによって生成された Java パッケージの名前で、XML スキーマを表す Java クラスが含まれます。

または、Spring XML では以下の通りです。

<camelContext id="jaxb" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <jaxb prettyPrint="true" contextPath="GeneratedPackageName"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

XMLBeans

XML スキーマ型と Java 型間の代替的なマッピングを提供します (http://xmlbeans.apache.org/ を参照してください) 。XMLBean では、アンマーシャリングは XML データ型を Java オブジェクトに変換し、マーシャリングは Java オブジェクトを XML データ型に変換します。たとえば、XMLBean を使用して XML データを Java オブジェクトにアンマーシャリングするには、以下のようなコードを使用します。

from("SourceURL").unmarshal().xmlBeans()
.<FurtherProcessing>.to("TargetURL");

または、Spring XML では以下の通りです。

<camelContext id="xmlBeans" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <xmlBeans prettyPrint="true"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

XStream

XML 型と Java 型間のもう 1 つのマッピングを提供します (http://www.xml.com/pub/a/2004/08/18/xstream.html を参照してください) 。XStream はシリアライゼーションライブラリー (Java シリアライゼーションなど) で、Java オブジェクトを XML に変換できるものです。XStream では、アンマーシャリングは XML データ型を Java オブジェクトに変換し、マーシャリングは Java オブジェクトを XML データ型に変換します。

from("SourceURL").unmarshal().xstream()
.<FurtherProcessing>.to("TargetURL");
注記

XStream データフォーマットは現在 Spring XML ではサポート されません

2.6.3. エンドポイントバインディング

バインディングの概要

Apache Camel において、バインディング とは、エンドポイントにコントラクトを結び付ける方法です。たとえば Data Format、Content Enricher、または検証ステップを適用することでコントラクトを結び付けます。入力メッセージには条件または変換が適用され、出力メッセージには補完的な条件または変換が適用されます。

DataFormatBinding

DataFormatBinding クラスは、特定のデータフォーマットをマーシャリングしたりアンマーシャリングしたりするバインディングを定義する場合に有効です (「マーシャリングとアンマーシャリング」 を参照)。この場合、バインディングの作成に必要なのは、コンストラクターに必要なデータフォーマットへの参照を渡して DataFormatBinding インスタンスを作成することだけです。

たとえば、例2.2「JAXB バインディング」 の XML DSL スニペットは、Apache Camel エンドポイントに関連付けられたときに、JAXB データフォーマットをマーシャリングおよびアンマーシャリングできるバインディング (ID は jaxb) を示しています。

例2.2 JAXB バインディング

<beans ... >
    ...
    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

バインディングとエンドポイントの関連付け

エンドポイントとバインディングを関連付けるには、以下の方法を使用できます。

Binding URI

バインディングをエンドポイントに関連付けるには、エンドポイント URI に binding:NameOfBinding を接頭辞として付けます。ここで NameOfBinding は、バインディングの Bean ID になります (例: Spring XML で作成されたバインディング Bean の ID)。

たとえば、以下の例では、ActiveMQ エンドポイントを 例2.2「JAXB バインディング」 で定義された JAXB バインディングに関連付ける方法を示しています。

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:orderQueue"/>
            <to uri="binding:jaxb:activemq:otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>

BindingComponent

接頭辞を使用してバインディングをエンドポイントに関連付ける代わりに、関連付けを暗黙的に行い、バインディングが URI に表示されないようにすることもできます。暗黙的なバインディングを持たない既存のエンドポイントの場合、最も簡単な方法は BindingComponent クラスを使用してエンドポイントをラップすることです。

たとえば、jaxb バインディングを activemq エンドポイントに関連付けるには、以下のように新しい BindingComponent インスタンスを定義します。

<beans ... >
    ...
    <bean id="jaxbmq" class="org.apache.camel.component.binding.BindingComponent">
        <constructor-arg ref="jaxb"/>
        <constructor-arg value="activemq:foo."/>
    </bean>

    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

jaxbmq の 2 つ目のコンストラクター引数 (オプション) で URI 接頭辞を定義します。これで、この jaxbmq ID をエンドポイント URI のスキームとして使用できるようになりました。たとえば、このバインディングコンポーネントを使用して以下のルートを定義できます。

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="jaxbmq:firstQueue"/>
            <to uri="jaxbmq:otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>

上記のルートは、Binding URI のアプローチを使用する以下のルートと同じです。

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:foo.firstQueue"/>
            <to uri="binding:jaxb:activemq:foo.otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>
注記

カスタムの Apache Camel コンポーネントを実装する開発者は、org.apache.camel.spi.HasBinding インターフェイスを継承するエンドポイントクラスを実装することで、これを実現できます。

BindingComponent コンストラクター

BindingComponent クラスは以下のコンストラクターをサポートします。

public BindingComponent()
無引数の形式です。プロパティー注入を使用してバインディングコンポーネントインスタンスを設定します。
public BindingComponent(Binding binding)
このバインディングコンポーネントを指定された Binding オブジェクトの binding に関連付けます。
public BindingComponent(Binding binding, String uriPrefix)
このバインディングコンポーネントを指定された Binding オブジェクトの binding、および URI 接頭辞 uriPrefix に関連付けます。これが、最も一般的に使用されるコンストラクターです。
public BindingComponent(Binding binding, String uriPrefix, String uriPostfix)
このコンストラクターは、追加の URI ポストフィックス uriPostfix 引数をサポートします。これは、このバインディングコンポーネントを使用して定義された URI に自動的に追加されます。

カスタムバインディングの実装

マーシャリングおよびアンマーシャリングのデータフォーマットに使用される DataFormatBinding に加えて、独自のカスタムバインディングを実装することができます。カスタムバインディングを以下のように定義します。

  1. org.apache.camel.Processor クラスを実装して、(from 要素に登場) コンシューマーエンドポイントで受信するメッセージに対して変換を行います。
  2. 補完関係となる org.apache.camel.Processor クラスを実装して、プロデューサーエンドポイント (to 要素に登場) から送信されるメッセージに対して逆変換を行います。
  3. org.apache.camel.spi.Binding インターフェイスを実装します。これは上記のプロセッサーインスタンスのファクトリーとして機能します。

Binding インターフェイス

例2.3「org.apache.camel.spi.Binding インターフェイス」org.apache.camel.spi.Binding インターフェイスの定義を示しています。このインタフェースは、カスタムバインディングを定義するために実装する必要があります。

例2.3 org.apache.camel.spi.Binding インターフェイス

// Java
package org.apache.camel.spi;

import org.apache.camel.Processor;

/**
 * Represents a <a href="http://camel.apache.org/binding.html">Binding</a> or contract
 * which can be applied to an Endpoint; such as ensuring that a particular
 * <a href="http://camel.apache.org/data-format.html">Data Format</a> is used on messages in and out of an endpoint.
 */
public interface Binding {

    /**
     * Returns a new {@link Processor} which is used by a producer on an endpoint to implement
     * the producer side binding before the message is sent to the underlying endpoint.
     */
    Processor createProduceProcessor();

    /**
     * Returns a new {@link Processor} which is used by a consumer on an endpoint to process the
     * message with the binding before its passed to the endpoint consumer producer.
     */
    Processor createConsumeProcessor();
}

バインディングを使うタイミング

バインディングは、多くの異なるエンドポイントに同じ種類の変換を適用する必要がある場合に有効です。