34.2. メッセージ

概要

メッセージオブジェクトは、以下の抽象モデルを使用してメッセージを表します。

  • メッセージボディー
  • メッセージヘッダー
  • メッセージの添付

メッセージボディーとメッセージヘッダーは任意タイプ (Object タイプとして宣言) で宣言でき、メッセージの添付は javax.activation.DataHandler タイプとして宣言され、任意の MIME タイプを含めることができます。メッセージコンテンツの具体的な内容を取得する必要がある場合は、型コンバーターメカニズムを使用して、またマーシャリングおよびアンマーシャリングメカニズムを使用しても、ボディーとヘッダーを別のタイプに変換できます。

Apache Camel メッセージの重要な機能の 1 つは、メッセージ本文とヘッダーの Lazy Creation をサポートしていることです。場合によっては、メッセージを解析しなくてもルートを通過できることがあります。

Message インターフェイス

org.apache.camel.Message インターフェースは、例34.2「Message インターフェイス」 に示されているように、メッセージボディー、メッセージヘッダー、およびメッセージの添付にアクセスするためのメソッドを定義します。

例34.2 Message インターフェイス

// Access the message body
Object getBody();
<T> T  getBody(Class<T> type);
void   setBody(Object body);
<T> void setBody(Object body, Class<T> type);

// Access message headers
Object getHeader(String name);
<T> T  getHeader(String name, Class<T> type);
void   setHeader(String name, Object value);
Object removeHeader(String name);
Map<String, Object> getHeaders();
void setHeaders(Map<String, Object> headers);

// Access message attachments
javax.activation.DataHandler getAttachment(String id);
java.util.Map<String, javax.activation.DataHandler> getAttachments();
java.util.Set<String> getAttachmentNames();
void addAttachment(String id, javax.activation.DataHandler content)

// Access the message ID
String getMessageId();
void   setMessageId(String messageId);

Message インターフェースのメソッドの詳細な説明は、「Message インターフェイス」 を参照してください 。

本文、ヘッダー、および添付の Lazy Creation

Apache Camel は、ボディー、ヘッダー、および添付の Lazy Creation をサポートします。つまり、メッセージボディー、メッセージヘッダー、またはメッセージ添付ファイルを表すオブジェクトは、必要になるまで作成されません。

たとえば、In メッセージから foo メッセージヘッダーにアクセスする以下のルートについて考えてみましょう。

from("SourceURL")
    .filter(header("foo")
    .isEqualTo("bar"))
    .to("TargetURL");

このルートでは、SourceURL によって参照されるコンポーネントがレイジーの作成をサポートすることを前提としている場合、In メッセージヘッダーは header("foo") 呼び出しが実行されるまで実際に解析されません。この時点で、基礎となるメッセージ実装はヘッダーを解析し、ヘッダーマップを設定します。メッセージの 本文 は、ルートの最後の to("TargetURL") の呼び出し時に到達するまで解析されません。この時点で、ボディーはターゲットエンドポイント TargetURL に書き込むために必要な形式に変換されます。

本文、ヘッダー、および添付を生成する前の最後の瞬間まで待機することで、不要な型変換を回避できます。場合によっては、解析を完全に回避できます。たとえば、ルートにメッセージヘッダーへの明示的な参照がない場合、メッセージはヘッダーを解析せずにルートを通過する可能性があります。

Lazy Creation が実際に実装されるかどうかは、基礎となるコンポーネントの実装によって異なります。通常、Lazy Creation は、メッセージボディー、メッセージヘッダー、またはメッセージの添付の処理の負荷がある場合に役立ちます。Lazy Creation をサポートするメッセージタイプの実装に関する詳細は、「Message インターフェイスの実装」 を参照してください 。

メッセージ ID の Lazy Creation

Apache Camel は、メッセージ ID の Lazy Creation をサポートします。つまり、メッセージ ID は、getMessageId() メソッドを実際に呼び出す場合にのみ生成されます。このメソッドの DefaultExchange.getExchangeId() の実装では、ID 生成を CamelContext で登録された UUID ジェネレーターに委任します。

エンドポイント実装では、エンドポイントが一意のメッセージ ID を必要とするプロトコルを実装する場合、getMessageId() メソッドを暗黙的に呼び出します。特に、JMS メッセージには、通常一意のメッセージ ID を含むヘッダーが含まれるため、JMS コンポーネントが自動的に getMessageId() を呼び出してメッセージ ID を取得します (これは JMS エンドポイントの messageIdEnabled オプションによって制御されます) 。

