2010年3月31日水曜日

BPEL 要員の集め方

前のポストで BPEL スキルについてあれこれ考えて、こんな図を描いてみた。
これをベースに要員調達について、特にどんなスキル・キーワードを条件として用いるべきか考えてみる。ポイントは以下のようになる。
  • 上図、また前ポストで示したように、BPEL技術は階層を成したXML技術構造のやや上層に位置し、XML×SOA×ワークフローが交叉する複合的な技術でもある。この特性をどう扱うか。
  • そもそもBPEL 技術者は絶対数が少ないが、これにどう対処するか。

■ 駄目な集め方
多分、こんな感じだと上手くいかない。
必須スキル:○○社BPEL製品

調達担当者は、「○○社BPEL製品経験者」ならば、当該製品のノウハウはもちろん BPEL標準仕様からXML・SOAの基盤技術まで一通りマスターしているだろうと考えて、下図のようなスキル分布を期待する。(調達担当者が要素技術について多少なりと理解しているという想定。やや楽観的だが。)
ところが現実の応募してくる人のスキル分布は、こんなふうになる。

畢竟、ただただ言われるままに、IDE上のグラフィカルなエディタを何十時間かいじってきただけの経験だと、どこまでが現場のローカルルールで、どこからがツールの仕様で、どの辺りが標準仕様なのか全く未分化なままだし、それを自覚することもないから、応用というものが全くきかない。XMLソースを普通に読み書きするだけの事を、異様に恐れたりするレベルの人。

で、普通なら正味のスキルを面談時に精査して、合格レベルに満たないなら次の応募者に期待という事になるが、そもそも BPEL技術者の絶対数が少ない上に、さらに「△△社」で絞っているものだから、「選ぶ」なんて贅沢な余裕が生じる程、応募者は来てくれない。

こんな応募条件を出すくらいだから調達者側のレベルからして推して知るべしで、面談で正しくスキルチェックができるほどの技量もない。従って、結局は職務経歴書に記載の「△△社BPEL製品」という記号の有無だけで採用が決まり、面談は形式的な挨拶程度ということになりがち。


■ マシな集め方
改善するとこうなる
必須のスキル
 ・XMLスキル(XSLT、XPath、XML Schema)
 ・SOA、Webサービス
望ましいスキル
 ・BPEL (○○社製品ならば尚可)
 ・その他ワークフロー技術
とりあえず、応募者がいないと比較も選別もできないから、思い切って該当者の少ない BPEL経験は必須から外してしまう。それに替えて XML/Webサービスのスキルを必須とし、高スキル技術者を募る。XML/Webサービス技術者も中~高レベルのとなるとそう多くはないが、それでも同等レベルの BPEL技術者よりは、はるかに流通している。

下図のような技術者を期待して待ち、首尾良けば、複数の候補者からベストな数名を採用してチームに組み入れる事になる。
もちろん BPEL 標準および△△社のツール/プラットフォームについての学習工数が発生する事にはなるが、基礎スキルが充実していれば採用者側が心配するほどには時間も労力も掛からない。

また上述の駄目な例として挙げたような特定ベンダーの条件を外すことで、下図のような技術者にも門戸を開くことになる。

このタイプの BPEL 技術者なら、作業開始の要点とローカルルールについて簡単にレクチャーし、座席を適切に配置しておけば、業務要件の把握していく作業のついでに自然と習得できてしまう。
むしろ、XML 良く知ってる人が BPEL や 特定ツールを習得するための工数について、募集側が過度に多く見積もっている場合、プロセスを BPEL で書くという作業を募集側自身が良く理解していない可能性がある。

つまるところ「XMLで定義・公開され、XMLをやり取りするサービスを、XMLで記述したプロセスで動かす。」という事に尽きるわけで、必要なスキルがどんなものなのか簡単に分かりそうなものだが、実際の現場はそうじゃなかったりする。


■ 応募者側からの見方
ここまで募集する側の視点で書いたけど、逆に応募する側、BPEL技術者の視点から言うと、「BPEL経験」だとか「○○社BPEL製品」なんて必須指定がある案件は、募集側の見識を疑ってかかる事もできる。

