この章では、Service Busサービスで使用するカスタム・トランスポート・プロバイダを開発する際の概念、機能および設計上の考慮事項について説明します。開発作業を綿密に計画すると、カスタム・トランスポート・プロバイダの開発に要する時間と労力を大幅に削減できます。
この章の内容は次のとおりです。
トランスポート・プロバイダは、トランスポート・ソフトウェア開発キット(SDK)のインタフェースを実装し、Service Busとメッセージを送受信するメカニズムとの橋渡しをします。このようなメカニズムには、HTTPなどの特定の転送プロトコルのみでなく、ファイルや電子メール・メッセージなど、他のエンティティが含まれる場合もあります。トランスポート・プロバイダは、トランスポート・エンドポイント(メッセージの送信元または送信先となるリソース)のライフ・サイクルおよび実行時の動作を管理します。
クライアントは、特定の転送プロトコルを使用してService Busにメッセージを送信します。トランスポート・プロバイダは、インバウンド・メッセージを処理します。サービス・クライアント・エンドポイントとの通信を処理し、Service Busへのメッセージのエントリ・ポイントとして機能します。バインディング・レイヤーは、メッセージの圧縮と解凍、メッセージのセキュリティ処理、パイプラインへのメッセージの引渡しを行います。Service Busを介したメッセージの基本的な流れについては、図1-3を参照してください。
ヒント:
Service Busのメッセージ・ブローカリングおよびトランスポート・レイヤーの役割の詳細は、「Oracle Service Busについて」を参照してください。Service Busを介したメッセージ・フローについてのより詳細なシーケンス・ダイアグラムは、「トランスポートSDKのUMLシーケンス・ダイアグラム」を参照してください。
デフォルトでは、Service Busには、HTTP、JMS、ファイル、FTPなど、一般的に使用されている複数の転送プロトコルをサポートするトランスポート・プロバイダが用意されています。これらのネイティブなプロバイダを使用して、前述の一般的な転送プロトコルを必要とするプロキシ・サービスおよびビジネス・サービスを構成できます。
ヒント:
ネイティブのトランスポート・プロバイダの使用および構成の詳細は、「JCAアダプタ、トランスポートおよびバインドの操作」を参照してください。
Service Busのメッセージ処理は、メッセージの送受信方法とは関係なく行われます。トランスポートSDKは、Service Busと、Service Busで送受信されるデータ・フローを扱うコンポーネントの間に抽象化レイヤーを提供します。この抽象化レイヤーがあることで、一意の転送プロトコルを扱うための新しいトランスポート・プロバイダを設計および開発できます。
SDKは、Service Busの他の部分から次を抽象化します。
特定のトランスポート・バインディングの処理。
サービス・エンドポイントのトランスポート・バインディングへのデプロイ。エンドポイントではメッセージの送信も受信も行うことができます。
モニター情報の収集。
エンドポイントの管理(中断と再開操作の実行および接続プロパティの設定など)。
サービス・レベル・アグリーメント(SLA)動作の適用(接続のタイム・アウトなど)。
この項では、トランスポートSDKの主要な機能について説明します。
トランスポートSDKを使用して開発されたトランスポート・プロバイダは、次のようにインバウンド・メッセージおよびアウトバウンド・メッセージを処理します。
通常、インバウンド・メッセージは、HTTPクライアントなどの外部ソースからService Busに送信されます。ペイロードおよびトランスポート・レベル・ヘッダーがある場合、トランスポートSDKは、それらを汎用的なデータ構造にパッケージ化します。その後、トランスポートSDKは、汎用フォーマットでService Busパイプラインにメッセージを渡します。
アウトバウンド・メッセージは、Service Busのビジネス・サービスから発信され、WebサービスまたはJMSキューなどの外部で管理されているエンドポイントに送信されます。トランスポートSDKは、Service Busパイプラインから汎用的なデータ構造を受け取り、対応するトランスポート固有のヘッダーおよびペイロードに変換し、外部システムに送信します。
トランスポートSDKは、アウトバウンド・メッセージおよびインバウンド・メッセージを個別に処理します。インバウンド・メッセージを1つの転送プロトコルにバインドし、アウトバウンド・エンドポイントで異なる転送プロトコルにバインドすることもできます。
一部のトランスポートでは、アーティファクトをOracle WebLogic Serverにデプロイする必要があります。たとえば、JMSプロキシ・サービスは、メッセージ駆動型Beanとして実装されます。このアーティファクト、EARファイルは、新しいJMSプロキシ・サービスを登録する際にデプロイする必要があります。同様に、EJBトランスポート・プロバイダではEARファイルを使用しますが、これは新しいEJBビジネス・サービスを登録する際にデプロイする必要があります。サービス登録の一環としてキューおよびトピックを作成することがあるJMSトランスポートなどのように、その他のタイプのアーティファクトのデプロイが必要になる場合があります。SDKにより、これらのアーティファクトをサポートし、Oracle WebLogic Serverのデプロイメント・サイクルに参加できます。これらのアーティファクト・ファイルのいずれかのデプロイメントが失敗した場合、Service Busのセッションに通知され、デプロイメントはキャンセルされます。SDKのこの機能により、サービスを最小単位で作成できます。一部が失敗が発生した場合、セッションは以前の状態に戻ります。
注意:
Oracle WebLogic Serverのデプロイメント・サイクルに参加するには、トランスポート・プロバイダがTransportWLSArtifactDeployer
インタフェースを実装している必要があります。この方法の第一の利点は、最小単位でOracle WebLogic Serverをデプロイできる点であり、必要に応じてロールバックすることもできます。このインタフェースの詳細は、「汎用インタフェースのサマリー」および「TransportWLSArtifactDeployerの実装が適している場合」を参照してください。
メッセージを処理する際、サーバーで動作するスレッド数には制限があるため、非同期的に行うことが重要です。この機能により、多数のメッセージを処理できるようにService Busを拡張できます。リクエストが処理されると、スレッドは解放されます。ビジネス・サービスが応答を受信すると(または、一方向の場合は要求を処理し終えると)、コールバックによってService Busに非同期的に通知します。
詳細は、「同期トランザクションのサポート」および「トランスポートSDKおよびスレッド・モデル」を参照してください。
トランスポートSDKを使用して、インバウンド・プロパティのモードおよびアウトバウンド・プロパティのモードを実装できます。これらの接続モードおよびエンドポイント・モードは、トランスポート・プロバイダのXMLスキーマ定義(XSD)ファイルで指定します。このファイルの詳細は、「ステップ3. トランスポート固有のアーティファクトのXMLスキーマ・ファイルの作成」を参照してください。このスキーマは、Service Busパイプラインでフィルタ処理およびルーティングを行う際に使用できます。
この項では、トランスポート・マネージャによって提供される関連機能について示します。トランスポート・マネージャは、様々なトランスポート・プロバイダの管理、エンドポイントの登録、制御、インバウンド・メッセージとアウトバウンド・メッセージの処理、およびその他の機能を一元化するための主要ポイントとなります。これらの機能は、トランスポート・プロバイダによる特定のサポートを必要としません。
トランスポートSDKは、アウトバウンド・メッセージのロード・バランシングおよびフェイルオーバーをサポートします。次のロード・バランシング・オプションがサポートされています。
なし: アウトバウンド・リクエストごとに、トランスポート・プロバイダが、URIが記載されているリストを巡回し、送信が成功するまで、各URIにメッセージの送信を試みます。
ラウンド・ロビン: 「なし」と似ていますが、トランスポート・プロバイダは最後に試行されたURIを追跡します。メッセージが送信されるたびに、プロバイダはリストの最後の位置から開始します。
ランダム: トランスポート・プロバイダは、URIが記載されているリストからランダムに試行します。
ランダムな重みベース: 各URIは、任意の重みに関連付けられます。アルゴリズムを使用して、この重みに基づいてURIを選択します。
この項では、カスタム・トランスポート・プロバイダの記述が必要となる基本的な使用例について説明します。別の方法を選択した方が適切な場合もあります。
トランスポートSDKの主要な使用例の1つは、既に内部アプリケーション間の通信に使用している特別なトランスポートをサポートすることです。このようなトランスポートでは、セット・アップされたハンドシェイク、ヘッダー・フィールド、メタデータ、またはトランスポート・レベルのセキュリティに独自の概念が用いられている場合があります。トランスポートSDKを使用して、個々のエンドポイント(インバウンドおよびアウトバウンドのいずれかまたは両方)の構成を可能にするService Busのトランスポートの実装を作成できます。カスタム・トランスポートを実装することで、特別なトランスポートのメタデータおよびヘッダー・フィールドをプロキシ・サービス・パイプラインで使用できるコンテキスト変数にマッピングできます。
信頼性、セキュリティ、パフォーマンス、管理、ユーザー・インタフェースおよびUDDIレジストリの使用のために、トランスポート・プロバイダをService Busのあらゆる側面にシームレスに統合する必要がある場合は、トランスポートSDKを使用してください。トランスポートSDKを使用してカスタム・トランスポートを開発した方が好ましい場合の例を次に示します。
カスタム・インタフェースを必要とし、組織の既存のアプリケーションをサポートする、独自開発のトランスポートを使用している場合。
CORBAアプリケーションとの通信にCORBAまたはIIOPプロトコルを使用している場合。
IMSおよびMainframeなど、その他のレガシー・システムを使用している場合。
既存のトランスポートでバリエーションを使用する場合。
LLP、AS3、およびACCORDなどの業界固有のトランスポートを使用している場合。
また、トランスポートSDKを使用して、Service Busで提供される既存のトランスポートの1つで特別なプロトコルをサポートできます。この例には、次のサポートが含まれます。
HTTPを介した、解析済またはバイナリのXMLで構成されたメッセージ。
HTTPを介したWS-RMまたは新しいWebサービス標準。
JMSを介したリクエスト/レスポンス・メッセージ。ただし、Service BusのJMSトランスポートでサポートされている2つのパターンのいずれとも異なるレスポンス・パターンを持つもの(たとえば、メッセージ・コンテキストで定義されているレスポンス・キューなど)。
トランスポートSDKを使用して新しいService Busトランスポート・プロバイダを作成する場合、多大な労力が必要となることがあります。トランスポートSDKは、カスタム・トランスポートが、Service Busにネイティブに付属するトランスポートの利便性と機能をすべて活用できるようにするために、多彩な機能をすべて備えた環境を提供します。ただし、このような多彩な機能を持ったカスタム・トランスポートは複雑になります。場合によっては、より簡単な別の方法を検討することをお薦めします。
既存のプロトコルを介して送受信される、異なるフォーマットのメッセージをサポートするためだけに拡張機能が必要な場合は、既存のトランスポートおよびJavaコールアウトを使用してメッセージを変換できる場合があります。たとえば、標準のJMSプロトコルを介して送信される(ASN.1またはシリアライズされたJavaオブジェクトなどの)特別なバイナリ・フォーマットを使用しているとします。この場合、サービスのタイプがバイナリの入出力メッセージを使用するメッセージング・サービスである、標準のJMSトランスポートを使用したサービスを定義することも検討できます。次に、パイプラインでメッセージ・コンテンツが必要な場合は、Javaコールアウト・アクションを使用してメッセージをXMLに変換したりXMLから変換したりできます。Javaコールアウトの使用の詳細は、「JavaコールアウトおよびPOJOの使用方法」を参照してください。
トランスポートSDKを使用してカスタム・トランスポート・プロバイダを開発することが最適とは言えないその他の例を次に示します。
既存のOracleソリューション(Oracle WebLogic Server、Oracle WebLogic Integration、Oracle Data Service Integrator、Oracle Business Process Management、Oracle Tuxedo、Oracle WebLogic Portalなど)をService Busと組み合せることにより、トランスポートの要件を満たす場合。
サービス有効化ツールを使用することによって、SOA方式を実装するためのより簡略な標準ベースのメカニズムが提供される場合。
(Service Busで動作確認されている)別の接続ソリューション(iWayアダプタ、Cyclone B2Bなど)でも要件に対応できる場合。
ある種の簡単なJava機能を抽象化する手段として、EJBを代用できる場合。
通常、カスタム・トランスポート・プロバイダは設計時部分と実行時部分から構成されています。設計時部分では、トランスポート・プロバイダへのエンドポイントの登録を行います。この構成動作は、UIインタフェースの実装によって実行されます。実行時部分では、メッセージの送受信のメカニズムを実装します。
新しいカスタム・トランスポート・プロバイダを開発する場合は、SDKによって提供される多数のインタフェースを実装する必要があります。この項では、SDKの設計時部分および実行時部分の構成をモデル化したUMLダイアグラムを示します。
ヒント:
Service Busでは、TransportProvider
インタフェースの実装は、トランスポート・プロトコル固有の構成プロパティおよび実行時プロパティの集中的な管理ポイントとなります。サポートされているプロトコルごとに、TransportProvider
オブジェクトの単一のインスタンスが存在します。たとえば、HTTPトランスポート・プロバイダ、JMSトランスポート・プロバイダ、およびその他のトランスポート・プロバイダに、それぞれ単一のインスタンスが存在します。
必要なインタフェースのリストは、「カスタム・トランスポート・プロバイダの開発」を参照してください。トランスポートSDKによって提供されるインタフェースおよびクラスの概要については、「トランスポートSDKのインタフェースおよびクラス」を参照してください。詳細は、「Oracle Service Bus Java APIリファレンス」を参照してください。
カスタム・トランスポート・プロバイダの設計時部分はユーザー・インタフェースの構成で成り立っています。この構成は、新しいビジネス・サービスまたはプロキシ・サービスが登録される際に、Oracle Service BusコンソールまたはIDEによって呼び出されます。図39-1に、トランスポート・プロバイダの設計時部分の構造を説明したUMLダイアグラムを示します。ダイアグラムでは次のインタフェースについて説明しています。
TransportManager: 転送プロバイダはこのインタフェースを介して転送マネージャと通信します。実装は公開されていません。
TransportProvider: サード・パーティはこのインタフェースを実装する必要があります。TransportProvider
は、TransportEndpoint
オブジェクトを追跡し、また、エンドポイントのライフ・サイクルも管理します。たとえば、トランスポート・エンドポイントは中断できますが、これはTransportProvider
インタフェースを介して管理されます。
TransportUIBinding: このインタフェースは、Oracle Service Busコンソールがトランスポート固有のページを表示する際に役立ちます。
注意:
各トランスポート・エンドポイントの構成は、任意のトランスポート・プロバイダのすべてのエンドポイントに対して汎用なプロパティ(URIなど)と、そのプロバイダのエンドポイントだけに固有のプロパティとで構成されます。図39-2は、共有のエンドポイント構成プロパティと転送プロバイダ固有の構成プロパティの関係を示しています。詳細は、「トランスポート・エンドポイントのプロパティの概要」を参照してください。
カスタム・トランスポート・プロバイダの実行時部分は、メッセージを受信し、これをService Busランタイムに配信します。また、Service Busランタイムから外部サービスにアウトバウンド・メッセージを配信します。
実行時フレームワークでは、トランスポート・プロバイダは、トランスポート・マネージャを呼び出してインバウンド・メッセージを受信したことを認識します。トランスポート・メッセージ・コンテキストにはインバウンド・メッセージのヘッダーおよび本文が含まれています。アウトバウンド・メッセージの場合、TransportSendListener
およびTransportSender
があります。トランスポート・プロバイダは、メッセージからヘッダーおよび本文を取得します。
図39-1に、トランスポート・プロバイダの実行時部分の構造を説明したUMLダイアグラムを示します。
トランスポートSDKを使用して新しいトランスポート・プロバイダを開発する前に、メッセージ・エンドポイントのトランザクション・モデルを検討することが重要です。この項では、Service Busで使用されるトランザクション・モデルおよびそのモデルがトランスポートSDKにどのように関係するかを説明します。
トランスポート・エンドポイントは、JMSプロキシ・サービスなどのService Busリソースであり、メッセージの送信元または送信先となります。Service Busでは、トランスポート・エンドポイントはプロトコル固有のトランスポート・プロバイダによって管理されます。トランスポート・プロバイダは、トランスポート・エンドポイントのライフ・サイクルおよび実行時動作を管理するプラグイン・オブジェクトです。
Service Busのトランザクション・モデルを理解するには、サービス・トランスポート・エンドポイントのプロパティを確認しておくと役に立ちます。
エンドポイントはトランザクション対応の場合と非対応の場合があります。トランザクション対応のエンドポイントは、メッセージを処理する際に、グローバル・トランザクションのコンテキスト内で開始または追加できます。次の例では、トランザクションのプロパティがエンドポイントによってどのように異なるかを示します。
XA接続ファクトリを使用するJMSプロキシ・サービスはトランザクション対応のエンドポイントです。メッセージを受信すると、コンテナは、トランザクションのコンテキスト内でメッセージが処理されるように、トランザクションが開始されたことを確認します。
Tuxedoプロキシ・サービスは、トランザクション対応でない場合があります。Tuxedoプロキシ・サービスは、メッセージを受信する前にTuxedoクライアント・アプリケーションによってトランザクションが開始された場合にのみトランザクション対応になります。
HTTPクライアントによって呼び出されるHTTPプロキシ・サービスには通常はトランザクションが関連付けられませんが、トランザクションを開始して、そのトランザクションのコンテキストでメッセージ・フローを実行するというオプションをHTTPプロキシ構成で設定できます。
任意のエンドポイントで、次のメッセージ・パターンのいずれかを使用できます。
一方向: レスポンスを受け取りません。一方向のエンドポイントの例としては、レスポンスを受け取らないJMSプロキシ・サービスがあります。
同期: リクエストまたはレスポンスを意味します。この場合、レスポンス・メッセージとリクエスト・メッセージは暗黙的にペアになります。これは、リクエストが出された時点からレスポンスを受け取るまでの間にトランスポート・チャネルで他のトラフィックが発生し得ないためです。ほとんどの場合、同期メッセージは、アウトバウンド・リクエストの呼出しのブロックを意味します。EJBエンドポイントは同期です。HTTPエンドポイントも同期です(レスポンスを受信するまで新しいリクエストは送信できません)。
非同期: リクエストおよびレスポンスを意味します。レスポンスは、JMSトランスポートおよびJMSCorrelationID
メッセージ・プロパティによる相関関係などの、トランスポート固有のメカニズムによって要求と関連付けられます。たとえば、リクエストおよびレスポンスを持つJMSビジネス・サービス・エンドポイントは非同期です。
すべてのService Busプロキシ・サービスはトランザクション伝播をサポートします。すなわち、トランザクションが存在していない場合に開始できます。また、アウトバウンド・ビジネス・サービスが非同期の場合でも、オプションとして、レスポンスがそのトランザクションのコンテキストで発生するように保証できます。つまり、非同期パターンを実質的に同期パターンに変換します。アウトバウンド・ビジネス・サービスでは、既存トランザクションの中断など、その他のトランザクション・サポートも提供されます。
同期トランザクション対応トランスポートでは、次の例がサポートされます。
レスポンス・パイプラインの処理が受信トランザクションに含まれるのは、インバウンド・トランスポートが同期トランザクションをサポートする場合、またはトランザクションをレスポンスに伝播するようにプロキシ・サービスを構成する場合です。Service Busは、インバウンド・トランスポートが任意のアウトバウンド・トランスポートとペアになっている場合にこの使用例をサポートします。ただし、次のパラグラフで説明するケースは例外です。
インバウンド・トランスポートが同期トランザクションでアウトバウンド・トランスポートが非同期トランザクションの場合、デッドロック状況が発生します。デッドロックが発生する原因は、トランザクションがコミットされるまではアウトバウンド・リクエストがビジネス・サービスで受信できないにもかかわらず、トランザクションが外部で開始され、Service Busがレスポンスを受け取って制御が戻るまでコミットされないためです。トランスポート・マネージャはこの状況を認識し、ランタイム・エラーをスローしてデッドロックを回避します。たとえば、Tuxedoプロキシ・サービスなどの同期トランザクションのインバウンド・エンドポイントを使用していて、JMSビジネス・サービスなどのようにアウトバウンド・エンドポイントが非同期トランザクションである場合、レスポンスを受信するまでアウトバウンド・リクエストはトランザクションをコミットしません。外部エンティティがリクエストを受け取り、処理するまでは、レスポンスを受信できません。
また、この場合、レスポンス・パイプラインで実行されるパブリッシュ・アクションは、トランザクションの一部として行われます。これはリクエスト・パイプラインで実行されるパブリッシュ・アクションがトランザクションの一部として行われるのと同様です。
注意:
複数のアクションが(リクエスト・パイプラインまたはレスポンス・パイプラインの)トランザクションに参加できます。これには、パブリッシュ・アクション、サービス・コールアウト・アクション、およびレポート・アクションが含まれます。
たとえば、インバウンドTuxedoトランスポートが同期トランザクションの場合、リクエスト・パイプラインおよびレスポンス・パイプラインが完了した場合のみコミットできます。この場合、トランスポート・マネージャは、トランザクション・コンテキストをインバウンド・スレッドからアウトバウンド・スレッドに転送します。レスポンス・スレッドが終了すると、トランザクション・コントロールおよび結果が呼出しクライアントに返されます。
サービス・コールアウト・パイプライン・アクションを使用すると、パイプラインから別のサービスへのコールアウトを行うことができます。同期トランザクション対応のトランスポートに対しサービス・コールアウト・アクションが実行された場合、「必ず1回」および「ベスト・エフォート」のサービス品質がサポートされます。「必ず1回」では、アウトバウンド・メッセージの送信が開始されるまでは終了エラーが発生しないことを前提として、メッセージがインバウンドからアウトバウンドに1回だけ配信されます「ベスト・エフォート」では、それぞれの送信で独自のトランザクション・コンテキストが定義されます(トランザクション対応のトランスポート方式の場合)。「ベスト・エフォート」が指定されている場合、メッセージングの機能に信頼性はなく、重複するメッセージは除去されませんが、パフォーマンスが最適化されます。詳細は、「TransportOptionsの操作」を参照してください。
同期トランザクション対応のトランスポートへのコールアウトは必要に応じて既存のトランザクションの一部になります。たとえば、グローバル・トランザクション中にリクエスト・パイプラインを実行しいても、サービス・コールアウトはトランザクションへの参加を許可されます。たとえば、EJBサービスへのコールアウトがある場合、必要に応じてサービス品質の値を「必ず1回」に設定することで、サービスがそのトランザクションに参加できます。
サービス・コールアウトの詳細は、「コンソールでのサービス・コールアウト・アクションの追加」を参照してください。
次の条件に当てはまる場合、トランスポート・プロバイダを呼び出してアウトバウンド・リクエストを送信する前に、トランスポート・フレームワークがトランザクションを中断します。
アウトバウンド・サービス・エンドポイントがトランザクション対応です。
進行中のグローバルXAトランザクションがあります。
サービス品質が「ベスト・エフォート」に設定されている場合。
「送信」操作が完了すると、中断されていたトランザクションが再開されます。
トランスポートSDKにより、ユーザーおよびサード・パーティは、Service Busに新しいトランスポートをプラグインできます。Service Busのセキュリティ・モデル内では、トランスポート・プロバイダは信頼性のあるコードと見なされます。セキュリティ・ホールによる潜在的なセキュリティ上の脅威を避けるため、トランスポート・プロバイダの実装は慎重に設計することが重要です。このドキュメントには、安全なトランスポート・プロバイダを開発する方法についての具体的なガイドラインは含まれていませんが、この項では、あるトランスポートSDKのセキュリティ目標について説明します。
トランスポート・プロバイダは、インバウンド認証のメカニズムがそのトランスポートに適しているものはすべて自由に実装できます。例:HTTPトランスポートは次の認証方式をサポートします。
HTTP基本認証
HTTPヘッダーで送信されるカスタム認証トークン
HTTPSトランスポート・プロバイダは、上記の認証方法の他に、SSLクライアント認証をサポートします。HTTPトランスポート・プロバイダおよびHTTPSトランスポート・プロバイダのどちらも、匿名のクライアント・リクエストをサポートします。
トランスポート・プロバイダは、適用可能な任意のトランスポート・レベル認証スキームを実装します。トランスポート・プロバイダがクライアントを認証する場合、weblogic.security.Security.runAs(subject)
のスコープ内でTransportManager.receiveMessage()
を呼び出し、Service BusがクライアントのSubjectオブジェクトを使用できるようにする必要があります。このメソッドの詳細は、「Oracle Service Bus Java APIリファレンス」を参照してください。
注意:
JavaのSubjectクラスの詳細は、http://docs.oracle.com/javase/7/docs/api/javax/security/auth/Subject.html
を参照してください。
プロキシ・サービスは、次のように、このSubjectを使用します。
プロキシ・サービスへのアクセス制御中
メッセージ・コンテキスト変数$inbound/ctx:security/ctx:transportClient/*
へのデータの入力
IDの伝播および資格証明マッピングの入力として(メッセージ・レベルのクライアント認証もある場合を除く)
トランスポート・プロバイダが認証をサポートしない、または匿名のリクエストをサポートする場合、リクエストをディスパッチする前に匿名サブジェクトがスレッド上にあることを確認する必要があります。通常、トランスポート・プロバイダは、匿名としてすでに実行しています。そうでない場合、プロバイダは次の呼出しを行う必要があります。
Subject anonymous = SubjectUtils.getAnonymousUser() Security.runAs(anonymous, action)
トランスポート・プロバイダは、インバウンド・クライアント認証の構成に必要な、任意のOracle Service Busコンソール構成ページの提供も行います。トランスポート・プロバイダは、インバウンド認証モデルを明確に記録しておく必要があります。
トランスポート・プロバイダは、アウトバウンド認証スキームがそのトランスポートに適しているものはすべて自由に実装できます。トランスポートSDKには、ユーザー名およびパスワードによるアウトバウンド認証、(双方向) SSLクライアント認証およびJAAS Subject認証を容易に実現するための方法が含まれています。
Service Busのサービス・アカウントを使用して、ユーザー名およびパスワードによるアウトバウンド認証を実装できます。サービス・アカウントは、最上級で最高位のService Busリソースです。Oracle Service BusコンソールまたはJDeveloperでサービス・アカウントを作成して管理します。トランスポート・プロバイダでは、それぞれのトランスポート固有の構成を自由に設計し、サービス・アカウントへの参照を含めることができます。このようにして、トランスポート・プロバイダは、サービス・アカウントによって提供される資格証明管理メカニズムを利用できます。
トランスポート・プロバイダでは、サービス・アカウントの構成の詳細について懸念する必要はありません。サービス・アカウントのタイプは、次の3つです。
静的: 静的なサービス・アカウントは、固定されたユーザー名およびパスワードで構成されます。
マップされている: マップされたサービス・アカウントには、リモート・ユーザーおよびリモート・パスワードのリストがローカル・ユーザーからリモート・ユーザーへのマップとともに含まれます。マップされたサービス・アカウントでは、必要に応じて、任意のリモート・ユーザーに匿名サブジェクトをマップできます。
パススルー: パススルー・サービス・アカウントは、Service Busクライアントのユーザー名およびパスワードがバックエンドに送信される必要があることを示しています。
アウトバウンド・エンドポイントは、サービス・アカウントへの参照を持つことができます。サービス・アカウントへの参照は、トランスポート固有のエンドポイントの構成に格納する必要があります。プロキシ・サービスが、メッセージをこのアウトバウンド・エンドポイントにルーティングする場合、トランスポート・プロバイダは、サービス・アカウントへの参照をCredentialCallback.getUsernamePasswordCredential(ref)
に渡します。Service Busは、サービス・アカウントの構成に応じて、ユーザー名およびパスワードを返します。この方法には、IDの伝播と資格証明マッピングの構成をトランスポート固有の詳細な作業から分離することで、トランスポートSDKを簡素化できるという利点があります。また、この構成の共有も可能になります。複数のエンドポイントが同じサービス・アカウントを参照できます。
注意:
CredentialCallback
オブジェクトは、TransportSender.getCredentialCallback()
を呼び出すことによりトランスポート・プロバイダで使用できるようになります。
CredentialCallback.getUsernamePasswordCredential()
は、weblogic.security.UsernameAndPassword
インスタンスを返します。これは、ユーザー名およびパスワードを取得するためのメソッドを持つ簡単なクラスです。返されるユーザー名およびパスワードは、サービス・アカウントのタイプによって異なります。サービス・アカウントのタイプが静的である場合、固定されたユーザー名およびパスワードが返されます。サービス・アカウントのタイプがマップされている場合、クライアント・サブジェクトを使用してリモートのユーザー名およびパスワードがルックアップされます。サービス・アカウントがパススルーの場合、クライアントのユーザー名およびパスワードが返されます。
注意:
次のいずれかが当てはまる場合、マップされたサービス・アカウントは、CredentialNotFoundException
をスローします。
インバウンド・クライアントのマップが存在しない。
インバウンドのセキュリティ・コンテキストが匿名であり、匿名マップが存在しない。
Service Busは、アウトバウンドSSLクライアント認証をサポートします。この場合、アウトバウンドSSLリクエストを出すプロキシ・サービスを、SSL用のPKIキー・ペアを使用して構成する必要があります。これには、プロキシ・サービス・プロバイダへの参照が含まれますが、このドキュメントでは、詳細については取り上げていません。SSLクライアント認証用のキー・ペアを取得するには、トランスポート・プロバイダがCredentialCallback.getKeyPair()
を呼び出す必要があります。この例として、HTTPSトランスポート・プロバイダがあります。
一部のトランスポートでは、サービスに接続するために資格証明が必要になります。たとえば、FTPサーバーへの認証には、FTPエンドポイントが必要になる場合があります。トランスポート・プロバイダは、静的なサービス・アカウントを利用して、接続を確立するためのユーザー名およびパスワードを取得できます。これらの接続は、特定のクライアント・リクエストのかわりとしての確立されるものではないため、この場合、マップされたサービス・アカウントまたはパススルー・サービス・アカウントは使用できません。トランスポート・プロバイダでこのアプローチを採用する場合は、サービス・アカウントへの参照を使用してエンドポイントを構成する必要があります。実行時に、トランスポート・プロバイダは、TransportManagerHelper.getUsernamePassword()
を呼び出して、静的なサービス・アカウントへの参照を渡す必要があります。
Service Busは、すべてのインバウンド・リクエストについてプロキシ・サービスへのアクセス制御を実施します。トランスポート・プロバイダでは、アクセス制御を実施するための、またはアクセス制御ポリシーを管理するためのインタフェースを提供する必要はありません。
アクセス制御ポリシーはほとんどの使用例を対象としていますが、トランスポート・プロバイダに固有の理由で、Service Busによって行われるアクセス制御チェックの他に独自のアクセス制御メカニズムが必要な場合は、それらを実装できます。この場合は、Oracle販売代理店にお問い合せください。通常は、トランスポート・プロバイダで、Service Busを使用してアクセス制御を処理する方法をお薦めします。
アクセスが拒否されると、TransportManager.receiveMessage()
は、TransportException
内にラップされているAccessNotAllowedException
をスローします。トランスポート・プロバイダは、TransportException
の根本原因を確認します。根本原因がAccessNotAllowedException
である場合、トランスポート・プロバイダは、特別なエラー処理を行う場合があります。たとえば、この場合、HTTP/Sトランスポート・プロバイダはHTTP 403 (forbidden)エラー・コードを返します。
注意:
Service Busは、アクセス制御の判断を行うために、認可プロバイダがリクエスト・ヘッダーを使用できるようにします。
「アウトバウンド・リクエストの認証」で説明したように、Service Busには、3つのタイプのサービス・アカウントが用意されています。トランスポート・プロバイダは、サービス・アカウントを利用して、アウトバウンド認証のためのユーザー名およびパスワードにアクセスできます。サービス・アカウントは、Service Busのトランスポート・プロバイダに対し、すべてのIDの伝播および資格証明マッピングの詳細を非表示にしています。
図39-4に、1つのインバウンド・メッセージを処理する仮想のトランスポート・エンドポイントを表す、Service Busのスレッド・モデルを示します。
サーブレットなどのフロント・エンド・アーティファクトが、インバウンド・メッセージを取得します。リクエストを、アウトバウンド・エンドポイントにルーティングし、非同期的に送信できます。この時点で、スレッドは解放されます。その後しばらくして、コールバックを使用して、レスポンスがService Busに送り返されます。レスポンスが受信され、パッケージ化されて、Service Busパイプラインに渡されます。その後、パイプラインが、レスポンスをクライアントに送信する準備ができていることをインバウンド・エンドポイントに通知します。スレッドが使用できないのは必要な間のみであるため、この処理はスケーラブルです。
インバウンド・リクエストの処理中、同じスレッドで次のアクションが実行されます。
トランスポート・エンドポイントのフロント・エンド・アーティファクトがインバウンド・メッセージを受信します。このフロント・エンド・アーティファクトは、HTTPサーブレットやJMSメッセージ駆動型Beanのインスタンスなどです。
トランスポート・エンドポイントの実装により、メッセージはTransportMessageContext
オブジェクトにパッケージ化され、Service Busランタイムに渡されます。TransportMessageContext
インタフェースの詳細は、「リクエストおよびレスポンス・メッセージのメタデータおよびヘッダーの表現」を参照してください。
パイプラインは、構成されているリクエスト・パイプライン・アクションを実行します。
パイプラインでインバウンド・メッセージを処理すると同時に、同じ(リクエスト)スレッドで、Service Busランタイムは、アウトバウンド・メッセージを外部サービスに配信するよう、登録されているアウトバウンド・トランスポート・エンドポイント(このエンドポイントは、同じプロバイダで管理されている場合と管理されていない場合がある)に要求します。
その後しばらくして、外部サービスは、レスポンス・メッセージを配信するよう、アウトバウンド・エンドポイントに非同期的に要求します。アウトバウンド・エンドポイントは、トランスポート固有のコールバック・オブジェクトを使用して、事前に登録されている必要があります。
注意:
この時点で、最初のリクエスト・スレッドは解放され、別のリクエストが使用できるようにOracle WebLogic Serverのスレッド・プールに戻されます。
アウトバウンド・レスポンス・メッセージの処理中、同じスレッドで次のアクションが実行されます。
レスポンス・メッセージは、TransportMessageContext
オブジェクトにパッケージ化され、レスポンス処理のためにService Busランタイムに戻されます。この処理は、リクエスト・スレッドとは別のスレッドで実行されます。新しいスレッドは、レスポンス・スレッドと呼ばれます。
レスポンス・メッセージが処理された後、Service Busランタイムは、レスポンスをコール元に送り返すことを通知するよう、InboundTransportMessageContext
オブジェクトに要求します。InboundTransportMessageContext
インタフェースの詳細は、「リクエストおよびレスポンス・メッセージのメタデータおよびヘッダーの表現」を参照してください。
トランスポート・プロバイダが、非同期の(非ブロッキング)アウトバウンド・コールをネイティブに実装していない場合は、インバウンド・リクエスト・メッセージを受信したスレッドとは別のスレッドで、Service Busランタイムにレスポンスを返す必要があります。これを行うためにトランスポート・プロバイダは、リクエスト・スレッドでブロッキング方法によりコールを実行し、トランスポートSDKのヘルパー・メソッドを使用して、Service Busランタイムにレスポンスを返します。
たとえば、EJBトランスポート・プロバイダは、非同期(非ブロッキング)のアウトバウンド呼出しを実装していません。基底のAPIはブロッキングAPIです。これに対処するには、プロバイダがブロッキング呼出しを行い、その後で、TransportManagerHelper.schedule()
を使用して処理に対するレスポンスをスケジュールします。EJBトランスポート・プロバイダの詳細は、「EJBトランスポートの使用」を参照してください。
トランスポート・サブシステムは、意図的に、Service Busと非同期的に対話するようになっています。これは、非同期での動作が、同期での動作よりもスケーラブルであるため望ましいからです。非同期の対話用に1つ、および同期の対話用に1つと、2つの別々のAPIを作成するのではなく、Service Busランタイムでは非同期の対話が必要です。この処理は、ブロッキング呼出しやコールバックでのレスポンスをポストするなどの方法により、トランスポート開発者が行う必要があります。いずれにせよ、レスポンスは、リクエストとは別のスレッドで実行する必要があります。
図39-4に示すスレッド・ダイアグラムは、ルーティングに焦点を当てたものです。トランスポート・サブシステムは、リクエストまたはレスポンス・パイプラインの処理中に実行されるService Busのパブリッシュ・アクションとサービス・コールアウト・アクションに対して同じように動作します。これらのアクションは、トランスポート・サブシステムの範囲外およびService Busパイプラインの範囲内で実行されます。そのため、パブリッシュおよびサービス・コールアウトのスレッディング動作とトランスポート・プロバイダのスレッディング動作には違いがいくつかあります。
ただし、次の場合に注意してください。
サービス・コールアウト: 非同期的にレスポンスを受信するまで、パイプライン・プロセッサがスレッドをブロックします。その後、ブロックされたスレッドはパイプラインの実行を再開します。この目的は、後でパイプライン・アクションで使用できる変数をバインドし、ビジネス・ロジックを実行することです。そのため、レスポンスが返される前にビジネス・ロジックが実行されるように、これらのアクションがブロックする必要があります。
パブリッシュ: 非同期的に応答を受信するまで、パイプライン・プロセッサがスレッドをブロックしない場合もあります。その後、このスレッドは、残りのリクエストまたはレスポンス・パイプラインの処理の実行を続行します。
ヒント:
サービス・コールアウト・アクションにより、ユーザーは、Service Busにすでに登録されているプロキシまたはビジネス・サービスに対し、同期(ブロッキング)呼出しを構成できます。メッセージのターゲット・サービスを特定し、そのサービスへメッセージをパッケージ化し、送信する方法を構成するには、パブリッシュ・アクションを使用してください。サービス・コールアウト・アクションおよびパブリッシュ・アクションの詳細は、「コンソールでのサービス・コールアウト・アクションの追加」および「コンソールでのパブリック・アクションの追加」を参照してください。
トランスポート・プロバイダには、メッセージ・コンテンツの独自のネイティブ表現があります。たとえば、HTTPトランスポートはjava.io.InputStream
を使用し、JMSは、様々なタイプのMessageオブジェクトがあります。また、Tuxedoにはバッファがあり、Oracle WebLogic Server WebサービスのスタックはSAAJを使用します。ただし、プロキシ・サービスの実行時は、コンテンツのネイティブ表現は、メッセージ・コンテキストです。Service Busは、InputStreamからメッセージ・コンテキストへのまたはその逆などの一部の一般的な変換シナリオをサポートしますが、トランスポートでの表現とメッセージ・コンテキストの間の変換は、最終的にはトランスポート・プロバイダが行います。
通常、トランスポートSDKが、トランスポートの2つの異なるコンテンツ表現を直接変換することはありません。ただし、2つのトランスポートが互換性のある表現を使用していて、コンテンツを再エンコードする必要がない場合は、SDKによって、(たとえば、インバウンド・ファイル・トランスポートからアウトバウンドHTTPトランスポートにFileInputStreamを渡すことにより)ソース・コンテンツを直接パススルーできます。ただし、ソース・コンテンツでなんらかの処理が必要な場合は、最初にソース・コンテンツをメッセージ・コンテキストに復号化し、その後で標準のメカニズムを使用して送信トランスポート用のコンテンツを生成した方が適切です。
コンテンツは、Source
インタフェースのインスタンスとして表されます。TransportSender
やTransportMessageContext
などのメッセージ・コンテンツを処理するトランスポートSDKインタフェースは、すべてメッセージ・ペイロードを渡す際に、Source
インタフェースを使用します。Source
における要件はごくわずかです。Source
は、基本となるSource
インタフェースで定義されている2つのメソッドを使用した、バイト単位のストリームへのプルベースおよびプッシュベースの変換をサポートする必要があります。Source
は、シリアライゼーション中に、TransformOptions
パラメータで指定されている、文字セット・エンコーディングなどの様々なトランスフォーメーションのオプションを考慮しない場合があります。
すべてのSource
オブジェクトは基底のシリアライゼーション・インタフェースを実装する必要がありますが、Source
オブジェクトのコンテンツの基礎となる表現は実装固有のものです。そのため、InputStream、JMS Messageオブジェクト、Stringまたは特定のトランスポートに最も適している表現に基づいたSource
オブジェクトを使用できます。通常、Source
を実装することで、基本的なシリアライゼーション・メソッドのみでなく、基底のコンテンツに直接アクセスできるようになります。たとえば、内部でString
オブジェクトを使用してそのコンテンツを格納するStringSource
は、内部データにアクセスするためのgetString()
メソッドを提供します。その後、Source
の最終的なコンシューマは、これらのソース固有のAPIを呼び出して、基底のコンテンツを抽出し、シリアライゼーションのオーバーヘッドを回避できます。
また、Transformer
オブジェクトを使用して、Sourceを他のタイプのSourceに変換することもできます。トランスポート・プロバイダなどのSource
コンシューマが、認識できないSource
インスタンスを受け取った場合は、多くの場合、認識できるSource
インスタンスに変換できます。その後、ソース固有のAPIを使用して、認識できるSource
から基底のコンテンツを抽出できます。ただし、トランスポート・プロバイダは多くの場合、単に基本的なシリアライゼーション・メソッドを使用してコンテンツをシリアライズし送信します。詳細は、「SourceおよびTransformerクラスとインタフェース」を参照してください。
Sourceは、トランスポート・レイヤーとバインディング・レイヤーの間の一般的なコンテンツ表現です。バインディング・レイヤーは、トランスポート・レイヤーで使用されるSource
表現と実行時にパイプラインで使用されるメッセージ・コンテキストとの間でコンテンツを変換するエンティティです。変換がどのように行われるかは、サービスのタイプ(そのバインディングのタイプ)と添付の有無によって異なります。厳密にはトランスポートSDKの役割ではありませんが、独自のSource
オブジェクトを定義しているすべてのトランスポート・プロバイダは、この変換プロセスを認識している必要があります。
添付が存在しない場合、受信したSource
は単にコアとなるメッセージ・コンテンツを示します。受信したSource
を特定のタイプのSource
に変換し、その後で基底のコンテンツを抽出することでMessageContext
が初期化されます。たとえば、XMLベースのサービスの場合、受信したSource
はXmlObjectSource
に変換されます。その後、XmlObjectSource
からXmlObject
が抽出され、$body
コンテキスト変数内でペイロードとして使用されます。同様に、SOAPサービスはXmlObjectSource
に変換されます。ただし、<SOAP:Header>
および<SOAP:Body>
要素を抽出して$header
および$body
コンテキスト変数を初期化できるようにするために、抽出されたXmlObject
がSOAP Envelopeである必要がある点が異なります。
定義された一連のサービス・タイプで使用される標準的なSource
のタイプを次に示します。
SOAP: XmlObjectSource
XML: XmlObjectSource
TEXT: StringSource
MFL: MFLSource
バイナリ・サービスの場合、Source
の変換は行われません。かわりに、Source
は、SourceRepository
に登録され、結果の<binary-content/>
XMLは、$body
内でペイロードとして使用されます。
添付が存在する場合、Source
は最初にMessageContextSource
に変換されます。MessageContextSource
から、2つのタイプのSource
オブジェクトが取得されます。1つが添付で、もう1つがコア・メッセージです。コア・メッセージのSource
は、前述のとおり処理されます。添付を表すSource
は、AttachmentsSource
に変換されます。AttachmentsSource
から、XMLが取得され、$attachments
コンテキスト変数および任意のバイナリの添付コンテンツを表す登録済のSourceを含むSourceRepository
の初期化に使用されます。図39-5に、このプロセス全体を示します。
トランスポート・レイヤーに渡すためにMessageContext
内のデータからSource
を作成する場合にも、同様の変換が実行されます。コア・メッセージは、サービスのタイプの標準的なSource
に変換できるSource
インスタンスで表現されています。ほとんどの場合、Source
は、すでに標準的なSource
のインスタンスになっていますが、必ずしもそうであるとは限りません。添付が存在する場合、トランスポート・レイヤーに渡されるSource
は、MessageContextSource
インスタンスに変換できるSourceになります。トランスポート・プロバイダが、事前定義されたトランスポート・ヘッダーとしてContent-Type
をサポートする場合、一般的に、配信されたSource
はMessageContextSource
のインスタンスになります。それ以外の場合、配信されたSource
はMimeSource
のインスタンスであることが多いですが、これもMessageContextSource
に変換できます。
この違いの理由は、トランスポート・ヘッダーとしてContent-Type
をネイティブにサポートするトランスポートでは、ペイロードではなく、トランスポート・ヘッダーにトップ・レベルのMIMEヘッダーが含まれている必要があるためです。この例としては、HTTPおよび電子メールがあります。Content-Type
をネイティブにサポートしないトランスポートでは、これらのトップ・レベルのMIMEヘッダーがペイロードに含まれている必要があります。Content-Type
ヘッダーは、複数のMIMEパッケージのデコードに不可欠であるためです。
表39-1はソースと、そのソースを組込みのTransformerによって変換できるソース・タイプの一覧を示しています。たとえば、StringSource
からXmlObjectSource
への変換を処理する組込みのトランスフォーメーションはありますが、StringSource
をMFLSource
に変換できるトランスフォーメーションはありません。通常、これらのトランスフォーメーションは両方のSource
のタイプで使用される内部データ表現の情報を利用します。
表39-1 組込みのトランスフォーメーション
パブリック・ソース | 変換後のソース・タイプ |
---|---|
ソース |
|
StreamSource |
StreamSource |
ByteArraySource |
ByteArraySource |
StringSource |
|
XmlObjectSource |
|
DOMSource |
|
MFLSource |
|
MimeSource |
|
SAAJSource |
|
MessageContextSource |
|
これらの一般的なトランスフォーメーションは元のSource
タイプの情報を使用せずに行われますが、かわりに、すべてのSourceが実装している基本的なシリアライゼーション・メソッドのgetInputStream()
およびwriteTo()
を利用します。したがって、XmlObjectSource
からByteArraySource
への変換は最終的には可能ですが、XmlObjectSource
の内部情報を使用して行われることはありません。
注意:
トランスポートで実装されているカスタム・ソースの多くは、(基底のデータが構造化されていないバイトの収集である場合は特に)これらの一般的なトランスフォーメーションで処理できます。たとえば、ファイル・トランスポートは、ディスク上のファイルから直接コンテンツを取り出すカスタム・ソースを使用します。ただし、データは構造のない単なるバイトのセットであるため、XmlObjectSource
などへのカスタム・トランスフォーメーションを実行する必要はありません。一般的なトランスフォーメーションで、すべてのSourceが実装している基本的なシリアライゼーション・メソッドのみを使用して、このカスタムFileSource
を処理できます。
詳細は、「SourceおよびTransformerクラスとインタフェース」を参照してください。