この章では、パイプラインおよび分割-結合内からカスタムJavaコードを呼び出すことで、Service Busの機能を拡張する方法について説明します。Service Busのパイプラインと分割-結合は、それぞれJavaコールアウト・アクションを備えており、それによってパイプラインまたは分割-結合の外部のPlain Old Java Object (POJO)を呼び出すことができます。
この章の内容は次のとおりです。
POJOへのJavaコールアウトの構成については、「コンソールでのJavaコールアウト・アクションの追加」を参照してください。
Javaコールアウト・アクションによって、Javaアーカイブ(JAR)ファイル内のメソッドにアクセスし、自身のパイプラインおよび分割-結合に処理ロジックを追加できます。コールアウトを構成するときに、メソッドの引数を指定でき、必要に応じてセキュリティのためのサービス・アカウントを指定できます。パラメータは、メッセージ・コンテキスト変数にマップできます。静的メソッドには、どのPOJOからもアクセスできます。
また、 Javaコールアウトを使用してJavaオブジェクトを作成し、パイプラインに格納したり、Javaオブジェクトをパラメータとして他のJavaコールアウトに渡したりすることもできます。
ヒント:
JSON型変数は、その文字列化表現でjava.lang.String
型の引数に渡されます。
Service BusでJavaコールアウトを使用できるシナリオは次のとおりです。
DTDの検証、Javaでのフィールド間のセマンティック検証などカスタム検証の実行。
バイナリ・ドキュメントからbase64Binaryへの変換(またはその逆)、カスタムJava変換クラスの使用などのカスタム変換の実行。
カスタム認証および認可の実行。例としては、メッセージ内のカスタム・トークンを認証および認可する必要があるシナリオがあります。ただし、Service Busは、パイプラインまたは分割-結合によって以降に呼び出されるサービスまたはPOJOに、認証されたユーザーのIDを伝播することはできません。
メッセージに情報を追加するためのルックアップの実行。たとえば、ファイルまたはJava表を使用して、メッセージに情報を追加できる任意のデータをルックアップできます。
バイナリ・データへのアクセス。POJOへのJavaコールアウトを使用してバイナリ・ドキュメントの最初の数バイトを検出し、MFLの型を推測できます。返されるMFL型は、次のMFL変換アクションによる非XMLからXMLへのトランスフォーメーションで使用されます。
カスタム・ルーティング・ルールまたはルール・エンジンの実装
Javaオブジェクトの作成とパイプラインへの格納。
別のJavaコールアウトへのパラメータとしてのJavaオブジェクトの受け渡し。
JEJBプロキシ・サービスを使用したJEJBによるリモートEJB操作またはサービスの呼出し。
Javaコールアウトの入力と戻りの型は制限されていません。パイプラインでのJavaオブジェクトの格納と受け渡しの詳細は、「Body変数内のJavaコンテンツ」を参照してください。
Enterprise JavaBeans (EJB)もJava終了メカニズムを提供します。次の場合は、Javaコールアウトではなく、EJBを使用することをお薦めします。
すでにEJBを実装している場合。JEJBトランスポートでService Busを介してEJBコールによりEJBを呼び出し、メッセージ・ルーティング、UDDI統合、アラート、操作ごとのモニター、レポート、結果キャッシュなどのService Busの機能を利用できます。
JDBCデータベースへの読取りアクセスが必要な場合。この目的でPOJOを使用することもできますが、EJBはこのために専用に設計されているため、JDBCリソースの管理および接続に対して、より優れたサポートを提供します。
JDBCデータベースまたは他のJ2EEトランザクション・リソースへの書込みアクセスが必要な場合。EJBは、トランザクション・ビジネス・ロジック専用に設計されており、障害の適切な処理に対して、より優れたサポートを提供します。ただし、トランザクションとセキュリティ・コンテキスト伝播はPOJOを使用してサポートされ、JEJBトランスポートで、トランザクション・コンテキストでのエラー処理が提供されます。
アウトバウンド・メッセージには、POJOまたはEJBを使用するかわりにカスタム・トランスポートを記述することをお薦めします。
バイナリ・コンテンツを入力引数としてコールアウト・メソッドに渡すため、およびJavaコールアウト・メソッドからストリーミング・コンテンツの結果を受け入れるために、Javaコールアウトを使用してストリーミング・コンテンツを操作できます。
Javaコールアウト・メソッドに、バイナリ・コンテンツを入力引数としてストリーミング形式で渡すことができます。Service Busは入力引数のJavaタイプを確認して処理します。引数のタイプがjavax.activation.DataSource
の場合、システムはラッパーDataSource
オブジェクトを作成し、Source.getInputStream()
メソッドを呼び出して、対応するソースからInputStream
を取得します。このメソッドは、Javaコールアウト・コードから必要なだけ何回でも呼び出すことができます。
また、getContentType()
メソッドは、バイナリ・コンテンツがページングされたMIME添付ファイルでないかぎり、application/octet-stream
を返します。バイナリ・コンテンツがページングされたMIME添付ファイルである場合は、対応するMIME部分のContent-Typeヘッダー(存在する場合)が使用されます。
同様に、getName()
メソッドは、バイナリ・コンテンツがページングされたMIME添付ファイルでないかぎり、バイナリ・コンテンツの参照属性の文字列値を返します。バイナリ・コンテンツがページングされたMIME添付ファイルである場合は、対応するMIME部分のContent-IDヘッダー(存在する場合)が使用されます。getOutputStream()
メソッドは必要に応じてUnsupportedOperationException
をスローします。
完了後、結果はJavaコールアウト・メソッド引数に渡されます。入力ストリームのバイナリ・オクテットを正しく解釈するために、Javaコールアウト・メソッドでContent-Transfer-Encodingヘッダーの値が必要な場合もあります(たとえば、エンコーディングがバイナリ、7ビット、8ビットのいずれであるかを判別する場合ど)。次に示すように、このパラメータを別個の引数として渡すことができます。
$attachments/*:attachment[1]/*:Content-Transfer-Encoding/text()
入力引数がDataSourceでない場合、Service Busは引数をbyte[]配列に変換します。
Javaコールアウト・メソッドからストリーミング・コンテンツ結果を取得できます。この処理のために、Service Busは結果のJavaタイプを確認し、適切なコンテキスト変数の値を対応するctx:binary-content
XML要素に設定して、新しいソースをソース・リポジトリに追加します。
注意:
Javaコールアウト・メソッドからファイルのコンテンツを返す場合、javax.activation.FileDataSource
のインスタンスを使用することができます。
パイプラインまたは分割-結合がソースのバイナリ・コンテンツを必要とする場合、ctx:binary-content
要素に対応するDataSource
オブジェクトをリポジトリから検索して、バイナリ・オクテットを取得するためにDataSource.getInputStream()
メソッドを呼び出します。
getInputStream()
メソッドは、トランスポート・レイヤーでのアウトバウンド・メッセージの再試行に応じるなどのために、メッセージ処理時に何度も呼び出されることがあることに注意してください。
POJOは、Service BusでJARリソースとして登録されます。JARリソースの詳細は、「JARファイルの操作」を参照してください。
通常、JARはサイズを小さくし、簡単なものにすることをお薦めします。JARが呼び出すサイズの大きいコードまたは使用される大きなフレームワークは、システム・クラス・パスに含めることをお薦めします。システム・クラス・パスを変更する場合は、サーバーを再起動する必要があります。
従属クラスと重複クラスは同じJARリソースに入れることをお薦めします。それらが本来別のものである場合は、異なるJARリソースに入れます。JARリソースに変更を行うと、それを参照するすべてのサービスが再デプロイされます。これは、Service Busシステムにとって時間の浪費となる可能性があります。同じクラスを、競合させずに複数のJARリソースに配置できます。JARファイルは、最初に参照されたときに、動的にクラス・ロードされます。
1つまたは複数のサービスで、単一のPOJOを呼び出せます。そのサービス内のすべてのスレッドが同じPOJOを呼び出すため、POJOはスレッド・セーフである必要があります。POJOのクラスまたはメソッドは同期でき、この場合、呼出しを行うすべてのプロキシ・サービスのすべてのスレッドによるアクセスを順序付けします。POJOコードによって、任意のより詳細な並行処理(たとえば、データベース読込みの結果キャッシュへのアクセスの制御や、古いキャッシュ・エントリ処理の実装)を実装する必要があります。
通常、POJOの場合、スレッドの作成は推奨されません。