特に、そういった選択肢を過度に狭め得る条件を必須にしておきながら、そのくせ「急募」だったり「稼働時間高」なんて場合は、プロジェクト自体も採用側の思考も、とっくに破綻していると考えてまず間違いない。

まあ不景気だし、金に困っている場合などは、タコ部屋かマグロ漁船に飛び込む気持ちで、敢えて短期間やってみるって選択もありかもしらんが。

2010年3月30日火曜日

OSS 11g/Human Task

シンプルな Human Task を作って動かしてみる。

■■■ 環境/前提/準備
■ 環境
  • Oracle SOA Suite 11g
  • Oracle JDeveloper 11g
  • サーバ: 192.168.0.3(余りに重いので作業マシンとサーバマシンを分けた)
  • Weblogicコンソール: http://192.168.0.3:7001/console/
  • Enterprise Manager: http://192.168.0.3:7001/em/
  • ワークリスト: http://192.168.0.3:7001/integration/worklistapp/

■ ユーザ追加
  • Weblogic のコンソールで以下のようにナビゲート
    base_domain > Summary of Security Realms > myrealm > Users and Groupsタブ > Usersタブ
  • New でユーザを追加。 ここでは approver とした。


■■■ アプリ作成
■ コンポジット作成
  • 新規プロジェクト 作成する
    • 名前: 任意(SimpleHumanTaskとした)
    • プロジェクト・テクノロジ: SOAを選択
    • コンポジット・テンプレート: BPEL を使用するコンポジット
※ 勝手にBPELプロセス作成ウィザードが始まる

■ BPELプロセス作成
  • 名前:任意(SimpleHumanTaskProcess とした)
  • テンプレート:非同期BPELプロセス
  • SOAPサービスとして公開:チェック

■ HumanTask 作成
  • composite.xml を開く
  • コンポーネントのレーンにヒューマン・タスクを置く
  • 任意の名前を入力(ここではEvaluation とした)
  • ダブルクリックして編集開始
    • 一般/タイトル:<%'Evaluate Input'%>
    • データ/ペイロードの追加
      • [その他のペイロードの追加]
      • "要素"を選択
      • 虫眼鏡のアイコンからタイプチューザを起動し、以下を選択
        "プロジェクトのスキーマ・ファイル">SimpleHumanTaskProcess.xsd>process
      • ワークリストにより編集可能: チェック
    • 割当てを選択
    • Stage1をダブルクリック
      • タイプ: 単一
      • 値ベース: チェック
      • ユーザの追加
      •  識別タイプ: ユーザ
      •  データ型: 名前別
      •  値: approver (以下のようにアイデンティティ・ルックアップが使える)

  • composite エディタ上で、BPELプロセスから HumanTask にワイアリング

■ BPEL の編集
  • receiveInput と callbackClient の間に HumanTask を置く
  • タスク定義で上で Evaluation を選択
  • タスクパラメータに inputVariable/payload/processを指定
  • taskSwitch を展開して、各case 内のassign を編集
    • REJECTケース内のassign を展開してコピー操作を追加
      • from: 式'rejected'
      • to: output/payload/processResponse/result
    • 同様に APPROVEケースで式'approved', 残りのケースに式'expired'を追加

■ フォームの作成
  • BPELエディタ上でHumanTask を右クリック
  • [タスクフォームの自動生成]を実行
  • しばらく待つとかなりの量のソースが自動生成され、フォームエディタが開いて自動生成完了

■■■ デプロイとテスト
■ デプロイ
  • SimpleHumanTask プロジェクトをデプロイする
  • アプリケーションメニューのデプロイから EvaluationForm をデプロイ
    ※プロジェクトのコンテキストメニューのデプロイではない
    ※万一でぷろいエラー[Deployer:149140]が出たら、Weblogic のコンソールを開いて左上の"Change Center"からセッションをクリア

