2010年4月27日火曜日

Swordfish の GettingStarted 試行

久しぶりに Eclipse のサイトを見てみると、Eclipse の新しい SOA Initiativeが発足したと言う、04/21 付けのアナウンスがあった。リンクをたどると、こんな Webinar を見つけたので早速やってみる。

以下のような内容
  • 00:00 part 1 Swordfish の概要と準備
  • 05:55  target platform の設定方法
  • 06:46 part 2 サンプル作成
  • 08:15  step 1 FlightReservation Provider
  • 13:53  step 2 PaymentProcessing Provider
  • 16:40  step 3 FlightBooking Provider
  • 24:25 part 3 Service Registry の使用
  • 29:10 結び

思い切り端折って言うと、OSGiベースで"分散ESB"を実現するための仕組みと、Eclipse によるサポート。Java 的には、DI に Spring、Webサービスには CXF を使っている。

SCA ではないけど、このチュートリアルでもコンポジットという考え方を採用している。既存の Webサービス(Provider)に対して、これを用いる Consumer を定義し、それらを部品とする上位のサービスをコンポジットとして定義するような方式。

ちなみに、この Getting Started も WSDL ファースト。昔は Javaコードを書いてから Webサービスで公開って流れのチュートリアルもあった気がするが、最近は見かけない。WSDL ライティングについても、チーム内で共有できそうなベストプラクティスとアンチパターンを見繕っておいた方が良さそう。

2010年4月26日月曜日

BPEL×AntiPatterns

以前のポストでは CodeSmell の BPEL への適用を調べてみた。同じ要領で、AntiPatterns の「ソフトウェア開発のアンチパターン」について、一個一個考えてみる。

尚、★印は5段階に分類した要注意の度合いで、発生頻度×影響度って感じ(感覚ベースの脳内統計だが・・・)。

■ Spaghetti Code ★★★★★

BPEL の言語的性質から、実行パスがもつれたり絡んだりする事はそれほど無くて、古典的な意味でのスパゲティにはならないが、グローバル変数がらみの広義のスパゲティになる事が多い。

グローバル・スコープに変数を定義して、複数のアクティビティで上書きしながらワーク領域として使いまわしているコードがあったりすると、可読性が落ちるわ潜在バグの温床になるわで、生産性と品質の両面に大きなダメージがある。


■ The Blob ★★★★
オリジナルは、与えられた責務が多すぎてオブジェクトが肥大化している状態を言うが、BPEL でもプロセスが長すぎて困るのは良くある。

長いからその分いろんな改修や仕様変更の影響を受けやすく、複数担当者で作業対象がカブる率が高くなり、生産性にかなり悪影響がある(担当者のアサインの仕方にもよるが)。

改善のためには BPELコーディングの面よりも、主にプロセス設計の面からのアプローチが有効と考えられる。例えば、プロセスを分割するとか、サブプロセスとして別サービスに括りだすとか。
■ Functional Decomposition ★★★★
オリジナル AntiPatterns では、オブジェクト指向開発なのに非オブジェクト指向で書かれたコード、例えばポリモーフィズムを使うべきところで if文や switch文を使っているなどの悪習を指す。

言語の本来の性質や目的に合っていないコーディングという意味では、BPEL の場合だとサービスのオーケストレーションに寄与していないコードが怪しい。例えば<assign> しか含まないループや分岐は、BPEL ではなく XSLT で書くべきケースが多い(書き易さの面でも)。
■ Cut-and-Paste_Programming ★★★★
BPEL でも重複コードは頻出で、やはり大体コピペで作られる。ただし BPEL 自体、小さなサブルーチンに細かく分割するのに向いてる言語ではないため、普通のALGOL系言語より重複しやすい。

そういった仕方の無い面もあるにせよ、やはり度が過ぎると、たった一つの変更が何十個所もの改修に及んだりしてダメージが大きいため、できるものなら解消したい。

やり方は、xpath 関数を拡張するとか、XSLT に切り出して再利用するとか、プロセスの一部を別サービスに切り出すなど。いずれのやり方も自明でも無いし常に適用可能でもないので、工夫と妥協が必要。
■ Input Kludge ★★★★
都合の良い入力条件でしかまともに動かないプログラムを指したアンチパターン。

オブジェクト指向開発だと xUnit や TDD が高度に発達して、既にかなり普及しているけど、それらのノウハウを BPEL に適用するのは現状ではなかなか難しい。入出力XMLデータの検証くらいは簡単にできるけど、途中の Web サービスとのやり取りまで含む検証は、意外と手間がかかるしシナリオの想定も難しい。

あと厳密に Input Kludge に該当するか分からないが、開発環境で本物の Webサービスの代わりに使うスタブでも同様の問題が生じる。スタブ化しようとするサービスのドキュメントの不備や解釈のブレによって、なかなか実物のサービスと開発者の想定が一致しない。で、スタブでは動いたが実サービスを繋いだテストでは不具合が出るということになる。