CamelContext で UUID ジェネレーターを登録する方法の詳細は、「ビルトイン UUID ジェネレーター」 を参照してください。

初期メッセージの形式

In メッセージの最初のフォーマットはソースエンドポイントによって決定され、Out メッセージの初期フォーマットはターゲットエンドポイントによって決定されます。基礎となるコンポーネントで Lazy Creation がサポートされる場合、メッセージはアプリケーションによって明示的にアクセスされるまで解析されません。ほとんどの Apache Camel コンポーネントでは、raw 形式でメッセージボディーを作成します。たとえば、byte[]ByteBufferInputStreamOutputStream のようなタイプを使用して表現します。これにより、初期メッセージの作成に必要なオーバーヘッドは最小限に抑えられます。より詳細なメッセージ形式は、通常、型コンバーター または マーシャリングプロセッサー に依存します。

型コンバーター

メッセージの最初のフォーマットは重要ではありません。組み込み型コンバーターを使用して、メッセージをある形式から別の形式に簡単に変換できるためです (「組み込み型コンバーター」 を参照)。型変換機能を公開する Apache Camel API には、さまざまな方法があります。たとえば、convertBodyTo(Class type) メソッドをルートに挿入して、In メッセージのボディーを以下のように変換できます。

from("SourceURL").convertBodyTo(String.class).to("TargetURL");

In メッセージのボディーが、java.lang.String に変換されます。以下の例は、In メッセージボディーの最後に文字列を追加する方法を示しています。

from("SourceURL").setBody(bodyAs(String.class).append("My Special Signature")).to("TargetURL");

ここでは、メッセージボディーは文字列を最後に追加する前に文字列形式に変換されます。この例では、メッセージボディーを明示的に変換する必要はありません。以下のように使用することもできます。

from("SourceURL").setBody(body().append("My Special Signature")).to("TargetURL");

ここでは、append() メソッドは、引数を追加する前にメッセージボディーを文字列に自動的に変換します。

メッセージの型変換メソッド

org.apache.camel.Message インターフェイスは、型変換を明示的に実行するメソッドを公開します。

  • getBody(Class<T> type) - T 型としてメッセージボディーを返します。
  • getHeader(String name, Class<T> type) - 名前付きヘッダー値を T 型として返します。

サポートされる変換タイプの完全なリストは、「組み込み型コンバーター」 を参照してください。

XML への変換

単純なタイプ (byte[]ByteBufferString など) 間の変換をサポートする他に、組み込み型コンバーターは XML 形式への変換もサポートします。たとえば、メッセージのボディーを org.w3c.dom.Document タイプに変換できます。この変換には、メッセージ全体を解析し、XML ドキュメント構造を表すノードのツリーを作成する必要があるため、単純な変換よりも負荷が高くなります。以下の XML ドキュメントタイプに変換することができます。

  • org.w3c.dom.Document
  • javax.xml.transform.sax.SAXSource

XML 型変換は、単純な変換よりも厳密な適用性を持ちます。すべてのメッセージ本文が XML 構造に準拠するわけではないので、このタイプの変換が失敗する可能性があることを念頭に置いてください。一方、ルーターが XML メッセージタイプのみを扱うシナリオが多数あります。

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

マーシャリング では、高レベルなフォーマットを低レベルなフォーマットに変換し、アンマーシャリング では低レベルなフォーマットを高レベルなフォーマットに変換する必要があります。以下の 2 つのプロセッサーは、ルートでマーシャリングまたはアンマーシャリングを実行するために使用されます。

  • marshal()
  • unmarshal()

たとえば、シリアライズされた Java オブジェクトをファイルから読み取り、それを Java オブジェクトにアンマーシャリングするには、例34.3「Java オブジェクトのアンマーシャリング」 で示されるルート定義を使用することができます。

例34.3 Java オブジェクトのアンマーシャリング

from("file://tmp/appfiles/serialized")
    .unmarshal()
    .serialization()
    .<FurtherProcessing>
    .to("TargetURL");

最終的なメッセージの形式

In メッセージがルートの最後に到達すると、ターゲットエンドポイントはメッセージボディーを物理エンドポイントに書き込むことのできる形式に変換する必要があります。ソースエンドポイントに到達する Out メッセージにも同じルールが適用されます。この変換は通常、Apache Camel の型コンバーターを使用して暗黙的に実行されます。通常、これには、byte[] アレイから InputStream タイプへの変換など、低レベルのフォーマットから別の低レベルのフォーマットへの変換を行います。