■ テスト
  • Enterprise Manager で SimpleHumanTask を選択し、[Test]を実行する
  • Input Arguments の領域で、payload/input に 何か適当に入力
  • [Test Web Service] ボタンを押下
    • [Launch Message Flow Trace]を押下するとフローの状態が表示され、BPEL プロセスと Evaluation ヒューマン・タスクが Running 状態のままになのが分かる。
  • ワークリストに ブラウザからapprover でログインすると、回ってきたタスクが表示されている。
  • ダブルクリックするとフォームが開く
  • [承認]ボタンを押す。
    • 再度、Enterprise Manager からプロセスの様子を見ると、全部 Completed になったのが分かる

2010年3月21日日曜日

BPEL スキルの考察

思うところがあって、BPEL スキルがどんな風に構成されているか整理してみた。


術語の定義によっては若干変わるだろうけど(自分でも明日書いたら違うものになると思う)、だいたい上図のように ①XML基礎技術、②サービス指向技術、③ワークフロー技術という3つの技術が交わる領域の、さらに一部分をBPEL が占めるような配置になるんじゃないだろうか。

で、BPEL にはそれ自体に関するスキル以前に前提となるような技術要素あり、それぞれ①~③の領域に含まれていて、上図では特に依存性が強いものについて水色のハイライトで示した。

図中、重なった部分での①~③の各領域は均等の重みではなくて、私見では以下のようなバランスになる。
  • XML 基礎技術 → 5
  • サービス指向技術 → 3
  • ワークフロー技術 → 2
また、それに加えて依存関係の順序もあって、まず XML技術、次にその上にサービス指向技術が重なってXML Webサービス技術の領域を形成し、またその上にワークフロー技術が重なり BPELを含むワークフロー記述用 XML 仕様が来るのだと思う。

さらに、実際のプロジェクトでは標準仕様を独自に拡張した何らかの製品を使うので、この一層も含めて、今度は縦に切った形で図式化すると以下のようになる。
以上のようなイメージが、BPEL スキルの内訳とその依存関係、また BPEL 周りの周辺技術について自然に思い浮かぶものだと思う。まあ主観に違いないけれど、XML、SOA、ワークフローを体系的に勉強した経験があれば、細部を除いて概ね意見が一致する自明な認識ではなかろうか。

ところが、現実のプロジェクトで各種の残念な事情が重なると、これと全く違うイメージが形成されて、マネージメント層から業務エンジニア層・プログラマ層までプロジェクトチーム全体で共有されてしまう事がある(あるいは共有されているかのように振舞うことを強いられる)。

まだ上手くまとまらないが、列挙するとこんな感じ。
  • プロジェクトで採用された特定ベンダの BPEL 実装を、BPELの全てだと思い込んでいる。
  • 最初に示した図と内外を逆に、「BPEL」という大きなカテゴリに XSLTなどの基礎 XML 技術や、SOA や WSDL などの Webサービス技術が包含されていると思い込んでいる。
  • 特定ベンダの BPEL ツール使用経験を見て、XML基礎技術、サービス指向技術、ワークフロー技術のスキルレベルまでも満たされているものと思い込んでしまう。
脳内イメージは、たぶんこんな図式と推測できる。
このように、スキル要素の捉え方が大幅に間違っていると、プロジェクトの運営に当たって至る所で(教育、人員調達、情報共有、etc.)問題が生じる事は、リーダ/マネージャ経験者ならすぐ想像がつくと思う。

後日、今回の記事をベースにもうちょっと敷衍してみたい。

Oracle BPEL/string-join

入力メッセージ中の繰り返し要素を、区切り文字で連結して他のサービスに渡したりするようなコーディングは良くあると思う。例えば、検索用の Webサービスが外部にあるとして、これに渡す条件文を組み立てたりするのが典型的か。

この部分を 敢えてBPEL だけで書いたらこんな風になるけど...
...実際にはそんなフローを書く人は少ない。BPEL やワークフローを体系的に勉強していなくても、こんな粒度の細々したステップを書くのはまずかろうと、いくらなんでも普通は気づく(IDE は JDeveloper)。