プロジェクトの性質によって対処法はまちまちだろうけど、なるべく早いフェーズでテストと実装(特にスタブ)の戦略は立てておく必要がある。


■ Lava Flow ★★★
使われなくなったコードのことで、デッドコードとも言われる。仕様変更の対応などに伴って BPEL でもよく発生する。あるBPELプロセスの全体、またはその部分、或いはBPELから使用している*.xslファイルや*.xsdファイルなどが、いつの間にか使われなくなったりする。

これについても、無駄なメンテナンスが発生するので、なるべく早く削除すべき。(ちなみにコメントアウトして残す癖のある人もいるが、良い習慣ではない。)
■ Golden Hammer ★★★
オリジナル AntiPatterns では、ある特定の解法や技術を何にでも盲目的に適用してしまう事を指す。ややキツ過ぎる言い方になるが、日本語だと「バカの一つ覚え」ってところだろうか。

BPEL 開発でも、知識が足りないまま作業開始して手探りで進めているようなプロジェクトで、頻繁に生じる。過去に見かけて印象に残った例だと、BPEL外部の XMLファイルの内容にアクセスするために、標準 xpath 関数のdocument() を使えばいい事を知らずに、無理やり orcl:lookup-xml()を使っていたコードなどがあった。
■ Ambiguous Viewpoint ★★★
分析の視点と実装の視点の混同、特に分析・設計時に実装の問題を混入させてしまう事を指す。

BPELの場合、OO言語を用いた開発に比べて、実装に先立つ設計作業の比重が大きかったりするが、ここでワーク変数の扱いだとかデータ加工の具体的ロジックなどまで含めてしまうのは、本当に百害あって一利なしなのでやめるべき。


■ Continuous Obsolescence ★★
準拠する仕様や基盤となる製品のバージョンアップにともなって、既存コードが絶え間なく陳腐化していく現象を指す。BPEL開発 の場合、まず BPEL、XSLT、XPATHといった標準仕様、またそれらについて各製品独自に拡張した部分、さらに 基盤となる BPEL/SOA 製品などについて、各々、時間の進行に伴ってバージョンが上がって行く事になる。

まあ、そもそも疎結合が SOA の謳い文句なので、外部サービスのバージョンアップの影響は余り受けずに済む。サポート期限などは別にして、陳腐化についてはそれほど神経質にならなくてもいいかも。

尚、開発を始める段階でなるべく新鮮は最新版の製品を使えば、陳腐化までの時間を長引かせる事はにはなるが、下記の Walk through a Minefield には注意する必要がある。
■ Walk through a Minefield ★★
リリース後間も無い未知のバグを含む新製品を採用して、問題解決に困ってしまうというアンチパターン。

これは発生頻度もダメージも、プロジェクトや製品ごとにまちまち。対策としては、プロトタイピングとか、反復型プロセスで早期に問題を燻り出したりとか、まあ普通のリスク回避策しかないか。開発に取り掛かった時点で「枯れている」製品を選ぶのも一つの手だが、これも気をつけないと陳腐化リスクが大きくなる。
■ Poltergeists ★★
存在意義があまりないクラス。

BPEL の場合だと、例えばサービスを一個呼ぶだけのプロセスなど単にコンポジットから呼び出せば済むような、オーケストレーションが無いプロセスはこれに当たると考えられそう。
■ Mushroom Management ★★
エンドユーザから隔離されたデベロッパが、十分な要件定義も与えられないまま、想像でコーディングするしか無い状況に追い込まれること。まあ BPELに限らずシステム開発プロジェクトの初歩的な問題なので割愛。


■ Boat Anchor ★
現在の開発対象システムには不要と思われる贅沢な機能を満載したソフトやハード。

単にお金が掛かるというだけなら、自分の金じゃないし払う方の勝手だけど、そのために本当に必要なリソースが圧迫されるとしたら、PM かステークホルダに具申する必要がある。

また OSS の軽量な製品で事足りるのに、重すぎて扱いにくい商用製品が使われてたりすることもよくある。開発端末ではありえないレベルの高スペック・サーバマシンじゃないと動作しないような BPEL 製品だとか、そういうのは本当に生産性が落ちるから、極力避けたい。
■ Dead End ★
他所から入手した再利用コンポーネントを部分変更した後、サポートを受けられなくなってしまうこと。
まあ、あまり起こりそうに無いし、気にしなくてもいいか。

2010年4月24日土曜日

Galileo/ODE/Tomcat

Eclipse の BPEL Plugin と ODE の併用メモ。

2010年4月時点での最新の環境を使いたいが、ネット上の既存のチュートリアルは Ganymede のみ対象だったり、度々発生するエラーの対処法がなかったりするので、ちょっと整理しておく。

■ 環境
  • Tomcat 6.0.2
  • Eclipse 3.5 Galileo
  • ODE 1.3.3

