BRMS ビジネスプロセス管理ガイド

JBoss Enterprise BRMS Platform 5

JBoss 開発者およびルール作成者向け

エディッション 5.3.1

Red Hat Content Services

概要

JBoss Enterprise Business Rules Management System 5.3.1 のビジネスプロセス管理機能の利用ガイド

前書き

第1章 はじめに

1.1. はじめに

JBoss BRMS 5.3 の Business Process Management 機能により、ビジネス目標を達成するために必要となる手順を記載したフローチャートとしてビジネスプロセスをモデル化できるようになります。
プロセス例

図1.1 プロセス例

JBoss BRMS および Business Process Management (BPM) エンジンは、JBoss Enterprise Application Server 5.1.2 を実行するスタンドアローンインストレーションとしてデプロイするか、既存のアプリケーションサーバーとしてデプロイ可能です。認定済みの設定および互換性のある設定のすべてが http://www.redhat.com/resourcelibrary/articles/jboss-enterprise-brms-supported-configurations から一覧で確認いただけます。
インストールの説明は、『JBoss BRMS 5.3 スタートガイド』を参照してください。
JBoss BRMS 5.3 の Business Process Management 機能は Java で記述されており、BPMN 2.0 仕様 (完全な詳細は 『Business Process Model and Notation (BPMN) 2.0 Specification』 を参照してください) を実装しています。
以下のツールがライフサイクル全体のビジネスサイクルに対応できるよう含まれています。
  • ビジネスプロセスの作成や編集を行うための JBoss BRMS ユーザーインターフェースに埋め込まれたグラフィカルエディター
  • ビジネスプロセスの作成や編集を行うための JBoss Developer Studio 向けのグラフィカルエディタープラグイン
  • プロセスの監視、ヒューマンタスク管理、レポート追加機能を提供する管理コンソール
  • プロセスの保存、バージョニング、管理を行うために JBoss BRMS リポジトリと統合
  • 外部のヒューマンタスクサービスと統合

第2章 ビジネスプロセス管理 API

2.1. API

JBoss BRMS Platform ナレッジ API を使用して、プロセス、ビジネスルール、複合イベント処理をロード、実行します。
この画像は、ナレッジセッションとナレッジベースについて API 内の移行を説明しています。ナレッジベースはプロセス定義を含み、ナレッジセッションはプロセスインスタンスを実行します。

図2.1 ナレッジベースとナレッジセッション

API は以下を目的としています。
  1. プロセス定義を含むナレッジベースの作成
  2. 新規プロセスインスタンスの開始、既存プロセスインスタンスのシグナル、リスナーの登録を行えるようにセッションを作成
ナレッジベースは、アプリケーションのプロセス定義を提供します。定義は、ナレッジベースに含まれるか、ナレッジベースから参照してクラスパスやファイルシステムなど別のリソースにロードします。
ナレッジベースへアクセスできるセッションについては、初期化してプロセスエンジンと通信しプロセスの実行を行う必要があります。プロセスが開始されると、そのプロセス定義の新規インスタンスが作成されこのインスタンスで固有のプロセスインスタンスのステータスを保持します。

2.2. ナレッジベースの作成

ナレッジベースには、セッションの実行が必要のあるプロセス定義すべてを含むか、参照する必要があります。
ナレッジビルダーを使用して必要とされるリソース (例: クラスパスまたはファイルシステム) からプロセスをロードして、このナレッジビルダーから新しいナレッジベースを作成します。以下のコードスニペットは、クラスパスからのリソースを使用して、プロセス定義を 1 つ含むナレッジベースを作成します。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("MyProcess.bpmn"), ResourceType.BPMN2);
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
ResourceFactory には、ファイルシステム、URL、InputStream、Reader からファイルをロードするよく似たメソッドが含まれています。
ナレッジベースはセッション間で共有でき、通常アプリケーション開始時に作成されます。ナレッジベースは動的に変更可能で、プロセスをランタイム時に追加または削除できます。

2.3. セッションの作成

セッション (新規プロセスを開始してイベントに関するシグナルを送信) は、プロセスエンジンと対話してプロセスを実行するために作成されます。必要なだけセッションを開始できますが、アプリケーションの要件によってセッション 1 つ (このセッションはアプリケーションの複数ヶ所から呼び出し可能) で十分な場合もあります。
以下のコードスニペットは、先ほど作成したナレッジベースをもとにセッションを作成して、その ID でプロセスを開始します。
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ProcessInstance processInstance = ksession.startProcess("com.sample.MyProcess");
ProcessRuntime インターフェースは、例2.1「ProcessRuntime インターフェース」 に記載されているように、プロセスと対話するセッションメソッドすべてを定義します。

例2.1 ProcessRuntime インターフェース

	/**
	 * Start a new process instance.  The process (definition) that should
	 * be used is referenced by the given process id.
	 * 
	 * @param processId  The id of the process that should be started
	 * @return the ProcessInstance that represents the instance of the process that was started
	 */
    ProcessInstance startProcess(String processId);

    /**
	 * Start a new process instance.  The process (definition) that should
	 * be used is referenced by the given process id.  Parameters can be passed
	 * to the process instance (as name-value pairs), and these will be set
	 * as variables of the process instance. 
     * 
	 * @param processId  the id of the process that should be started
     * @param parameters  the process variables that should be set when starting the process instance 
	 * @return the ProcessInstance that represents the instance of the process that was started
     */
    ProcessInstance startProcess(String processId,
                                 Map<String, Object> parameters);

    /**
     * Signals the engine that an event has occurred. The type parameter defines
     * which type of event and the event parameter can contain additional information
     * related to the event.  All process instances that are listening to this type
     * of (external) event will be notified.  For performance reasons, this type of event
     * signaling should only be used if one process instance should be able to notify
     * other process instances. For internal event within one process instance, use the
     * signalEvent method that also include the processInstanceId of the process instance
     * in question. 
     * 
     * @param type the type of event
     * @param event the data associated with this event
     */
    void signalEvent(String type,
                     Object event);

    /**
     * Signals the process instance that an event has occurred. The type parameter defines
     * which type of event and the event parameter can contain additional information
     * related to the event.  All node instances inside the given process instance that
     * are listening to this type of (internal) event will be notified.  Note that the event
     * will only be processed inside the given process instance.  All other process instances
     * waiting for this type of event will not be notified.
     * 
     * @param type the type of event
     * @param event the data associated with this event
     * @param processInstanceId the id of the process instance that should be signaled
     */
    void signalEvent(String type,
                     Object event,
                     long processInstanceId);

    /**
     * Returns a collection of currently active process instances.  Note that only process
     * instances that are currently loaded and active inside the engine will be returned.
     * When using persistence, it is likely not all running process instances will be loaded
     * as their state will be stored persistently.  It is recommended not to use this
     * method to collect information about the state of your process instances but to use
     * a history log for that purpose.
     * 
     * @return a collection of process instances currently active in the session
     */
    Collection<ProcessInstance> getProcessInstances();

    /**
     * Returns the process instance with the given id.  Note that only active process instances
     * will be returned.  If a process instance has been completed already, this method will return
     * null.
     * 
     * @param id the id of the process instance
     * @return the process instance with the given id or null if it cannot be found
     */
    ProcessInstance getProcessInstance(long processInstanceId);

    /**
     * Aborts the process instance with the given id.  If the process instance has been completed
     * (or aborted), or the process instance cannot be found, this method will throw an
     * IllegalArgumentException.
     * 
     * @param id the id of the process instance
     */
    void abortProcessInstance(long processInstanceId);

    /**
     * Returns the WorkItemManager related to this session.  This can be used to
     * register new WorkItemHandlers or to complete (or abort) WorkItems.
     * 
     * @return the WorkItemManager related to this session
     */
    WorkItemManager getWorkItemManager();

2.4. イベントリスナー

セッションは、リスナーの登録や削除のメソッドを提供します。ProcessEventListener を使用して、プロセスの開始や完了、ノードの出入りなど、プロセス関連のイベントをリッスンすることができます。ProcessEventListener クラスの様々なメソッドが以下の例で示されています。イベントオブジェクトは、プロセスインスタンスやイベント関連するノードインスタンスなど関連の情報にアクセスできるようにします。この API を使用してイベントリスナーを登録することができます。

例2.2 ProcessEventListener クラス

public interface ProcessEventListener {

  void beforeProcessStarted( ProcessStartedEvent event );
  void afterProcessStarted( ProcessStartedEvent event );
  void beforeProcessCompleted( ProcessCompletedEvent event );
  void afterProcessCompleted( ProcessCompletedEvent event );
  void beforeNodeTriggered( ProcessNodeTriggeredEvent event );
  void afterNodeTriggered( ProcessNodeTriggeredEvent event );
  void beforeNodeLeft( ProcessNodeLeftEvent event );
  void afterNodeLeft( ProcessNodeLeftEvent event );
  void beforeVariableChanged(ProcessVariableChangedEvent event);
  void afterVariableChanged(ProcessVariableChangedEvent event);

}
'Before' および 'after' イベントは通常スタックのように振る舞います。つまり、以前のイベントの直接的結果として発生したイベントはイベントの 'before' と 'after' の間で発生します。例えば、後続のノードは、ノードから離れた結果としてトリガーされた場合、 (最初のノードを離れたことが直接の原因で、2 番目のノードをトリガーされているため) 'NodeTriggered' イベントは離れたノードの 'beforeNodeLeftEvent' と the 'afterNodeLeftEvent' の間で発生します。このトリガーは、イベント間の関係をより簡単にもたらすことができます。同様に、プロセス開始の直接的な結果となる 'NodeTriggered' と 'NodeLeft' イベントはすべて 'beforeProcessStarted' と 'afterProcessStarted' イベントの間で発生します。一般的に特定のイベントが発生した場合に通知が必要であれば、'before' イベントのみを参照します (イベントが実際に発生する直性に起こるため)。'after' イベントだけを参照する場合、イベントが違う順番で引き起こされていると感じるかもしれませんが、今回の場合は 'after' イベントはスタックとしてトリガーされているためです (このイベントがすでに引き起こされた結果としてすべてのイベントがトリガーされている場合のみ 'after' イベントが引き起こされます)。このイベントに関連する処理がすべて完了したことを確認したい場合のみ、'After' イベントを使用します。例えば、特定のプロセスインスタンスの開始が完了した時に通知が必要な場合などは、'after' イベントが理想的です。
すべてのノードが常に 'NodeTriggered' や 'NodeLeft' イベントを生成するわけではないことに注意してください。ノードの種類により、'NodeLeft' イベントのみを生成するノードもあり、'NodeTriggered' イベントのみを生成するノードもあります。例えば、 (他のノードによりトリガーされたのではなく外部からアクティベートされたがため、'left' イベントが生成されているため) 中間イベントを 'Catch' してもトリガーされたイベントは生成されません。同様に、中間イベントが 'throw' されても 'left' イベントは生成されません (外向きの接続がないためノードから実際には離れていないため 'triggered' イベントのみが生成されます)。
イベントリスナーは、(コンソールまたはファイルシステムのファイルへ) 監査ログを作成するために利用できるように提供されています。この監査ログには、ランタイム時に発生したイベントがすべて含まれています。これらのロガーはデバッグ目的でのみ使用するようにしてください。
以下のロガーの実装はデフォルトでサポートされています。

表2.1 サポートされているロガー

タイプ 説明 必須の引数
コンソール ロガーが閉じられたり、イベントの数が所定のレベルに達したりした場合は、出力がコンソールに書き込まれます。 ログすべきナレッジセッション
ファイル 出力は XML でファイルに書き込まれます。
ログすべきナレッジセッション
作成するログファイル名
スレッドファイル 指定の間隔があくと、出力がファイルに書きだされます。これは、デバッグ中にリアルタイムの進捗を可視確認する際に便利です。
ログすべきナレッジセッション
作成するログファイル名
イベントを保存する間隔 (ミリ秒)
KnowledgeRuntimeLoggerFactory は、以下の例のようにロガーをセッションに追加できるようにします。アプリケーションの使用が終わるとロガーを常に終了するようにしてください。

例2.3 KnowledgeRuntimeLogger

KnowledgeRuntimeLogger logger =
    KnowledgeRuntimeLoggerFactory.newFileLogger( ksession, "test" );
// add invocations to the process engine here,
// e.g. ksession.startProcess(processId);
...
logger.close();
ファイルベースのロガーにより作成されたログファイルには、ランタイム時に発生したすべてのイベントをまとめて XML ベースのサマリーが含まれています。Drools プラグインで Audit View を使用して JBoss Developer Studio で開くことができます。Audit View ではイベントがツリー形式で確認できます。'before' と 'after' イベントの間で発生したイベントは、各イベントの子として表示されます。以下のスクリーンショットは、プロセスが開始された結果、Start ノードと Action ノード、End ノードがアクティベートされ、プロセスが完了するという簡単な例です。
この画像は、Start ノードと End ノードが実行されるプロセスの例を示しています。

第3章 プロセスの概要

3.1. プロセスの概要

この画像は、プロジェクトマネージャーと人事マネージャー経由の自己評価の手順を示しています。

図3.1 ビジネスプロセス

ビジネスプロセスは、実行する必要のある一連の手順を順番に説明したフローチャートです。プロセスは、接続を用いて相互にリンクしているノードの集まりで構成されています。各ノードは、全体プロセスの 1 手順を表しており、接続はノードが次のノードへ移行する方法を指定しています。所定のノードタイプが多数定義されています。
プロセスは、以下の方法で作成できます。

3.2. プロセスノード

実行可能なプロセスには、別の種類のノードで構成されており、各ノードはそれぞれつながっています。BPMN 2.0 仕様は、主に 3 種のノードを定義しています。
イベント

プロセスの最初と最後は両方、イベントの種類です。中間イベントは、プロセス実行中に発生する可能性のあるイベントを指します。

アクティビティ

アクティビティは、プロセス実行中に行う必要のあるアクションのことです。

ゲートウェイ

ゲートウェイは、プロセスを通る実行パスを定義する際に使用します。

3.3. プロセスプロパティ

全プロセスには以下のプロパティが含まれています。
  • ID: プロセスの一意 ID
  • 名前: プロセスの表示名
  • バージョン: プロセスのバージョン番号
  • パッケージ: プロセスが定義されているパッケージ (名前空間)
  • 変数 (オプション): プロセス実行時にデータを格納する変数
  • スイムレーン: ヒューマンタスクを割り当てるためのプロセスに使用するスイムレーン
関連トピック:

3.4. イベント

プロセスには、開始イベント、中間イベント、終了イベントが含まれています。イベントにはすべて、ノードを識別する ID と名前 (ノードの表示名) が含まれています。追加のプロパティは以下の表に表示されています。

表3.1 イベント

イベントタイプ 追加のプロパティ 使用法
開始イベント
イベントの開始を示す緑のボタン
プロセスには開始ノード 1 つと外向きの接続が 1 つが含まれています。プロセスの実行は常に開始ノードから始まります。
終了イベント
イベントの終了を示す赤/ピンクのボタン
  • Terminate:
    終了イベントは、全プロセスを終了するか、現在の実行パスだけを終了します。
プロセスには 1 つ以上の終了イベントが含まれます。各終了イベントには、内向き接続 1 つがあり、外向きの接続はありません。
プロセスが終了すると、(実行の並行パスにある) アクティブなノードはすべてキャンセルされます。終端処理のない終了イベントは、現在実行中のパスを終了しますが、他のパスが継続できるようにします。終端処理のある終了イベントは、イベントノードの中に完全な丸があり視覚的に区別できます。反対に終端処理のない終了イベントはイベントノードの中に何も入っていません。サブプロセス内で終端イベントノードを使用する場合、サブプロセスだけでなく最上位のプロセスインスタンスを終了する点に注意してください。
エラー送出イベント
中央に赤いジグザグのアイコンがついたピンクのボタン
  • FaultName:
    問題の名前を提示します。この名前を用いて、この種類の問題を処理できる適切な例外ハンドラーを検索します。
  • FaultVariable:
    この問題に関連するデータが保存されている変数名を渡します。このデータも、例外ハンドラーに渡されます (もしあれば)。
エラーイベントは、プロセス内の例外的な状態を通知するために使用します。このイベントには内向き接続が 1 つあり、外向き接続はありません。プロセス内でエラーイベントに到達すると、指定の名前を持ったエラーを送出します。プロセスでは、この種の問題を処理できる適切なエラーハンドラーを検索します。エラーハンドラーが見つからない場合は、プロセスインスタンスが中断されます。
エラーハンドラーは、XML で作業している場合、境界イベントを使用して指定することができます。
タイマーキャッチイベント
時計の形に似た金色のボタン
  • Timer period:
    後続の 2 つのトリガーでどれくらいの時間が開いているか。期間が 0 の場合、タイマーは 1 度だけトリガーされます。
タイマーキャッチイベントは、指定の時間が経過した後、1 回または複数回トリガー可能なタイマーを表します。タイマーイベントには、内向き接続が 1 つと外向き接続が 1 つあります。プロセス内でタイマーイベントに到達すると、関連付けられているタイマーが開始します。
式の構文や詳細については、「タイマー」 を参照してください。
シグナルキャッチイベント
中央に三角印がついた金色のアイコン
  • EventType:
    予期されるイベントのタイプ
  • VariableName:
    このイベントに関連付けられたデータが保存されている変数の名前
シグナルイベントは、プロセス実行時に内部または外部のイベントに対応するために使用することができます。シグナルイベントには、内向き接続なく、外向き接続 1 つ含まれています。このイベントは、予期されるイベントの種類を指定します。イベントの種類が検出されると、このイベントノードに接続されたノードがトリガーされます。
プロセスインスタンスは、以下を使用して、指定のイベントの発生についてシグナルを受けることができます。
ksession.signalEvent(eventType, data, processInstanceId)
これは、イベントの種類に関して待機中のプロセスインスタンスにある (アクティブな) シグナルイベントノードをすべてトリガーします。このイベントに関連するデータは、データパラメーターを使用して渡すことができます。イベントノードが変数名を指定している場合、イベント発生時にこのデータはその変数にコピーされます。
イベントはサブプロセス内で利用できますが、これらのイベントノードはサブプロセスがアクティブな場合のみアクティブになります。
シグナルは、スクリプトを用いてプロセスインスタンス内から生成できます。例えば、
kcontext.getKnowledgeRuntime().signalEvent(eventType, data, kcontext.getProcessInstance().getId());
プロセスタスクすべてが正しい順序で実行されるようにすること以外に、プロセス外で起こるイベントに対応するように、プロセスエンジンに指示をすることも可能です。プロセス外で発生するイベントを明示的に表現することで、プロセスの作成者はプロセスがそのイベントに対してどのように反応すべきか指定できます。
イベントにはタイプがあり、データを関連付けることもできます。ユーザーはイベントタイプと関連データを定義することができます。
プロセスは、メッセージイベントを使用することでどのようにイベントに対応するか指定できます。イベントノードは、ノードが関連するイベントの種類を指定する必要があります。また、そのイベントに関連付けられたデータを受け取る変数の名前も定義できます。こうすることで、プロセス内で後続するノードがイベントデータにアクセスでき、このデータを元に適切なアクションを起こすことができるのです。
プロセスの実行中のインスタンスに対して、イベントのシグナルを様々な方法で送ることができます。
  • 内部イベント: プロセス内のアクション (例: アクションノードのアクション、または一部のノードの on-entry または on-exit アクション) は周りにあるプロセスインスタンスに対して、内部イベントの発生についてシグナルを送ることができます。内部イベントのサンプルコードは以下のとおりです。
    kcontext.getProcessInstance().signalEvent(type, eventData);
  • 外部イベント: プロセスインスタンスに対して、以下のようなコードを使うことで外部からイベントを通知できます。
    processInstance.signalEvent(type, eventData);
  • イベント相関を使った外部イベント: プロセスインスタンスを直接通知するのではなく、イベントタイプをベースとするイベント相関を使うことでイベントに関連しているプロセスインスタンスがどれであるか、自動的にエンジン側で判断できます。一部のタイプの外部イベントをリッスンするイベントノードを含むプロセスインスタンスは、イベントが発生するたびに通知されます。プロセスエンジンに対してこのようなイベントに関してシグナルを送るには、以下のコードを使います。
    ksession.signalEvent(type, eventData);

3.5. アクティビティ

アクティビティとは、プロセスの実行中に行う必要のあるアクションのことです。各アクティビティには、内向き接続が 1 つと外向き接続が 1 つ含まれています。
各アクティビティにはノードを識別する ID と、ノードの名前を表示する名前があります。追加のプロパティは以下の表に記載しています。

