第14章 コネクターおよびアダプター

14.1. はじめに

JBoss Enterprise Service Bus のすべてのクライアントとサービスがネイティブで使用するプロトコルとメッセージ形式を理解できるわけではありません。したがって、ESB 対応エンドポイント (JBossESB を理解するもの) と ESB 対応エンドポイント (JBossESB を理解しないもの) との間を橋渡しする必要があります。このような橋渡しをする技術はさまざまな分散システムで長年使用され、コネクター、ゲートウェイ、またはアダプターと呼ばれることがよくあります。
JBossESB の目的の 1 つは、広範なクライアントとサービスが対話できるようにすることです。JBossESB では、このために JBossESB または任意の ESB を使用してこのようなクライアントとサービスをすべて作成する必要がありません。JBossESB 内には相互運用性のバスの抽象的な表記が存在するため、JBossESB 対応ではない場合があるエンドポイントでもバスに「プラグイン」できます。

注記

これ以降で「ESB 内」または「ESB 内部」という言葉は ESB 対応エンドポイントのことを意味します。
すべての JBossESB 対応クライアントとサービスはメッセージを使用して相互に通信します。メッセージは情報交換の標準的な形式であり、ヘッダー、ボディ (ペイロード)、添付、および他のデータを含みます。また、すべての JBossESB 対応サービスはエンドポイント参照 (EPR) を使用して識別されます。
レガシー相互運用性シナリオの場合に JBossESB などの SOA インフラストラクチャーで ESB 対応クライアントが ESB 対応サービスを使用したり、ESB 対応クライアントが ESB 非対応サービスを使用したりできることが重要です。この相互有用性を実現するために JBossESB が使用するコンセプトはゲートウェイを使用することです。ゲートウェイは ESB 対応の世界と ESB 非対応の世界を橋渡しし、メッセージを EPR に変換したり、逆に EPR をメッセージに変換したりできるサービスです。
JBossESB は現在ゲートウェイとコネクタをサポートします。次のセクションでは、両方のコンセプトを調べ、その使用方法を説明します。

14.2. ゲートウェイ

JBossESB のすべてのユーザーが ESB に対応しているわけではありません。ユーザーが ESB によって提供されるサービスと対話できるように、JBossESB にはゲートウェイ (非 ESB クライアントとサービスからのメッセージを受け取り、必要な宛先にメッセージをルーティングできる特殊なサーバー) のコンセプトが存在します。
ゲートウェイは、ESB 対応リスナーと非常によく似た動作をする特殊なリスナープロセスです。ただし、いくつかの重要な違いがあります。
  • ゲートウェイクラスはファイル、JMS メッセージ、SQL テーブルなどに含まれる任意のオブジェクトを取得できる一方で (各「ゲートウェイクラス」は特定のトランスポートに特化されています)、JBossESB リスナーはこのドキュメントの「メッセージ」セクションで説明されたように JBossESB 正規化メッセージのみを処理できます。ただし、これらのメッセージには任意のデータを含めることができます。
  • 「メッセージ作成」アクションを実行するには 1 つのアクションクラスのみが呼び出されます。ESB リスナーはアクション処理パイプラインを実行できます。
  • 「取得される」オブジェクトは ESB メッセージオブジェクトを返す単一の「compose クラス」 (アクション) を呼び出すために使用されます (このオブジェクトは ESB 対応サービスであるターゲットサービスに配信されます)。設定時に定義されたターゲットサービスはレジストリによって実行時に EPR (または EPR の一覧) に変換されます。基礎となるコンセプトはレジストリによって返された EPR は ESB メッセージのヘッダに含まれる 'toEPR' と類似するということですが、受信オブジェクトは「ESB 非対応」であり、toEPR を動的に決定することができないため、この値は設定時にゲートウェイに提供され、すべての送信メッセージに含まれます。