■ BPEL Plugin
Eclipseの[Install New Software]で、アップデートサイトに以下のURLを指定してプラグインを追加。
http://swordfish-tooling.googlecode.com/svn/trunk/org.eclipse.swordfish.third-parties/bpel/

インストール中に javax.wsdl が足りないって言ってきたら、Eclipse のplugin フォルダに以下の 3つの jar を入れてやり直し。(既にあるものは、それでOK)
2010/04/27 追記
eclipse-rcp-galileo-SR2-win32 (Eclipse 3.5.2) をベースにすると、上記エラーは発生しない。また上記の javax.wsdl*.jar を追加する方法だと、後で partner link を定義するときに別の問題(LinkageError)が発生する可能性があるが、最初からEclipse 3.5.2をベースにしておけば、この問題も回避できる。

注) 以下のURLのアップデートサイトは Eclipse 3.4でしかうまく動かない。
http://download.eclipse.org/technology/bpel/update-site/

以下、参考にしたサイト
■ ODE WAR版
ODE 1.3.3の war版をダウンロードして、zip の中身の ode.war を Tomcat の webapps下に置く。

Tomcat を Eclipse の Server Runtime として動かしている場合、ode.war の置き場所は以下のようになる。
{ワークスペース・フォルダ}\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps

ここに置くと、勝手にデプロイされてodeフォルダが生成される。

■ デプロイ
developerworks の記事[→リンク]に、HelloWorld の BPEL版の作成からデプロイまで説明している部分があるのでやってみる。上述の作業が問題なくできていれば、Eclipse の Web Service Explorer で "Hello World" が返ってくる。

ちなみに BPELを更新したら、*.deployed ファイルを消すと再デプロイされる。

■ 雑感
  • ODE は WS-BPEL 準拠という事で、なかなか記述性が高く読みやすそう。上の HelloWorld でも "$input.payload/tns:input"みたいな書き方をしている(BPEL4WS 系ならgetVariableData()を使ったダラダラした記述になる)。
  • 商用のBPEL製品に比べると、やはり機能的にあっさりしすぎの感もある。特に監査情報がブラウザから見られないのは、開発時辛いかも。
  • 逆に機能がスリムな分、使用感が軽そうなのは良い。特に各開発者のマシンに一式インストールして動かせそうなのは良い。無駄にでかすぎる商用製品だと、結局1台の高スペックマシンに BPEL エンジンを載せて全員で共用したりする羽目になって、却って生産性が酷い事になったりする。
  • 後は、SCA、JBI、EIP 製品との組み合わせか。他のサービスといかにうまく連携させるか、アーキテクトの腕によるところが大きくなりそう。

2010年4月23日金曜日

BPEL×code smell

BPELコードの良し悪しを判断するガイドラインぽいのが無いかと探してみたが、これと言った物が見当たらない。こんな時に一から自分で考えるのはたいてい愚策なので、既存のものを叩き台にしてみる。

特に「良し悪し」の「悪し」の判別に役立つもの、つまりアンチパターンが欲しいので、まずは Refactoring に載っている CodeSmell を検討してみる。BPEL がオーケストレーション言語であるのに対して、CodeSmell は 主に OOP分野の話だから、そもそも異質ではあるけど、まあ業界の常識だし自分でもよく知っているので出発点としては適当。そんなわけで、Refactoring に載ってる 22個の CodeSmell から、BPEL でも当てはまりそうなものをピックアップしてみる。

============
まずは、CodeSmell がもたらす開発作業への悪影響が BPEL でも大きそうなものから

■ Duplicated Code
一般に CodeSmell の最たるものされているのがこの「重複コード」。BPEL 開発でも頻出で、例えば複数のプロセスで共通的に使う変数の初期化コードだとか、フォルト・ハンドラだとかがコピペで書かれると、この CodeSmell が生じる。

ただし、普通のALGOL系OO言語ならば、小さな重複を1~3行程度の小さなメソッドに切り出すような"mercilessly" なリファクタリングもいたって普通だけど、BPEL はそういうの向いてない。例えば、同じ<assign>アクティビティが重複しているからといって、「別プロセスに切り出して」なんてのは無理があるので、多少の重複は仕方なかったりする。

それでもやっぱり何とかしたいとなったら、こんな回避策になるだろうか
  • XSLT で書けるような重複ロジックは *.xsl ファイルに切り出して、<assign>中の doXslTransform() で実行する
  • Xpath 式に組み込めそうな部分で、且つ、使っている BPEL 製品 がXpath 関数を拡張 する仕組みを持っているなら、BPELエンジンに組み込んでXpathから字呼び出す。

■ Long Method/Large Class
BPEL だと長すぎるプロセスがこれに相当するだろうか。