表3.2 アクティビティ

アクティビティの種類 追加のプロパティ 使用法
スクリプトのタスク
この画像はノードに関連付けられたスクリプトタスクを指しています。
  • Action:
    ノードに関連するアクションスクリプト
スクリプトタスクは、このプロセスで実行すべきスクリプトを指しています。関連のアクションは、実行スべきこと、アクションのコーディングに使用する方言 (Java または MVEL)、実際のアクションコードを指定します。このコードは、変数や Global 変数にアクセスできます。また、事前定義されている変数 'kcontext' もあり、これは 'ProcessContext' オブジェクトを参照します (このオブジェクトを使用して現在の ProcessInstance または NodeInstance にアクセスできます。また変数の取得と設定や以下を使って ksession へアクセスできるように、このオブジェクトを使用することができます)。
kcontext.getKnowledgeRuntime())
プロセス内でスクリプトタスクに到達すると、アクションを実行して次のノードに進みます。
ユーザータスク
この図はノードに関連付けられたユーザータスクを指しています。
  • TaskName:
    ヒューマンタスクの名前
  • Priority:
    ヒューマンタスクの優先順位を指定する整数
  • Comment:
    ヒューマンタスクに関連するコメント
  • ActorId:
    ヒューマンタスクの実行を担当するアクター ID。アクター ID の一覧を指定するには、区切り文字としてコンマ (',') を使用してください。
  • GroupId:
    ヒューマンタスクの実行を担当するグループ ID。グループ ID の一覧を指定するには、区切り文字としてコンマ (',') を使用してください。
  • Skippable:
    ヒューマンタスクが任意かどうかを指定します。
  • Content:
    このタスクに関連付けられたデータ
  • Swimlane:
    このヒューマンタスクノードの一部となるスイムレーン
  • On entry および on exit アクション
    このノードが出入の際に実行されるアクションスクリプト
  • Parameter mapping:
    プロセス変数の値をヒューマンタスクのパラメーターにコピーします。ヒューマンタスクが作成されると、この値はコピーされます。
  • Result mapping:
    ヒューマンタスクからの結果パラメーターをプロセス変数にコピーします。結果と呼ばれる変数を持つヒューマンタスクには、ヒューマンアクターにより返されたデータが含まれ、結果変数 ActorId にはこのタスクを完了したアクターの ID が含まれます。
プロセスは、ヒューマンアクターにより実行する必要のあるタスクが関連します。ユーザータスクは、ヒューマンアクターにより完了されるアトミックタスクを指します。ユーザータスクはスイムレーンとあわせて使用して、複数のヒューマンタスクを同様のアクターに割り当てることができます。スイムレーンとヒューマンタスクに関する詳細情報は、ヒューマンタスクの章を参照してください。
サービスタスク
この図はノードに関連付けられたサービスタスクを指しています。
  • Parameter mapping:
    プロセス変数の値を作業アイテムのパラメーターにコピーします。作業アイテムが作成されると、この値はコピーされます。
  • Result mapping:
    アイテムが完了した時点で、作業アイテムからの結果パラメーターをプロセス変数にコピーします。例えば、FileFider の作業アイテムにパラメーターファイルがある場合、検索基準と一致するファイルの一覧を返します。そしてこのファイル一覧は、プロセス内で利用するプロセス変数にバインドできます。
  • On entry および on exit アクション
    このノードが出入の際に実行されるアクション
  • 追加パラメーター
    各種類の作業アイテムは、作業アイテムの種類にあったパラメーターを追加で定義できます。ユーザーは、これらの値を直接渡すか、パラメーターマッピングを定義することができます。両方のメソッドが使用される場合、パラメーターマッピングがユーザーが提示したパラメーターより優先されます。この値は、作業アイテムの作成時に取得され、変数上で toString() を呼び出した結果により、代入式は置き換えられます。この式は (変数の値を解決するために) 変数名となる可能性もありますが、より詳細な MVEL 式を使用することも可能です (#{person.name.firstname})。
サービスタスクは、このプロセスで実行すべき作業の抽象ユニットを指します。プロセスエンジンの外で実行される作業はすべて、サービスタスクを使用して (宣言的な方法で) 表現する必要があります。様々な種類のサービス (例:e-メールの送信、メッセージのロギングなど) が事前定義されていますが、各種ドメイン固有サービスまたは作業アイテムを定義できます。詳細は、ドメイン固有プロセスの章を参照してください。
ビジネスルールタスク
この図は、ノードに関連付けられたビジネスルールタスクのアイコンを指しています。
  • RuleFlowGroup
    この RuleFlowGroup ノードのルールセットを指すルールフローグループの名前です。
ビジネスルールタスクは、評価する必要のあるルールセットのことです。ルールは、Drools ルール形式を使用して別ファイルで定義します。ルールは、ルールのヘッダーで ruleflow-group 属性を使用することで、指定のルールフローグループの一部となります。プロセスでルールタスクに到達すると、エンジンは該当の ruleflow-group の一部であるルールの実行を開始します (あれば)。このルールフローグループにアクティブなルールがなくなると、次のノードに自動的に進み実行されます。つまり、ルールフローグループの実行中は、現在アクティブなルールフローグループに所属する新規アクティベーションをアジェンダに追加することができます。これは、他のルールがファクトに変更を加えるため発生します。ルールフローがすでにアクティブな場合、ルールフローグループはアクティブな状態を保ち、ルールフローグループでアクティブなルールがすべて終わってから、実行は次に継続されます。
組み込みサブプロセス
このアイコンは、ノードコンテナーの機能を果たす組み込みサブプロセスの図です。
  • VariableID
    variable_name からの変数 ID を持つ他の変数とは違い、組み込みサブプロセスは以下の形式の変数 ID を持ちます。
    subprocess_node_id:variable_name
  • Variables
    このノード実行時にデータを保存するために、追加の変数を定義することができます。詳細は 「データ」 を参照してください。
サブプロセスとは、ノードコンテナーの役割を果たせるように他のノードを含めることができるノードです。これは、このサブプロセスノードの中にプロセスの一部を埋め込むだけでなく、このコンテナー内にある全ノードにアクセス可能な追加変数も定義できます。サブプロセスは、開始イベント 1 つと、1 つ以上の終了イベントが必要です。
再利用可能なサブプロセス
このアイコンは、再利用可能なサブプロセスの図で、別のプロセス内でプロセスが開始することを指します。
  • ProcessId:
    実行すべきプロセスの ID
  • Wait for Completion:
    False の場合、このプロセスはサブプロセスが開始するとすぐに継続されます。
    True の場合、サブプロセスが終了 (完了または中断) するまで待機します。
  • Independent:
    True の場合、子プロセスが独立プロセスとして開始され、親プロセスが完了しても、この子プロセスは終了されません。
    Independent は Wait for Completion が true に設定されている場合は False のみ設定可能です。False に設定されている場合、サブプロセスは親プロセスが終了するとキャンセルされます。
  • On entry および on exit アクション
    このノードが出入の際に実行されるアクション
  • Parameter in/out mapping:
    サブプロセスノードは、変数に "in" と "out" マッピングを定義することができます。"in" マッピングに指定された変数は、プロセス開始時に (関連のパラメーターとあわせて) パラメーターとして使用されます。"out" マッピングに定義された子プロセスの変数は、子プロセスが完了すると、このプロセスの変数にコピーされます。"out" マッピングは "wait for completion" が true に設定されている場合のみ利用可能です。
再利用可能なサブプロセスは、プロセス内から別のプロセスを呼び出すという部分を指します。再利用可能なサブプロセスノードにプロセス内で到達すると、エンジンは、指定の ID を持つプロセスを開始します。
マルチインスタンスのサブプロセス
このアイコンはマルチインスタンスのサブプロセスの図ですが、このサブプロセスはプロセス内にあるセグメントを複数回実行することが可能です。
  • CollectionExpression:
    配列形式または java.util.Collection 型の要素の集まり
  • VariableName
    この集まりからの現在の要素を含む変数の名前。これにより、複合ノードが選択した要素にアクセスできるようになります。
インスタンスが複数あるサブプロセスは特殊なサブプロセスで、プロセス内にあるセグメントを複数回実行できます (ただしコレクション内のの要素ごとに 1 回)。埋め込みプロセスのフラグメントは、指定のコレクション内の要素でそれぞれ終了するまで待機してから次に進みます。コレクションの式が Null または空のコレクションと評価した場合、複数インスタンスのサブプロセスは直後に完了して次の外向き接続に進みます。
有効な Java コードであればどれでも、スクリプトノード内で使用することができます。スクリプトノード向けにコードを記述する際に注意する点:
  • ビジネスユーザーが理解する必要のあるハイレベルのビジネスプロセスを定義する場合は、プロセス内にローレベルの実装詳細は含めないようにしてください。スクリプトタスクを使用して変数を操作することも可能ですが、サービスタスクのような他のコンセプトを使用してより高いレベルのより複雑な動作をモデリングすることもできます。
  • スクリプトは、エンジンスレッドを使用してスクリプトを実行するため immediate でなければなりません。実行するまでに時間があくスクリプトは、非同期サービスタスクとしてモデリングする必要があります。
  • スクリプトノード経由で外部のサービスに問い合わせしないようにしてください。代わりに、サービスタスクを使用して外部サービスとのモデル通信を使用してください。
  • スクリプトは例外を送出しないようにしてください。ランタイムの例外はスクリプト内で検出して管理するか、プロセス内で処理できるようにシグナルかエラーに変換する必要があります。
kcontext 変数

この変数は org.drools.runtime.process.ProcessContext 型で、複数タスクに利用できます。

  • 現在のノードインスタンス (該当する場合) を取得します。このノードインスタンスは、名前や型などのデータのクエリが可能です。現在のノードインスタンスの取り消しもできます。
    NodeInstance node = kcontext.getNodeInstance();
    
    String name = node.getNodeName();
  • 現在のプロセスインスタンスを取得します。このプロセスインスタンスは、データ (名前、id、processid など) のクエリができ、内部イベントを中断またはシグナルを送ることが可能です。
    ksession.signalEvent(eventType, data,  processInstanceId)
  • 変数の値の取得と設定
  • ナレッジランタイムにアクセスすることで、プロセスの開始、(外部) イベントのシグナル、データの挿入などが可能になります。
方言

Java および MVEL の両方を使用できます。Java アクションは、有効な Java コードでなければなりません。MVEL アクションはビジネススクリプト言語 MVEL を使用してアクションを表現できます。MVEL は有効な Java コードに対応していますが、パラメーターのネスト化アクセスにも追加対応しており (例:person.name instead of person.getName())、その他のスクリプト関連を強化しています。そのため、MVEL 式がビジネスユーザーにとってもより便利なものとなっています。例えば、プロセスの "requester" 変数で人の名前を出力するというアクションは、以下のようになります。

// Java dialect
System.out.println( person.getName() );

//  MVEL dialect
System.out.println( person.name );

3.6. ゲートウェイ

ゲートウェイは、プロセス全体で複数の実行パスを提供できるようにします。ゲートウェイには、Diverging gateway と Converging gateway の 2 種類があります。Diverging gateway は、プロセス内にブランチを作成して、Converging gateway はブランチを再度統合することでブランチを閉じます。
以下の方法でプロセスのブランチを作成できます。
  • AND (Parallel)
    コントロールのフローは、外向き接続 (ブランチ) すべてでも同時に継続されます。
  • XOR (Exclusive)
    コントロールのフローは、外向き接続の 1 つでのみ継続されます。優先順位が最も低く制約があり、True と評価される接続が選択されます。制約の定義に関する詳細は、「制約」 を参照してください。外向き接続の内、必ず 1 つはランタイム時に true と評価される必要があります。そうでないとランタイム時に例外が送出されます。
この画像はゲートウェイの複数パスを示しています。

図3.2 Diverging Gateway

Diverging gateway には、内向き接続が 1 つと、外向き接続が 2 つ以上あります。Diverging Gateway には以下のプロパティが含まれます。
  • ID: ノードの ID (1 つのノードコンテナー内で一意)
  • Name: ノードの表示名
  • Type: AND または XOR
  • Constraints: 各外向き接続にリンクされている制約 (exclusive および inclusive gateways)
この画像は、複数の Diverging Gateway と様々な接続を表します。

図3.3 Converging Gateway

Converging gateway には内向き接続が 2 つ以上、外向き接続が 2 つあります。Converging gateway には以下のプロパティが含まれています。
  • ID: ノードの ID (1 つのノードコンテナー内で一意)
  • Name: ノードの表示名
  • Type: AND または XOR
使用する Diverging Gateway の種類により、Converging Gateway は以下のように様々な形で動作します。
  • 並行 (AND) 分岐が使用された場合、Converging Gateway はすべての内向きブランチが完了するまで待機してから次に進みます。
  • 排他 (XOR) 分岐が使用された場合、Converging Gateway は 1 つの内向き接続が完了したらすぐ、次に進みます。

注記

Inclusive (OR) gateway には現在対応していません。

3.7. データ

プロセスの実行中に、データを取得、格納、次に渡す、使用することができます。ランタイムデータをプロセスの実行時に格納するには、プロセス変数を使用します。変数は、名前とデータ型で定義します。基本的なデータ型には、Boolean、Int、String や様々な種類のオブジェクトサブクラスなどが含まれます。
変数は、変数のスコープ内で定義できます。プロセス自体の変数スコープがトップレベルのスコープとなります。サブスコープはサブプロセスを使用して定義できます。サブスコープで定義されている変数は、そのスコープ内のノードに対してのみアクセスできます。
変数にアクセスするたびに、プロセスは、その変数を定義する適切な変数スコープを検索します。ノードは常に親コンテナーにある変数を検索します。変数が見つからない場合は、ノードはプロセスインスタンス自体に到達するまで、親の親のコンテナーというように上位のコンテナーを検索します。変数が見つからない場合は、読み取りアクセスは null と出して、書き込みアクセスはエラーメッセージを生成します。これは、プロセス実行時に並行して行われています。
変数は以下のような方法で利用できます。
  • プロセスレベルの変数は、startProcess メソッドの呼び出すへパラメーターをマッピングすることで、プロセス開始時に設定できます。これらのパラメーターは、プロセススコープで変数として設定されます。
  • スクリプトアクションは、単にスクリプト内のローカルパラメーターとして変数の名前を使用することで、直接変数にアクセスできます。例えば、プロセスがそのプロセス内で "org.jbpm.Person" 型の変数を定義する場合、プロセス内のスクリプトは以下のように直接これにアクセスすることも可能です。
    // call method on the process variable "person"
    
    person.setAge(10);
    ナレッジコンテキストで、スクリプト内の変数の値を変更することが可能です。
    kcontext.setVariable(variableName, value);
  • サービスタスク (および再利用可能なサブプロセス) は、変数を外向きのパラメーターにマッピングすることで、外部 (または別のプロセスインスタンス) にプロセス変数の値を渡すことができます。例えば、サービスタスクのパラメーターマッピングは、プロセス変数 x の値はサービスが呼び出されrう直線にタスクパラメーター y にマッピングするべきであることを定義することができます。また、プロセス変数の値をハードコード化されたパラメーター文字列に #{expression} を使用することで注入することができます。例えばヒューマンタスクの説明は以下のように定義することができます。
    You need to contact person #{person.getName()}
    
    人がプロセス変数の場合。サービスを呼び出す必要がある場合、この式は実際の人の名前で置き換えられます。またサービス (または再利用可能なサブプロセス) のよく似た結果は、結果マッピングを使用して変数にコピーし直すことができます。
  • その他の様々なノードもデータにアクセスすることができます。例えば、イベントノードはイベントに関連付けられているデータを変数に格納することができます。詳細については、各種ノードタイプのプロパティを確認してください。
最後に、プロセス (およびルール) はグローバル変数 (グローバルに定義された変数とナレッジセッションのデータ) にアクセスすることができます。グローバル変数は変数のようにアクション内で直接アクセスすることができます。グローバル変数はプロセスの一部と定義しなければ利用することができません。以下を使用することでグローバル変数を設定することができます。
ksession.setGlobal(name, value)
グローバル変数は、以下を使用してプロセススクリプト内から設定することができます。
kcontext.getKnowledgeRuntime().setGlobal(name,value);.

3.8. 制約

ビジネスプロセスには、コード制約とルール制約の 2 種類の制約があります。
  • コード制約は、この制約に到達すると直接評価される Boolean 式です。コード制約は Java または MVEL のどちらかで記述します。Java および MVEL の両制約はプロセス内で定義されているグローバル変数と変数に直接アクセスできます。
    以下に有効な Java コードの制約に関する例を示しています。ここでは、person がプロセス内の変数となります。
    return person.getAge() > 20;
    以下に有効な MVEL コードの制約に関する例を示しています。ここでは、person がプロセス内の変数となります。
    return person.age > 20;
  • ルール制約は通常の Drools ルール条件と同じです。Drools ルール言語の構文を使用して複雑な制約を表現します。これらのルールは、他のルールと同様、作業メモリ内のデータを参照することができます。また、グローバル変数へも直接参照可能です。以下に有効なルール制約の例を示しています。
    Person( age > 20 )
    これは、作業メモリで 21 歳以上の人がいるかテストします。
ルール制約は、プロセス内に定義された変数へ直接アクセスできません。しかし、プロセスインスタンスを作業メモリに追加して、お使いのルール制約内のプロセスインスタンスと合致させることで、ルール制約内の現在のプロセスインスタンスを参照することができます。ロジックが含まれており、これで WorkflowProcessInstance 型の processInstance 変数が作業メモリ内にある他のプロセスインスタンスではなく、現在のプロセスインスタンスのみと照合されるようにします。プロセスインスタンスをセッションに挿入する必要がある点に注意が必要です。プロセスインスタンスを更新する必要がある場合、Java コードか、プロセス内の on-entry、on-exit、明示的なアクションを使用してください。ルール制約の以下の例は、プロセスの name 変数に格納されている値と同じ名前を持つ人を検索します。
processInstance : WorkflowProcessInstance()
Person( name == ( processInstance.getVariable("name") ) )
# add more constraints here ...

3.9. タイマー

タイマーノードには、delay と period があります。delay は、ノードがアクティベートされてから初めてタイマーがトリガーされるまでの間、待機する時間を指定します。period は、後に続くトリガーのアクティベートとその次のアクティベートまでの時間を定義します。period が 0 の場合は繰り返しのないタイマーとなります。
delay と period の定義構文は以下の通りです。
[#d][#h][#m][#s][#[ms]]
この構文では、日、時間、分、秒、ミリ秒 (指定がない場合のデフォルト値) を指定できます。例えば、"1h" という式は、タイマーをトリガーするまで1時間待機します。
式に #{expr} を使用して動的にプロセス変数をもとに期間を取得するか、プロセス変数 (例: myVariable.getValue()) をもとにより複雑な式を取得します。
タイマーサービスは、正しいタイミングでタイマーがトリガーされるようにします。タイマーは、これ以上トリガーされないようにキャンセルすることも可能です。
タイマーイベントは、プロセスフローに追加することができます。アクティベートされるとタイマーを開始して、トリガーされると一度または繰り返しタイマーノードを継承するノードをアクティベートします。つまり、正の値の period を持つタイマーの外向き接続が複数回トリガーされることを意味します。タイマーノードをキャンセルすると、関連付けられたタイマーもキャンセルされ、それ以降トリガーが起こらないようにします。

3.10. プロセスの更新

時間が経つにつれてプロセスの要件が変更する場合がありません。プロセスを更新するには、プロセスの更新版をデプロイする必要があります。更新プロセスには、古いプロセスと区別するため更新版の番号がないといけません。既存のプロセスインスタンスがいまだに古いプロセスを必要とする場合があるため、これは必要です。
プロセスを更新する際は必ず、すでに実行中のプロセスインスタンスがどうなるか判断することが重要です。可能性として 3 つあげられます。
  • Proceed: 実行中のプロセスインスタンスは通常どおり進み、プロセスインスタンスの開始時に定義したようにプロセス定義に従います。結果、すでに実行中のインスタンスは、プロセスが更新されていないかのように振る舞います。新規インスタンスは、更新プロセスを使用して開始することができます。
  • Abort (および restart): すでに実行中のインスタンスは中断されます。必要であればプロセスインスタンスは新規プロセス定義を使用して再起動されます。
  • Transfer: プロセスインスタンスは新規プロセス定義に移行されます。つまり正常に移行されると、更新されたプロセスロジックに従い実行が継続されます。詳細は 「プロセスインスタンスの移行」 を参照してください。
デフォルトの動作は、proceed のアプローチを取りますが、同じプロセスが複数バージョンデプロイされることになります。既存のプロセスインスタンスは、そのインスタンスを開始したときに使用したプロセス定義に従い実行を継続します。
バージョン番号は、プロセスインスタンスが使用するプロセス定義のバージョンがどれかを判断できるようにトラッキングする必要があります。プロセスの現在のバージョンは以下で取得できます。
processInstance.getProcess().getVersion()

3.11. プロセスインスタンスの移行

プロセスインスタンスには、後ほど実行を継続するのに必要なランタイムの情報がすべて含まれています。これは、このプロセスインスタンス (変数など) にリンクされたデータや、プロセス図の現在のステータスも含まれています。現在アクティブなノードごとに、ノードインスタナスにはノードのステータスが含まれています。このノードインスタンスには、そのノードの実行に関連付けられた追加のステータス情報も含まれています。ノードに 1 つずつ違った種類のノードインスタンスがあります。
プロセスインスタンスには、ランタイムのステータスのみが含まれており、このプロセスインスタンスの実行時に従うべきプロセスロジックを指す特定のプロセスに関連付けられています (間接的に ID 参照を使用して)。定義やランタイムのステータスを明確に区別することで、このプロセスをベースとして全プロセスインスタンスの間で定義を再利用でき、ランタイムのステータスを最小限に抑えることができます。結果、実行中のプロセスインスタンスを新しいバージョンに更新して古いプロセスロジックではなく新しいものを使用するのは、参照するプロセス ID を古いものから新しいものに変えるだけです。
しかし、これには、プロセスインスタンスのステータス (変数インスタンスとノードインスタンス) が含まれておらず、プロセスインスタンスも移行する必要がある場合もあります。プロセスのみが延長され、既存の待機ステータスがすべて保持された場合、プロセスインスタンスのランタイムステータスは変更する必要はありません。ただし、より精緻なマッピングが必要になる可能性もあります。例えば、既存の待機ステータスが削除され複数の待機ステータスに分割された場合、待機ステータスにある既存のプロセスインスタンスは簡単に更新できません。しかし、新しいプロセス変数が利用されると、変数は、残りの更新プロセスで利用できるように、正しく初期化する必要がある場合もあります。
WorkflowProcessInstanceUpgrader を使用して、ワークフロープロセスインスタンスを新しいプロセスインスタンスにアップグレードすることができます。プロセスインスタンスには新しいプロセス ID が渡されます。デフォルトでは、古いノードインスタンスが自動的に新しいノードインスタンスに同じ ID のままでマッピングされます。しかし、古い (一意の) ノード ID から新しいノード ID へのマッピングを提供することができます。親のノード ID の後に (コロンで区切り) このノード ID を置くと一意のノード ID となり、複合ノードが使用された場合にノードを識別することができます (ノード ID はノードコンテナーの中でのみ一意であるため)。新しいノード ID はノードコンテナーの中だけで新しいノード ID となっており、一意のノード ID への参照は必要ありません。以下のコードスニペットは一例となっています。
// create the session and start the process "com.sample.process"
KnowledgeBuilder kbuilder = ...
StatefulKnowledgeSession ksession = ...
ProcessInstance processInstance = ksession.startProcess("com.sample.process");

// add a new version of the process "com.sample.process2"
kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(..., ResourceType.BPMN2);
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

// migrate process instance to new version
Map<String, Long> mapping = new HashMap<String, Long>();
// top level node 2 is mapped to a new node with id 3
mapping.put("2", 3L); 
// node 2, which is part of composite node 5, is mapped to a new node with id 4
mapping.put("5.2", 4L); 
WorkflowProcessInstanceUpgrader.upgradeProcessInstance(
   ksession, processInstance.getId(),
   "com.sample.process2", mapping);
このようなマッピングで不十分な場合、個別の状況に対して独自のカスタムパッマーを記述することができます。まず、プロセスインスタンスを切断して、ステータスを随時変更してから、プロセスインスタンスを再接続します。これは、WorkflowProcessinstanceUpgrader が行うこととよく似ています。

3.12. マルチスレッド

3.12.1. マルチスレッド

以下の文では、論理技術の 2 種類のマルチスレッドを利用します。技術マルチスレッド (Technical multi-threading) は、複数のスレッドやプロセスがコンピューター上で Java や C プログラムなどにより開始された場合に発生します。また、論理マルチスレッド (Logical multi-threading) は、プロセスが並行ゲートウェイに到達した後に BPM プロセスで見られるマルチスレッド化のことです。機能的には、元のプロセスは 2 つのプロセスに分割され、並行して実行されています。
BPM エンジンは、論理マルチスレッドに対応しています。例えば、並行ゲートウェイを含むプロセスに対応しています。1 つのスレッドを使用して論理マルチスレッドを実装するようにしているため、論理マルチスレッドを含む BPM プロセスは技術スレッド 1 つでのみ実行されます。これの主な理由は、複数の (技術) スレッドが同じプロセスにある場合、それぞれステータスの情報をやり取りできる状態でなければなりません。この要件によりいくつか複雑になっています。マルチスレッドにより、パフォーマンスの面で利点がでてくるように見えますが、別のスレッド間で各自に連携されるように、余分なロジックが必要になってきます。つまり、スレッド間での連携が取れる保証がないのです。競合やデッドロックを避ける必要があるため、オーバーヘッドも余計に発生してきます。

3.12.2. エンジン実行

一般的に、BPM エンジンはアクションを順番に実行します。例えば、エンジンがプロセス内でスクリプトタスクに遭遇した場合、スクリプトを動機的に実行して、このスクリプトが完了するまで待機して完了すると実行を継続します。同様に、プロセスが並行ゲートウェイに遭遇すると、外向きのブランチを順番にトリガーしていきます。実行は常に即時に行われるため、これが可能となっています。つまり、非常に早く実行されて、ほとんどオーバーヘッドを生み出さないためです。結果、ユーザーがこれが行われていることに気づきません。同様に、プロセス内のアクションスクリプトも同期的に実行され、エンジンはアクションスクリプトが完了するまで待機して終わってからプロセスを継続します。例えば、スクリプトの一部で Thread.sleep(...) を実行しても、エンジンが別の場所で実行を継続することはなく、その期間中エンジンスレッドをブロックします。
同様の原理がサービスタスクでも適用されます。プロセス内でサービスタスクに到達すると、エンジンはこのサービスのハンドラーも同期的に呼び出します。エンジンは completeWorkItem(...) メソッドが返ってくるまで待機してから、実行を継続します。お使いのサービスハンドラーが即時実行を行わない場合、サービスハンドラーがサービスを非同期的に実行することが重要です。
この例としては、外部サービスを呼び出すサービスタスクなどです。リモートでこのサービスの呼び出しを遅延して結果を待つのは長すぎるため、このサービスの呼び出しを非同期的に行うと良いでしょう。つまり、ハンドラーは、サービスの呼び出しのみを行い、エンジンの通知は後に結果が返ってきた際に行います。その間、プロセスエンジンはプロセスの実行を継続します。
非同期呼び出しの必要のあるサービスとして典型的な例は、ヒューマンタスクです。アクションを起こす人がリクエストに対応するまで、エンジンを待機させたくないためです。ヒューマンタスクハンドラーは、ヒューマンタスクノードがトリガーされるまで、(割り当てられたアクターのタスク一覧に) 新しいタスクは作成されません。エンジンは、(必要があれば) 残りのプロセスの実行を継続することができ、ハンドラーはユーザーがタスクを完了した時点で非同期的にエンジンの通知を行います。

3.13. 非同期ハンドラー

シンプルな Java を使用して非同期サービスハンドラーを実装するには、新しいスレッドで実際のサービスを実行してください。
public class MyServiceTaskHandler implements WorkItemHandler {
        
  public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
    new Thread(new Runnable() {
      public void run() {
        // Do the heavy lifting here ...
      }
    }).start();
  }

  public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
  }
      
}
通常、ハンドラーには作業アイテムを実行するためのビジネスロジックが実装されていませんが、ハンドラーは、作業を行う既存のサービスに問い合わせを行います。例えば、ヒューマンタスクハンドラーがたんにヒューマンタスクサービスを呼び出して、そこにタスクを追加するとします。非同期ハンドラーを実装するには、このサービスの非同期呼び出しが必要になってきます。これは、この対話に利用するテクノロジーにより変わってきますが、Web サービスの非同期呼び出しを行い JMS メッセージを外部サービスなどに送信するといった単純なものもあります。