いくつかの既成の compose クラスが存在します。デフォルトの「file」 compose クラスはファイルの内容をメッセージボディにパッケージ化します (JMS メッセージの場合と同様)。SQL テーブル行のデフォルトのメッセージ compose クラスは設定で指定されたすべての列の内容を java.util.Map にパッケージ化します。
ほとんどの場合はこれらのデフォルトの compose クラスで十分ですが、ユーザーが独自のメッセージ compose クラスを提供することは比較的簡単です。唯一の要件は a) 単一の ConfigTree 引数を受け取るコンストラクターを持つこと、b) メッセージ compose メソッド (デフォルト名は 'process' ですが、コンストラクター呼出し時に提供される ConfigTree 内の <action> エレメントの 'process' 属性で異なった名前を設定することができます) を提供することです。処理メソッドはタイプ Object の単一の引数を取り、メッセージ値を返す必要があります。
JBossESB 4.5 以降、FileGatewayfile-filter-class 設定属性を受け入れ、ゲートウェイが使用するファイルを選択する際に使用する FileFilter 実装を定義できるようになります。インスタンスが org.jboss.soa.esb.listeners.gateway.FileGatewayListener.FileFilterInit のタイプの場合、ユーザー定義の FileFilter インスタンスは、ゲートウェイが初期化します。この場合、init メソッドが呼び出され、ゲートウェイ ConfigTree インスタンスに渡されます。
デフォルトでは、入力サフィックスが設定ファイルに定義され、サフィックスが返された場合、以下の FileFilter 実装が定義され、FileGateway により使用されます。あるいは、入力サフィックスがない場合、作業サフィックス、エラーサフィックス、ポストサフィックスと一致しない限り、どのファイルでも受け入れられます。

14.2.1. ゲートウェイデータマッピング

非 JBossESB メッセージはゲートウェイが受け取ったときにメッセージに変換する必要があります。これをどのように行うか、受け取ったデータをメッセージのどこに置くかはゲートウェイの種類によって異なります。この変換をどのように行うかはゲートウェイの種類によって異なります。デフォルトの変換方法は以下で説明されています。
  • 入力メッセージが JMS TextMessage である場合は、関連付けられた String がデフォルトで指定されたボディ部分に置かれます。ObjectMessage または BytesMessage である場合、コンテンツは Body 部分で指定された BytesBody.BYTES_LOCATION 内に置かれます。
  • ローカルファイルゲートウェイ: コンテンツは BytesBody.BYTES_LOCATION で指定された Body 部分内に置かれます。
  • Hibernate ゲートウェイ: コンテンツは ListenerTagNames.HIBERNATE_OBJECT_DATA_TAG で指定されたボディ部分内に置かれます。
  • リモートファイルゲートウェイ: コンテンツは BytesBody.BYTES_LOCATION で指定されたボディ部分内に置かれます。

注記

InVM transport の導入により、同じアドレス空間 (VM) 内にサービスをゲートウェイとしてデプロイできるようになり、ゲートウェイとリスナー間の対話が効率的になりました。

14.2.2. ゲートウェイデータマッピングの変更方法

このマッピングがどのように行われるかを変更する場合、その方法はゲートウェイの種類によって異なります。
  • org.jboss.soa.esb.listeners.message.MessageComposer インターフェースのインスタンスは変換を行います。デフォルトの動作を変更するには、独自の compose メソッドと decompose メソッドを定義する適切な実装を提供します。新しい MessageComposer 実装は composer-class 属性名を使用して設定ファイルで提供する必要があります。
  • これらの実装は作成クラスを定義するために反射的な方法を使用します。独自のメッセージ composer クラスを提供し、どのインスタンスを使用するかをゲートウェイに通知するために設定ファイルで composer-class 属性名を使用します。メッセージが必要な場合はクラスのどの操作を呼び出すかをゲートウェイに通知するために composer-process 属性を使用できます。このメソッドはオブジェクトを受け取り、メッセージを返す必要があります。指定されていない場合は、プロセスのデフォルト名が使用されます。

注記