原因には、プロセス設計の問題とコーディングの問題の2つの側面があると思う。前者なら例えば、本来は2つ以上の連続するプロセスを一本のものとして捉えてしまっている場合などで、後者なら、重複コード等、他の CodeSmell によるBPELコードの肥大化などが考えられる。

まあ、一見長すぎに見えても妥当なプロセス設計も当然あるはずなので一概には言えないが、ただし肥大化の原因が以下のような場合、解消の必要がありそう
  • 重複コードや不要コードなど、他の CodeSmell によるプロセス肥大化
  • BPELプロセスで、ループや条件分岐を含むデータ加工をしている。

■ DivergentChange/ShotgunSurgery
変更の影響に関する二つの CodeSmell。

DivergentChange はあるプログラム要素(クラスとかメソッド)が、いろんな種類の仕様/設計変更から影響を受けすぎているというもの。ShotgunSurgery は逆に、一つの仕様/設計変更が、余りに多くのプログラムの部分に影響を与えているというもの。

前者は BPEL での例がちょっと思い浮かばないが、後者の ShotgunSurgery は、例えばプロジェクト共通のフォルトハンドリングの方法が変わって、それに準拠している全てのプロセスの faulthandler を書き直すようなケースで、現場でもよくある。

■ Lazy Class
BPEL でも、仕様変更に対応してるうちに、あるプロセスが使われなくなったりする。また、プロセスが使っていた XSLT ファイルや XMLSchema ファイルなども同様のことが起こる。これも無駄な保守コストがかかるのでまずい。

■ TemporaryField
オリジナルの CodeSmell は、特定の状況でしか使わないデータを、メソッド・パラメータとかローカル変数ではなく、インスタンス変数にしちゃってるというアンチパターン。

BPELプロセスだと、局所的に使うだけの変数をグローバルに宣言したりして、無駄に広いスコープを与えているコードがこれに近いと思う。(IDE によっては、変数を宣言する時にデフォルトでグローバル変数にしているものがあり、結構良く見かける。このグローバル変数を使いまわしたりすると、本当にひどい難読コードになる。)

変数のスコープはなるべく短くすべしという基本は、やはりBPELでも成り立つと思う。

■ Incomplete Library Class
オリジナルは、いまいちニーズを充足しきれていない、惜しいライブラリを指す。BPEL でいうとベンダ独自の拡張機能あたりにそういう事があるかもしれない。

■ Comments
諸説あるが OOPでのコメントのつけ方の有力なガイドラインとして、メソッドの頭のコメント(JavaならJavaDocコメント)だけ書いて、メソッドの中では原則コメントを書かず、コメントなんかを書く労力をコメント無しでも理解しやすいコードを書くことに向けるべしというのがある。