第4章 BPMN 2.0 Notation

4.1. Business Process Model and Notation (BPMN) 2.0 仕様

Business Process Model and Notation (BPMN) 2.0 仕様では、ビジネスプロセスをグラフィカルに表現するための規格を定義します。これには、プロセス定義の保存や共有の定義要素や XML 形式の実行セマンティクスなどが含まれます。
以下の表では、BPMN 2.0 仕様の対応要素や追加の要素や属性についても含まれています。

表4.1 BPMN 2.0 対応の要素と属性

要素 対応の属性 対応の要素 拡張属性 拡張要素
定義 rootElement BPMNDiagram
process processType isExecutable name id property laneSet flowElement packageName adHoc version import global
sequenceFlow sourceRef targetRef isImmediate name id conditionExpression priority
interface name id operation
operation name id inMessageRef
laneSet lane
lane name id flowNodeRef
import* name
global* identifier type
イベント
startEvent name id dataOutput dataOutputAssociation outputSet eventDefinition x y width height
endEvent name id dataInput dataInputAssociation inputSet eventDefinition x y width height
intermediateCatchEvent name id dataOutput dataOutputAssociation outputSet eventDefinition x y width height
intermediateThrowEvent name id dataInput dataInputAssociation inputSet eventDefinition x y width height
boundaryEvent cancelActivity attachedToRef name id eventDefinition x y width height
terminateEventDefinition
compensateEventDefinition activityRef documentation extensionElements
conditionalEventDefinition condition
errorEventDefinition errorRef
error errorCode id
escalationEventDefinition escalationRef
escalation escalationCode id
messageEventDefinition messageRef
message itemRef id
signalEventDefinition signalRef
timerEventDefinition timeCycle timeDuration
アクティビティ
task name id ioSpecification dataInputAssociation dataOutputAssociation taskName x y width height
scriptTask scriptFormat name id script x y width height
script text[mixed content]
userTask name id ioSpecification dataInputAssociation dataOutputAssociation resourceRole x y width height onEntry-script onExit-script
potentialOwner resourceAssignmentExpression
resourceAssignmentExpression expression
businessRuleTask name id x y width height ruleFlowGroup onEntry-script onExit-script
manualTask name id x y width height onEntry-script onExit-script
sendTask messageRef name id ioSpecification dataInputAssociation x y width height onEntry-script onExit-script
receiveTask messageRef name id ioSpecification dataOutputAssociation x y width height onEntry-script onExit-script
serviceTask operationRef name id ioSpecification dataInputAssociation dataOutputAssociation x y width height onEntry-script onExit-script
subProcess name id flowElement property loopCharacteristics x y width height
adHocSubProcess cancelRemainingInstances name id completionCondition flowElement property x y width height
callActivity calledElement name id ioSpecification dataInputAssociation dataOutputAssociation x y width height waitForCompletion independent onEntry-script onExit-script
multiInstanceLoopCharacteristics loopDataInputRef inputDataItem
onEntry-script* scriptFormat script
onExit-script* scriptFormat script
ゲートウェイ
parallelGateway gatewayDirection name id x y width height
eventBasedGateway gatewayDirection name id x y width height
exclusiveGateway default gatewayDirection name id x y width height
inclusiveGateway default gatewayDirection name id x y width height
データ
property itemSubjectRef id
dataObject itemSubjectRef id
itemDefinition structureRef id
ioSpecification dataInput dataOutput inputSet outputSet
dataInput name id
dataInputAssociation sourceRef targetRef assignment
dataOutput name id
dataOutputAssociation sourceRef targetRef assignment
inputSet dataInputRefs
outputSet dataOutputRefs
assignment from to
formalExpression language text[mixed content]
BPMNDI
BPMNDiagram BPMNPlane
BPMNPlane bpmnElement BPMNEdge BPMNShape
BPMNShape bpmnElement Bounds
BPMNEdge bpmnElement waypoint
Bounds x y width height
waypoint x y

4.2. BPMN 2.0 プロセスの例

プロセスの XML ファイルは 2 つの部分で構成されています。上の部分は ("process" 要素) 別のノードやプロパティの定義が含まれており、下側の部分 ("BPMNDiagram" element) には、ノードの場所など全描画情報が含まれています。プロセスの XML は、 <process> 要素 1 つだけで構成されています。この要素には、プロセス関連のパラメーター (型、名前、id、パッケージ名) が含まれており、ヘッダー部分 (変数、グローバル、インポート、レーンなどのプロセスレベルの情報を定義可能)、プロセス内の各ノードを定義するノード部分、プロセス内のすべてのノード間の接続が含まれる接続部分の 3 つのサブセクションからなっています。ノード部分は、ノードごとに固有の要素があります。各要素は、様々なパラメーターやそのノード型のサブ要素を定義します。
'Hello World' というフレーズを出力するという、単純な hello world というプロセスは、以下の画像のように描画表現できます。
この画像は、グラフィカルなプロセス "Hello World" の Start イベントと End イベントを示しています。

図4.1 グラフィカルな Hello World プロセス

BPMN 2.0 XML を使って表現したこのプロセスの実行可能なバージョンは、以下の例に記載しています。

例4.1 BPMN 2.0 XML Hello World プロセス

<?xml version="1.0" encoding="UTF-8"?><definitions id="Definition"
             targetNamespace="http://www.example.org/MinimalExample"
             typeLanguage="http://www.java.com/javaTypes"
             expressionLanguage="http://www.mvel.org/2.0"
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
             xs:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:tns="http://www.jboss.org/drools"><process processType="Private" isExecutable="true" id="com.sample.HelloWorld" name="Hello World" ><!-- nodes --><startEvent id="_1" name="StartProcess" /><scriptTask id="_2" name="Hello" ><script>System.out.println("Hello World");</script></scriptTask><endEvent id="_3" name="EndProcess" ><terminateEventDefinition/></endEvent><!-- connections --><sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" /><sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" /></process><bpmndi:BPMNDiagram><bpmndi:BPMNPlane bpmnElement="Minimal" ><bpmndi:BPMNShape bpmnElement="_1" ><dc:Bounds x="15" y="91" width="48" height="48" /></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_2" ><dc:Bounds x="95" y="88" width="83" height="48" /></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" ><dc:Bounds x="258" y="86" width="48" height="48" /></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_1-_2" ><di:waypoint x="39" y="115" /><di:waypoint x="75" y="46" /><di:waypoint x="136" y="112" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_2-_3" ><di:waypoint x="136" y="112" /><di:waypoint x="240" y="240" /><di:waypoint x="282" y="110" /></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions> 


  

    
    
    
      
    
    
        
    

    
    
    

  

  
    
      
        
      
      
        
      
      
        
      
      
        
        
        
      
      
        
        
        
      
    
  

プロセスは、BRMS ユーザーインターフェース (詳細は 「プロセスデザイナー」 を参照)、JBoss Developer Studio (詳細は 「JBoss Developer Studio」 を参照) に含まれているデザイナーを使用するか、手動で XML に直接記述することで BPMN 2.0 仕様で定義できます。

第5章 プロセスデザイナー

5.1. プロセスデザイナー

プロセスデザイナーは、BRMS ユーザーインターフェースからアクセスでき、このデザイナーを使用してドラッグアンドドロップ形式のインターフェースでプロセスの作成、閲覧、編集、更新が可能になります。
この画像は、BRMS ユーザーインターフェースからのプロセスデザイナーの外観です。

5.2. プロセスデザイナーの設定

プロセスデザイナーとは、JBoss BRMS ユーザーインターフェースやレポジトリと密統合されている個別アプリケーションで、設定について JBoss BRMS に加えられた変更はプロセスデザイナーにも適用されていなければなりません。プロセスデザイナーは、 jboss-as/server/production/deploy/designer.war/profiles/ ディレクトリにある jbpm.xml ファイルで設定しています。
設定属性には以下が含まれます。
  • protocol: 使用するプロトコル (http/https)
  • host: localhost:8080
  • subdomain: jboss-brms/org.drools.guvnor.Guvnor/oryxeditor
  • usr: admin (デフォルト。有効な JBoss BRMS ユーザーを使用すること)
  • pwd: admin (デフォルト。有効な JBoss BRMS ユーザーのパスワードと一致すること)

注記

ホストとポートが変更された場合、その情報は production/deploy/jboss-brms.war/WEB-INF/classes/preferences.properties でも更新されます。

5.3. プロセスの作成と検証

以下の手順では、BRMS ユーザーインターフェース内のプロセスデザイナーを使用して簡単なプロセスを作成する方法について説明しています。プロセスデザイナーを使用するには、ユーザーは BRMS ユーザーインターフェースにログインする必要があります。

手順5.1 プロセスの作成

  1. ナビゲーションパネルから、Knowledge BasesCreate NewNew BPMN2 を選択します。
  2. Name: のダイアログボックスでプロセスの名前を入力します。
  3. ドロップダウンメニューからプロセス作成に使用するパッケージを選択して、説明を入力します。

    注記

    Red Hat は、プロセス属性のすべてが他のパッケージに正常にインポートされるとは限らないため、この段階ではグローバルエリアでプロセスを作成しないように推奨しています。
  4. プロセスは、画面の左側にある Shape レポジトリパネルから画面の中央にあるキャンバスにプロセス要素をドラッグアンドドロップして作成します。
    Shape レポジトリパネルからプロセスを開始するノードを選択して、キャンバスにドラッグします。
    プロセスデザイナーの右側にある properties パネルの Name の横にある値のカラムをクリックしてノードに名前をつけます。
  5. プロセスで次に来るノードを追加するには、Shape レポジトリパネルから必要なノード型を選択してキャンバスにドラッグします。
    Properties パネルでノードのプロパティを編集します。
  6. 次にノードの接続ですが、最初のノードをクリックして、矢印アイコンを選択してホールドした状態で、2 番目のノードにドラッグします。
  7. プロセスが完了するまでノードと接続の追加を繰り返します。
プロセスデザイナーとユニコード文字

新規プロセスの作成時には、プロセス名やプロセス ID にユニコード文字を含めないようにしてください。現在、この機能はサポートされておらず、プロセスアセットの保存やリトリーブの際にプロセスデザイナーが予期せぬ動作をする可能性があります。

プロセスの検証

プロセスデザイナーは、プロセスが完了していることを確認するために利用することができます。バリデーションエラーが発生した場合、エラーメッセージが表示されますが、バリデーションエラーを使用してプロセスが全体的に正しいかどうかの確認はしないようにしてください。

プロセスの検証は、プロセスデザイナーの上部にあるメニューバーの validate process ボタンを選択します。
バリデーションエラーがあった場合は、エラーのあるノードの横にエラーのマークが表示されます。エラーのマークの上にカーソルを持っていくと、バリデーションエラーについて説明が記載されたツールのヒントが表示されます。

5.4. 既存プロセスのインポート

5.4.1. 既存の BPMN2 プロセスのインポート

既存の BPMN2 プロセスをデザイナーにインポートするには、プロセスデザイナーのトップメニューにあるインポートアイコンを選択して、Import from BPMN2 を選びます。インポートメニューには、2 つのオプションがあります。
  • Upload an existing file from the local filesystem (ローカルのファイルシステムから既存のファイルをアップロード)
  • Copy and paste the BPMN2 XML directly into the import dialogue box (インポートのダイアログボックスに BMPN2 XML をコピー、貼り付け)
BPMN2 プロセスがすでにインポートされ、プロセスを変更する必要がある場合、プロセスはプロセスデザイナーで編集してください。元のプロセスは上書きされませんので、同じプロセスを 2 回インポートしないようにしてください。
プロセスデザイナーには、プロセスをインポートする際に Data Object、Lane、Group の視覚的なサポートが提供されています。インポートする BPMN2 ファイルに、これらのノードの位置の情報が含まれていない場合、手動で位置情報を追加する必要があります。
(JBoss Developer Studio でデザインしたプロセスをインポートするには、『BRMS スタートガイド』を参照してください)。

5.4.2. jPDL 3.2 から BPMN2 への移行

重要

