BPL プロセスについて
Ensemble ビジネス・プロセス言語 (BPL) は、標準の XML ドキュメント内で実行可能なビジネス・プロセスを記述するために使用する言語です。BPL の構文は、ビジネス・プロセス・ロジックを定義するための推奨 XML 標準の複数の項目に基づいています。BPL ビジネス・プロセス・クラスは、Ens.BusinessProcessBPLOpens in a new tab から派生します。BPL ビジネス・プロセス・クラスは、BPL をサポートするという点を除いて、Ens.BusinessProcessOpens in a new tab から派生したクラスとすべての点で同じです。
管理ポータルで BPL クラスを作成するには、[Ensemble]、[ビルド] の順にクリックし、[ビジネス・プロセス] をクリックします。Ensemble には Ensemble, ビジネス・プロセス・デザイナ ページが表示されます。(スタジオで BPL クラスを開くと、ビジネス・プロセス・デザイナが起動します。“スタジオでの BPL 作成に関する注意事項” を参照してください)。
管理ポータルの [ビジネス・プロセス・デザイナ] ページに移動すると、ビジネス・プロセス・デザイナが開いて、このネームスペース内で最後に操作したビジネス・プロセスが表示されます。タイトル・バーの左側にあるタブには、その BPL クラスの名前が表示されます。以下のいずれかの方法で、異なるビジネス・プロセスを操作対象として選択することもできます。
-
[新規作成] をクリックして、ビジネス・プロセス・ウィザードを使用して BPL ビジネス・プロセスを作成します。
-
[開く] をクリックして、ビジネス・プロセス・デザイナを使用して既存の BPL ビジネス・プロセスを編集します。
ビジネス・プロセス、データ変換、およびビジネス・ルールで使用可能なオプションが重複していることに注意してください。違いを確認する場合は、"Ensemble プロダクションの開発" の “ビジネス・ロジック・ツールの比較” を参照してください。
ビジネス・プロセス・ウィザードの使用
[ビジネス・プロセス・ウィザード] を使用すると、Ens.BusinessProcessBPLOpens in a new tab から継承した BPL ビジネス・プロセス・クラスをすばやく作成できます。このウィザードで表示される次のダイアログでは、作成する BPL ビジネス・プロセスの予備的特性を定義できます。
以下のフィールドの値を入力します。
このビジネス・プロセス・クラスを格納するパッケージの名前を入力するか、ネームスペース内のパッケージのリストから選択します。
この BPL ビジネス・プロセス・クラスの名前を入力します。
(オプション) データ変換の説明を入力します。これはクラスの説明として使用されます。
[OK] をクリックしてウィザードを完了すると、BPL ダイアグラムの開始点と終了点がビジネス・プロセス・デザイナに表示され、その BPL ビジネス・プロセスにアクティビティを追加できる状態になります。
ビジネス・プロセス・リスト
Ensemble, ビジネス・プロセス・リスト ページには、アクティブな Ensemble ネームスペースで定義されているビジネス・プロセス・クラスのリストが表示されます。管理ポータルでこのページに移動するには、[Ensemble]、[ビルド] の順にクリックし、[ビジネス・プロセス] をクリックします。
BPL ビジネス・プロセスは青色で表示されます。BPL ビジネス・プロセスをダブルクリックすると、その BPL ビジネス・プロセスが [ビジネス・プロセス・デザイナ] に表示されます。黒色で表示されるビジネス・プロセスは、スタジオで編集する必要のあるカスタム・クラスです。
ビジネス・プロセス・クラスを選択することで、そのビジネス・プロセス・クラスをリボン・バーにある以下のコマンドのいずれかのターゲットにできます。
-
[新規作成] — 前述したように、ビジネス・プロセス・ウィザードが起動します。
-
[開く] (BPL クラスのみ) — 選択したビジネス・プロセスを編集します。
-
[エクスポート] — 選択したビジネス・プロセス・クラスを XML ファイルにエクスポートします。
-
[インポート] — XML ファイルにエクスポートされたビジネス・プロセスをインポートします。
-
[削除] — 選択したビジネス・プロセス・クラスを削除します。
-
[インスタンス] — 実行中のプロダクション内のビジネス・プロセスの現在のインスタンスを一覧表示します。ビジネス・プロセスがその処理を完了している場合は、このページにはエントリは表示されません。
"Ensemble の監視" を参照してください。
-
[ルール・ログ] — このビジネス・プロセスによって呼び出されたルールのビジネス・ルール・ログを表示します。
"Ensemble の監視" を参照してください。
Ensemble の他のクラスと同じように、ビジネス・プロセス・クラスをエクスポートおよびインポートすることもできます。管理ポータルの システム, クラス ページの使用や、スタジオの [ツール] メニューにある [エクスポート] コマンドや [インポート] コマンドの使用も可能です。
BPL 機能
BPL は、標準の XML ドキュメント内で実行可能なビジネス・プロセスを記述するために使用する言語です。BPL 構文は、Web サービス向けビジネス・プロセス実行言語 (BPEL4WS または BPEL)、ビジネス・プロセス管理言語 (BPML または BPMI) など、ビジネス・プロセス・ロジックの定義を目的とする複数の推奨 XML 標準に基づいています。
BPL は、その他に指定されている XML ベースの標準のスーパセットで、統合ソリューション構築の補助を目的とした追加要素を提供します。これらの追加要素でサポートされているのは以下のとおりです。
-
<branch>、<if>、<switch>、<foreach>、<while>、<until> など、実行フロー・コントロール要素。これらの要素やその他の BPL 構文要素の使用方法の詳細は、"Ensemble ビジネス・プロセス言語 (BPL) リファレンス" を参照してください。
-
ビジネス・プロセス・ロジックからの実行可能コードの生成。
-
ビジネス・プロセス・ロジックへのSQL およびカスタム記述コードの埋め込み。
-
ビジネス・プロセス・デザイナ (ビジネス・プロセス・ロジックをグラフィカルに表示および編集するためのフル機能を備えたビジュアル・モデリング・ツール)。このツールは、ビジネス・プロセスのビジュアル表示および BPL 表示間での完全なラウンドトリップ・エンジニアリングを備えています。一方の表示で変更を行うと、変更内容が自動的に他方に反映されます。
-
ビジネス・プロセスと統合ソリューションのその他のメンバ間での、非同期および同期メッセージング両方の自動サポート。BPL を使用すると、このようなエラーの発生しやすい難しいタスクを合理化できます。
-
永続的な状態。BPL では、長時間実行中のビジネス・プロセスが非アクティブであり、非同期の応答を待機しているような場合に、そのビジネス・プロセスに実行の自動中断を許可し、Ensemble に埋め込まれた組み込み型の永続キャッシュに実行状態を効果的に保存できるようにします。Ensemble では自動的に、保存されているすべての状態が管理され、処理の再開が適切に管理されます。
-
リッチで多様性に富むデータ変換サービス。これには、ビジネス・プロセス内に埋め込まれた SQL クエリも含まれます。
BPL ビジネス・プロセスは、管理ポータルまたはスタジオを使用して作成できます。推奨される方法は、管理ポータルの Ensemble, ビジネス・プロセス・デザイナ ページからビジネス・プロセス・ウィザードを使用することです。詳細は、以降の章を参照してください。
ビジネス・プロセスのコンポーネントとしての使用法
ビジネス・プロセス・コンポーネントまたはBPL コンポーネントは、プログラマが BPL 言語のモジュール式の再利用可能な一連の手順として指定する BPL ビジネス・プロセスです。BPL コンポーネントは、他のプログラミング言語における関数、マクロ、サブルーチンと似ています。
別の BPL ビジネス・プロセスのみが BPL コンポーネントを呼び出すことができます。これは、BPL の <call> 要素を使用して呼び出します。BPL ビジネス・プロセス・コンポーネントは、タスクを実行すると、呼び出された BPL ビジネス・プロセスに制御を戻します。
Ensemble アーキテクチャでは、ある BPL ビジネス・プロセスを使用して別の BPL ビジネス・プロセスを呼び出せるようになっています。オプションのコンポーネントを指定することにより、さらに便利になります。これにより、特定の BPL ビジネス・プロセスを、以下のようなより単純な下位レベルのコンポーネントに分類できます。
-
スタンドアロンのビジネス・プロセスとして実行することを目的としないコンポーネント (ただし、このアーキテクチャでその妨げになるものはありません)
-
(BPL 言語の関数、マクロ、サブルーチンという意味での) 再利用可能コンポーネント
コンポーネントでないビジネス・プロセスは、より複雑で特殊な目的で設計され、コンポーネントより高い概念レベルで動作するものと想定されます。BPL のコンポーネント以外は、BPL コンポーネントを呼び出してタスクを実行することが想定されます。
任意の BPL ビジネス・プロセスに対して、コンポーネントの指定を使用するための要件はありません。BPL プログラマは、目的に合わせて適宜利用できます。
ビジネス・プロセスをコンポーネントに変換するには、その BPL ビジネス・プロセスに対して最上位レベルの <process> コンテナの属性を設定します。この属性は component という名前であり、その値は 1 (真) または 0 (偽) に設定できます。構文の詳細は、"Ensemble ビジネス・プロセス言語 (BPL) リファレンス" を参照してください。
component 属性の値を設定するには、以下のいずれかを実行します。
-
ビジネス・プロセス・デザイナ の [一般] タブで、[コンポーネント] を選択して、このプロセスをコンポーネント・ライブラリに組み込みます。
-
スタジオを使用して、クラス・コードの XData BPL ブロック内の BPL <process> 要素を編集します。
BPL ビジネス・プロセスからコンポーネントに対する <call> をセットアップするには、後述する “コール・アクティビティの追加” を参照してください。
ビジネス・プロセスの実行コンテキスト
ビジネス・プロセスのライフ・サイクルでは、ビジネス・プロセスが実行を中断または再開するたびに、一定のステータス情報をディスクに保存し、またディスクからリストアする必要があります。この機能は、完了までに数日または数週間かかる可能性のある長期実行のビジネス・プロセスにおいては特に重要です。
BPL ビジネス・プロセスでは、実行コンテキストと呼ばれる、変数グループを使用したビジネス・プロセスのライフ・サイクルをサポートしています。BPL ビジネス・プロセスの実行が中断および再開されるたびに、実行コンテキスト内の変数が自動的に保存およびリストアされます。これらの変数は、すべての BPL ビジネス・プロセス、つまり、Ens.BusinessProcessBPLOpens in a new tab から継承したすべてのビジネス・プロセス・クラスに使用できます。
Ens.BusinessProcessOpens in a new tab から継承したカスタム・ビジネス・プロセスは、組み込みの実行コンテキストにアクセスできないため、カスタム・コードを使用して同様の処理を実行する必要があります。
実行コンテキスト変数には、BPL ビジネス・プロセス内のすべてのアクティビティで利用可能なものがあります。その他の変数は通常利用可能ですが、ビジネス・プロセスが実行しているアクティビティのタイプによっては、スコープ内に含まれる場合もあれば、含まれない場合もあります。以下のトピックでは、実行コンテキスト変数と、その変数が BPL ビジネス・プロセスで使用される状況について説明します。変数には、以下のものがあります。
<process>、<context>、<call> などの BPL 要素の BPL 構文に関する詳細は、"Ensemble ビジネス・プロセス言語 (BPL) リファレンス" を参照してください。これには、コンテキスト変数の参照情報も記載されています。
context オブジェクト
context オブジェクトは、<process> 要素内の任意の箇所で BPL ビジネス・プロセスによって使用可能です。context は、ビジネス・プロセスのライフ・サイクル中に永続化される必要のある任意のデータ用の汎用コンテナです。BPL ビジネス・プロセスの作成時に、各データ項目を context オブジェクト上のプロパティとして定義します。推奨手順は、“context オブジェクトの定義” を参照してください。
context オブジェクト上のプロパティを定義したら、通常のドット構文と対象のプロパティ名を使用して、BPL 内のどこからでもそれらのプロパティを参照できます (例 : context.MyData)。
request オブジェクト
request オブジェクトには、元の要求メッセージ・オブジェクトに含まれていたプロパティが格納されています。元の要求メッセージ・オブジェクトとは、このビジネス・プロセスを最初にインスタンス化させた受信メッセージです。これは基本要求と呼ばれます。
request オブジェクトは、<process> 要素内であれば、BPL ビジネス・プロセスによって使用できます。request オブジェクトのプロパティを参照するには、request.OriginalThought のようにドット構文とプロパティ名を使用します。
response オブジェクト
response オブジェクトには、ビジネス・プロセス・インスタンスが返す最終的な応答メッセージ・オブジェクトを構築するのに必要なプロパティが含まれます。ビジネス・プロセスは、ライフ・サイクルの最後に達したとき、または <reply> アクティビティを検出したときに、この最終的な応答を返します。
response オブジェクトは、<process> 要素内であれば、BPL ビジネス・プロセスによって使用できます。response オブジェクトのプロパティを参照するには、response.BottomLine のようにドット構文とパラメータ名を使用します。
callrequest オブジェクト
callrequest オブジェクトには、<call> で送信する要求メッセージ・オブジェクトを作成する際に必要となるすべてのプロパティが含まれます。
<call> アクティビティは、要求メッセージを送信し、必要に応じて応答を受信します。BPL <call> 要素には、要求メッセージ・オブジェクトのプロパティに値を挿入する <request> アクティビティが含まれている必要があります。そのため、<request> には、callrequest オブジェクトのプロパティに値を挿入する一連の <assign> アクティビティが用意されています。これらの値には、通常、元の request オブジェクトのプロパティ値が使用されますが、任意の値を割り当てることができます。
<request> 内の <assign> アクティビティが完了すると、すぐにメッセージが送信され、関連付けられた callrequest オブジェクトはスコープから外れます。callrequest は、関連付けられた <request> アクティビティの外部では意味を持たないため、関連付けられた <call> が次のアクティビティであるオプションの <response> の処理を開始するときには、既にスコープから外れています。
関連する <request> 要素のスコープ内であれば、callrequest.UserData のようにドット構文を使用して、callrequest のプロパティを参照できます。
callresponse オブジェクト
<call> アクティビティが完了すると、callresponse オブジェクトには、<call> に返された応答メッセージ・オブジェクトのプロパティが追加されます。<call> が応答を待たないアクティビティとして設計されていた場合、callresponse はありません。同様に、<sync> を使用して応答を待っていても、<sync> 要素で指定されたタイムアウト期間内に応答が返ってこなかった場合は、callresponse が存在しません。
応答を待つ <call> はすべて、<call> 内に <response> アクティビティが存在している必要があります。<response> アクティビティの目的は、応答値を取得し、それをビジネス・プロセス全体で使用できるようにすることです。callresponse オブジェクトは、<response> アクティビティ内であればどこでも使用できます。ただし、<response> アクティビティが完了した時点で、関連する callresponse オブジェクトはスコープから外れます。そのため、ビジネス・プロセスの他の場所で callresponse の値を使用する場合は、その値に対して context オブジェクトまたは response オブジェクトのプロパティへの <assign> を実行し、値を受信した <response> アクティビティが完了するまでに、この処理を実行する必要があります。
callresponse のプロパティを参照するには、callresponse.UserAnswer のようにドット構文を使用します。
syncresponses コレクション
syncresponses は、<sync> によって同期化された <call> アクティビティの名前をキーとするコレクションです。
<sync> アクティビティが開始されると、新しい応答に備えて、syncresponses が消去されます。<call> アクティビティが返されると、応答がコレクションに格納されます。<sync> アクティビティが完了すると、syncresponses には、必要な応答のすべてまたは一部が格納されるか、何も格納されません (synctimedout を参照してください)。syncresponses は、関連する <call> および <sync> アクティビティが含まれた <sequence> の内部であれば使用できますが、<sequence> の外部ではスコープから外れます。
同期化された呼び出しの 1 つから応答値を参照するには、構文 syncresponses.GetAt("name") を使用します。
ここで、関連する <call> は <call name="name"> と定義されます。
synctimedout 値
synctimedout は 0、1、または 2 の値を取る整数値です。synctimedout は、いくつかの呼び出し後の <sync> アクティビティの結果を示します。synctimedout の値をテストできるのは、<sync> の後から、該当する呼び出しと <sync> を含む <sequence> の直前までです。synctimedout の値は、以下の 3 つのいずれかになります。
-
0 の場合、どの呼び出しもタイムアウトになっていません。すべての呼び出しが時間内に完了しました。<sync> アクティビティに timeout が設定されていない場合も、この値が返されます。
-
1 の場合、1 つ以上の呼び出しがタイムアウトになりました。つまり、時間切れのため、完了できなかった <call> アクティビティがあります。
-
2 の場合、1 つ以上の呼び出しが中断されました。
synctimedout は、関連する <call> アクティビティと <sync> アクティビティが含まれた <sequence> の内部であれば、BPL ビジネス・プロセスに使用できますが、<sequence> の外部では、スコープから外れます。通常、synctimedout を取得してステータスを確認し、その後、syncresponses コレクションの完了した呼び出しから応答を取得します。synctimedout を参照するには、synctimedout のように、整数の変数名と同じ構文を使用します。
status 値
status は、成功または失敗を示す %StatusOpens in a new tab 型の値です。
BPL ビジネス・プロセスのエラー処理は自動的に実行されます。BPL ソース・コードで status 値をテストまたは設定する必要はありません。ここでは、特殊な状況下で BPL ビジネス・プロセスを終了しなければならない場合に備えて、status 値が設けられています。
BPL ビジネス・プロセスが開始されると、status には成功を示す値が自動的に割り当てられます。status に成功値が割り当てられているかどうかを確認するには、ObjectScript ではマクロ $$$ISOK(status)、Basic ではメソッド $SYSTEM.Status.IsOK(status) を使用します。このテストで True 値が返された場合、status には成功値が格納されています。
BPL ビジネス・プロセスの実行中に status が失敗値を受け取ると、そのビジネス・プロセスは即座に終了し、該当するテキスト・メッセージがイベント・ログに書き込まれます。この処理は、status がどのような状況で失敗値を受け取ったかにかかわらず実行されます。したがって、status に失敗値を設定すれば、BPL ビジネス・プロセスをいつでも正常に終了することができます。
status では、以下のいずれかの方法で失敗値を取得できます。
-
status は、ビジネス・プロセスが別のビジネス・ホストに対して実行した任意の <call> から返された %StatusOpens in a new tab 値を自動的に受け取ります。この %StatusOpens in a new tab の値が失敗を示す場合、status には自動的にその失敗値が入ります。これは、status を設定する最も一般的な方法で、BPL コードで特別な文を使用しなくても、自動的に処理されます。
-
<assign> アクティビティで、status を失敗値に設定できます。そのために、一般的には <if> 要素を使用して前のアクティビティの結果をテストし、<true> 要素または <false> 要素の中で <assign> を使用して失敗条件が存在すれば status を失敗値に設定します。
-
<code> アクティビティ内の文では、status を失敗値に設定できます。<code> アクティビティがすべて完了するまで、BPL ビジネス・プロセスは status 値の変更を認識しません。したがって、status が失敗の場合に <code> アクティビティを即座に終了するには、status に失敗値を設定した直後に、<code> アクティビティ内に終了コマンドを配置する必要があります。
status に失敗値が割り当てられているかどうかを確認するには、ObjectScript ではマクロ $$$ISERR(status)、Basic ではメソッド $system.Status.IsError(status) を使用します。このテストで True 値が返された場合、status には失敗値が格納されています。このテストは、メイン BPL ビジネス・プロセスに戻る前に <code> アクティビティの本体内でのみ実行できます。ビジネス・プロセスは任意の <call>、<assign>、または <code> アクティビティの後に status で失敗値を取得したことを検出すると、自動的にエラーで終了してしまいます。
BPL ビジネス・プロセスでは、<process> 内であればどこでも status を使用できます。status を参照するための構文は、%StatusOpens in a new tab 型の変数の場合と同じです。つまり status となります。
その他すべての実行コンテキスト変数名と同様、status は BPL の予約語です。上記の場合を除き、この予約語を使用しないでください。
process オブジェクト
process オブジェクトは、BPL ビジネス・プロセス・オブジェクトの現在のインスタンスを表します。process オブジェクトの目的は、BPL ビジネス・プロセスのフロー内の任意のコンテキストから (例えば、<code> アクティビティのテキスト・ブロック内から)、SendRequestSync() や SendRequestAsync() などの任意のビジネス・プロセス・メソッドを呼び出せるようにすることです。
process オブジェクトは、<process> 要素内であれば、BPL ビジネス・プロセスで使用できますが、一般的には <code> アクティビティ内でのみ必要になります。process オブジェクトのメソッドを参照するには、process.SendRequestSync() や process.ClearAllPendingResponses のようにドット構文とメソッド名を使用します。
BPL ビジネス・プロセスの例
以下のサンプル・ビジネス・プロセスは、ENSDEMO ネームスペースの Demo.Loan というサンプル・プロダクション・パッケージ内のクラスに似ています。このビジネス・プロセスでは、3 つの異なる銀行にプライム・レートと信用承認情報を相談できます。
/// Loan Approval Business Process for Bank Soprano.
/// Bank Soprano simulates a bank with great service but
/// somewhat high interest rates.
Class Demo.Loan.BankSoprano Extends Ens.BusinessProcessBPL
{
XData BPL
{
<process request="Demo.Loan.Msg.Application"
response="Demo.Loan.Msg.Approval">
<context>
<property name="CreditRating" type="%Integer"/>
<property name="PrimeRate" type="%Numeric"/>
</context>
<sequence>
<trace value='"received application for "_request.Name'/>
<assign name='Init Response'
property="response.BankName"
value='"BankSoprano"'>
<annotation>
Initialize the response object.
</annotation>
</assign>
<call name="PrimeRate"
target="Demo.Loan.WebOperations"
async="1">
<annotation>
Send an asynchronous request for the Prime Rate.
</annotation>
<request type="Demo.Loan.Msg.PrimeRateRequest"/>
<response type="Demo.Loan.Msg.PrimeRateResponse">
<assign property="context.PrimeRate"
value="callresponse.PrimeRate"/>
</response>
</call>
<call name="CreditRating"
target="Demo.Loan.WebOperations"
async="1">
<annotation>
Send an asynchronous request for the Credit Rating.
</annotation>
<request type="Demo.Loan.Msg.CreditRatingRequest">
<assign property="callrequest.TaxID" value='request.TaxID'/>
</request>
<response type="Demo.Loan.Msg.CreditRatingResponse">
<assign property="context.CreditRating"
value="callresponse.CreditRating"/>
</response>
</call>
<sync name='Wait'
calls="PrimeRate,CreditRating"
type="all"
timeout="10">
<annotation>
Wait for the response from the async requests.
Wait for up to 10 seconds.
</annotation>
</sync>
<switch name='Approved?'>
<case name='No PrimeRate'
condition='context.PrimeRate=""'>
<assign name='Not Approved'
property="response.IsApproved"
value="0"/>
</case>
<case name='No Credit'
condition='context.CreditRating=""'>
<assign name='Not Approved'
property="response.IsApproved"
value="0"/>
</case>
<default name='Approved' >
<assign name='Approved'
property="response.IsApproved"
value="1"/>
<assign name='InterestRate'
property="response.InterestRate"
value="context.PrimeRate+10+(99*(1-(context.CreditRating/100)))">
<annotation>
Copy InterestRate into response object.
</annotation>
</assign>
</default>
</switch>
<delay
name='Delay'
duration="2+($zcrc(request.Name,4)#5)">
<annotation>
Wait for a random duration.
</annotation>
</delay>
<trace value='"application is "
_$s(response.IsApproved:"approved for "_response.InterestRate_"%",
1:"denied")'/>
</sequence>
</process>
}
}