で XSLT で書いたりするが、惜しいかな、いかにも手続き型っぽいこんな感じのコードが多い。
<xsl:template match="/">
<client:processResponse>
<client:result>
<xsl:for-each select="/client:process/client:input">
<xsl:choose>
<xsl:when test="position() > 1">
<xsl:text>,</xsl:text>
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</client:result>
</client:processResponse>
</xsl:template>
JDeveloper の XSLマップ デザイナ前提だと手続き型になるしかないけど、上記コードは実はこの時点でデザイナが使えなくなってる。<for-each> の使い方が違うとか、<choose> 内には<when> 要素が必要だとか意味不明なことを言ってくるが、見ての通りそんな問題は存在しない。

というわけで、これ以上糞ツールに気を使っても面白くないので、XSLT らしく関数型で書いてみる。
<xsl:template match="/">
<client:processResponse>
<client:result>
<xsl:apply-templates select="client:process/client:input[1]"/>
</client:result>
</client:processResponse>
</xsl:template>

<xsl:template match="client:input[following-sibling::client:input]">
<xsl:value-of select="."/>
<xsl:text>-</xsl:text>
<xsl:apply-templates select="following-sibling::client:input[1]"/>
</xsl:template>

<xsl:template match="client:input[not(following-sibling::client:input)]">
<xsl:value-of select="."/>
</xsl:template>
繰り返し文や条件文を全否定する気はサラサラないけど、関数型の書法の方が応用が利くので、こっちの方がお勧め。

もう一個の改善点は、XSLT 変換の範囲。

上記コードは、もともと Transform アクティビティ生成の結果作られたものを書き直したものなので、BPEL側の<assign>ではメッセージタイプからメッセージタイプへの変換になっている。従って、client:processResponse がもっと複雑な構造だと、<xsl:template match="/"> の中に 要素の複製や空要素の生成など無駄なコードが大量発生がちなので、次はこれを改善。
<xsl:template match="/">
<xsl:apply-templates select="client:process/client:input[1]"/>
</xsl:template>

<xsl:template match="client:input[following-sibling::client:input]">
以下同文

上記コードの出力は連結したテキストのみとなるので、このXSLTの出力を受ける BPEL 内の<to>要素に query 属性で processResponse/client:result を指定しておけば、最小限の要素をピンポイントで指定したコードになる。(XSLT内に<xsl:output method="text"/>も含めておく)

実は、更にもう一段階ある。

どうも JDeveloperでは、標準的な XSLT 関数なのに IDE的にサポートされていないものがあるらしい。例えば document()関数なども、ドロップダウンリストに表示されなかったりする。

ここまで例として取り上げてきた文字列の連結では、string-join 関数が使える。せっかく再帰で書いた上の XSLTコードがもったいないけど、実は 3行で書けちゃったりする。
<xsl:template match="/client:process">
<xsl:value-of select="string-join(client:input, ',')"/>
</xsl:template>

うーん、なんだか今日はずいぶん無駄なコードを書いたかも・・・

2010年3月19日金曜日

雑感:BPELとXSLT

なんかのフレームワークの設定ファイルくらいでしか XML を触った事のない Java/.NET の技術者が、いきなり BPEL 書きの仕事を始めると、SOAP や WSDL のような SOA/Webサービスの仕様だとか、それ以前の XSLT や XPath のような XML の基礎技術まで、BPEL というカテゴリに包含される技術だと思ってしまう傾向があるらしい。
特に XSLT などは、Transform アクティビティ(Oracle BPELの話)でしか使った事がない人が想像するよりも、本来は遥かにいろいろできたりするので、けっこうもったいない。

例として、1 から任意の自然数nまでの合計を求める処理を考えてみる。
これを 変数とループを使って手続き型のBPEL コードで書くこともできるけど、初歩のXSLT を知っていれば以下のようなXSLT で書くことができる。
<?xml version="1.0" encoding="windows-31j" ?>

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:n1="http://xmlns.oracle.com/OracleBpelTest1App_jws/Project2/BPELProcess2">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:call-template name="sum">
<xsl:with-param name="n" select="n1:process/n1:n" />
</xsl:call-template>
</xsl:template>
<xsl:template name="sum">
<xsl:param name="n"/>
<xsl:choose>
<xsl:when test="$n = 1">1</xsl:when>
<xsl:otherwise>
<xsl:variable name="x">
<xsl:call-template name="sum">
<xsl:with-param name="n" select="$n - 1" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$n + $x" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