jPDL 3.2 から BPMN2 への移行ツールは実験的な機能で、ユーザーがこの機能を有効化する必要があります。Red Hat は jPDL 3.2 移行ツールのサポートはしていません。

手順5.2 jPDL 3.2 移行ツールの有効化

  1. サーバーを停止します。
  2. server/profile/deploy/designer.war/profiles/ ディレクトリから jbpm.xml を探します。
  3. JPDL 移行プラグインツールのエントリから以下のコメントタグを削除します。
         	            <!-- plugin name="ORYX.Plugins.JPDLMigration"/ -->
    
  4. コメントタグを削除した状態で、このファイルを保存します。
         	            <plugin name="ORYX.Plugins.JPDLMigration"/>
    
  5. サーバーを再起動します。
  6. JBoss BRMS ユーザーインターフェースにログインして、プロセスデザイナーに移動します。jPDL 移行ツールボタンがプロセスデザイナーのユーザーインターフェースに追加されています。
    jPDL 移行ツール

    図5.1 jPDL 移行ツール

5.5. プロセスの表示と共有

プロセスデザイナーでデザインしたプロセスやアクセスするプロセスは、プロセスデザイナーにアクセスできない人が参照できるように様々な形式で保存することができます。プロセスの保存対応形式は、以下の通りです。
  • ERDF
  • JSON
  • PDF
  • PNG
  • BPMN2
  • SVG

注記

ビジネスプロセスコンソールのユーザーがプロセス図を参照するには、PNG ファイルで保存する必要があります。これは、プロセスデザイナーのウィンドウの一番下にある PNG オプションをクリックすることで可能となります。
プロセスデザイナーのトップメニューにある共有アイコンを選択することでプロセスを共有するためのコードを作成することも可能です。以下の形式が利用可能です。
  • プロセスの画像
  • プロセスの PDF
  • 埋め込みプロセス
プロセスの開発中に プロセスの BPMN2 ソースコードを参照するには、SourceView Source を選択します。

5.6. ドメイン固有サービスノードの定義

プロセスデザイナーはドメイン固有ノードに対応しています。プロセスデザイナーの BPMN2 ステンシルセットにサービスノードを含めるには、JBoss Developer Studio (「JBoss Developer Studio」 参照) または BRMS ユーザーインターフェースからサービスノードの定義をアップロードしてください。

手順5.3 サービスノードの定義

  1. ナビゲーションパネルから、Knowledge BasesCreate NewNew Work Item Definition を選択します。
  2. Name: のダイアログボックスで定義の名前を入力します。
    サービスノードを割り当てるパッケージを選択するか、Create in Global Area を選択して、説明を追加し OK をクリックします。
  3. 必要であればサービスノードを設定します。
    例えば、e-メールサービスノードは Email に、パラメーターは ToFromSubjectBody に、型はすべて文字列に指定することができます。既存のパラメーターを編集して Parameter ボタンを使って新しいパラメーターを追加します。
    作業タスクの必須名を表示するには、表示名を編集します。
    FileSave Changes 選択します。
  4. サービスノードのアイコンをアップロードします。
    Create NewCreate a file を選択します。
    Name のダイアログボックスに名前を入力します。
    ファイルの拡張子の種類を入力します。
    ファイルを作成すべきパッケージを選択して、OK をクリックします。
  5. Choose File をクリックしてローカルファイルシステムから画像を選択して、Upload をクリックします。
  6. アイコンをサービスノードに追加します。
    ナビゲーションパネルからパッケージ名をクリックします。次に WorkItemDefinition タブを展開してワークを選択して、対象のサービスノードの open をクリックします。アイコンについては、PNG と GIF の形式に対応しています。
    このアイコンは、Select Icon to add のドロップダウンメニューから選択できるようになっています。使用するアイコンを選択します。
  7. FileSave Changes をクリックします。
  8. 新しいノードをプロセスに追加するには、プロセスを開きます。
    1. ナビゲーションパネルから Knowledge BasesPackages を選択して、対象のパッケージを選びます。
    2. assets タブのプロセスエリアを展開して、必要とするプロセスの open をクリックします。
  9. 必要であれば、Shape Repository から Service Tasks タブを展開してプロセス上の新しいサービスノードをドラッグします。

5.7. サービスレポジトリへの接続

ドメイン固有サービスと作業アイテムは、サービスレポジトリに保存することができます。サービスレポジトリの設定の方法については、「サービスレポジトリ」 を参照してください。

手順5.4 サービスレポジトリへの接続

  1. JBoss BRMS ユーザーインターフェースにログインします。
  2. 編集する既存プロセスを選択するか、新しいプロセスを作成して、プロセスデザイナーにアクセスします。
  3. サービスレポジトリのアイコンを選択して、サービスレポジトリ URL に移動します。
    サービスレポジトリの接続アイコン

    図5.2 サービスレポジトリ接続

  4. サービスレポジトリの URL を入力して、Connect をクリックします。
  5. 対象のサービスをダブルクリックしてパッケージに追加して、プロセスデザイナーの Shape Repository で利用できるようにします。

5.8. プロセスとタスクフォームの生成

デザイナーでは、プロセスとタスクを ftl 形式で生成することができます。これらの形式は、jBPM コンソールで完全対応しています。この機能の使用を開始するには、デザイナーツールバーの "Generate Task From Templates" ボタンを設置します。
これが Generate Task Form Templates ボタンです。
プロセス BPMN2 に対してすべて繰り返し実行して、プロセスとプロセス内にある各ヒューマンタスクに対してフォームを作成します。定義済みのプロセス変数とヒューマンタスクデータ入力/出力パラメーター、関連性を使用してフォームフィールドを作成します。生成したフォームは Guvnor に保存され、ユーザーには Guvnor にソースへのリンクと、作成した各フォームが含まれるページが表示されます。
この画像は、Generate Template についてで、Guvnor ソースへのリンクを提供しています。
全フォームは jBPM コンソール内で利用できます。また、各フォームには基本的な JavaScript フォームバリデーションが含まれており、プロセス変数やヒューマンタスクデータ入力/出力の関連定義などをもとにバリデーションが行われます。以下に生成されたヒューマンタスクフォームの例を示しています。
生成されたヒューマンタスクフォーム
プロセスやタスクフォームを生成するには、プロセスに ID パラメーターセットが、各ヒューマンタスクに TaskName パラメーターが含まれるようにしてください。タスクフォームはピュア HTML、CSS、JavaScript で構成して、HTML エディターで簡単に編集できるようにします。プロセスデザイナーには編集機能がないため、フォームが生成されるたびに (同名の) 既存のフォームは上書きされます。

第6章 JBoss Developer Studio

6.1. JBoss Developer Studio

JBoss Developer Studio は Red Hat カスタマーポータル (https://access.redhat.com) から入手いただける JBoss Integrated Development Environment (JBoss-IDE) です。JBoss Developer Studio は、JBoss Enterprise BRMS をお使いの開発者にツールやインターフェースを提供します。
インストールや設定の説明は、『JBoss BRMS スタートガイド』を参照してください。

注記

JBoss Developer Studio の JBoss BRMS プラグインは、ベースとなっているオープンソースプロジェクトの名前で知られています。Guvnor は BRMS ユーザーインターフェースとレポジトリがベースとしているプロジェクト、Drools はルールエンジンがベースとしているプロジェクト、jBPM はビジネスプロセス管理機能の元となっているプロジェクトです。

6.2. プロジェクトの作成

手順6.1 新規プロジェクトの作成

  1. FileNewProject を選択します。
  2. jBPMjBPM project を選択します。
  3. プロジェクト名を Project name: テキストボックスに入力して、Next をクリックしてください。

    注記

    JBDS では、サンプルの HelloWorld プロセスをプロジェクトに追加するオプションがあります。このデフォルト設定を確定して、次のステップでサンプルプロジェクトのテストを行います。
  4. プロジェクトをテストするには、主なメソッドを含む Java ファイルを右クリックして、Runrun asJava Application を選択してください。
    Console タブに出力が表示されます。

6.3. プロセスの作成

手順6.2 新規プロセスの作成

  1. 新しいプロセスを作成するには、FileNewOther を選んでから、jBPMBPMN2 Process を選択します。
  2. プロセスの親フォルダーを選択します。
  3. File name: ダイアログボックスに名前を入力して、Finish をクリックしてください。
  4. プロセスの .bpmn ファイルを右クリックしてグラフィカルエディターを開き、Open With を選んで BPMN2 Process Editor の横にあるラジオボタンをクリックします。
  5. プロセスにノードを追加するには、パレット内の対象のノードをクリックして、ノードを設置すべきキャンバスをクリックします。
  6. シーケンスフローでノードを接続します。パレットから Sequence Flow を選択して、接続する各ノードをクリックします。
  7. ノードのプロパティを編集するには、ノードをクリックして JBDS ワークスペースの一番下のパネルにある properties タブを開き、編集する値をクリックします。
    properties タブが開いていない場合、パッケージパネルの bpmn ファイルを右クリックして Show inProperties を選択します。
  8. 保存アイコンをクリックしてプロセスを保存します。

6.4. バリデーションとデバッグ

JBoss Developer Studio ではプロセスのバリデーションとデバッグが可能です。
バリデーション

プロセスのバリデーションを実施するには、.bpmn ファイルを右クリックして Validate を選択します。

バリデーションが正常に完了すると、エラーなしまたは警告が書かれたダイアログボックスが表示されます。
バリデーションに失敗すると、エラーが Problems タブに表示されます。問題を修正してバリデーションを再度実行します。
デバッグ

プロセスをデバッグするには、.bpmn ファイルを右クリックして Debug AsDebug Configurations を選択します。テスト設定に必要な変更を加えて Debug をクリックします。

エラーが発見されない場合は、プロセスが実行されます。
エラーが発見された場合、JBoss Developer Studio の下のウィンドウにエラーの説明が表示されます。エラーを修正してデバッグプロセスを再実行してください。
デバッグプロセスに関する詳細情報は、「デバッグ」 を参照してください。

第7章 永続性

7.1. 永続性

データベースに情報を永続的に格納することで、予期せぬ中断からプロセスが復帰できるようになります。JBoss BRMS 5.3 Standalone ではデフォルトで永続的に情報の格納が行われますが、デプロイ可能な Web アプリケーションとして JBoss BRMS 5.3 をデプロイする場合は永続性の設定が必要となります。
永続的な格納が可能な情報の種類は以下のとおりです。
  • ランタイム
  • プロセス定義
  • 履歴情報 (ログ)
本章では、様々な永続性の種類、およびその設定方法について説明します。

7.2. ランタイムのステータス

7.2.1. ランタイムのステータス

プロセスが開始すると、そのプロセスのインスタンスが作成されます。例えば、販売注文のプロセスの例を見てみます。販売注文が依頼されるたびに、販売注文のプロセスのインスタンスが 1 つ作成され、このインスタンス内にはその販売注文に関連する情報のみが含まれます。そのインスタンスが永続的に格納された場合、少し時間がたった時点で実行を継続していくために必要となる必要最小限の情報のみが格納されます。エンジンは自動的にデータベース内にランタイムのステータスを保存することで、エンジンが呼び出されるたびに、呼び出しの最後およびセーフポイント (安全な状態)で変更が保存されるようにします。
データベースからエンジンをリストアする必要があった場合でも、プロセスインスタンスをリロードして手動でトリガーしないようにしてください。プロセスインスタンスは、タイマーの失効、プロセスインスタンスが依頼したタスクの完了、またはプロセスインスタンスに送信されたシグナルなどでトリガーされると、自動的に実行を再開します。エンジンは自動的にオンデマンドでプロセスインスタンスをリロードします。プロセスのスナップショットはリロードされ、スナップショットが取られてから発生した変更については失われてしまう点に留意することが重要です。
最新のスナップショットのステータスは以下でリトリーブ可能です。
ksession.getProcessInstance(id)
ランタイムの永続データは内部のものとみなされ、データが格納されるデータベーステーブルには直接アクセスしないようにしてください。プロセスインスタンスの現在の実行ステータスに関する情報が必要な場合は、履歴ログを参照してださい (「履歴ログ」 参照)。

7.2.2. セーフポイント

プロセスインスタンスのステータスは、プロセス実行中のセーフポイントで保存されます。セーフポイントは、プロセスインスタンスが完了/中断した時点、または実行中の全並行パスで待機状態に到達した時点で発生します。プロセスインスタンスがセーフポイントで永続的に保存されると、プロセスインスタンスの現在のステータスや影響を受ける可能性のあるその他のプロセスインスタンスすべてが保存されます。

7.2.3. バイナリの永続性

バイナリの永続性はマーシャリングとして知られていますが、プロセスインスタンスのステータスをバイナリのデータセットに変換することです。バイナリの永続性とは、情報を永続的に保存、リトリーブする際に使用するメカニズムです。同じメカニズムがセッションステータスや作業アイテムのステータスにも適用されています。
プロセスインスタンスのステータスが永続化されると、以下の 2 つのことが発生します。
  • プロセスインスタンスの情報がバイナリデータに変換されます。パフォーマンスの理由から、通常の Java の直列化ではなくカスタムの直列化メカニズムが使用されています。
  • バイナリデータはプロセスインスタンスに関する他のメタデータと併せて保存されます。このメタデータには、プロセスインスタンス ID、プロセス ID、プロセスの開始日が含まれています。
プロセスインスタンスのステータス以外に、セッション自体もタイマージョブなど別形式のステータスとして保存することも可能です。また、セッションにはビジネスルールを評価するデータも保存することができます。このセッションのステータスは、セッション ID やメタデータの一部とともにバイナリデータセットとして別途保存されています。セッションステータスは、指定の ID でセッションをリロードすることでリストアできます。セッション ID は、 ksession.getId() を使用してリトリーブ可能です。
通常プロセスインスタンスのバイナリデータセットは、最小限の実行ステータスのみを格納しているため比較的小さくなっています。単純なプロセスインスタンスの場合、バイナリデータセットには通常 1 つまたは少しのノードインスタンスが含まれています (現在実行中のノードまたは既存変数の値)。
バイナリの永続性を行うと、データモデルはシンプルかつサイズが小さくなります。
sessioninfo、processinstanceinfo、eventtypes、workiteminfo ノードを提供するデータモデル

図7.1 データモデル

sessioninfo エンティティには、プロセスインスタンスが実行中の (ナレッジ) セッションのステータスが含まれています。

表7.1 SessionInfo

フィールド 説明 Null 許容型
id プライマリキー Null 不可
lastmodificationdate エンティティがデータベースに最後に保存された時間  
rulesbytearray セッションのステータスが含まれているバイナリデータセット Null 不可
startdate セッションの開始時間  
optlock 楽観ロックの値としての機能を果たすバージョンフィールド  
processinstanceinfo エンティティには、プロセスインスタンスのステータスが含まれています。

表7.2 ProcessInstanceInfo

フィールド 説明 Null 許容型
instanceid プライマリキー Null 不可
lastmodificationdate エンティティがデータベースに最後に保存された時間  
lastreaddate エンティティがデータベースから最後にリトリーブされた時間  
processid プロセスの名前 (ID)  
processinstancebytearray プロセスインスタンスのステータスが含まれているバイナリデータセット Null 不可
startdate プロセスの開始時間  
state プロセスインスタンスのステータスを示す整数 Null 不可
optlock 楽観ロックの値としての機能を果たすバージョンフィールド  
eventtypes エンティティには、プロセスインスタンスで発生した/実行するイベントに関する情報が含まれています。

表7.3 EventTypes

フィールド 説明 Null 許容型
instanceid processinstanceinfo プライマリキーを参照しており、このカラムにはかい部キーの制約があります。 Null 不可
element プロセスで行ったイベントに関連する文字フィールド  
workiteminfo エンティティには、作業アイテムのステータスが含まれています。

表7.4 WorkItemInfo

フィールド 説明 Null 許容型
workitemid プライマリキー Null 不可
name 作業アイテムの名前  
processinstanceid プロセスの (プライマリキー) ID。このフィールドには外部キーの制約はありません。 Null 不可
state 作業アイテムのステータスを表す整数 Null 不可
optlock 楽観ロックの値としての機能を果たすバージョンフィールド  
workitembytearay 作業アイテムのステータスを含むバイナリデータセット Null 不可

7.3. 永続性の設定

7.3.1. 永続性の設定

永続性は、JBoss BRMS 5.3 スタンドアローンではデフォルトで設定されていますが、JBoss BRMS 5.3 をデプロイ可能な Web アプリケーションとしてデプロイする場合は、クラスパスに jar ファイルを追加して永続性の設定を行う必要があります。

7.3.2. 依存関係の追加

以下のパッケージは、手動の永続性設定が必要です。
  • JBoss BRMS 5.3 デプロイ可能パッケージ
  • データベースベンダーの JDBC ドライバー
  • トランザクションマネージャー
必要な依存パッケージを手動で追加するには、BRMS 5.3 デプロイ可能アーカイブに同梱されている jboss-jbpm-engine.zip アーカイブから必要な jar ファイルをコピーして、アプリケーションクラスパスで利用できるようにします。
JTA ベースのトランザクションマネージャーに Bitronix を、H2 in-memory データベースを使用する JPA 永続性プロバイダーとして Hibernate を組み合わせて使用する場合、以下の jar ファイルが必要です。

注記

以下のリストは例示のみを目的としています。サポート範囲の設定については、http://www.redhat.com/resourcelibrary/articles/jboss-enterprise-brms-supported-configurations のサイトでご覧ください。
  • jbpm-test
  • jbpm-persistence-jpa
  • drools-persistence-jpa
  • persistence-api
  • hibernate-entitymanager
  • hibernate-annotations
  • hibernate-commons-annotations
  • hibernate-core
  • commons-collections
  • dom4j
  • jta
  • btm
  • javassist
  • slf4j-api
  • slf4j-jdk14
  • h2

7.3.3. 永続性を使用するためのエンジン設定

jbpm-test モジュールの JBPMHelper クラスには、セッションを作成するメソッドがあり、設定ファイルを使用してこのセッションを設定します。以下の情報は、永続性が有効になっている H2 in-memory データゲースを使用する jBPM.properties ファイルの例を紹介しています。

例7.1 jBPM.properties ファイルの例

# for creating a datasource
persistence.datasource.name=jdbc/jbpm-ds
persistence.datasource.user=sa
persistence.datasource.password=
persistence.datasource.url=jdbc:h2:tcp://localhost/~/jbpm-db
persistence.datasource.driverClassName=org.h2.Driver

# for configuring persistence of the session
persistence.enabled=true
persistence.persistenceunit.name=org.jbpm.persistence.jpa
persistence.persistenceunit.dialect=org.hibernate.dialect.H2Dialect

# for configuring the human task service
taskservice.enabled=true
taskservice.datasource.name=org.jbpm.task
taskservice.transport=mina
taskservice.usergroupcallback=org.jbpm.task.service.DefaultUserGroupCallbackImpl
JBPMHelper クラスを使用してデータソースを登録することができます。
JBPMHelper.setupDataSource();
また、JBPMHelper クラスは、セッションの作成にも使用可能です (ナレッジベースが作成された後)。
StatefulKnowledgeSession ksession = JBPMHelper.newStatefulKnowledgeSession(kbase);
メソッドは、この ksession (例: startProcess) で呼び出すことが可能となり、エンジンは作成したデータソースですべてのランタイムのステータスを永続化します。
さらに、JBPMHelper クラスは、セッション ID を渡すことでデータベースからセッションのステータスをリストアしてセッションを再作成する際に使用できます。セッション ID は ksession.getId() を使用してリトリーブします。
StatefulKnowledgeSession ksession = 
    JBPMHelper.loadStatefulKnowledgeSession(kbase, sessionId);

7.3.4. セッション ID

7.3.4.1. セッション ID

直近に使用した永続セッションのセッション ID も jbpmSessionId.ser ファイルに格納されます。jbpmSessionId.ser ファイルが存在しない場合は、作成されセッション ID が保存されます。ファイルが存在する場合はセッション ID がこのファイルから読み込まれ、セッションがデータベースからロードされるので、サーバーを再起動した後もセッションを再度ロードすることができます。
デフォルトでは、jbpmSessionId.ser ファイルは jboss-as/server/profile/tmp/ ディレクトリにありますが、jboss-as/server/profile/deploy/business-central-server.war/WEB-INF/classes/ ディレクトリにある jbpm.console.propertiesjbpm.console.tmp.dir プロパティを修正することで変更できます。

7.3.5. トランザクション

デフォルトでは、アプリケーション内にトランザクション境界がない場合、エンジンは自動的に別のトランザクションとしてエンジン上で各メソッドの呼び出しを実行します。トランザクション境界を指定できるため、複数のコマンドを 1 つのトランザクションに統合することなどもできます。
以下のサンプルコードは、Bitronix トランザクションマネージャーを使用しています。
// create the entity manager factory and register it in the environment
EntityManagerFactory emf =
    Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa" );
Environment env = KnowledgeBaseFactory.newEnvironment();
env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
env.set( EnvironmentName.TRANSACTION_MANAGER,
         TransactionManagerServices.getTransactionManager() );

// create a new knowledge session that uses JPA to store the runtime state
StatefulKnowledgeSession ksession =
    JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );

