この記事は、Birgit DuerrsteinによるdeveloperWorksの記事「Dynamic Service Binding with WebSphere Process Choreographer」で解説されている手法に基づいています。今回の記事では、Webサービス・バインディングの他のプロパティーを動的に変更する方法を学びます。また、この手法を利用したBPELプロセスのサンプル実装も示します。(ダウンロードするには、右のナビゲーションの「Sample code」をクリックしてください。)
BPEL(Business Process Execution Language)は、ビジネス・プロセスの動作を指定するXMLベースの言語です。BPELは、IBM、BEA Systems, Inc.、およびMicrosoft® の開発者によって開発され、2003年4月にOASIS(Organization for the Advancement of Structured Information Standards)標準委員会に提出されました。BPELはビジネス・プロセスをWebサービス間の対話として記述し、プロセスをWebサービスとして表現します。WebSphere Business Integration Server Foundation V5.1(Server Foundation)には、この言語の実装が含まれています。WebSphere Application Developer Integration Edition(Application Developer)は、BPELプロセス用のグラフィカル・エディターを含み、ビジネス・プロセスからエンタープライズ・アーカイブ(EAR)ファイルを作成します。
BPELプロセスは、処理中に呼び出す抽象Webサービスだけを記述します。Application DeveloperがBPELソース・ファイルからインストール可能なEARファイルを作成するときに、プロセス開発者は実際のバインディングと具体的なサービス・エンドポイントを指定しなければなりません。ただし、プロセス開発時点では、抽象Webサービスを実装するサービス・エンドポイントが不明な場合もあります。ビジネス・プロセスを処理する段階になって初めて、実際のサービス・エンドポイント・アドレスがわかるという場合があります。
WebSphere Business Process Choreographerでは常に、プロセスからWebサービスを呼び出すときに具体的なポートとエンドポイントを指定する必要があります。したがって、プロセス開発時点で、どのサービスを呼び出すかわからない場合には、後で呼び出すサービスに一致するダミー・サービスを作成する必要があります。このダミー・サービスを使用して、BPELフロー内にパートナー・リンクを作成します。
パートナー・リンクによって参照されるダミー・サービスは、次の項目について、後で呼び出すサービスと同じものを使用しなければなりません。
- バインディング・タイプ(doc/literal、rpc/encodedなど)
- メソッド・シグネチャ(メソッド名、パラメーター、パラメーター・タイプ)
- ポート・タイプ
Webサービス・バインディングの次のようなプロパティーを実行時に動的に変更することが可能です。
- エンドポイントURL(ホスト名、ポート、パス)
- ターゲット・サービス名
- ポート名
注:最後の2つのプロパティーのいずれかを変更する場合は、両方の値を同時にリセットする必要があります。
パートナー・リンク設定とサービス・エンドポイント変数を作成する
Birgit Duerrsteinの記事のガイドラインに従って、パートナー・リンクのプロパティーを正しく設定し、サービス・エンドポイント情報を保持するBPEL変数を作成してください。
注:この手法を機能させるには、適切なパートナー・リンクのパートナー・リンク属性resolution scopeをcomputedに設定する必要があります。
リスト1のサンプルのJavaTM コードの断片は、動的サービス・バインディングで使用するためにEndpointReferenceTypeクラスのインスタンスを初期化する方法を示しています。
リスト1. ポート名とターゲット・サービスの変更
/** Sample code to create and populate an EndpointReferenceType, and apply it
* to a partner link.
* NB: A porttype describes the interface of a service.
* (operations and input/output messages). It CANNOT be changed.
*/
// -- create EndpointReferenceType
EndpointReferenceType epr = new EndpointReferenceType();
// -- set service name and port name
ServiceNameType snt = new ServiceNameType();
// Value "http://service.test.com" is obtained from:
// <wsdl:definitions targetNamespace="http://service.test.com"
// Value "ServiceAService" is obtained from:
// <wsdl:service name="ServiceAService">
snt.setValue(new QName("http://service.test.com", "ServiceAService"));
// Value "ServiceA" is obtained from
// <wsdl:port binding="intf:ServiceASoapBinding" name="ServiceA">
snt.setPortName(new NCName("ServiceA"));
epr.setServiceName(snt);
// -- set address
AttributedURI addr = new AttributedURI();
try {
// Value "http://localhost:9080/EPRserviceA/services/ServiceA" is obtained from:
// <wsdlsoap:address location="http://localhost:9080/EPRserviceA/services/ServiceA"/>
addr.setValue(new URI("http://localhost:9080/EPRserviceA/services/ServiceA"));
}
catch(MalformedURIException e) {
System.out.println("exception= " + e);
}
epr.setAddress(addr);
// -- set the partnerlink
setPartnerLink("Service", epr);
|
EndpointReferenceTypeクラスをポピュレートするために必要な値の中には、すぐにはわからないものもあるので、サンプルのWSDL(Web Services Description Language)ファイルをリスト2に示します。上記のJavaコード(リスト1)では、リスト2のWSDLから必要な値を抽出すべき箇所をコメントで示しています。(ServiceAは、パートナー・リンクのオリジナルのサービスWSDLと同じポート・タイプ定義でなければなりません。)
リスト2. サービスServiceAのサンプルのWSDLファイル
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://service.test.com"
xmlns:impl="http://service.test.com" xmlns:intf="http://service.test.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="http://service.test.com"
xmlns="http://www.w3.org/2001/XMLSchema" xmlns:impl="http://service.test.com"
xmlns:intf="http://service.test.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<element name="doit">
<complexType>
<sequence>
<element name="arg" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="doitResponse">
<complexType>
<sequence>
<element name="doitReturn" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="doitRequest">
<wsdl:part element="intf:doit" name="parameters"/>
</wsdl:message>
<wsdl:message name="doitResponse">
<wsdl:part element="intf:doitResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="Service">
<wsdl:operation name="doit">
<wsdl:input message="intf:doitRequest" name="doitRequest"/>
<wsdl:output message="intf:doitResponse" name="doitResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ServiceASoapBinding" type="impl:Service">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="doit">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="doitRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="doitResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ServiceAService">
<wsdl:port binding="intf:ServiceASoapBinding" name="ServiceA">
<wsdlsoap:address location="http://localhost:9080/EPRserviceA/services/ServiceA"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
サンプルの最後の行のsetPartnerLinkメソッドを使用したくない場合は、Birgit Duerrsteinの記事のガイドラインに従って、サービス・エンドポイントを上書きしてください。
2つのプロジェクト交換ファイルが用意されています。この2つのファイルで、サンプルBPELのフロー全体を表しています。
最初のzipファイルをダウンロードしてください(「Sample code」アイコンをクリックしてください)。これにはサービス・プロジェクトEPRsampleが含まれていて、その中にEPRprocess BPELプロセスが含まれています。
次に、2番目のzipファイルをダウンロードしてください。これには3つのWebサービス・プロジェクトが含まれています。
- EPRservice: EPRprocess BPELプロセスが使用するオリジナル・サービス
- EPRserviceA、EPRserviceB: ポート・タイプはEPRserviceと同じですが、ポート名とサービス名が異なる2つの代替サービス
両方のプロジェクト交換ZIPファイルをApplication Developerワークスペースにインポートしてください。そのためには、それぞれのファイルについて次の手順を実行してください。
- 「File」>「Import」をクリックします。
- 「Project Interchange」を選択して、「Next」をクリックします。
- インポートしたいZIPファイルを選択します。
- 「Select All」をクリックして、ZIPファイル内のすべてのプロジェクトをインポートします。
- 「Finish」をクリックします。
サンプル・コードを実行するには、これらすべてのプロジェクトをServer FoundationサーバーまたはApplication Developer Integrated Test Environmentにデプロイする必要があります。
下記の図1aは、Business Process Choreographer Explorerでビジネス・プロセスのインスタンスを起動して、デフォルトのサービスを呼び出す方法を示しています。図1bは、Business Process Choreographer Explorerでデフォルト・サービスを呼び出したときの出力を示しています。図1cは、デフォルト・サービスのSystemOut.logファイルの出力を示しています。
図1a. デフォルト・サービスを呼び出すためのプロセス入力
図1b. デフォルト・サービスを呼び出したときのプロセス出力
図1c. デフォルト・サービスを呼び出したときのSystemOut.log
[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:31:18:112 CET] dc9c077 SystemOut O service=
[2/27/06 15:31:18:112 CET] dc9c077 SystemOut O nothing to do -> invoke deployed service
[2/27/06 15:31:18:112 CET] dc9c077 SystemOut O +++ snippet in finish
[2/27/06 15:31:21:346 CET] 4bb58071 SystemOut O *** ------------------------------------
[2/27/06 15:31:21:346 CET] 4bb58071 SystemOut O *** Service doit() arg= anystring
[2/27/06 15:31:21:346 CET] 4bb58071 SystemOut O *** ------------------------------------
[2/27/06 15:31:21:507 CET] dc9c077 SystemOut O +++ snippet out start
[2/27/06 15:31:21:507 CET] dc9c077 SystemOut O copy service result
[2/27/06 15:31:21:517 CET] dc9c077 SystemOut O +++ snippet out finish
|
図2aには、ServiceAサービスを呼び出すための入力が示されています。図2bには、ServiceAサービスのプロセス出力が示されています。図2cは、ServiceAサービスのSystemOut.logを示しています。
図2a. ServiceAサービスを呼び出すためのプロセス入力
図2b. ServiceAサービスを呼び出したときのプロセス出力
図2c. ServiceAサービスを呼び出したときのSystemOut.log
[[2/27/06 15:37:19:962 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:37:19:962 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:37:19:982 CET] dc9c077 SystemOut O service= ServiceA
[2/27/06 15:37:19:992 CET] dc9c077 SystemOut O ServiceA EPR=
--------------------------------------------------------------------------------
EndpointReferenceType
address = 'http://localhost:9080/EPRserviceA/services/ServiceA'
portType = 'null'
serviceName = '{http://service.test.com}ServiceAService'
--------------------------------------------------------------------------------
[2/27/06 15:37:19:992 CET] dc9c077 SystemOut O +++ snippet in finish
[2/27/06 15:37:21:424 CET] 4bb58071 SystemOut O ***------------------------------------
[2/27/06 15:37:21:424 CET] 4bb58071 SystemOut O *** ServiceA doit() arg= anystring
[2/27/06 15:37:21:424 CET] 4bb58071 SystemOut O ***------------------------------------
[2/27/06 15:37:21:464 CET] dc9c077 SystemOut O +++ snippet out start
[2/27/06 15:37:21:464 CET] dc9c077 SystemOut O copy service result
[2/27/06 15:37:21:464 CET] dc9c077 SystemOut O +++ snippet out finish
|
図3aには、ServiceBサービスを呼び出すための入力が示されています。図3bには、ServiceBサービスを呼び出したときのプロセス出力が示されています。図3cには、SystemOut.logが示されています。
図3a. ServiceBサービスを呼び出すためのプロセス入力
図3b. ServiceBサービスを呼び出したときのプロセス出力
図3c. ServiceBサービスを呼び出したときのSystemOut.log
[[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:43:43:143 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:43:43:143 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:43:43:153 CET] dc9c077 SystemOut O service= ServiceB
[2/27/06 15:43:43:163 CET] dc9c077 SystemOut O ServiceB EPR=
--------------------------------------------------------------------------------
EndpointReferenceType
address = 'http://localhost:9080/EPRserviceB/services/ServiceB'
portType = 'null'
serviceName = '{http://service.test.com}ServiceBService'
--------------------------------------------------------------------------------
[2/27/06 15:43:43:163 CET] dc9c077 SystemOut O +++ snippet in finish
[2/27/06 15:43:44:144 CET] 4bb58071 SystemOut O *** ------------------------------------
[2/27/06 15:43:44:144 CET] 4bb58071 SystemOut O *** ServiceB doit() arg= anystring
[2/27/06 15:43:44:144 CET] 4bb58071 SystemOut O *** ------------------------------------
[2/27/06 15:43:44:184 CET] dc9c077 SystemOut O +++ snippet out start
[2/27/06 15:43:44:184 CET] dc9c077 SystemOut O copy service result
[2/27/06 15:43:44:184 CET] dc9c077 SystemOut O +++ snippet out finish
|
この記事では、EndpointReferenceTypeクラスによって提供される機能を使用して、BPELプロセスから呼び出されるターゲットWebサービスのエンドポイントURL、ポート名、およびサービス名を実行時に変更します。この機能によって、異なる環境間でのBPELコードの移植性が高まり、BPELコードの保守性と堅牢性が向上し、実行時におけるターゲットWebサービスの再配置が可能になります。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Sample implementation BPEL process | ws-bpelwsadcode1.zip | 30KB | HTTP |
| Sample implementation BPEL process | ws-bpelwsadcode2.zip | 25KB | HTTP |
- IBM Webサイトで、WebSphere Studio Application Developer Integration Edition, V5.11の機能について、さらに学んでください。
- 「Dynamic Service Binding with WebSphere Process Choreographer」(developerWorks、2004年6月)では、IBM WebSphere Business Integration Server FoundationでWebサービスをBPELビジネス・プロセスにバインドする方法と、それらのバインディングを動的に変更する方法が説明されています。