メッセージ作成を再定義するのにどのメソッドを使用するかに関係なく、ボディだけでなくメッセージのコンテンツを完全に制御できることに注意してください。たとえば、元のコンテンツの内容や送信者などに基づいて新しく作成されたメッセージに対して ReplyTo または FaultTo EPR を定義する場合は、ヘッダーも変更することを考慮する必要があります。

14.3. JCA を介した接続

JCA メッセージインフローを ESB ゲートウェイとして使用できます。この統合では MDB ではなく ESB の軽量インフロー統合を使用します。サービスに対してゲートウェイを有効にするには、最初にエンドポイントクラスを実装する必要があります。このクラスは org.jboss.soa.esb.listeners.jca.InflowGateway クラスを実装する必要がある Java クラスです。
public interface InflowGateway
{
  public void setServiceInvoker(ServiceInvoker invoker);
}

エンドポイントクラスはデフォルトのコンストラクターまたは ConfigTree パラメーターを受け取るコンストラクターを持つ必要があります。この Java クラスはバインドする JCA アダプターのメッセージタイプも実装する必要があります。以下は JMS アダプターにフックする単純なエンドポイントクラスの例です。
public class JmsEndpoint implements InflowGateway, MessageListener
{
  private ServiceInvoker service;
  private PackageJmsMessageContents transformer = new PackageJmsMessageContents();

  public void setServiceInvoker(ServiceInvoker invoker)
  {
    this.service = invoker;
  }

  public void onMessage(Message message)
  {
    try
    {
      org.jboss.soa.esb.message.Message esbMessage = transformer.process(message);
      service.deliverAsync(esbMessage);
    }
    catch (Exception e)
    {
      throw new RuntimeException(e);
    }
  }
}

このクラスに対して定義されたゲートウェイ 1 つに対して JmsEndpoint クラスの 1 つのインスタンスが作成されます。これはプールされる MDB とは異なります。このクラスの 1 つのインスタンスのみが各受信メッセージにサービスを提供するため、スレッドセーフコードを記述する必要があります。
設定時に ESB は ServiceInvoker を作成し、エンドポイントクラスの setServiceInvoker メソッドを呼び出します。次に ESB は JCA エンドポイントを有効にし、エンドポイントクラスインスタンスがメッセージを受信できる状態になります。JmsEndpoint の例では、インスタンスが JMS メッセージを受け取り ESB メッセージタイプに変換し、ターゲットサービスで呼び出す ServiceInvoker インスタンスを使用します。

注記

JMS エンドポイントクラスは、ESB の配布が org.jboss.soa.esb.listeners.jca.JmsEndpoint 下に存在する状態で提供されます。このクラスを任意の JMS JCA インフローアダプタとともに何度も使用することができます。

14.3.1. 構成

JCA インフローゲートウェイは jboss-esb.xml ファイルに設定されます。以下に例を示します。
<service category="HelloWorld_ActionESB"
  name="SimpleListener"
  description="Hello World">
  <listeners>
    <jca-gateway name="JMS-JCA-Gateway"
     adapter="jms-ra.rar"
     endpointClass="org.jboss.soa.esb.listeners.jca.JmsEndpoint">
    <activation-config>
     <property name="destinationType" value="javax.jms.Queue"/>
     <property name="destination" value="queue/esb_gateway_channel"/>
    </activation-config>
  </jca-gateway>
...
 </service>

<service category="HelloWorld_ActionESB"
  name="SimpleListener"
  description="Hello World">
  <listeners>
    <jca-gateway name="JMS-JCA-Gateway"
     adapter="jms-ra.rar"
     endpointClass="org.jboss.soa.esb.listeners.jca.JmsEndpoint">
    <activation-config>
     <property name="destinationType" value="javax.jms.Queue"/>
     <property name="destination" value="queue/esb_gateway_channel"/>
    </activation-config>
  </jca-gateway>
...
 </service>
JCA ゲートウェイは <jca-gateway> エレメントに定義されます。JCA ゲートウェイはこの XML エレメントの設定可能な属性です。

表14.1 jca-gateway 設定属性