// start the transaction
UserTransaction ut =
  (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();

// perform multiple commands inside one transaction
ksession.insert( new Person( "John Doe" ) );
ksession.startProcess( "MyProcess" );

// commit the transaction
ut.commit();
永続性と同時並行処理の詳細は、「マルチスレッド」 を参照してください。

7.4. 履歴ログ

7.4.1. 履歴ログ

履歴ログには、プロセスインスタンス実行に関する情報が格納されているため、これらの情報を後からリトリーブしたり閲覧したりすることができます。例えば、実行したプロセスや実行中のプロセスの数に関する履歴ログ情報などです。
実行情報の履歴ログは、プロセスエンジンが実行中に生成したイベントをベースにして作成されます。これは、jBPM ランタイムエンジンにイベントをリッスンするという一般的なメカニズムがあるため、可能です。これらのイベントから必要な情報を簡単に抽出して、データベースに永続的に格納することができます。また、ログ記録した情報の範囲を絞るために、フィルターを使用することも可能です。

7.4.2. ビジネスアクティビティ監視のデータモデル

jbpm-bam モジュールには、JPA や Hibernate を使用して直接データベースにプロセス関連の情報を格納するイベントリスナーが含まれています。データモデル自体は、プロセスインスタンスの情報、ノードインスタンスの情報、(プロセス) 変数インスタンスの情報の 3 つのエンティティで構成されています。
データベース内のプロセス関連の情報

図7.2 ビジネスアクティビティ監視のデータモデル

ProcessInstanceLog の表には、プロセスインスタンスに関する基本的なログ情報が含まれます。

表7.5 ProcessInstanceLog

フィールド 説明 Null 許容型
id ログエンティティのプライマリキーおよび ID Null 不可
end_date プロセスインスタンスの終了日 (あれば)  
processid プロセスの名前 (ID)  
processinstanceid プロセスインスタンス ID Null 不可
start_date プロセスインスタンスの開始日  
NodeInstanceLog の表には、各プロセスインスタンス内で実行されたノードの情報が含まれます。ノードインスタンスが内向き接続の 1 つから入ってくるか、外向き接続の 1 つから出てくる度に、ノードの情報がこの表に格納されます。

表7.6 NodeInstanceLog

フィールド 説明 Null 許容型
id ログエンティティのプライマリキーおよび ID Null 不可
log_date イベントの日付  
nodeid プロセス定義内の対象ノードのノード ID  
nodeinstanceid ノードインスタンス ID  
nodename ノード名  
processid プロセスインスタンスが実行するプロセス ID  
processinstanceid プロセスインスタンス ID Null 不可
type イベントのタイプ (0 = enter, 1 = exit) Null 不可
VariableInstanceLog の表には、変数インスタンスの変更に関する情報が含まれています。デフォルトは、変数が変更された後にだけログのエントリを生成するようになっていますが、変数の値が変更する前でもエントリをログ記録することができます。

表7.7 VariableInstanceLog

フィールド 説明 Null 許容型
id ログエンティティのプライマリキーおよび ID Null 不可
log_date イベントの日付  
processid プロセスインスタンスが実行するプロセス ID  
processinstanceid プロセスインスタンス ID Null 不可
value ログが作成された時点の変数の値  
variableid プロセス定義の変数 ID  
variableinstanceid 変数インスタンス ID  

7.4.3. データベースへのプロセスイベントの格納

データベースにプロセス履歴のログを残すには、ロガーをセッションに登録してください。
StatefulKnowledgeSession ksession = ...;
JPAWorkingMemoryDbLogger logger = new JPAWorkingMemoryDbLogger(ksession);

// invoke methods one your session here

logger.dispose();
このロガーは他の監査ロガーとよく似ており、addFilter メソッドを呼び出すことで 1 つ以上のフィルターを追加して、該当する情報のみがデータベースに格納されるようにします。
ロガーは、必要なくなると破棄する必要があります。
永続データベースは、JBoss BRMS 5.3 のデプロイ可能インストレーションの business-central-server.war/WEB-INF/classes/META-INF/ ディレクトリにある persistence.xml ファイルで設定します。
       <?xml version="1.0" encoding="UTF-8" standalone="yes"?><persistence
           version="1.0"
           xsi:schemaLocation=
           	"http://java.sun.com/xml/ns/persistence
           	 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
       		 http://java.sun.com/xml/ns/persistence/orm 
       		 http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
           xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://java.sun.com/xml/ns/persistence"><!--persistence-unit name="ProcessService"><jta-data-source>java:/DefaultDS</jta-data-source><properties><property name="hibernate.hbm2ddl.auto" value="create-drop"/></properties></persistence-unit--><persistence-unit name="org.jbpm.persistence.jpa" transaction-type="JTA"><provider>org.hibernate.ejb.HibernatePersistence</provider><jta-data-source>java:/DefaultDS</jta-data-source><mapping-file>META-INF/JBPMorm.xml</mapping-file><class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class><class>org.drools.persistence.info.SessionInfo</class><class>org.drools.persistence.info.WorkItemInfo</class><class>org.jbpm.process.audit.ProcessInstanceLog</class><class>org.jbpm.process.audit.NodeInstanceLog</class><class>org.jbpm.process.audit.VariableInstanceLog</class><properties><property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/><property name="hibernate.max_fetch_depth" value="3"/><property name="hibernate.hbm2ddl.auto" value="update" /><property name="hibernate.show_sql" value="false" /><property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" /></properties></persistence-unit></persistence>
       

        
         
         
          
         
        

         
           
                  
           
           
           
           
           
           
           
           
                       
             
             
               
             
                   
         


第8章 Business Central コンソール

8.1. Business Central コンソール

ビジネスプロセスは、Web コンソールで管理できます。Web コンソールには、プロセスインスタンスの管理機能 (開始/停止/検査)、(ヒューマン) タスクリストの検査や実行機能、レポート生成機能が含まれています。
Business Central コンソールは、スタンドアローン JBoss BRMS 5.3 ではインストールされてます。インストールの方法については、『BRMS スタートガイド』を参照してください。デプロイ可能パッケージから JBoss BRMS 5.3 を使用する場合は、コンソールをインストールする必要があります。このコンソールには、2 つの war ディレクトリが含まれており、アプリケーションサーバーにデプロイする必要があります。これらのディレクトリには、必要なライブラリや実際のアプリケーションが含まれています。jar の 1 つにはサーバーアプリケーションが、もう 1 つにはクライアントが含まれています。詳細は 『BRMS スタートガイド』を参照してください。

8.2. Business Central コンソールと BRMS 統合

8.2.1. Business Central コンソールと BRMS 統合

Business Central コンソールは、JBoss BRMS レポジトリと統合されています。コンソールは、レポジトリで利用可能なパッケージからアーチファクトをリトリーブします (注: グローバルエリアのパッケージは含まれていません)。パッケージは BRMS でビルドしてからでないと、コンソールで表示されません。パッケージを更新、再構築して、更新ボタンを押すとコンソールから更新したパッケージにアクセスできるようになります。
コンソールは、BRMS レポジトリから利用可能なパッケージすべてをリトリーブしようとしますので、全パッケージを BRMS で正常にビルドする必要があります。コンソールがリトリーブするパッケージの範囲を制限することができます。詳細については、「Business Central コンソールの設定」 を参照してください。
BRMS で全パッケージを一度にビルドするには、ナビゲーションメニューから Knowledge BasesCreate NewRebuild all package binaries を選択します。

8.2.2. Business Central コンソールの設定

管理コンソールは、jboss-as/server/profile/deploy/business-central-server.war/WEB-INF/classes/ ディレクトリの jbpm.console.properties ファイルで設定されています。このファイルでは以下のプロパティが設定されています。

注記

以下に記載のプロパティがすべて jbpm.console.properties ファイルにデフォルトで含まれているわけではありません。
  • jbpm.console.server.host (デフォルト localhost)
  • jbpm.console.server.port (デフォルト 8080)
  • jbpm.console.task.service.host (デフォルト localhost)。タスクサーバーがデプロイされるホストは全トランスポートに適用されます。
  • jbpm.console.tmp.dir: 直近に使用した永続セッションのセッション ID を格納する jbpmSessionId.ser ファイルの場所を設定する際に使用する任意のプロパティ
  • jbpm.console.task.service.port: タスクサーバーがデプロイされるポート (HornetQ を使用している場合は 5446)
  • jbpm.console.task.service.strategy (デフォルト HornetQ)
  • JMSTaskClient.connectionFactory (デフォルトなし): JMS のみを対象とする接続ファクトリの JNDI 名
  • JMSTaskClient.acknowledgeMode (デフォルトなし): JMS のみを対象とする応答確認 (AM) モード
  • JMSTaskClient.transactedQueue (デフォルトなし): JMS のみを対象とするトランザクションキューの名前
  • JMSTaskClient.queueName (デフォルトなし): JMS のみを対象とするキューの名前
  • JMSTaskClient.responseQueueName (デフォルトなし): JMS のみを対象とする応答キューの名前
  • guvnor.protocol (デフォルト http)
  • guvnor.host (デフォルト localhost:8080)
  • guvnor.subdomain (デフォルト drools-guvnor)
  • guvnor.usr (デフォルト admin)
  • guvnor.pwd (デフォルト admin)
  • guvnor.packages (Guvnor からロードするパッケージをコンマで区切った一覧。パッケージが指定されていない場合は、全パッケージが表示されます。表示対象のパッケージが指定されている場合は、指定のパッケージのみが表示されることを忘れないでください)。
  • guvnor.connect.timeout (デフォルト 10000)
  • guvnor.read.timeout (デフォルト 10000)
  • guvnor.snapshot.name (デフォルト LATEST): 使用するスナップショットを指定する任意のプロパティです。

注記

このファイルに含まれるパスワードとユーザー名は、jboss-as/server/production/deploy/jboss-brms.war/WEB-INF/components.xml の認証情報と一致する必要があります。認証情報がどちらか一方で変更された場合、どちらの場所にある情報も変更する必要があります。
コンソールの複数のインスタンスやコンソールにアタッチされているプロセスエンジンが永続データベースで同じデータを共有できるようにするため、Business Central コンソールのクラスタリングが可能です。コンソールのクラスタリングをすると、クラスター全体に利用可能なプロセスを拡張し、クラスター内のノードに問題が発生した場合でもフェールオーバーが必ず行われるようにします。詳細は 『BRMS スタートガイド』を参照してください。

8.2.3. ユーザーとグループの管理

ヒューマンタスクサービスでは、グループメンバーがそのグループに割り当てられたタスクを獲得できるようにユーザーをグループメンバーとして定義する必要があります。コンソールは、username / group の関連性を使用します。JBoss BRMS 5.3 スタンドアローンインストレーションを使用している場合は、グループの割り当ては、server/profile/conf/props/ ディレクトリの brms-roles.properties ファイルで指定します。
別のログインモジュールを設定することも可能です。セキュリティ認証については、『BRMS 管理者ガイド』を参照してください。

8.3. Business Central コンソールへのログイン

Business Central コンソールにログインするには、Web ブラウザーを http://localhost:8080/business-central に指定して、ユーザーを有効化した際に作成したユーザーの認証情報を入力します。Business Central コンソールから、ビジネスプロセスを管理できます。

8.4. プロセスインスタンスの管理

Business Central コンソールには、インストールされたナレッジベースの一部としてビジネスプロセスの管理機能があります。

プロセスインスタンスの管理

プロセスインスタンスの管理
Processes メニューの配下にあるプロセスインスタンスの表には特定のプロセス定義に対して実行中のインスタンスがすべて表示されます。この特定のプロセスインスタンスについての詳細を表示するには、プロセスインスタンスを 1 つ選択してください。
新規プロセスインスタンスの開始
新しいプロセスインスタンスは、プロセス定義一覧からプロセス定義を選択して Start を押して開始します。フォームがプロセスと関連付けられている場合 (プロセス開始前に追加情報を要求)、フォームが表示されます。フォームへの入力を終えると、提供した情報を使用してプロセスが開始されます。
プロセスインスタンスのステータスの確認
特定のプロセスインスタンスのステータスを確認するには、Diagram ボタンをクリックします。すると、現在アクティブなノードに赤い三角の印がついた状態でプロセスフロー図が表示されます。
プロセスインスタンスの変数の確認
トップレベルのプロセスインスタンス変数は、Instance Data ボタンをクリックすることで確認できます。
プロセスインスタンスの終了
プロセスインスタンスを終了するには、Terminate ボタンをクリックします。
プロセスインスタンスの削除
プロセスインスタンスを削除するには、Delete ボタンをクリックします。
プロセスのシグナル送信
中間シグナルイベントを検出するように定義されたプロセスにシグナルを送信するには、signal ボタンをクリックします。

8.5. ヒューマンタスクのリスト

コンソールのタスク管理のセクションは、現在のタスクの一覧を確認することができます。グループタスクの一覧には、固有のユーザー 1 名に割り当てられていないタスクの内、現在ログイン中のユーザーが取得可能なリストを表示しています。タスクを実行するには、個人タスクの一覧からタスクを選択して、View をクリックします。フォームが選択したタスクに関連付けられている場合 (追加情報を必要とする場合など) フォームが表示されます。フォームの入力が終わると、タスクも完了します。

8.6. サービスハンドラーの登録

サービスハンドラーは、カスタムのサービスタスクとしてドメイン固有サービスを実行するために登録する必要があります。プロセスには実行する必要のあるサービスについて概略の説明しか含まれていないため起こり、結果ハンドラーはサービスの呼び出しを行います。
サービスハンドラーは、クラスパスに各ハンドラーのクラス実装を指定する設定ファイルを追加して登録します。drools.workItemHandlers プロパティを使用して、ファイル名をスペースで区切ったリストとしてどの設定ファイルをロードするのか、drools.session.conf ファイル内で指定します。
drools.workItemHandlers = CustomerWorkItemHandlers.conf
これらのファイル名には、サービスの実行に使用すべきエントリマップ、名前、対象の WorkItemHandler インスタンスを含める必要があります。設定ファイルは、MVEL スクリプト言語を使用して型のマップ Map<String,WorkItemHandler>: を指定しています。
[
   "log" : new org.jbpm.process.instance.impl.demo.SystemOutWorkItemHandler(),
]
実装クラス (および依存関係) もサーバーの war のクラスパスに追加する必要があります。

8.7. 新規プロセスとタスクフォームの追加

フォームは、新規プロセスの開始とヒューマンタスクの完了に使用することができます。固有のプロセス定義のフォームを作成するには、名前が {processId}.ftl というテンプレートを作成します。テンプレート自体は、HTML を使用してフォームをモデリングします。例えば、com.sample.evaluation.ftl ファイルは HTML を使用して以下のようなフォームをモデリングします。
<html><body><h2>Start Performance Evaluation</h2><hr><form action="complete" method="POST" enctype="multipart/form-data">
Please fill in your username: <input type="text" name="employee" /></BR><input type="submit" value="Complete"></form></body></html>







特定の種類のヒューマンタスクに対するタスクフォームは、{taskName}.ftl という名前のテンプレートを作成することでヒューマンタスクと関連付けることができます。フォームから現在のヒューマンタスクを表すタスクパラメーターにアクセスできるため、タスクフォームはタスクの入力項目に基づいて動的に調節することができます。タスクパラメーターは、jbpm-human-task モジュールで定義されているように、タスクモデルのオブジェクトです。これにより、タスクフォームをタスクに関連する入力データや説明をもとにカスタマイズすることができます。例えば、先ほど紹介した評価フォームはタスクパラメーターを使用してタスクの説明にアクセスして、以下のようにタスクフォームにその説明を表示します。
<html><body><h2>Employee evaluation</h2><hr>
${task.descriptions[0].text}<br/><br/>
Please fill in the following evaluation form: 
<form action="complete" method="POST" enctype="multipart/form-data">
Rate the overall performance: <select name="performance"><option value="outstanding">Outstanding</option><option value="exceeding">Exceeding expectations</option><option value="acceptable">Acceptable</option><option value="below">Below average</option></select><br/><br/>
Check any that apply:<br/><input type="checkbox" name="initiative" value="initiative">Displaying initiative<br/><input type="checkbox" name="change" value="change">Thriving on change<br/><input type="checkbox" name="communication" value="communication">Good communication skills<br/><br/><input type="submit" value="Complete"></form></body></html>


















タスクフォームは、パラメーターマッピングを使用してプロセス変数からユーザータスクノードにマッピングされる追加のタスクパラメーターにもアクセスできます。詳細は 「ヒューマンタスク」 を参照してください。これらのタスクパラメーターも直接タスクフォームの中からアクセスすることができます。例えば、タスクフォームに顧客の依頼を確認させるようにするには、ユーザータスクノードは (依頼を出した顧客の) userId、コメント(依頼の説明)、日付 (実際の依頼の日付/時間) をプロセスからタスクにタスクパラメーターとしてコピーします。そうすると、これらのパラメーターは、タスクフォームから直接アクセスできるようになります。
<html><body><h2>Request Review</h2><hr>
UserId: ${userId} <br/>
Description: ${description} <br/>
Date: ${date?date} ${date?time}
<form action="complete" method="POST" enctype="multipart/form-data">
Comment:<BR/><textarea cols="50" rows="5" name="comment"></textarea></BR><input type="submit" name="outcome" value="Accept"><input type="submit" name="outcome" value="Reject"></form></body></html>








ユーザーがタスクフォームに入力して提示したデータは、タスク完了時に結果パラメーターとして追加されます。データ要素の名前が結果パラメーターの名前として使用されます。例えば、上記の最初のタスクを完了すると、結果のパラメーターのマップに performance、initiative、change、communication と呼ばれる結果変数が含まれます。結果パラメーターには、これらの結果パラメーターを結果マッピングでプロセス変数にマッピングすることで、関連のプロセスからアクセスできます。
フォームは、(例えば jbossas/server/profile/lib ディレクトリの jar の中にあるか、jbpm コンソールサーバー war の jbpm-gwt-form.jar のサンプルフォームのセットに追加されている) クラスパスにあるか、JBoss BRMS プロセスレポジトリに格納することができます。

8.8. REST インターフェース

Web コンソールには、REST が公開する機能に対する REST インターフェースがあります。これにより、プロセスインスタンスの開始やタスクリストのリトリーブなどの機能が使用できるように、プロセスエンジンと簡単に統合することができます。
REST インターフェースが公開する一覧 URL は、以下の URL から確認いただけます。
例えばタスクは、以下を使ってクローズできます。
/business-central-server/rs/task/{taskId}/close
以下を使って、新しいプロセスインスタンスを開始することができます。
/business-central-server/rs/process/definition/{id}/new_instance

第9章 ドメイン固有プロセス

9.1. ドメイン固有サービスノード

ドメイン固有のプロセスは、ドメイン固有の拡張を使用してデフォルトのプロセスコンストラクトを拡張します。ドメイン固有言語は、1 つのアプリケーションドメインを対象としているため、解決しようとしている問題に深く関係するコンストラクトを提供でき、プロセスが簡単に理解でき、ある程度は自己文書化できます。ドメイン固有の作業アイテム (またはサービスノード) は、実行の必要のあるアトミックな作業単位を表しています。これは、プロセスのコンテキストで何を実行するかを宣言形式で指定することで表現できます。
ドメイン固有のサービスノードは、以下でなければなりません。
  1. 宣言型 (how ではなく what を記述)
  2. ハイレベル (コードなし)
  3. コンテキストに適合可能
ドメイン固有のサービスノードを定義して、プロセス言語に統合することができます。以下の画像は、医療のコンテキストにおけるプロセスの例となっています。このプロセスには、看護師依頼のタスクに関するドメイン固有のサービスノード (血圧測定、処方、介護医療機関への通知) が含まれています。

例9.1 看護師の依頼タスク

ドメイン固有サービスのノード例

9.2. 作業アイテムの定義

作業アイテムは、アトミックな作業単位を宣言型で表しています。作業アイテムには一意名やパラメーターが含まれており、アイテム毎に結果が表示されるであろう場所に結果を含めることもできます。結果パラメーターやアイコンなしの作業アイテムの通知は、以下のように定義できます。
  Name: "Notification"
  Parameters
  From [String]
  To [String]
  Message [String]
  Priority [String]
作業アイテムの定義は、META-INF ディレクトリのプロジェクトパスにある 1 つまたは複数の設定ファイル (.wid ファイル拡張) で指定します。プロパティは、名前と値のペアで指定します。パラメーターと結果はマッピングされ、各パラメーター名は結果として期待されるデータ型にマッピングされます。設定ファイルには、その作業アイテムの表示名やアイコンも含まれています。

例9.2 MVEL を使用した「通知」作業アイテムの例

import org.drools.process.core.datatype.impl.type.StringDataType;
[
  // the Notification work item
  [
    "name" : "Notification",
    "parameters" : [
      "Message" : new StringDataType(),
      "From" : new StringDataType(),
      "To" : new StringDataType(),
      "Priority" : new StringDataType(),
    ],
    "displayName" : "Notification",
    "icon" : "icons/notification.gif"
  ]

]
アイコンは、.gif か .png 形式でなければなりません。いずれの形式でも、ピクセルサイズは 16x16 とします。また、アイコンは resources ディレクトリに保存するものとします。
project/src/main/resources/icons/notification.gif
作業アイテムにはすべて、アイテム内に定義したプロパティに加え、以下の 3 つのプロパティも含まれています。
  1. Parameter Mapping:
    プロセス内の変数の値を作業アイテムのパラメーターにマッピングします。作業アイテムは、実際のプロセスインスタンスの現在のステータスにしたがいカスタマイズすることが可能です (例えば、通知の優先順位はプロセス固有の情報に左右されるなど)。
  2. Result Mapping:
    結果をプロセス変数にマッピングします。これは作業アイテムが実行された後に返される値で、この変数を残りのプロセスで利用できるようにします。
  3. Wait for completion:
    デフォルトでは、依頼された作業アイテムが完了するまで待機してから、プロセスを継続します。また、Wait for completion を False に設定することで、(結果を待たずに) 作業アイテムの依頼直後にプロセスを継続させることも可能です。
以下のプロセスは、Java を実行するドメイン固有ノードの作成例で、クラスやメソッドパラメーターを依頼しています。これには、カスタムの java.gif アイコンが含まれており、以下のファイルや結果として出されたスクリーンショットなどで構成されています。

例9.3

import org.drools.process.core.datatype.impl.type.StringDataType;
[
  // the Java Node work item located in:
  // project/src/main/resources/META-INF/JavaNodeDefinition.conf
  [
    "name" : "JavaNode",
    "parameters" : [
      "class" : new StringDataType(),
      "method" : new StringDataType(),
    ],
    "displayName" : "Java Node",
    "icon" : "icons/java.gif"
  ]

]

9.3. 作業定義の登録

プロセスの編集に JBoss Developer Studio を使用すると、drools.workDefinitions プロパティを使用して、プロジェクトに関連するカスタムの作業アイテム定義ファイルを登録することができます。このプロパティは、作業定義を含むファイル一覧 (スペース区切りのリスト) を表します。例えば、プロジェクトの META-INF ディレクトリに drools.rulebase.conf ファイルを含め、以下の行を追加します。
  drools.workDefinitions = MyWorkDefinitions.wid
上記により、デフォルトのドメイン固有ノード型 EMAIL および LOG が JBoss Developer Studio のプロセスエディターで新たに定義された NOTIFICATION ノードで置き換えられます。新たに作成したノード定義を既存のパレットノードに追加するだけの場合は、drools.workDefinitions プロパティを以下のように調整して、デフォルトの設定ファイルも含めます。
  drools.workDefinitions = MyWorkDefinitions.conf WorkDefinitions.conf

注記

ドメイン固有ノードに関する独自の定義には、.wid 拡張を使用するように推奨しています。
JBoss Enterprise BRMS ユーザーインターフェースで作業アイテムを更新する方法は 「ドメイン固有サービスノードの定義」 を参照してください。

9.4. サービスノードの実行

プロセスエンジンには、WorkItemHandlers に作業アイテムを委譲して実行させる WorkItemManager が含まれています。WorkItemHandlers は、作業アイテムの処理が完了すると WorkItemManager に通知します。「通知 (Notification)」の作業アイテムを実行するには、NotificationWorkItemHandler を作成する必要があります (WorkItemHandler インターフェースの実装)。
package com.sample;

import org.drools.runtime.process.WorkItem;
import org.drools.runtime.process.WorkItemHandler;
import org.drools.runtime.process.WorkItemManager;

public class NotificationWorkItemHandler implements WorkItemHandler {

  public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
    // extract parameters
    String from = (String) workItem.getParameter("From");
    String to = (String) workItem.getParameter("To");
    String message = (String) workItem.getParameter("Message");
    String priority = (String) workItem.getParameter("Priority");
    // send email
    EmailService service = ServiceRegistry.getInstance().getEmailService();
    service.sendEmail(from, to, "Notification", message);
    // notify manager that work item has been completed
    manager.completeWorkItem(workItem.getId(), null);
  }

  public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
    // Do nothing, notifications cannot be aborted
  }

}
この WorkItemHandler は、E-メールとして通知を送信直後に、WorkItemManager に作業アイテムの処理完了を通知します。すべての作業アイテムの処理が直接完了できるわけではない点にご注意ください。作業アイテムの実行に時間がかかる場合、非同期的に実行が継続され WorkItemManager への通知は後ほど送信されます。作業アイテムが完了前に中断してしまった場合、abort メソッドを使用してアイテムの中断方法を指定する必要があります。
WorkItemHandlers は、以下の API を使用して WorkItemManager に登録する必要があります。
ksession.getWorkItemManager().registerWorkItemHandler(
    "Notification", new NotificationWorkItemHandler());