ただ BPEL の場合、コードだけ(たとえばアクティビティの命名の工夫とか)でそれをやるのは難しいので、無理せずコメントを書いた方が良い場合が多いかも。(もちろんコメントがなくても分かるように書けるならそれにこしたことはないが。

============
以下、敢えて書こうと思えば書けるけど、実際には発生しにくそうな CodeSmell

■ SpeculativeGenerality
「現状で必ずしも必要ないが常識的に考えて必要だろう」というノリのコーディングを指す。YAGNI 違反という事になって、KISS原則にも抵触するからまずい。

BPEL だと余り無いような気がするが、敢えてそういうコードを書こうとしたら多分書けてしまうので、人によってはこういうの多いかも。

■ Alternative Classes with Different Interfaces
入力か出力の型が違うだけの理由で別々の BPEL プロセスを書いたりしたら、このCodeSmellに該当するだろうか。ただしサービスとして BPEL を呼ぶ前に XSLT で変換するようにすれば良いだけなので、実際にはなさそう。

■ MiddleMan
まあ他のBPELプロセスを呼ぶだけのBPELプロセスなんて、誰も書かないだろうけど、不可能ではない。


============
以下、あまり BPEL と関係ない CodeSmell

■ Long Parameter List
入力 XMLデータの大きさは BPEL の問題ではない

■ FeatureEnvy
オブジェクトの話なので関係ない

■ DataClumps
やり取りするデータの話なので、XMLSchema の問題

■ PrimitiveObsession
これも強いて言えば XMLSchema の問題

■ SwitchStatements
オリジナルはswitch の代わりに多態を使えというものだが、BPELでは関係ない

■ ParallelInheritanceHierarchies
継承の話なので関係なし

■ MessageChains
オリジナルはあるデータにアクセスするためのオブジェクトの経路に、クライアントが全面的に依存してしまっている「デメテルの法則」違反を指しているが、BPEL プロセスで XPath を用いてアクセスするのは問題ない。

■ InappropriateIntimacy
オブジェクト指向でのクラスの凝集性の話で関係ない

■ DataClass
オブジェクト指向でのカプセル化の話なので関係ない
※本質的な意義を持たないという意味では、サービスをinvoke しないプロセスとか

■ RefusedBequest
オブジェクト指向での継承に関する話なので関係ない

2010年4月7日水曜日

XMLSchema/ベストプラクティス

ネット上で閲覧できる XMLSchema のベストプラクティスがいくつかあるが、そのうちの一つ。

XML Schemas: Best Practices

ベストプラクティスのカタログの典型的なものは、個々のプラクティスやパターンを一つのユニットとして、形式を統一して分類し、列挙したようなものが多いが、これはスキーマ設計をする上での判断の分岐点を示してから、採り得る選択肢をメリット・デメリットと共に詳しく解説していく構成になっている。

以下、簡単な紹介。

Default Namespace - targetNamespace or XMLSchema? →原文
デフォルト名前空間(schema 定義の「xmlns=」に指定するやつ)に何を選ぶか。選択肢は以下。
  • targetNamespace に指定した名前空間をデフォルトとする
    <xsd:schema targetNamespace="○○" xmlns="○○" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ~/>
  • "http://www.w3.org/2001/XMLSchema"をデフォルトとする
    <schema targetNamespace="○○" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:△△="○○" ~/>
  • デフォルト名前空間を使わない
    <xsd:schema targetNamespace="○○" xmlns:△△="○○" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ~/>

原文では、どれを選ぶのかについて好みに依存する部分が大きいとされている。個人的には、(3)のパターンでxmlns:tns="○○"として統一するのが、一貫性も可読性もそこそこ維持できると思う。


Hide (Localize) Versus Expose Namespaces →原文
schema 要素の elementFormDefault 属性を"qualified"にするか "unqualified"にするか。

それぞれの長所短所の解説に加えて、qualified 版とunqualified 版の2つのコピーを提供するというプラクティスが紹介されている。(2重管理になる心配をしてしまうが、どうなんだろう。)

Global versus Local →原文
要素や型を、グローバル(<schema>直下に定義)にするかローカルにするか。

以下、三つの選択肢について解説されている。
  • Russian Doll design・・・ローカルに定義
  • Salami Slice design・・・グローバルに要素を定義
  • The Venetian Blind design・・・グローバルに型を定義

Element versus Type
要素として定義するか型として定義するか。迷うくらいなら型として定義する事が推奨されている。

Zero, One, or Many Namespaces →原文
複数のスキーマを定義する際、どのように targetNamespace を指定すればよいか。3つの選択肢について詳説
  • Heterogeneous Namespace Design・・・個別に targetNamespace を与える
  • Homogeneous Namespace Design・・・一個の targetNamespace で統一
  • Chameleon Namespace Design・・・主となるスキーマにtargetNamespaceを与え、従となるものには与えない

Variable Content Containers →原文
複数種の要素を載せるコンテナ要素の定義の仕方。4つのアプローチについて詳説。
  • an abstract element and element substitution
  • a <choice> element
  • an abstract type and type substitution
  • a dangling type

Composition versus Subclassing →原文
オブジェクト指向プログラミングにおける「継承かコンポジションか?」という問題と同じで、やはり Composition が強く推奨されている。

Creating Extensible Content Models →原文
スキーマモデルにどのように拡張性を与えるか。
  • Extensibility via Type Substitution
  • Extensibility via the Element
後者が推奨されているが、Non-Determinism問題への注意が喚起され、<other>要素を用いた回避策の紹介がある。

Extending XML Schemas →原文
ある XML文書をチェックするのに XMLSchemasの文法だけで足りない場合にどうするか。以下3解法の長所短所を解説。
  • Supplement with Another Schema Language
  • Write Code to Express Additional Constraints
  • Express Additional Constraints with an XSLT/XPath Stylesheet

Should the targetNamespace be a URL or a URN? →原文
URL/URNの使い分けについての考察。本来ユニークな識別子にすぎない名前空間の指定に URL が使われると、これがリソースのロケーションと誤解されることが多いという問題が、まず提起される。この問題を踏まえたうえで、将来性としては URL に分があるとし、回避策として http://の代わりに namespace://やxmlns://を用いるというプラクティスが紹介されている。

What's the best way to version schemas? →原文
スキーマの変更にともなうバージョン管理・使い分けの手法
  • Change the (internal) schema version attribute.
  • Create a schemaVersion attribute on the root element.
  • Change the schema's targetNamespace.
  • Change the name/location of the schema.

Achieving Maximum Dynamic Capability in your Schemas →原文
ダイナミックであるほど良い XMLSchema であるという価値観をまず提示。その心得を「postpone decisions as long as possible」として打ち出している。以下の2つのプラクティスが紹介されている。
  • targetNamespace を指定しないままにしておく
  • <import>のschemaLocationを指定しないままにしておく
targetNamespace は常に指定するべしというプラクティス集もあるが・・・

2010年4月5日月曜日

OSS 11g/JMS Adapter

Oracle SOA Suite 11g で JMS Adapter を使ってみる。

非同期で受け取った SOAP メッセージを、メディエータ経由でJMSにキューイングするルーティングを、コンポジットで実装してみたい。

最初は、BPEL から JMS にキューイングするプロセスを考えたけど、要はコンポジットでのJMS アダプタの設定が肝であって、BPELからのJMS 呼び出しは他の <invoke>と変わらず、Getting Started 目的としては BPEL は蛇足だと気づいて割愛。コンポジットだけで構成した。

■■ JMS キュー作成
以下の3つを Weblogic コンソールで設定する
  • キュー作成
  • コネクションファクトリ作成
  • コネクションプール作成

■ JMS キュー作成
  • Domain Structureで base_domain/Services/Messaging/JMS Modules を選択
  • JMS Modulesで SOAJMSModuleを選択
  • [New] 押下→"Queue"を選択 → [Next]
    • Name: greetingQueue
    • JNDI Name: jms/greetingQueue
  • [Next]
    • Subdeployments:SOASubDeployment
    • Targets/JMS Servers:SOAJMSServer
  • [Finish]


■ JMS Connection Factory 作成
  • Domain Structureで base_domain/Services/Messaging/JMS Modules を選択
  • JMS Modulesで SOAJMSModuleを選択
  • [New] 押下→"Connection Factory"選択 → [Next]
    • Name: greetingCF
    • JNDI Name: jms/greetingCF

  • [Next]→ [Finish]


■ Connection Pool 作成
  • Domain Structureで base_domain/Deployments を選択
  • Deployments テーブルでJmsAdapterを選択
  • Settings for JmsAdapter/Configurationタブ/Outbound Connection Poolsタブ
  • [New]
  • oracle.tip.adapter.jms.IJmsConnectionFactoryを選択して[Next]
    • JNDI Name: eis/Queue/greeting
  • [Finish]※deployment plan location とか言うのを聞かれたら適当にディレクトリを掘って、パスを指定する
  • Configurationタブ/Outbound Connection Poolsタブに戻る
  • oracle.tip.adapter.jms.IJmsConnectionFactory を展開して、eis/Queue/greetingを選択
  • ConnectionFactoryLocation の Property Value に jms/greetingCF を指定
  • [Save]
  • Deployments テーブルに戻って JmsAdapter を再デプロイ(チェックして[Update])


■■ コンポジット・アプリ作成
■プロジェクト作成
  • 名前:ここでは SimpleJmsQueueing とした
  • プロジェクトテクノロジ:SOA
  • コンポジットテンプレート:空のテンプレート

このコンポジットで使う XML スキーマを、以下のように作成。
  • SOAコンテンツ/xsd フォルダのコンテキストメニューから[新規]
  • ファイルを選択し、message.xsdを作成。内容は以下。
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://studies.oss11g/simple.jms.queueing"
    xmlns:tns="http://studies.oss11g/simple.jms.queueing"
    attributeFormDefault="qualified" elementFormDefault="qualified">
    <element name="greeting" type="tns:GreetingType"/>
    <complexType name="GreetingType">
    <sequence>
    <element name="message" type="string" />
    </sequence>
    </complexType>
    </schema>


■ Webサービス
  • Webサービスを[公開されたサービス]のレーンにドロップ
  • 歯車ボタンでスキーマから WSDL を生成
  • リクエストタブでURLに message.xsd の greeting 要素を選択
    レスポンス以下のタブは放置
  • 他はめんどくさいので全部デフォルト


■ JMS アダプタ
  • [外部参照]のレーンにJMS アダプタをドロップ
  • 名前はここではJMS_Queueとした。
  • JMSプロバイダに Oracle Weblogic JMS を指定
  • AppServer 接続:デプロイとかで使ってるいつものやつ
  • アダプタ・インタフェイス:操作およびスキーマから定義
  • 操作:メッセージ発行、操作名はデフォルトまま
  • 発行操作のパラメータ:
    • 接続先名:参照ボタンで greetingQueue を指定
    • JNDI名:eis/Queue/greeting
  • メッセージ
    • URL:message.xsd の greeting を指定
  • 終了


■ メディエータ
  • [コンポーネント]レーンにメディエータをドロップ
  • 名前:デフォルト/テンプレート:デフォルトのまま
  • Mediator1 から Service1 と JMS_Queue にワイアリング
  • Mediator1 の編集開始
    • 「次を利用して変換」の×ボタンを押下
    • 「新規マッパーファイルの作成」を選択して[OK]
  • 開いた XSLT エディタで左の message と右の message をつなげる

■■ テスト
SoapUI か EMコンソールから、いつもどおりにリクエスト送信。キューに入ったメッセージは WebLogic コンソールから確認できる。

2010年4月4日日曜日

SOA Composer

Oracle SOA Suite 11g の Release 1 Patch Set 1 (11.1.1.2.0)から、デプロイした後にWebブラウザからビジネスルールを編集するための、SOA Composer というものが使えるようになった。

http://{server}:{port}/soa/composer でアクセスできる。

前々ポストのIF-THENルールの編集画面

前ポストのデシジョンテーブルの編集画面

2010年4月3日土曜日

OSS 11g/Business Rule 2

前ポストで IF-THEN を使った BusinessRule を試してみた。今度は Decision Table でやってみる。

■ 仕様
前回とほぼ同じで、入力文字列が5文字以上なら文字列"LONG"、でなければ文字列"SHORT"を返すという仕様。これを Webサービス → BPELプロセス → ビジネスルールの構成で動かしてみる。アホらしい仕様だが、Getting Started なのでこんな感じ。

■ 環境
・Oracle SOA Suite 11g (11.1.1.2.0)
・Oracle JDeveloper 11g

■ コンポジット作成
  • プロジェクト名:適当。ここではSimpleDecisionTable とした
  • プロジェクト・テクノロジ:SOAを選択
  • コンポジット・テンプレート:BPEL を使用するコンポジット
※勝手にBPELプロセスの作成が始まる。以下の作業に続く。

■ BPELプロセス作成
  • 名前:適当。ここでは SimpleDecisionTableProcess とした
  • テンプレート:同期BPELプロセス
  • SOAPサービスとして公開:チェック

■ スキーマにファクトを追加
SimpleDecisionTableProcess.xsd が自動生成され、process と processResponse の定義が含まれているが、これを更に以下のように編集
  • 列挙型 CategoryValueを追加
    <simpleType name="CategoryValue">
    <restriction base="string">
    <enumeration value="SHORT"/>
    <enumeration value="LONG"/>
    </restriction>
    </simpleType>
  • BusinessRuleに与えるファクトを追加
    <element name="facts">
    <complexType>
    <sequence>
    <element name="length" type="int"/>
    </sequence>
    </complexType>
    </element>
  • 既存のprocessResponse/resultの型を CategoryValue に変更(名前空間のプレフィクスも適当は調整しておく。)

■ BusinessRule 作成
  • composite.xml を開く
  • コンポーネントのレーンにビジネスルールをドラッグ
  • 適当に名前を指定。ここでは LenghtCategoryTable とした。
  • 緑のプラスボタンで入力を追加
    • プロジェクトのスキーマ・ファイルからfacts を選択
  • 緑のプラスボタンで出力を追加
    • プロジェクトのスキーマ・ファイルからprocessResponse を選択
  • 作成したビジネスルールにBPELプロセスからワイアリング
※ルールの定義は後で。

■ BPEL の編集
  • receiveInput と replyOutput の間に Assign を置いて、以下のようなコピー操作を追加
    • From:string-length(bpws:getVariableData('inputVariable','payload','/client:process/client:input'))
    • To:/変数/プロセス/変数/facts/client:facts/client:length

  • 上で追加した Assign の下にBusinessRule を置く
    • 名前は適当。ここでは デフォルトのままとした。
    • ディクショナリに LenghtCategoryTable を指定
    • 以下のように入力ファクトを追加
      • From:変数/プロセス/変数/facts/client:facts
      • To:変数/{凄い長い名前の変数}/client:facts
        ※To の「変数」は、ダブルクリックしないと展開されないので注意。展開すると凄い長い名前の変数が表示される
    • 以下のように出力ファクトを追加
      • From:変数/{凄い長い名前の変数}/processResponse
      • To:変数/プロセス/変数/outputVariable/payload/processResponse

■ デシジョン表の作成
  • composite.xmlからビジネスルールの編集を開始
  • 緑のプラスボタンから[デシジョン表の作成]
    • バケットセットの編集
      • 範囲リストの追加
      • 名前:LengthRange/データ型:int/フォーム:Range
      • さらに以下のように編集
    • ファクトの編集
      • facts を選択して編集開始
      • lengthのバケットセットに LengthRange を設定
    • ルールセット Ruleset_1 を選択して編集
      • こんな感じにする

■ デプロイ-テスト
  • SimpleBusinessRule のコンテキストメニューからデプロイ
  • SoapUI か emコンソール からリクエストを送る
    • process/input に空文字列, "abcd", "こんちは"等を指定すると"SHORT"
    • process/input に"abcde", "こんにちは"を送ると"LONG"が返ってくる

■ 雑感
今回やったようなのは極端に簡単な処理なので、標準BPEL コードでも出来ることではあるけど、BPEL から Business Rule として切り出すことで、一般的に以下のような効用が期待できる。

(1) BPEL プロセスの簡素化
BPEL の本来の目的からも、またスパゲティ化を回避する意味でも、他サービスをオーケストレイトしない制御ロジック(繰り返し/条件分岐)は BPEL に含めるべきではない。その変わりに XSLT か BusinessRule として切り出して BPEL をシンプルに保つべき。(設計上の都合に由来するなら XSLT、ビジネス要因に由来するものは BusinessRule。)

(2) ビジネスルールの外部化
コンポジットアプリをデプロイした後からでも、ビジネスの変更を契機として
ルールだけを独立に変更したい状況もある。またこの作業を、いちいち IT層 の人間に頼まずに、ビジネス層の人間が直接実施するニーズもあるはず。そうなると BPEL や XSLT では敷居が高いが、Business Ruleにしておけば、ウェブベースのルールエディタを使ってデプロイ後にも編集できる(11.1.1.2.0)。

2010年4月2日金曜日

OSS 11g/Business Rule 1

シンプルな BusinessRule を作ってみる。

IF-THEN と デシジョンテーブルがあるが、今回は IF-THEN でやる事にした。

■ 仕様
BPEL プロセスからビジネスルールを実行するという事にだけ着目したいので、いつものごとく、極力シンプルな仕様にする。
  • SOAP で公開された BPEL プロセスが、リクエストメッセージ中の XMLデータをビジネスルールに渡す。
  • ビジネスルールは受け取った XMLデータ中の <input>要素の文字列長を判別して、5文字以下なら文字列"SHORT"、5文字長なら文字列"LONG"を<result>要素に設定したレスポンスメッセージを生成する。
  • BPEL プロセスは、ビジネスルールが生成したレスポンスをクライアントに返す

■ 環境
・Oracle SOA Suite 11g (11.1.1.2.0)
・Oracle JDeveloper 11g

■ コンポジット作成
  • プロジェクト名:任意。ここではSimpleBusinessRuleとした
  • プロジェクト・テクノロジ:SOAを選択
  • コンポジット・テンプレート:BPEL を使用するコンポジット
※勝手にBPELプロセスの作成が始まる。以下の作業に続く。

■ BPELプロセス作成
  • 名前:適当。ここでは SimpleBusinessRuleProcess とした
  • テンプレート:同期BPELプロセス
  • SOAPサービスとして公開:チェック

■ BusinessRule 作成
  • composite.xml を開く
  • コンポーネントのレーンにビジネスルールをドラッグ
  • 適当に名前を指定。ここでは LengthCategory とした。
  • 緑のプラスボタンで入力を追加
    • プロジェクトのスキーマ・ファイルからprocess を選択
  • 緑のプラスボタンで出力を追加
    • プロジェクトのスキーマ・ファイルからprocessResponse を選択
  • 作成したビジネスルールにBPELプロセスからワイアリング
※ルールの定義は後で。

■ BPEL の編集
  • receiveInput と replyOutput の間に Business Rule を置く
  • 名前は適当。ここでは CategorizeLength とした。
  • ディクショナリに LengthCategory を指定
  • 以下のように入力ファクトを追加
    • From:変数/プロセス/変数/inputVariable/payload/process
    • To:変数/{凄い長い名前の変数}/process
      ※To の「変数」は、ダブルクリックしないと展開されないので注意。展開すると凄い長い名前の変数が表示される
  • 以下のように出力ファクトを追加
    • From:変数/{凄い長い名前の変数}/processResponse
    • To:変数/プロセス/変数/outputVariable/payload/processResponse

■ ルールの作成
  • composite.xmlからビジネスルールの編集を開始
  • 緑のプラスボタンから[ルールの作成]
    • テストの挿入: process.input.length() <= 5
    • アクションの挿入: assert new processResponse(result:"SHORT")
  • 緑のプラスボタンからもう一個[ルールの作成]
    • テストの挿入: process.input.length() > 5
    • アクションの挿入: assert new processResponse(result:"LONG")
下図のようになる
※「<何とかの挿入>」というリンクをクリックして内容を組み立てていく方式だが、ちょっとクセがある。説明するのはちょっと難しいけど、やってみると使い方はすぐ分かる。

ただし難しくて理解しにくい事は無いけど、別に使い易い事もなく、むしろ、なんか面倒くさい。言語リファレンスとAPIドキュメントさえ見やすいところに用意してくれてさえいれば、こんな感じのバカチョン的なフォームよりも、自動補完付きのソースエディタの方がマシな気がする。

JDeveloper - SOA Composite Editor 全般でそんな印象を受ける。ルールエディタだけなら、ビジネスピープルを意識してこうなったのかとも思うけど、他はどうなんだろう。


■ デプロイ-テスト
  • SimpleBusinessRule のコンテキストメニューからデプロイ
  • SoapUI か Enterprise Manager からリクエストを送る(SoapUI の方がお勧め)
    • process/input に空文字列,"a", "abcde", "こんにちは"等を指定すると"SHORT"
    • process/input に"abcdef", "こんにちは!"を送ると"LONG"が返ってくる


■ 次回予定
デシジョンテーブルで同じようなことをやってみる。あと BPEL プロセスとビジネスルールの関係についてちょっと考えてみたい。