これを "exercise1.xsl" というファイル名でプロジェクトに含めておくと、BPEL のAssign アクティビティからこんな感じで呼び出せる。
<assign name="Assign_1">

<copy>
<from expression="ora:processXSLT('exercise1.xsl',bpws:getVariableData('inputVariable','payload','/client:process'))"/>
<to variable="sum"/>
</copy>
</assign>

ora:processXSLTから*.xsl ファイルを実行するところまでは同じでも、いつもの BPEL の Transform とは主に以下のような点で違う。
  • transformation パターンのアノテーションがない。
  • XSLTがtextを出力している。
  • to で単純型の変数を指定して、これでXSLTの出力を受けている。
  • XSL に oracle-xsl-mapper インストラクションが無い

なんだかこの例だと手続き型の作法で書いたBPELコードと大差ないし、下手したら XSLT に不慣れな人には余計複雑に見えるようなった気がしないでもないが・・・

ただ、センスも腕もそこそこあるプログラマが、XSLT みたいなフツーのXML技術でできることを活用しないまま「BPELが不便すぎて」だとか「BPEL仕様の制約が・・・」なんてブツクサ言うのを見ると、ちょっともったいない気がする。第一、本人のスキルも十分生かされていないだろうし。

思うに、IDE のグラフィカルなデザイナ上では、XML 技術のわずかな部分しか使うことができない。入力XML要素から出力XML要素に線を引っ張るだけの作業がアホらしくなったら、いっそ 思い切って transform アノテーションを外してソース直接編集に切り替えた方が、自分にもチームにも品質にも、いろいろ良い効果があるかも。

2010年3月14日日曜日

Oracle BPEL/Java Embedding/正規表現

正規表現のグループ機能を使いたいが、matches(intputString, regexPattern) だとマッチングの成否を返すだけなので、Java Embedding を使ってみることにした。

環境:Fusion Middleware 11g + JDeveloper 11g

やりたい事は、例えば「テキストに含まれる最初の日付文字列から曜日を取り出す」といった感じの問題で、こんなふうにしたい。
<soapenv:Body>
<bpel:process>
<bpel:input>
こんにちは
今日の日付は 2010/03/13(土)
です。
</bpel:input>
</bpel:process>
</soapenv:Body>
<env:Body>
<processResponse xmlns="http://xmlns.oracle.com/OracleBpelTest1App_jws/Project1/BPELProcess1">
<result>土</result>
</processResponse>
</env:Body>

試しにBPEL デザイナ上でこんなコードを書いてみた。
更にソースエディタで、Java_Embedding_1 の直前に 以下のようにimport を記述する。
    <bpelx:exec import="org.w3c.dom.Element"/>
<bpelx:exec import="java.util.regex.*"//>

SoapUI から動かすと、期待したリクエスト/レスポンスが得られることが確認できた。

まあわりとすんなりいくが、以下、若干イラっとした点。
最初、org.w3c.dom.Element を import し忘れていたため、コンパイル時に普通に「シンボルが見つからない」という事になるが、コンパイラビューのメッセージには「クラスパスが正しくないので、正しく設定しろ」との文言が出る。これに騙されて、本来の原因に気づくまでクラスパス関連を確認し始めたりして、時間を無駄する羽目になる。JDeveloper はこういうミスリーディングな挙動が本当に多すぎてストレスがたまる。

2010年3月8日月曜日

Oracle BPEL 11g/Compensation

Oracle BPEL の Compensation の試し書き。


outerScope と innerScope の二重のスコープで、outerScope に faultHandler、innerScope に compensationHandler を定義するようなつくりにしてみた。

実行の流れとしては、innerScope 内の sayHi でレスポンスに文字列 "Hi!"を書き込んでからスコープを完了した直後、わざと fault を <throw>。この fault は outerScope の <faultHandler > でキャッチされるが、この<catch>節には innerScope の 補償が含まれているため、compensationHandler 内の sayBye が実行されて、レスポンスに "Bye!"が追記される。