作業アイテムの実行をプロセス自体から切り離すことで、次のような利点があります。
  1. プロセスがより宣言形式になり、方法でななく何を実行するのかを指定します。
  2. 環境の変更は、作業アイテムハンドラーを変更することで実装することができます。プロセス自体は変更しないようにしてください。
  3. 作業アイテムハンドラーが対象のサービスとの統合を行なっている場合、別の環境でも同じプロセスを利用することができます。
  4. 作業アイテムハンドラーは、プロセスやプロジェクトの境界を超えて、簡単に共有できます (プロセス自体にコードが埋め込まれている場合はより困難になります)。
  5. コンテキストにあわせて、様々な作業アイテムハンドラーを使用することができます。例えば、テストやシミュレーションには、作業アイテムを実行する必要がない場合もあります。このような場合、テスト時にはダミーの特別作業アイテムハンドラーを使用します。

9.5. サービスレポジトリ

ドメイン固有サービスは、他のユーザーが利用できるようにレポジトリに追加することができます。
サービスは、設定ファイルを作成してサービスレポジトリに追加します。この設定ファイルには、必要な情報をすべて含め、さらに必要なファイルをリンクします。「作業アイテムの定義」にもあるように、設定ファイルは、通常の作業定義の設定ファイルを拡張したバージョンとなっています。

例9.4 サービスレポジトリの設定ファイル

     import org.drools.process.core.datatype.impl.type.StringDataType;
     [
       [
         "name" : "Twitter",
         "description" : "Send a twitter message",
         "parameters" : [
         	"Message" : new StringDataType()
         ],
         "displayName" : "Twitter",
         "eclipse:customEditor" : "org.drools.eclipse.flow.common.editor.editpart.work.SampleCustomEditor",
         "icon" : "twitter.gif",
         "category" : "Communication",
         "defaultHandler" : "org.jbpm.process.workitem.twitter.TwitterHandler",
         "documentation" : "index.html",
         "dependencies" : [ 
           "file:./lib/jbpm-twitter.jar", 
           "file:./lib/twitter4j-core-2.2.2.jar"
         ]
       ]
     ]
  • icon プロパティは、拡張設定ファイルと同じフォルダーにある (指定のファイル名の) ファイルを参照するようにしてください (これにより、インポートウィザードからのダウンロードやプロセス図での使用が可能になります)。アイコンは、16x16 GIF ファイルでなければなりません。
  • category プロパティは、レポジトリをブラウズする際に利用する、このサービスのカテゴリを定義します。
  • defaultHandler プロパティは、デフォルトのハンドラー実装を定義します (WorkItemHandler インターフェースを実装する java クラスで、サービスの実行に使用可能)。これにより、レポジトリからサービスをインポートする際に、このサービスのハンドラーとして自動的に登録されます。
  • documentation プロパティは、サービスが何をしてどのように機能するのかを説明している文書ファイルを定義します。このプロパティは、拡張設定ファイルと同じフォルダーにある (指定のファイル名の) HTML ファイルを参照するようにしてください (これにより、インポートウィザードからのダウンロードやプロセス図での使用が可能になります)。
  • dependencies プロパティは、このサービスを実行するために必要となる追加の依存関係を定義します。通常このプロパティにはハンドラー実装 jar が含まれていますが、追加で外部の依存関係が含まれる場合もあります。サービスのインポート時にインポートウィザードからダウンロードができるように、これらの依存関係も指定の場所 (拡張設定ファイルの場所と相対的なフォルダー) にあるレポジトリーに設置する必要があります。
またレポジトリの root には、レポジトリでサービスを検索する際に処理すべきフィルダーをすべて参照する index.conf ファイルが配備されている必要があります。これらのフォルダーには、それぞれ以下を含めるものとします。
  • フォルダーと同じ名前の拡張設定ファイル (例: サービスタスクを定義する Twitter.conf)
  • 設定ファイル内で参照するアイコン
  • 設定ファイル内で参照する文書
  • 設定ファイル内で参照する依存関係 (例: lib フォルダー内)
追加のサブフォルダーのスキャンに使用できるように、レポジトリの各サブディレクトリに index.conf を追加します。インポートウィザードを使用してレポジトリをブラウズしてもレポジトリの階層構造は表示されない点に留意してください。代わりに設定ファイルの category プロパティを使用します。
以下の例では、JBoss Developer Studio と併せて使用する際にサービスレポジトリからリソースをインポートする方法について説明しています。

手順9.1 サービスレポジトリからのリソースのインポート手順

  1. プロジェクトを右クリックして Import... を選択します。
  2. インポートするリソースのソースを選択します。GuvnorResources from Guvnor を選び、Next をクリックします。
  3. リソースに移動します。Guvnor 内のリソースのあるパッケージを選択して、そのリソースをハイライトします。Menu をクリックします。
  4. リソースのインポート先を選択して、Finish をクリックします。

第10章 ヒューマンタスク

10.1. ヒューマンタスク

ヒューマンタスクとは、人間のアクター (ヒューマンアクター) が介入する必要のあるプロセス内のタスクのことです。BRMS ビジネスプロセス管理は、ヒューマンアクターとの対話をモデリングできるように、プロセス内のヒューマンタスクノードに対応しています。ヒューマンタスクノードがあると、ヒューマンアクターが実施しなければならないタスクのプロパティをプロセスデザイナーで定義することができます。例えば、ヒューマンタスクノードは、タスクのタイプ、アクター、タスクに関連するデータを定義することができます。バックエンドのヒューマンタスクサービスは、ランタイム時のタスクのライフサイクルを管理します。ヒューマンタスクサービスの実装は、WS-Human Task 仕様をベースとしており、実装は完全にプラグ可能です。つまり、必要であれば独自のヒューマンタスクソリューションを統合することができるのです。
プロセスにヒューマンタスクを含めるには、以下の手順に従う必要があります。
  • ヒューマンタスクノードは、プロセスモデル内に含める必要があります。
  • タスク管理コンポーネントは、BRMS BPM (BRMS 5.3 スタンドアローンには WS-Human Task が同梱されている) と統合する必要があります。
  • エンドユーザーは、タスクを依頼、請求、完了するためにヒューマンタスククライアントと対話する必要があります。

10.2. ヒューマンタスクのプロセスへの追加

10.2.1. ユーザータスクノード

この画像は、ユーザータスクノードのプロセスについて示しています。
ユーザータスクノードは、ヒューマンアクターが実行する必要のあるアトミックタスクを表しています。

注記

ヒューマンタスクノードは、その他の外部サービスと同じとみなされ、ドメイン固有サービスとして呼び出されなければなりません。詳細は 「ドメイン固有サービスノード」 を参照してください。
ユーザータスクノードには、以下のプロパティが含まれています。
  • ID: ノードの ID (1 つのノードコンテナー内で一意)
  • Name: ノードの表示名
  • TaskName: ヒューマンタスクの名前
  • Priority: ヒューマンタスクの優先順位を指定する整数
  • Comment: ヒューマンタスクに関連するコメント
  • ActorId: ヒューマンタスクの実行を担当するアクター ID。アクター ID の一覧を指定するには、区切り文字としてコンマ (',') を使用してください。
  • GroupId: ヒューマンタスクの実行を担当するグループ ID。グループ ID の一覧を指定するには、区切り文字としてコンマ (',') を使用してください。
  • Skippable: ヒューマンタスクが任意かどうかを指定します。アクターがタスクの実行をしないと決定することができるかどうか。
  • Content: このタスクに関連付けられたデータ
  • Swimlane: このヒューマンタスクノードの一部となるスイムレーン。スイムレーンは、同じアクターに複数のヒューマンタスクを簡単に割り当てることができます。
  • On entry and on exit actions: このノードが出入の際に実行されるアクションスクリプト
  • Parameter mapping: プロセス変数の値をヒューマンタスクのパラメーターにコピーできるようにします。ヒューマンタスクを作成すると、値がコピーされます。
  • Result mapping: ヒューマンタスクの結果パラメーターの値をプロセス変数にコピーできるようにします。ヒューマンタスクが完了すると、値がコピーされます。ヒューマンタスクには結果変数 "Result" があり、これにはヒューマンアクターが返すデータが含まれています。変数 "ActorId" には、タスクを実際に実行するアクターの ID が含まれています。
ユーザータスクノードは、JBoss Developer Studio または、BRMS ユーザーインターフェースに埋め込まれているプロセスデザイナーで編集する際の Properties ビューで編集することができます。

10.2.2. 動的なヒューマンタスクプロパティ

name、actorID、priority などのプロパティは、プロセスの作成時にユーザータスクノードに追加することができますが、ヒューマンタスクのプロパティによっては、このノードが所属するプロセスインスタンスの別の部分からのデータに依存している場合があるため、ヒューマンタスクのプロパティを動的に追加する必要性がでてきます。ヒューマンタスクのプロパティを動的にする方法は 2 種類あります。
#{expression}
String 型のタスクパラメーターの場合、#{expression} を使用して文字列に任意の式の値を埋め込むことができます。例えば、タスクに関連するコメントが "Please review this request from user #{user}" であったとします (この user はプロセス内の変数です)。 #{user} は、特定のプロセスインスタンスの実際のユーザー名で置き換えられます。#{expression} の値は、ヒューマンタスクが作成されると解決され、 #{...} は解決後の toString() 値で置き換えられます。この指揮は、単に変数の名前 (この場合変数の値で解決される) ですが、より高度な MVEL 式も利用可能です。例えば、#{person.name.firstname} を式として使用することもできます。この方法は String パラメーターにのみ仕様することができる点に注意してください。その他のパラメーターは、パラメーターマッピングを使用して、そのパラメーターに値をマッピングする必要があります。
パラメーターマッピング
プロセス変数の値 (または変数から取得した値) はタスクパラメーターにマッピングすることができます。例えば、プロセス内の変数が ID となっているユーザーにタスクを割り当てる必要がある場合、このタスクは ID 変数をパラメーター Actorid にマッピングすることで完了できるようになります。

10.2.3. ユーザーとグループの割り当て

タスクは、ユーザー毎に割り当てることができ、タスクは指定のユーザーのタスク一覧にのみ表示されます。タスクが複数のユーザーに割り当てられている場合、その中のユーザーであればタスクの請求、実行ができます。
また、タスクは 1 つ以上のグループに割り当てることができます。同様に指定のグループのタスク一覧に表示され、そのグループのメンバーであれば誰でもタスクの請求、実行ができます。

10.2.4. 標準のヒューマンロール

ビジネスプロセス管理のタスクと通知は、一般のヒューマンロールに割り当てることが可能です。以下のリストは、これらの一般的なロールについて記載しています。
  • Task Initiator - タスクインスタンスを作成します。
  • Task Stakeholders - タスクインスタンスの結果を担当します。
  • Potential Owners - タスクを受け取りそのタスクを完了することができます。
  • Actual Owner - 実際にタスクを実行します。
  • Excluded Owners - タスクを準備、開始できません。
  • Business Administrators - Task Stakeholders ロールを実行しますが、タスク型レベルで行います。
  • Notification recipients - タスクに関連する通知を受領します。

注記

Task Stakeholder は BRMS BPM 5.3.1 では特別な権限はありませんが、Business Administrator は Task Owner でなくてもタスクの請求、停止、解放、一時停止、再開、省略、委譲、移行、アクティベート、終了を行う権限があります。

10.2.5. タスクのエスカレーションと通知

タスクのエスカレーションが場合によっては必要になります。例えば、タスクに割り当てられたユーザーが一定の時間以内にそのタスクを完了できない場合などです。このような場合、タスクは別のアクターかグループに再割当てされます。以下のステータスにあるタスクに対して、エスカレーションを定義することができます。
  • 開始されていない (READY または RESERVED)
  • 完了されていない (IN_PROGRESS)
エスカレーションが発生するたびに、タスクは、以前に割り当てられていたユーザーから、エスカレーション定義のあるユーザーやグループに potential owners として割り当て直されます。Actual Owner がタスクに割り当てられると、エスカレーションがリセットされタスクが READY のステータスに入ります。
エスカレーション ID の単純な再割当て例
以下は、エスカレーションプロセスの際に指定した属性一覧です。
  • Users。この属性は、エスカレーション時にタスクを割り当てるべき、コンマ区切りのユーザー一覧です。この属性の許容値は、文字列の値と #{user-id} 式です。
  • Groups。この属性は、エスカレーション時にタスクを割り当てるべき、コンマ区切りのユーザー一覧です。この属性の許容値は、文字列の値と #{group-id} 式です。
  • Expires At。この属性は、エスカレーションを行うべき時間を定義します。タイマーと同様に時間の規格 (2m, 4h, 6d, など) で定義する必要があります。この属性の許容値は、文字列の値と #{expiresAt} 式です。
  • Type。この属性は、エスカレーションを行うべきタスクのステータスのタイプを特定します (not-started | not-completed)。
E-メール通知は「Notification」タブから送信されます。定義としてはエスカレーションと非常に似ています。E-メール通知は、以下のステータスのタスクに対して送信可能です。
  • 開始されていない (READY または RESERVED)
  • 完了されていない (IN_PROGRESS)
E-メールメッセージの使用方法を示す Notification タブ
E-メール通知には以下のプロパティがあります。
  • Type。この属性は、エスカレーションを行うべきタスクのステータスのタイプを特定します (not-started | not-completed)。
  • Expires At。この時間定義のプロパティは、エスカレーションを行うべき時間を特定します。タイマーと同様に時間の規格 (2m, 4h, 6d, など) で定義する必要があります。このプロパティの許容値は、文字列の値と #{expiresAt} 式です。
  • From。E-メールメッセージの From フィールドで使用する、任意のユーザーまたはグループ ID、許容値は文字列と式です。
  • To Users。通知の受信者となるユーザーの ID (コンマ区切りのリスト)。
  • To Groups。通知の受信者となるグループの ID (コンマ区切りのリスト)。
  • Reply To、通知の返信を受け取るべき任意のユーザーまたはグループ ID。
  • Subject。通知の件名。許容値は文字列と式となっています。
  • Body。通知の内容。許容値は文字列と式となっています。
通知は #{processVariable} でプロセス変数を、${taskVariable} でタスク変数を参照します。このように、プロセス変数はタスクの作成時に、タスク変数は通知時間に解決されます。以下のリストには、通知を行う際に使用するタスク変数が複数含まれています。
  • taskId: タスクインスタンスの内部 ID
  • processInstanceId: タスクが所属するプロセスインスタンスの内部 ID
  • workItemId: このタスクを作成する作業アイテムの内部 ID
  • processSessionId: ランタイムエンジンのセッション内部 ID
  • owners: タスクの Potential Owner となるユーザー/グループの一覧
  • doc: 定期的なタスクの変数を含むマップ