属性 必須 説明
name yes ゲートウェイの名前
アダプタ yes 使用しているアダプタの名前。JBoss では、デプロイした RAR のファイル名 (jms-ra.rar など) になります。
endpointClass yes エンドポイントクラスの名前
messagingType no アダプタのメッセージインターフェース。指定しない場合は、ESB がエンドポイントクラスに基づいた名前を付けます。
実行済み no デフォルトでは真に設定されます。JTA トランザクション内でメッセージを呼び出すかどうかを設定します。
<activation-config> エレメントは <jca-gateway> 内に定義する必要があります。このエレメントはアクションプロパティと同じ構文を持つ 1 つまたは複数の <property> エレメントを受け取ります。エンドポイントクラスにメッセージを送信するには <activation-config> 下のプロパティが使用されます。これは、JCA を MDB とともに使用する場合と変わりません。
<jca-gateway> 内には <property> エレメントを好きなだけ持つこともできます。このオプションは、追加の設定をエンドポイントクラスに渡すために提供されています。これらはコンストラクタに渡された ConfigTree によって読み取ることができます。

14.3.2. 標準のアクティベーションプロパティのマッピング

ESB プロパティの数は自動的に ActivationMapper を使用してアクティベーション設定にマッピングされます。このプロパティ、ロケーション、目的については以下の表にまとめられています。

表14.2 標準アクティベーションプロパティのマッピング

属性 Location 説明
maxThreads jms-listener 同時に処理できる最大メッセージ数
dest-name jms-message-filter JMS 宛先名
dest-type jms-message-filter JMS 宛先タイプ、QUEUE または TOPIC
selector jms-message-filter JMS メッセージセレクター
providerAdapterJNDI jms-jca-provider プロバイダーアダプターの JNDI ロケーションは、JCA インフローが使用してリモートの JMS プロバイダーにアクセスできます。これは、JBoss 固有のインターフェースで、デフォルトの JCA インフローアダプターによりサポートされていますが、必要であれば、他のインフローアダプターによる使用も可能です。
アクティベーション仕様へのプロパティのマッピングは、ActivationMapper インターフェースを実装することで、オーバーライドできます。また、グローバルまたは各 ESB デプロイメント設定内で宣言可能です。
ActivationMapper は、jbossesb-properties.xml ファイルを使うことでグローバルに指定されます。指定の JCA アダプターに使用するデフォルトのマッパーを定義します。設定するプロパティ名は org.jboss.soa.esb.jca.activation.mapper."adapter name"” で、値は ActivationMapper のクラス名です。
以下のスニペットでは、JBoss JCA アダプター (jms-ra.rar) のアクティベーション仕様でプロパティをマッピングする際に使用するデフォルトの ActivationMapper の設定を示しています。
<properties name="jca"> 
       <property name="org.jboss.soa.esb.jca.activation.mapper.jms-ra.rar"
            value="org.jboss.soa.esb.listeners.jca.JBossActivationMapper"/> 
   </properties>
デプロイメント内で ActivationMapper を指定すると、グローバル設定をオーバーライドします。マッパーをリスナー、バス、プロバイダー内で優先順位を保ちつつ指定可能です。
次のコード例は、プロバイダー設定内でマッパー設定を指定する例を示します。
<jms-listener name="listener" busidref="bus" maxThreads="100">
        <property name="jcaActivationMapper" value="TestActivationMapper"/>
    </jms-listener>
次のコード例は、プロバイダー設定内でマッパー設定を指定する例を示します。
<jms-bus busid="bus">
        <property name="jcaActivationMapper" value="TestActivationMapper"/>
        <jms-message-filter dest-type="TOPIC" dest-name="DestName"/>
    </jms-bus>
次のコード例は、プロバイダー設定内でマッパー設定を指定する例を示します。
<jms-jca-provider name="provider" connection-factory="ConnectionFactory">
        <property name="jcaActivationMapper" value="TestActivationMapper"/>
        <jms-bus busid="bus">
            <jms-message-filter dest-type="TOPIC" dest-name="DestName"/>
        </jms-bus>
    </jms-jca-provider>