11.11. Service Activator

概要

図11.9「Service Activator パターン」 に示されている Service Activator パターンは、受信したリクエストメッセージへの応答でサービスの操作が呼び出されるシナリオを説明します。Service Activator は、呼び出す操作を特定し、操作のパラメーターとして使用するデータを抽出します。最後に、Service Activator は、メッセージから抽出したデータを使用して操作を呼び出します。操作呼び出しは一方向 (リクエストのみ) または双方向 (リクエスト/リプライ) のいずれかになります。

図11.9 Service Activator パターン

Messaging Gateway パターン

多くの点で、Service Activator は従来のリモートプロシージャーコール (RPC) に類似しています。ここでは、操作呼び出しはメッセージとしてエンコードされます。主な違いは、Service Activator がより柔軟である必要があることです。RPC フレームワークは、リクエストおよびリプライメッセージエンコーディングを標準化します (たとえば、Web サービスの操作は SOAP メッセージとしてエンコードされます)。一方、Service Activator は通常、メッセージングシステムとサービスの操作間のマッピングを即応する必要があります。

Bean インテグレーション

Apache Camel が Service Activator パターンのサポートに提供する主なメカニズムが Bean インテグレーション です。Bean インテグレーション は、受信メッセージを Java オブジェクトのメソッド呼び出しにマッピングするための一般的なフレームワークを提供します。たとえば、Java fluent DSL は、bean() および beanRef() プロセッサーを提供し、ルートに挿入して、登録された Java Bean のメソッドを呼び出すことができます。メッセージデータの Java メソッドパラメーターへの詳細なマッピングは、 Bean バインディングによって決定され、Bean クラスにアノテーションを追加することで実装できます。

たとえば、JMS/ActiveMQ キューで受信されるサービスリクエストに対して、BankBean.getUserAccBalance() の Java メソッドを呼び出す以下のルートについて考えてみましょう。

from("activemq:BalanceQueries")
  .setProperty("userid", xpath("/Account/BalanceQuery/UserID").stringResult())
  .beanRef("bankBean", "getUserAccBalance")
  .to("velocity:file:src/scripts/acc_balance.vm")
  .to("activemq:BalanceResults");

ActiveMQ エンドポイント activemq:BalanceQueries から引き出されたメッセージは、銀行口座のユーザー ID を提供する単純な XML 形式です。以下に例を示します。

<?xml version='1.0' encoding='UTF-8'?>
<Account>
  <BalanceQuery>
    <UserID>James.Strachan</UserID>
  </BalanceQuery>
</Account>

ルートの最初のプロセッサー setProperty() は、In メッセージからユーザー ID を抽出し、userid エクスチェンジプロパティーに保存します。In ヘッダーは Bean の呼び出し後に利用できないため、プロパティーに保存することが推奨されます。

サービスのアクティベーションの手順は beanRef() プロセッサーによって実行されます。このプロセッサーは、受信メッセージを bankBean の Bean ID で識別される Java オブジェクトの getUserAccBalance() メソッドにバインドします。以下のコードは、BankBean クラスの実装例を示しています。

package tutorial;

import org.apache.camel.language.XPath;

public class BankBean {
    public int getUserAccBalance(@XPath("/Account/BalanceQuery/UserID") String user) {
        if (user.equals("James.Strachan")) {
            return 1200;
        }
        else {
            return 0;
        }
      }
}

message data to method パラメーターのバインディングは、UserID XML 要素の内容を user method パラメーターに注入する @XPath アノテーションによって有効にされます。呼び出しの完了時に、戻り値は Out メッセージのボディーに挿入され、ルートの次のステップのために In メッセージにコピーされます。Bean が beanRef() プロセッサーにアクセスできるようにするには、Spring XML でインスタンスをインスタンス化する必要があります。たとえば、以下の行を META-INF/spring/camel-context.xml 設定ファイルに追加して Bean をインスタンス化できます。

<?xml version="1.0" encoding="UTF-8"?>
<beans ... >
  ...
  <bean id="bankBean" class="tutorial.BankBean"/>
</beans>

Bean ID bankBean は、レジストリーでこの Bean インスタンスを特定します。

Bean 呼び出しの出力は、適切にフォーマットされた結果メッセージを生成するために Velocity テンプレートに注入されます。Velocity エンドポイント velocity:file:src/scripts/acc_balance.vm は、以下の内容を含む velocity スクリプトの場所を指定します。

<?xml version='1.0' encoding='UTF-8'?>
<Account>
  <BalanceResult>
    <UserID>${exchange.getProperty("userid")}</UserID>
    <Balance>${body}</Balance>
  </BalanceResult>
</Account>

エクスチェンジインスタンスは Velocity 変数 exchange として利用できます。これにより、${exchange.getProperty("userid")} を使用して userid エクスチェンジプロパティーを取得できます。現在の In メッセージのボディー ${body} には、getUserAccBalance() メソッド呼び出しの結果が含まれます。