以下はメッセージの通知例で、様々な変数がどのようにアクセスされるか例示しています。
<html><body><b>${owners[0].id} you have been assigned to a task (task-id ${taskId})</b><br>
		You can access it in your task 
		<a href="http://localhost:8080/jbpm-console/app.html#errai_ToolSet_Tasks;Group_Tasks.3">inbox</a><br/>
		Important technical information that can be of use when working on it<br/>
		- process instance id - ${processInstanceId}<br/>
		- work item id - ${workItemId}<br/><hr/>
		
		Here are some task variables available:
		<ul><li>ActorId = ${doc['ActorId']}</li><li>GroupId = ${doc['GroupId']}</li><li>Comment = ${doc['Comment']}</li></ul><hr/>
		Here are all potential owners for this task:
		<ul>
		$foreach{orgEntity : owners}
			<li>Potential owner = ${orgEntity.id}</li>
		$end{}
		</ul><i>Regards</i></body></html>
	
		
		
		
			
			
			
		
		
		
		
	

10.2.6. データマッピング

10.2.6.1. データマッピング

ヒューマンタスクは通常、実行の必要性のあるタスクのデータを、タスク実行担当のアクターに対して提示します。またヒューマンタスクは、アクターに対してタスク実行に関する結果データの一部を提出するように依頼します。一般的にタスクフォームを使用して、アクターへのデータの提示と結果の依頼を行います。

10.2.6.2. タスクパラメーター

タスクフォームに表示する必要のあるデータは、パラメーターマッピングを使用してそのタスクに渡します。パラメーターマッピングを使用して、プロセス変数の値をタスクパラメーターにコピーすることができます (「動的なヒューマンタスクプロパティ」で説明)。例えば、タスクフォーム、実際の依頼に表示する必要のある顧客名などが挙げられます。データをタスクにコピーするには、変数をタスクパラメーターにマッピングします。そうるすと、このパラメーターは、タスクフォームからアクセスできるようになります。

10.2.6.3. タスクの結果

プロセスに返す必要のあるデータは、結果マッピングを使用して、タスクからプロセス変数にマッピングしなおす必要があります。結果マッピングにより、タスクの結果の値をプロセス変数にコピーすることができます。これにはアクターが入力したデータなどが該当します。タスク結果の値は、残りのプロセスで使用できるように、タスクが完了してからコピーされます。

10.2.7. スイムレーン

ユーザータスクは、同じアクターに複数のヒューマンタスクを割り当てるスイムレーンを組み合わせて、使用することができます。スイムレーンに初めてタスクが作成されると、そのタスクに actorId が割り当てられ、スイムレーン内の全タスクにその actorId が割り当てられるようになります。このスイムレーンの後続タスクの actorId (指定されている場合) よりも優先されるため、スイムレーン内の最初のヒューマンタスクの actorId のみが考慮され、それ以外のタスクは最初にタスクに割り当てられた actorId が引き継がれるようになっています。
ヒューマンタスクをスイムレーンに追加するには、まずそのスイムレーンがプロセス内で定義されているようにしてください。定義されていない場合は、swimlane プロパティを編集してスイムレーンを定義します。次に、ユーザータスクノードの Swimlane パラメーターの値としてスイムレーンの名前を指定します。

10.2.8. データベースからのタスクの削除

ヒューマンタスクの情報は、org.jbpm.task.admin.TaskCleanUpProcessEventListener を使用してデータベースから削除します。このリスナーは関連のプロセス ID で完了した削除をアーカイブして削除する DefaultProcessEventListener です。
TaskCleanUpProcessEventListener は org.jbpm.task.admin.TasksAdmin インスタンスを使用します。このインスタンスは、org.jbpm.task.service.TaskService#createTaskAdmin() から取得できます。

例10.1 イベントリスナーのアタッチ

TasksAdmin admin = new TaskService(...).createTaskAdmin();
StatefulKnowledgeSession ksession = ...
ksession.addEventListener(new TaskCleanUpProcessEventListener(admin));

10.3. ヒューマンタスクサービス

10.3.1. ヒューマンタスクサービス

