2006年 9月 09日 土曜日 今回は,前回のエントリで作成したBPELから,前々回のエントリで作成したサービスをWebサービスで呼び出すことにします。
こんなイメージです。
【1. サービスのWebサービス化】
前々回に作成したサービス(BooksDataFacade,FooPriceListFacade,BarPriceListFacade)をWebサービス化します。手順は,前々回にBooksPricingProcessBeanをWebサービス化したときと同様です。Deployして,Webサービスのテスト機能で簡単に動作確認しておくと良いでしょう。
(*) 複数のWebサービスを同じパッケージで作成する場合,異なるクラスであってもWebメソッド名が重複すると上手く動作しないようです。findBooksData, findFooPriceList, findBarPriceListなど,Webメソッドの名前を変えるようにしましょう。
【2. WSDL,XMLスキーマの準備】
前回のBooksPricingProcessWebServiceBeanと同様の手順で,BooksDataWebServiceBean, FooPriceListWebServiceBean, BarPriceListWebServiceBeanのWSDL,XMLスキーマをローカルに保存,編集します。
【3. BPELの編集】
(1) WSDLのインポート,パートナーリンクの設定
編集した3つのWSDLファイルをBPELにインポートします。そして,それぞれのサービスに対応するパートナーリンクを設定します。
(2) アクティビティの配置
アクティビティを配置して,全体のプロセスが見えるようにしましょう。
(3) Assign1の設定
BPELエディタ上でAssign1を選択して,Mapperでコピー方法を設定します。
左側のFindBookPriceIn1から,右側のFindBooksDataIn1, FindFooPriceListIn1, FindBarPriceListIn1に線を引っ張ります。
NavigatorのBPEL Logical Viewで,それぞれのInvokeを右クリック,[Edit]を選択して,3つのサービスを呼び出すように設定します。Input Variable,Output VariableをCreateするのを忘れないようにしましょう。変数名はデフォルト値で構いません。
(5) Assign2の設定
BPELエディタ上でAssign2を選択して,Mapperでコピー方法を設定します。
左側のFindBooksDataOut1から,右側のFindBookPriceOut1に線を引っ張ります。
<copy>
<from variable="FindBooksDataOut1" part="parameters"/>
<to variable="FindBookPriceOut1" part="parameters"/>
</copy>
</assign>
(6) If1の設定
If1のMapperで,FindFooPriceListOut1のpriceをnumberとして評価した値が,FindBookPriceOut1のpriceをnumberとして評価した値より小さいことを条件として設定します。
(7) Assign3の設定
Assign3のMapperで,FindFooPriceListOut1のpriceをFindBookPriceOut1のpriceにコピーするように設定します。
If1とAssign3のBPEL該当箇所はこうなっているはずです。
<if name="If1">
<condition> ( number($FindFooPriceListOut1.parameters/return/price) < number($FindBookPriceOut1.parameters/return/price) ) </condition>
<then>
<assign name="Assign3">
<copy>
<from>$FindFooPriceListOut1.parameters/return/price</from>
<to>$FindBookPriceOut1.parameters/return/price</to>
</copy>
</assign>
</then>
</if>
(8) If2, Assign4の設定
FindBarPriceListOut1のpriceをnumberとして評価した値がFindBookPriceOut1のpriceをnumberとして評価した値より小さければ,FindBarPricListOut1のpriceをFindBookPriceOut1のpriceにコピーするように設定します。
【4. 実行】
BPELを実行してみましょう。BooksDataから取得したデータに加えて,FooPriceListとBarPriceListで安い方の価格が設定されたデータが戻ってくることを確かめます。
【5. BPELでのプロセス並行処理】
BPELではプロセスの並行処理が簡単に実行できます。これはJavaでプロセスを実行する場合に比較してアドバンテージになります。
Assign1の後に,並行処理のためのアクティビティであるFlowをDrag&Dropして,Invoke1, Invoke2, Invoke3を並行処理するようにアイコンを移動させます。これで並行処理が実行されるようになります。
前回のエントリで,SOAのレイヤ構成を想定したJava EE 5開発を試してみました。これにSOAを適用するとどのようなイメージになるのでしょうか?実際に,前回のアプリケーションをベースにSOAを試してみましょう。具体的には,リソースレイヤとサービスレイヤをそのまま使って,プロセスレイヤをBPELで実現します。
ただし,一気にそこまで行くのは大変なので,今回は,ひとまず簡単なプロセスを動かすところまでにしたいと思います。
【0. 前提条件】
必要なのは,前回と同じくNetBeans Enterprise Pack 5.5 EA版だけです。これには,SOA Starter Kitが含まれています。プラットフォームはJBIのオープンソース実装であるOpen ESBです。
【1. プロジェクトの作成,準備】
(1) プロジェクトの作成
[File]-[New Project]を選択すると,[New Project]ダイアログが起動します。
[Service Oriented Architecture]-[BPEL Module]を選択します。
としてプロジェクトを生成します。
PricingProcess_1.bpel, PricingProcess_1.wsdlが生成されます。
(2) WSDL,XMLスキーマの準備
このプロセスのエントリポイントをWebサービスとして定義するためのWSDL,XMLスキーマを準備します。前回のアプリケーションのBooksPricingProxessWebServiceBeanと同じWSDLとXMLスキーマを流用することにしましょう。
前回の最後の手順で使ったWebサービスのテスト画面にWSDLというリンクがあります。これをクリックしてWSDLを表示させてローカルに保存しましょう。(拡張子をwsdlにしましょう。)
こんな感じのWSDLになっているはずです。
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://ws/" name="BooksPricingProcessWebServiceBeanService">
<types>
<xsd:schema>
<xsd:import namespace="http://ws/" schemaLocation="http://xxx.xxx.xxx.xxx:8080/BooksPricingProcessWebServiceBeanService/BooksPricingProcessWebServiceBean/__container$publishing$subctx/META-INF/wsdl/BooksPricingProcessWebServiceBeanService_schema1.xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
</xsd:schema>
</types>
<message name="findBookPrice">
<part name="parameters" element="tns:findBookPrice"/>
</message>
<message name="findBookPriceResponse">
<part name="parameters" element="tns:findBookPriceResponse"/>
</message>
<portType name="BooksPricingProcessWebServiceBean">
<operation name="findBookPrice">
<input message="tns:findBookPrice"/>
<output message="tns:findBookPriceResponse"/>
</operation>
</portType>
<binding name="BooksPricingProcessWebServiceBeanPortBinding" type="tns:BooksPricingProcessWebServiceBean">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="findBookPrice">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="BooksPricingProcessWebServiceBeanService">
<port name="BooksPricingProcessWebServiceBeanPort" binding="tns:BooksPricingProcessWebServiceBeanPortBinding">
<soap:address location="http://xxx.xxx.xxx.xxx:8080/BooksPricingProcessWebServiceBeanService/BooksPricingProcessWebServiceBean" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
</port>
</service>
</definitions>
それから,WSDLの最初の方でXMLスキーマをインポートしています。このURLをブラウザのアドレスバーにコピーして,XMLスキーマを表示させ,これもローカルに保存します。(拡張子をxsdにしましょう)
そして,WSDLを今回の環境に合わせて編集します。
編集後のWSDLはこんな感じになります。(変更箇所をBold体で示しています。)
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://ws/" name="BooksPricingProcessWebServiceBeanService" xmlns:plink="http://schemas.xmlsoap.org/ws/2004/03/partner-link/">
<types>
<xsd:schema>
<xsd:import namespace="http://ws/" schemaLocation="BooksPricingProcessWebServiceBeanService_schema1.xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
</xsd:schema>
</types>
<!-- 中略 -->
<service name="BooksPricingProcessWebServiceBeanService">
<port name="BooksPricingProcessWebServiceBeanPort" binding="tns:BooksPricingProcessWebServiceBeanPortBinding">
<soap:address
location="http://localhost:18181/PricingProcess/PricingProcess_1" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
</port>
</service>
<plink:partnerLinkType name="BooksPricingProcessPartnerLinkType">
<plink:role name="provider" portType="tns:BooksPricingProcessWebServiceBean"/>
</plink:partnerLinkType>
</definitions>
【2. BPELの編集】
(1) WSDLのインポート
PricingProcess_1.bpelのNavigator画面で,[Imports]を右クリック,[Add Import]を選択して,編集したWSDLをインポートします。
(2) パートナーリンクの追加
右のパレットから,Partner LinkをDrag&Dropします。
としてPartnerLinkを追加します。
(3) Receive, Replyの設定
最初のアクティビティとしてReceive, 最後のアクティビティとしてReplyをDrag&Dropします。
BPEL Navigator画面で,Receive1を右クリック,[Edit]を選択すると,ReceiveのProperty Editorが起動します。
とします。
Receive1に関しては,ソースビューで属性としてcreateInstance="yes"を追加します。
<receive name="Receive1" partnerLink="PartnerLink1" operation="findBookPrice" portType="ns1:BooksPricingProcessWebServiceBean" variable="FindBookPriceIn1" createInstance="yes"/>
同様に,Reply1に関しても
と設定します。
(4) Assignの設定
Receive1とReply1の間にAssignをDrag&Dropします。最初から存在する空のアクティビティは削除します。
Assignは,変数に値をコピーするためのアクティビティです。NetBeans Enterprise PackにはMapperという機能があり,GUIでコピー内容を指定できます。メニュー[Window]-[Mapper]を選択すると,Mapperが起動されます。BPELエディタ上でAssign1を選択して,Assignの内容を設定しましょう。
例えば,FindBookPriceIn1のproductIdをFindBookPriceOut1のproductIdにコピーする場合には,Mapperの左から右へ線を引っ張るだけでO.K.です。
固定値を設定する場合には,Mapperのメニューから[string literal]あるいは[number literal]を選択して値を入力,右の該当箇所へ線を引っ張ります。
BPELエディタをソースビューに切り替えると,Assignの内容が確認できます。
<assign name="Assign1">
<copy>
<from>$FindBookPriceIn1.parameters/productId</from>
<to>$FindBookPriceOut1.parameters/return/productId</to>
</copy>
<copy>
<from>39.99</from>
<to>$FindBookPriceOut1.parameters/return/price</to>
</copy>
<copy>
<from>'Java EE and .NET Interoperability'</from>
<to>$FindBookPriceOut1.parameters/return/productName</to>
</copy>
</assign>
BPELやXPathの細かい文法を知らなくても編集できるのでとても便利です。
【3. 実行】
(1) Composite Applicationの作成
[File]-[New Project]を選択,[Service Oriented Architecture]-[Composite Application]を選択します。
として作成します。
次に,プロジェクト"PricingApp"を右クリック,[Add JBI Module]でプロジェクト"PricingProcess"を追加します。
(2) テストの作成
プロジェクト"PricingApp"の[Test]を右クリック,[Add Testcase]を選択します。Input.xmlのproductIdとして"SUNW-001"など適当な値を指定します。
(3) 実行
プロジェクト"PricingApp"をDeployして,テストを実行します。
どうですか?WSDLの準備がちょっと面倒ですが,後はとても簡単です。プラットフォームがJBIであることを意識する必要も無く,BPELを直接編集する必要もありません。
Sun Java CAPSのセミナーが開催されます。
開催間近ですが,是非,ご登録,ご聴講ください。
JavaOne 2006に合わせて,いろいろ公開されてます。
とりあえず一通り入ってそうなTools Bundleをインストールしてみました。
特徴はこのページに書かれている通りですが,私はチュートリアルにしたがってSOAサンプルプロジェクトを試してみました。Sun Java System Application Server上でJBIが動きます。特にBPELのデバッグ機能が面白いです。BPELにブレークポイントを設定したり,ステップ実行したり,BPEL変数の中身を覗いてみたり。
ちなみに…
工藤さんのblogにも紹介されているように,Identity管理の機能も面白そうです。
是非お試しあれ。
先日のSun Business .Nextにご来場いただいた皆様,ありがとうございました。
プレゼンテーション資料については間もなくWebサイトからダウンロード可能になると思います。
プレゼンテーション内で参照していた内容,URLについては先行してこちらでまとめておきます。併せてご参照ください。
それはそうとして,この講演の後,以前別の仕事でご一緒した方たちと久しぶりにご挨拶させていただきました。SOAのエバンジェリストをされている方,SOAの製品開発されている方など…,世の中は狭いですね。
SOAのITバリューを「空間」の軸から眺めてみましょう。
次に「リソース」の軸から。