これをSoapUI からの実行すると以下のようなレスポンスになる。
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<env:Header>
・・・略
</env:Header>
<env:Body>
<processResponse xmlns="http://xmlns.oracle.com/WorkflowPatternsApp_jws/BasicCflowPrj/CancelTask1Process">
<result>Hi!</result>
<result>Bye!</result>
</processResponse>
</env:Body>
</env:Envelope>


やってみるまで知らなかったけど、fault を投げている throw アクティビティを innerScope の中に入れてしまうと、compensation ハンドラが実行されなくなる。完了したスコープのみが補償対象になり得るというのが、BPEL仕様らしい。

ちなみに workflowpatterns の記述を見ると、BPELではこの Fault とCompensationを使ってCancel Task パターンが実現されるとあるけど、JDeveloper 上のモデルと workflowpatterns サイトの図解が全然似てなくて、なんだかよくわからない。

2010年3月3日水曜日

Oracle BPEL/複数のXML変数をXSLTに渡す

BPELで、二つの変数を XSLT の入力として使いたい場合、11g なら doXSLTransform を使えば良いけど、10g だと未サポートなので bpelx:append で要素をひとつにまとめて processXSLT 関数に渡すことになる。

このとき追加先となる BPEL変数は、スキーマ定義から逸脱して well-formed ではあっても valid ではない形にもなるが、非valid な XMLでも、内部の処理で変数として使う分には、別段、問題ないらしい。(さすがに外部に公開するサービスではまずいだろうけど。)

実は、自分の場合、内部の処理でも valid なXMLでないと駄目だと思い込んでしまって、若干はまった。XMLスキーマを変更して内部処理用の新たな型を追加しようとしたものの、最近入った現場ではそれがしにくい事情があって、けっこう悩んだ。valid でなくても良いんだと気づいたら本当にしょうもない話だが…

ちなみに JDeveloper の XSL デザイナの恩恵は得られないけど、もともと大して便利なツールじゃないし、これは別にいいや。<annotation> を取り除いて、Transform じゃない単なる Assign の xpath 関数にしてした上でソースを直接編集しても、それほど手間は変わらない。

2010年3月1日月曜日

Oracle BPEL/Email activity

Fusion Middleware 11g の Oracle BPEL で、Emailアクティビティを使ってみる。

■ 環境
・Fusion Middleware 11g、JDeveloper 11g
・Radish 3.0.0 (SMTP サーバ)

■ サーバ設定
BPEL に含めたEmailアクティビティを動かす前に、サーバ側の設定が必要となる。これをやっておかないと、BPEL の実行そのものはエラーにならないけど、メールは送られなかったりする。

◆ 電子メール・ドライバ・プロパティ
以下のように電子メール・ドライバ・プロパティを開く。

ここで、"Outgoing"で始まるプロパティを適当に設定する。試用目的なので、OutgoingMailServer に localhost とだけ指定したが、ポートやら、SMTP認証する場合のユーザ名/パスワードやら、一通り設定できる。

◆ ワークフロー通知プロパティ
以下のようにワークフロー通知プロパティの設定ページを開く。通知モードのデフォルトは「なし」になっているので、電子メールを選択する。それだけ。

設定したら再起動。

■ BPEL定義
Emailアクティビティを含む簡単なBPELフローを定義する。
中身はこんな風に設定してみる。ドメイン名とユーザ名は Radish で定義しておく。


先に進む前に、ちょっと観察してみる。

パートナーリンク NotificationService_1 は Emailアクティビティを追加したときに勝手に生成される。

Emailアクティビティ を展開すると、内部で構成されているinvoke アクティビティから、このパートナーリンクの操作 sendEmailNotification を呼んでいるのが分かる。
NotificationService_1の wsdl を見るとバインディングに java:binding が指定されている。初めて見た。

■ 実行
デプロイして実行すると Radish の MAILBOX にメールが入っているのが分かる。