ヒューマンタスクは、他の外部サービスと同様に、ドメイン固有サービスとして実装されます。プロセスにドメイン固有サービスを含める方法については、「ドメイン固有サービスノード」 を参照してください。ヒューマンタスクがドメイン固有サービスであるため、プロセス自体には実行する必要のあるヒューマンタスクの概略かつ抽象的な説明が含まれており、作業アイテムハンドラーはこの抽象タスクと固有の実装をバインドする役目を果たしています。このプラグ可能な作業アイテムハンドラーのアプローチでは、以下の説明にあるように渡されたヒューマンタスクサービスにプラグインするか、独自の実装を登録することができます。
デフォルトのヒューマンタスクの実装は、WS-HumanTask 仕様をベースとしています。この実装は、タスクのライフサイクル (作成、請求、完了など) を管理して、全タスクのステータスやタスクの一覧などを保存します。また、国際化、カレンダー統合、各種割り当て、委譲、締め切りなどの機能にも対応しています。これは jbpm-human-task モジュールの一部として実装されます。WS-HumanTask (WS-HT) 仕様は、この URL (http://download.boulder.ibm.com/ibmdl/pub/software/dw/specs/ws-bpel4people/WS-HumanTask_v1.pdf) からダウンロードできます。

10.3.2. タスクのライフサイクル

ユーザータスクノードがプロセスインスタンスの実行中にトリガーされるたびに、ヒューマンタスクは作成され、ヒューマンタスクが完了するか、中断されるまで、プロセスは終了しません。
ヒューマンタスクのライフサイクルは以下のようになっています。
  1. タスクが作成され、「Created」の段階で開始されます。
  2. このタスクは自動的に「Ready」の段階に移行され、タスクを請求できるユーザーのタスク一覧に表示されます。
  3. ユーザーがタスクを請求します。ここでステータスは「Reserved」に設定されます。
  4. ユーザーがタスクを開始 (および実行) します。ここでステータスは「InProgress」に変更されます。
  5. ユーザーがタスクを完了して、タスクの結果データが特定されます。ここでステータスは「Completed」に変更されます。ユーザーがタスクを完了できない場合、応答に問題があると通知され (関連の問題データなど)、ステータスは「Failed」に変更されます。
ヒューマンタスクのライフサイクルには、以下のステップも含まれます。
  • 別のユーザーにタスクを割り当てるようにタスクを委譲、移行。
  • タスクを呼び出し。タスクを請求した後、ユーザーはタスクを呼び出し、そのタスクを請求できるユーザーすべてが請求できる状態にします。
  • タスクを一時的に停止、再開。
  • 進行中のタスクを停止。
  • タスクを省略 (タスクが skippable と指定されている場合)。この場合はタスクは実行されません。

10.3.3. ヒューマンタスクサービスの統合

別のヒューマンタスクサービスを統合するには、カスタムの作業アイテムハンドラーを登録する必要があります。カスタムの作業アイテムハンドラーは以下のように登録します。
StatefulKnowledgeSession ksession = ...;
ksession.getWorkItemManager().registerWorkItemHandler("Human Task", new CommandBasedHornetQWSHumanTaskHandler());
デフォルトでは、このハンドラーはローカルマシンのヒューマンタスクサービスにポート 5446 で接続します。ヒューマンタスクサービスやポートを変更するには、CommandBasedHornetQWSHumanTaskHandler で setConnection(ipAddress, port) を呼び出します。
ヒューマンタスクサービスとプロセスエンジン、またはタスククライアントとの間での対話は、クライアントとサーバー間でメッセージを送信して行います。HornetQ がクライアントとサーバー間の通信にデフォルトのトランスポートメカニズムとなっています。

10.3.4. ヒューマンタスクサービスとの対話

Business Central コンソールは、ユーザーがヒューマンタスクサービスと対話するためのグラフィカルインターフェースを提供します。詳細は 「Business Central コンソール」 を参照してください。ヒューマンタスクサービスは、様々なメソッドを公開して、Java API からタスクのライフサイクルを管理できるようします。
タスククライアント (class org.jbpm.task.service.TaskClient) は、ヒューマンタスクのライフサイクル管理に以下のメソッドを提供しています。
public void start( long taskId, String userId, TaskOperationResponseHandler responseHandler )
public void stop( long taskId, String userId, TaskOperationResponseHandler responseHandler )
public void release( long taskId, String userId, TaskOperationResponseHandler responseHandler )
public void suspend( long taskId, String userId, TaskOperationResponseHandler responseHandler )
public void resume( long taskId, String userId, TaskOperationResponseHandler responseHandler )
public void skip( long taskId, String userId, TaskOperationResponseHandler responseHandler )
public void delegate( long taskId, String userId, String targetUserId,
                      TaskOperationResponseHandler responseHandler )
public void complete( long taskId, String userId, ContentData outputData,
                      TaskOperationResponseHandler responseHandler )
...
上記のメソッドはすべて、以下の引数を取ります。
  • taskId: タスクの ID。通常、ユーザーインターフェースのユーザータスク一覧で現在選択されているタスクから抽出されます。
  • userId: アクションを実行するユーザーの ID。これは、アプリケーションにログインしているユーザーの ID となっています。
  • responseHandler: タスクサービスとの通信は非同期であるため、結果が出ると通知がいくように応答ハンドラーを使用する必要があります。
TaskClient でメッセージが呼び出されると、メッセージが作成されサーバーに送信されます。サーバーは適切なアクションを実装しているロジックを実行します。
以下のコードサンプルは、タスククライアントの作成方法やタスクの作成、開始、完了の際にタスクサービスと対話する方法を提示しています。
//Use UUID.randomUUID() to ensure the HornetQ Connector has a unique name
	TaskClient client = new TaskClient(new HornetQTaskClientConnector("HornetQConnector" + UUID.randomUUID(), new HornetQTaskClientHandler(SystemEventListenerFactory.getSystemEventListener())));
	client.connect("127.0.0.1", 5446);
	CommandBasedHornetQWSHumanTaskHandler handler = new CommandBasedHornetQWSHumanTaskHandler(ksession);
	handler.setClient(client);
	handler.connect();
	ksession.getWorkItemManager().registerWorkItemHandler("Human Task", handler);

// adding a task
BlockingAddTaskResponseHandler addTaskResponseHandler = new BlockingAddTaskResponseHandler();
Task task = ...;
client.addTask( task, null, addTaskResponseHandler );
long taskId = addTaskResponseHandler.getTaskId();
        
// getting tasks for user "bobba"
BlockingTaskSummaryResponseHandler taskSummaryResponseHandler =
    new BlockingTaskSummaryResponseHandler();
client.getTasksAssignedAsPotentialOwner("bobba", "en-UK", taskSummaryResponseHandler);
List<TaskSummary> tasks = taskSummaryResponseHandler.getResults();

// starting a task
BlockingTaskOperationResponseHandler responseHandler =
    new BlockingTaskOperationResponseHandler();
client.start( taskId, "bobba", responseHandler );
responseHandler.waitTillDone(1000); 

// completing a task
responseHandler = new BlockingTaskOperationResponseHandler();
client.complete( taskId, "bobba".getId(), null, responseHandler );
responseHandler.waitTillDone(1000);

10.3.5. ユーザーとグループの割り当て

タスクは、ユーザー 1 名または複数名に割り当てることができます。タスクがユーザー 1 名に割り当てられた場合、そのユーザーのタスク一覧に表示されます。タスクが複数のユーザーに割り当てられた場合は、その中のユーザーの内 1 名がこのタスクを請求し実行することができます。また、タスクはグループにも割り当てることができ、タスクを割り当てたグループの 1 つでメンバーになっているユーザーがこのタスクを請求できるようになっています。
ユーザーおよびグループは、タスクを割り当てられるようにまず登録する必要があります。登録は動的に行うことができます。
EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.task");
TaskService taskService = new TaskService(emf, SystemEventListenerFactory.getSystemEventListener());
TaskServiceSession taskSession = taskService.createSession();
// now register new users and groups
taskSession.addUser(new User("userA"));
taskSession.addGroup(new Group("groupA"));
ヒューマンタスクサービスは、ユーザーとグループの間の関係は保持しません。user group callback クラスは、作成して jbpm-human-task.war/WEB-INF/web.xml ファイルにリストアップする必要があります。デフォルトの実装 org.jbpm.task.service.DefaultUserGroupCallbackImpl は、全ユーザーを全グループに割り当てます。これはテスト目的で提供されています。
user group callback クラスを追加するには、jbpm-human-task.war/WEB-INF/web.xml を開き、以下の例にあるようにクラスを追加します。
<!-- use org.jbpm.task.service.DefaultUserGroupCallbackImpl to configure sample user group callback for demo purpose--><init-param><param-name>user.group.callback.class</param-name><param-value>org.jbpm.task.service.DefaultUserGroupCallbackImpl</param-value></init-param>

	
	

jbpm-human-task モジュールには、src/test/java source フォルダーの org.jbpm.task.RunTaskService クラスが含まれており、server/profile/deploy/jbpm-human-task.war/WEB-INF/classes/org/jbpm/task/servlet/ ディレクトリにある LoadUsers.mvel と LoadGroups.mvel 設定ファイルに定義されているようにユーザーとグループを自動的に追加します。

10.3.6. ヒューマンタスクサービスの開始

プロセスエンジンと通信する、独立したヒューマンタスクサービスを使用する場合、サービスを開始する必要があります。
org.jbpm.task.service.TaskService taskService = new org.jbpm.task.service.TaskService(
  emf, SystemEventListenerFactory.getSystemEventListener());

TaskServiceSession taskServiceSession = taskService.createSession();

//adding users to TaskServiceSession
taskServiceSession.addUser(new User("Administrator"));
taskServiceSession.addUser(new User("jsmith"));
	    	    
LocalTaskService localTaskService = new LocalTaskService( taskService );
humanTaskHandler = new SyncWSHumanTaskHandler( localTaskService, ksession );
humanTaskHandler.setLocal( true );
humanTaskHandler.connect();
ksession.getWorkItemManager().registerWorkItemHandler( "Human Task", humanTaskHandler );	

//using HT API ...
List<TaskSummary> tasks = localTaskService.getTasksAssignedAsPotentialOwner("jsmith", "en-US");
タスク管理のコンポーネントは、Java Persistence API (JPA) を使用して永続的にタスク情報をすべて格納します。永続性を設定するには、persistence.xml 設定ファイルを編集します。
以下のサンプルは、タスク管理のコンポーネントを hibernate と in-memory H2 データベースで使用する方法について示しています。ただし、実稼働環境では H2 データベースはサポートされていない点に注意してください。以下は例示のみを目的としており、 hibernate.hbm2ddl.auto プロパティの値として create を指定すると、サーバーを再起動するたびに jBPM スキーマが再作成されていまいます。インデックスは 2 回以上作成するべきではなく、この機能は無効する必要があります。スキーマを作成した後に hibernate.hbm2ddl.auto プロパティの部分にコメントタグを設定してください。
<!-- <property name="hibernate.hbm2ddl.auto" value="create" /> -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><persistence
    version="1.0"
    xsi:schemaLocation=
      "http://java.sun.com/xml/ns/persistence
       http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
       http://java.sun.com/xml/ns/persistence/orm
       http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
    xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/persistence"><persistence-unit name="org.jbpm.task"><provider>org.hibernate.ejb.HibernatePersistence</provider><class>org.jbpm.task.Attachment</class><class>org.jbpm.task.Content</class><class>org.jbpm.task.BooleanExpression</class><class>org.jbpm.task.Comment</class><class>org.jbpm.task.Deadline</class><class>org.jbpm.task.Comment</class><class>org.jbpm.task.Deadline</class><class>org.jbpm.task.Delegation</class><class>org.jbpm.task.Escalation</class><class>org.jbpm.task.Group</class><class>org.jbpm.task.I18NText</class><class>org.jbpm.task.Notification</class><class>org.jbpm.task.EmailNotification</class><class>org.jbpm.task.EmailNotificationHeader</class><class>org.jbpm.task.PeopleAssignments</class><class>org.jbpm.task.Reassignment</class><class>org.jbpm.task.Status</class><class>org.jbpm.task.Task</class><class>org.jbpm.task.TaskData</class><class>org.jbpm.task.SubTasksStrategy</class><class>org.jbpm.task.OnParentAbortAllSubTasksEndStrategy</class><class>org.jbpm.task.OnAllSubTasksEndParentEndStrategy</class><class>org.jbpm.task.User</class><properties><property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/><property name="hibernate.connection.driver_class" value="org.h2.Driver"/><property name="hibernate.connection.url" value="jdbc:h2:mem:mydb" /><property name="hibernate.connection.username" value="sa"/><property name="hibernate.connection.password" value="sasa"/><property name="hibernate.connection.autocommit" value="false" /><property name="hibernate.max_fetch_depth" value="3"/><property name="hibernate.hbm2ddl.auto" value="create" /><property name="hibernate.show_sql" value="true" /></properties></persistence-unit></persistence>


  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    
      
      
      
      
      
      
      
      
      
    

10.3.7. Web アプリケーションとしてのヒューマンタスクサービス開始

ヒューマンタスクサービスは、デプロイメントを簡素化するために Web アプリケーションとして開始することができます。アプリケーション設定の一部として、ユーザーはスタートアップ時に適用する設定を選択できます。HumanTaskServiceServlet の init パラメーターを設定して、jbpm-human-task-war/WEB-INF/ ディレクトリにある web.xml で設定します。
以下のリストで、サポートされているパラメーターと、その意味についてまとめています。
全般設定:
  • task.persistence.unit: EntityManagerFactory (デフォルト org.jbpm.task) を構築する際に使用する永続ユニットの名前
  • user.group.callback.class: ユーザーとグループを解決するために使用する UserGroupCallback インターフェースの実装 (デフォルト DefaultUserGroupCallbackImpl。テスト目的でのみ提供)
  • escalated.deadline.handler.class: エスカレーションと通知を処理する際に使用する EscalatedDeadlineHandler インターフェースの実装 (デフォルト DefaultEscalatedDeadlineHandler)
  • user.info.class: E-メールアドレスや希望言語などユーザー/グループの情報を解決すうrために使用する UserInfo インターフェースの実装
  • load.users: これはユーザー情報を持つタスクサーバー データベースをを最初に生成する際に使用するファイルの場所を指定します。利用可能なファイルの種類は MVEL と properties で、接尾語は .mvel or .properties とします。このファイルはクラスパス (接頭辞 classpath:) か有効な URL に設置する必要があります。注記: カスタムのユーザーファイルを使用する場合は、管理者ユーザーが設置されている必要があります。
  • load.groups: これはグループ情報を持つタスクサーバー データベースをを最初に生成する際に使用するファイルの場所を指定します。利用可能なファイルの種類は MVEL と properties で、接尾語は .mvel or .properties とします。このファイルはクラスパス (接頭辞 classpath:) か有効な URL に設置する必要があります。注記: カスタムのユーザーファイルを使用する場合は、管理者ユーザーが設置されている必要があります。
トランスポート設定:
  • active.config: どのトランスポートを Task Server に設定するか制御する主要パラメーター。デフォルトは、HornetQ となっていますが、Mina や JMS にも対応しています。
Apache Mina:
  • mina.host: Apache Mina サーバーをバインドするために使用するホスト/ip アドレス (localhost)
  • mina.port: Apache Mina サーバーをバインドするために使用するポート (default 9123)
HornetQ:
  • hornetq.port: HornetQ サーバーをバインドするために使用するポート (default 5446)
JMS:
  • JMSTaskServer.connectionFactory: ルックアップする際の QueueConnectionFactory の JNDI 名 (デフォルトなし)
  • JMSTaskServer.transacted : JMS セッションでトランザクションがあるかどうかを指定する boolean フラグ (デフォルトなし)
  • JMSTaskServer.acknowledgeMode: 応答確認モード (デフォルト DUPS_OK_ACKNOWLEDGE).
  • JMSTaskServer.queueName: JMS キューの名前 (デフォルトなし)
  • JMSTaskServer.responseQueueName: JMS 応答キューの名前 (デフォルトなし)

10.4. ヒューマンタスクの永続性

10.4.1. ヒューマンタスクの永続性

以下のモデルは、ヒューマンタスクサービスにより使用される永続エンティティを示す実体関連図 (ERD: Entity Relationship Diagram) です。
ヒューマンタスクサービスのデータモデル

図10.1 ヒューマンタスクサービスのデータモデル

上記のデータモデルは、2 つのエンティティグループに分類されています。
  • task エンティティ: タスクの主要情報を表します (上記の ERD の右側を参照)。
  • deadlineescalationnotification エンティティ: タスクの締め切りとエスカレーションおよびその締め切りに関連付けられた通知 (上記の ERD の左側を参照)。
データモデルの重要なエンティティは他に i18ntextorganizationalentity の 2 つがあります。
  • i18ntext エンティティは、名前やユーザーが入力した説明などのテキスト (言語関連の場合もあり) を格納するために使用します。
  • organizationalentity エンティティはユーザーを表します。
「タスク関連のエンティティ」 の表の外部キーの欄は、データベース表の列に外部キー制約があるかどうかを示しており、null の欄は、データベース表の列に null を使用できるかどうかを示しています。
エンティティが null 値不可と説明されており、関連のエントリがない場合は、その列には -1 または 0 の値が入ります。

第11章 テストおよびデバッグ

11.1. 単体テスト

11.1.1. 単体テスト

ビジネスプロセスは、実装の詳細を組み込まず、ハイレベルで設計する必要があります。しかし、他の開発からの成果物と同様、それぞれライフサイクルがありビジネスプロセスは動的に更新されるため、ビジネスプロセスのテストを行うことは重要です。
特定のユースケースで予想どおりにプロセスが動作するように、特定の入力をもとに出力をテストするなど、単体テストを実施します。単体テストの簡素化のため、helper クラス JbpmJUnitTestCase (jbpm-test モジュール) が同梱されています。JbpmJUnitTestCase には以下が含まれています。
  • 一定のプロセスで新規ナレッジベースとセッションを作成するための Helper メソッド
  • 確認するための Assert ステートメント
    • プロセスインスタンスのステータス (active、completed、aborted)
    • どのノードインスタンスが現在アクティブであるか
    • どのノードがトリガーされたか (辿ってきたパスの確認)
    • 変数の値
以下の図には、開始イベント、スクリプトタスク、終了イベントが含まれています。junit テストの例では、新しいセッションの作成やプロセスの開始が行われるだけでなくプロセスインスタンスが正常に完了したことをもとに検証が行われます。また、これらの 3 つのノードが実行されたかどうかもチェックします。
hello world プロセスの例

図11.1 Hello World プロセスの例

例11.1 junit テストの例

public class MyProcessTest extends JbpmJUnitTestCase {

   public void testProcess() {
       // create your session and load the given process(es)
       StatefulKnowledgeSession ksession = createKnowledgeSession("sample.bpmn");
       // start the process
       ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");
       // check whether the process instance has completed successfully
       assertProcessInstanceCompleted(processInstance.getId(), ksession);
       // check whether the given nodes were executed during the process execution
       assertNodeTriggered(processInstance.getId(), "StartProcess", "Hello", "EndProcess");
    }
}

11.1.2. セッション作成のための Helper メソッド

エンジンとの対話に使用するナレッジベースやセッションの作成を簡素化するために、複数のメソッドが提供されています。
createKnowledgeBase(String... process):
任意のファイル名 (クラスパスからロード) にある全プロセスを含む新しいナレッジベースを返します。
createKnowledgeBase(Map<String, ResourceType> resources):
任意のファイル名 (クラスパスからロード) からの全リソースを含む新しいナレッジベースを返します。
createKnowledgeBaseGuvnor(String... packages):
任意のパッケージの Guvnor (プロセスレポジトリ) からロードされた全プロセスを含む新しいナレッジベースを返します。
createKnowledgeSession(KnowledgeBase kbase):
任意のナレッジベースから新しいステートフルナレッジセッションを作成します。
restoreSession(StatefulKnowledgeSession ksession, boolean noCache):
データベースからこのセッションを完全にリストアします。致命的な問題が発生した場合や試験的なリカバリをシミュレーションするためにセッションを再作成する際に利用可能です。noCache が true の場合、既存の永続キャッシュを使用せずにデータをリストアします。

11.1.3. アサーション

以下のアサーションは、プロセスインスタンスの現在のステータスを円滑にテストするために提供されています。
assertProcessInstanceActive(long processInstanceId, StatefulKnowledgeSession ksession):
指定の ID のプロセスインスタンスがまだアクティブな状態にあるかどうかを確認します。
assertProcessInstanceCompleted(long processInstanceId, StatefulKnowledgeSession ksession):
指定の ID のプロセスインスタンスが正常に完了したかどうかを確認します。
assertProcessInstanceAborted(long processInstanceId, StatefulKnowledgeSession ksession):
指定の ID のプロセスインスタンスが中断されたかどうかを確認します。
assertNodeActive(long processInstanceId, StatefulKnowledgeSession ksession, String... name):
指定の ID のプロセスインスタンスに指定のノード名を持つアクティブなノードが最低 1 つ含まれているかどうかを確認します。
assertNodeTriggered(long processInstanceId, String... nodeNames):
指定のノード名を持つプロセスインスタンスを実行中にノードインスタンスが (すでにアクティブな状態でなくなっていても) トリガーされたかどうか、1 つずつ指定のノード名を確認します。
getVariableValue(String name, long processInstanceId, StatefulKnowledgeSession ksession):
指定のプロセスインスタンスから指定の名前を持つ変数の値をリトリーブします。その後プロセス変数の値をチェックするために利用することができます。

11.1.4. 外部サービスとの統合のテスト

ドメイン固有プロセスを使用すると、テスト用ハンドラーを使用して固有のサービスが正しく依頼されたかどうかを確認することができます。
TestWorkItemHandler はデフォルトで提供されており、指定の型の作業アイテムをすべて収集するために登録することが可能です (各作業アイテムは、q 固有の e-メールの送信、q 固有サービスの呼び出しなど作業単位 1 つを表しており、タスクに関するデータがすべて含まれています)。テストハンドラーは単体テスト時に照会可能で、固有の作業がプロセス実行時に実際に依頼されているかどうか、そして作業に関連付けられているデータが正しいかどうかを確認します。
以下の例は、E-メール送信プロセスがどのようにテストされるかが記述されています。このテスト事例では、E-メールが送信できなかった場合に例外が送出されるかどうかをテストします (E-メールの送信が完了できなかった旨をエンジンに通知することでシミュレーション)。また、このテスト事例では E-メールが依頼されデータがその依頼と関連付けられた際に登録するだけのテストハンドラーを使用します。エンジンに E-メールの送信ができなかった旨を (abortWorkItem(..) を使用して) 通知すると、単体テストでは、プロセスが送信不可のログを残してエラーを生成してこの事例を正しく処理し、プロセスインスタンスを中断するかどうかを検証します。
E-メールプロセスをどのようにチェックするか示した図
public void testProcess2() {
    // create your session and load the given process(es)
    StatefulKnowledgeSession ksession = createKnowledgeSession("sample2.bpmn");
    // register a test handler for "Email"
    TestWorkItemHandler testHandler = new TestWorkItemHandler();
    ksession.getWorkItemManager().registerWorkItemHandler("Email", testHandler);
    // start the process
    ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello2");
    assertProcessInstanceActive(processInstance.getId(), ksession);
    assertNodeTriggered(processInstance.getId(), "StartProcess", "Email");
    // check whether the email has been requested
    WorkItem workItem = testHandler.getWorkItem();
    assertNotNull(workItem);
    assertEquals("Email", workItem.getName());
    assertEquals("me@mail.com", workItem.getParameter("From"));
    assertEquals("you@mail.com", workItem.getParameter("To"));
    // notify the engine the email has been sent
    ksession.getWorkItemManager().abortWorkItem(workItem.getId());
    assertProcessInstanceAborted(processInstance.getId(), ksession);
    assertNodeTriggered(processInstance.getId(), "Gateway", "Failed", "Error");
}

11.1.5. 永続性の設定

デフォルトでは、永続性はオフになっており、プロセスはメモリ内に存在します。
永続性をオンにするには、以下のようにテスト事例の作成時に Boolean をスーパーコンストラクターに渡し、setPersistence を true に設定します。
public class MyProcessTest extends JbpmJUnitTestCase {

    public MyProcessTest() {
        // configure this test to use persistence
        super(true);
        setPersistence(true);
    }
    ...

11.2. デバッグ

11.2.1. デバッグ

JBoss Developer Studio は、プロセスのデバッグや実行中のプロセスの状態を検証するために使用することができます。

11.2.2. プロセスインスタンスのビュー

プロセスインスタンスのビューでは、現在実行中のプロセスインスタンスを表示します。
プロセスインスタンスビューワーを開くには、WindowShow ViewOther を選び、DroolsProcess Instances を選択します。
以下のプロセスインスタンスビューの例では、現在実行中のプロセス (インスタンス) が 1 つと、実行中のノードインスタンス (ビジネスルールタスク) が 1 つあります。プロセスインスタンスをダブルクリックすると、プロセスインスタンスビューワーがプロセスインスタンスの進捗をグラフィックで表示します。

例11.2 プロセスインスタスビューのサンプル

プロセスインスタスビューのサンプル

11.2.3. ヒューマンタスクビュー

ヒューマンタスクビューは、実行中のヒューマンタスクサービスに接続して、特定のユーザーに該当するタスクを依頼することができます (ユーザーが Potential Owner のタスク、またはユーザーが請求したタスク/実行中のタスク)。その後、これらのタスクのライフサイクルを実施できます (タスクの請求、解放、実行タスクの開始、停止、タスクの完了など)。
ヒューマンタスクビューワーを開くには、WindowShow ViewOther を選択して、jBPM TaskHuman Task View を選びます。
接続先のタスクサービスを設定するには、WindowPreferencesDrools Tasks を選択して、IP アドレス、ポート、言語を入力します。

例11.3 ヒューマンタスクビューのサンプル

ヒューマンタスクビューのサンプル

11.2.4. 監査ビュー

監査ビューでは、監査ログ (セッションで記録されたイベントすべてのログ) を表示します。ロガーを作成するには、KnowledgeRuntimeLoggerFactory を使用して新規ロガーを作成しセッションにアタッチします。スレッドファイルロガーを使用すると、定期的な間隔でファイルシステムに監査ログを保存し、監査ビュワーで最新のステータスを表示することができるようになります。以下のスレッドファイルロガーでは、監査ログファイルと指定の間隔 (ミリ秒) について例示しています。

例11.4 スレッドファイルロガー

KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory
   .newThreadedFileLogger(ksession, "logdir/mylogfile", 1000);
// do something with the session here
logger.close();
監査ビューを開くには、WindowShow ViewAudit を選択します。
監査ビューで監査ツリーを開くには、監査ビューから選択したログファイルを開くか、監査ビューにファイルを単にドラッグしてください。ツリーベースのビューが監査ログを基に生成されます。親イベント (の直接の結果) により子イベント発生した場合、イベントは別のイベントのサブノードとして表示されます。
この図は、監査ログに関するツリービューです。

第12章 ビジネスアクティビティの監視

12.1. ビジネスアクティビティの監視

予期せぬイベントや動作をすぐに検出して対処できるように、プロセスの関しは必要です。ビジネスアクティビティの監視とは、イベントの解析をもとに、直接介入または自動介入のいずれかでリアルタイムにプロセスを監視する仕組みです。

重要

Red Hat は、JBoss BRMS 5.3 では監視ソリューションを提供しておりません。

第13章 統合

13.1. 統合

ビジネスプロセス管理エンジンは他のテクノロジと統合することができます。

13.2. OSGi

OSGi は宣言型サービスの動的モジュールシステムです。OSGi の各 jar はバンドルと呼ばれ、それぞれにクラスローダーが含まれています。各バンドルはエクスポートする (公開する) パッケージやインポートするパッケージ (外部の依存関係) を指定します。OSGi はこの情報を使用して、他のバンドルのクラスローダーをつなげます。主要な違いは、依存するバンドルを指定しない点 (または単一のモノリシッククラスパスを持つ点) です。代わりに、パッケージのインポートやバージョンを指定して、OSGi は利用可能なバンドルから依存関係などの情報を取得します。
コアの jBPM jar (およびコアの依存関係) はすべて OSGi に対応できるようになっています。(META-INF ディレクトリに) 依存関係を記述する MANIFEST.MF ファイルが含まれており、これらのマニフェストファイルは自動的にビルドにより生成され、jar を直接 OSGi 環境にプラグインすることができます。
以下の jBPM jar は OGSI に対応しています。
  • jbpm-flow
  • jbpm-flow-builder
  • jbpm-bpmn2
以下の例は、サービスレジストリを使用して OSGi 環境から必要なサービスをルックアップし、セッションを作成して、プロセスの開始やイベントのシグナル送信に使用できるようにしています。

例13.1 OSGi の例

ServiceReference serviceRef = bundleContext.getServiceReference( ServiceRegistry.class.getName() );
ServiceRegistry registry = (ServiceRegistry) bundleContext.getService( serviceRef );

KnowledgeBuilderFactoryService knowledgeBuilderFactoryService = registry.get( KnowledgeBuilderFactoryService.class );
KnowledgeBaseFactoryService knowledgeBaseFactoryService = registry.get( KnowledgeBaseFactoryService.class );
ResourceFactoryService resourceFactoryService = registry.get( ResourceFactoryService.class );

KnowledgeBuilderConfiguration kbConf = knowledgeBuilderFactoryService.newKnowledgeBuilderConfiguration( null, getClass().getClassLoader() );
KnowledgeBuilder kbuilder = knowledgeBuilderFactoryService.newKnowledgeBuilder( kbConf );
kbuilder.add( resourceFactoryService.newClassPathResource( "MyProcess.bpmn", Dummy.class ), ResourceType.BPMN2 );

KnowledgeBaseConfiguration kbaseConf = knowledgeBaseFactoryService.newKnowledgeBaseConfiguration( null, getClass().getClassLoader() );
KnowledgeBase kbase = knowledgeBaseFactoryService.newKnowledgeBase( kbaseConf );
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

13.3. Spring

Spring XML 設定ファイルを使用すると、ナレッジベースやセッションを Spring 環境で簡単に定義、設定できるようになります。これにより、セッションへのアクセスや Spring アプリケーション内からのプロセスの呼び出しが可能になります。
以下の Spring の設定ファイルの例では、クラスパスからロードされるプロセス定義を 1 つ持つナレッジベースをもとに、新しいセッションを設定しています。

例13.2 Spring 設定ファイルの例

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jbpm="http://drools.org/schema/drools-spring"       
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://drools.org/schema/drools-spring org/drools/container/spring/drools-spring-1.2.0.xsd><jbpm:kbase id="kbase"><jbpm:resources><jbpm:resource type="BPMN2" source="classpath:HelloWorld.bpmn2"/></jbpm:resources></jbpm:kbase><jbpm:ksession id="ksession" type="stateful" kbase="kbase" /></beans>

   
  
    
      
    
  

  


以下のコードでは、上記の Spring 設定をロードして、セッションを取得し、プロセスを開始します。
ClassPathXmlApplicationContext context = 
    new ClassPathXmlApplicationContext("spring-conf.xml");
StatefulKnowledgeSession ksession = (StatefulKnowledgeSession) context.getBean("ksession");
ksession.startProcess("com.sample.HelloWorld");
ドメインオブジェクトの 1 つにセッションを注入できる点 (例: 設定ファイルに以下のコード断片を追加) にも留意してください。
<bean id="myObject" class="org.jbpm.sample.MyObject"><property name="session" ref="ksession" /></bean>
  

結果、セッションはドメインオブジェクトに注入され、セッションに直接アクセスできるようになります。例:
public class MyObject {
  private StatefulKnowledgeSession ksession;
  public void setSession(StatefulKnowledgeSession ksession) {
    this.ksession = ksession;
  }
  public void doSomething() {
    ksession.startProcess("com.sample.HelloWorld");
  }
}

13.4. Maven

JBoss Enterprise BRMS 5.3.1 の Maven 統合は、Red Hat ではサポートしいません。以下は例示のみを目的で提供しています。

手順13.1 Drools と jBPM jar ファイルのローカル Maven レポジトリへのインポート

  1. https://access.redhat.com の Red Hat カスタマーサポートポータルからデプロイ可能パッケージ (Zip ファイル) をダウンロードします。DownloadsDownload your softwareBRMS Platform を選択して、バージョンと JBoss BRMS 5.3.1 を選びます。
  2. Zip アーカイブを展開します。
  3. jboss-brms-engine.zip および jboss-jbpm-engine.zip アーカイブを展開します。
  4. 以下の maven コマンドを実行して、Drools と jBPM jar ファイルをローカルの maven レポジトリにインポートします。
    mvn install:install-file -Dfile=knowledge-api-5.3.1.BRMS.jar -DgroupId=org.drools -DartifactId=knowledge-api -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=drools-core-5.3.1.BRMS.jar -DgroupId=org.drools -DartifactId=drools-core -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=drools-compiler-5.3.1.BRMS.jar -DgroupId=org.drools -DartifactId=drools-compiler -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=drools-decisiontables-5.3.1.BRMS.jar -DgroupId=org.drools -DartifactId=drools-decisiontables -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=drools-templates-5.3.1.BRMS.jar -DgroupId=org.drools -DartifactId=drools-templates -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=drools-persistence-jpa-5.3.1.BRMS.jar -DgroupId=org.drools -DartifactId=drools-persistence-jpa -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-flow-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-flow -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-flow-builder-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-flow-builder -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-bam-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-bam -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-bpmn2-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-bpmn2 -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-human-task-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-human-task -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-persistence-jpa-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-persistence-jpa -Dversion=5.3.1.BRMS -Dpackaging=jar
    mvn install:install-file -Dfile=jbpm-workitems-5.3.1.BRMS.jar -DgroupId=org.jbpm -DartifactId=jbpm-workitems -Dversion=5.3.1.BRMS -Dpackaging=jar
    

    注記

    上記の jar インポートファイルの一覧は完全ではありません。droolsknowledgejbpm すべての jar ファイルをインポートするようにしてください。
Maven pom.xml ファイルは、Maven でプロジェクトを構築した際に自動的に取得されるプロジェクトの依存関係を定義します。以下の pom.xml ファイルは、様々なユースケースに対して依存関係を宣言する方法の例です。
<?xml version="1.0" encoding="utf-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.jbpm</groupId><artifactId>jbpm-maven-example</artifactId><name>jBPM Maven Project</name><version>1.0-SNAPSHOT</version><brms-version>5.3.1.BRMS<brms-version>
  ...
  <dependencies><!-- core dependencies --><dependency><groupId>org.drools</groupId><artifactId>knowledge-api</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.mvel</groupId><artifactId>mvel2</artifactId><version>2.1.Beta6</version></dependency><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.3.1</version></dependency><!-- required to compile DRL --><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.eclipse.jdt.core.compiler</groupId><artifactId>ecj</artifactId><version>3.5.1</version></dependency><dependency><groupId>org.antlr</groupId><artifactId>antlr-runtime</artifactId><version>3.3</version><exclusions><exclusion><groupId>org.antlr</groupId><artifactId>stringtemplate</artifactId></exclusion></exclusions></dependency><!-- required to compile decision tables --><dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-templates</artifactId><version>${brms-version}</version></dependency><dependency><groupId>net.sourceforge.jexcelapi</groupId><artifactId>jxl</artifactId><version>2.6.10</version></dependency><!-- required for jBPM5 processes --><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-flow</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-flow-builder</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-bam</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-bpmn2</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-human-task</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-persistence-jpa</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.jbpm</groupId><artifactId>jbpm-workitems</artifactId><version>${brms-version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-persistence-jpa</artifactId><version>${brms-version}</version></dependency><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>2.4.1</version></dependency></dependencies></project>
   

   
   
   
   
   
   
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    

    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
      
        
          
          
        
      
    

    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    

    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    
    
      
      
      
    

これを Eclipse のプロジェクトのベースとして使用するには、M2Eclipse または "mvn eclipse:eclipse" を使用して eclipse の .project および .classpath ファイルをこの pom をベースに生成します。

付録A 改訂履歴

改訂履歴
改訂 5.3.1-4.4002013-10-31Rüdiger Landmann
Rebuild with publican 4.0.0
改訂 5.3.1-4Mon Aug 26 2013 Red Hat Content Services
Built from Content Specification: 12751, Revision: 493718 by lcarlon

法律上の通知

Copyright © 2013 Red Hat, Inc.
This document is licensed by Red Hat under the Creative Commons Attribution-ShareAlike 3.0 Unported License. If you distribute this document, or a modified version of it, you must provide attribution to Red Hat, Inc. and provide a link to the original. If the document is modified, all Red Hat trademarks must be removed.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat Software Collections is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.