Activitiの日本語情報をまとめています。この広告は、90日以上更新していないブログに表示しています。Taskのビジネスロジックで発生したエラー(例外)のハンドリング方法についてご紹介します。エラーハンドリングは、大きく2パターンに分かれています。1つ目は、発生したエラーをビジネスエラー(業務上のエラー)として扱い、業務プロセス上でその対応を行う方法です。2つ目は、単に一時的なシステムエラーとして扱い、リトライして対応する方法です。前者は注文された商品の在庫切れなど業務ルールと合致しないケースが発生し、それに対応するをフローを記述する場合に利用します。後者は、データベースとの接続エラーなど技術的な原因に起因したエラーが発生した際に利用されます。[コラム]システムエラーとビジネスエラーActivitiでは、システムエラーとビジネスエラーを明確に区別し、ビジネスエラーを業務プロセス上で表現する方針にしています。これに関して、Activitiのフォーラムでは、以下のような見解が述べられています。yourself.我々はエラー境界イベントを実装する際に内部で議論し、エラーイベントはプロセスに関連するエラーを表すものであるという結論に至った。Javaの例外は開発者によって実装されるものなので、開発者とアナリストの間で共通となるモデルからは隠蔽されなければならない。BPMN2.0の仕様自体はもっとも簡素なもので、そもそもシステムエラーとビジネスエラーを区別していません。BPM)ではシステムエラーに関しても業務フロー上で明示的に表現させる方針の製品も存在します。ビジネスエラー(業務エラー)のハンドリングビジネスロジックで発生したエラーを業務プロセス上で扱うには、JavaDelegateクラスからBpmnErrorをスローします。BpmnErrorをスローすることでエラーイベントが発生し、業務プロセス上のエラー境界イベントもしくはイベントサブプロセスでエラーイベントに対する制御フローを記述することが可能です。https://www.activiti.org/userguide/#serviceTaskExceptionHandlingエラーイベントの発生(BpmnErrorのスロー)エラーイベントを発生させるために、ビジネスロジック(JavaDelegateクラス)の内部からorg.activiti.engine.delegate.BpmnErrorクラスをスローします。https://www.activiti.org/javadocs//org/activiti/engine/delegate/BpmnError.htmlエラーのパターンが複数あり、それぞれを業務プロセス上で区別したい場合は、BpmnErrorクラスのコンストラクタにてエラーコードを指定します。指定したエラーコードは、エラーイベントのエラーコードとなります。エラーのパターンに応じたエラーコードを指定します。エラーのパターンに応じたエラーコードを指定します。発生したエラーイベントをキャッチし、制御するフローを業務プロセス上に記述します。ビジネスロジックを実行するサービスタスクに対して、エラー境界イベントもしくはエラー開始イベントから始まるイベントサブプロセスを配置し、サービスタスクから発生したエラーイベントに対する制御を記述します。code属性に指定します。サンプルフローユーザの入力ごとに2つのエラーハンドリングのパターンを実装したプロセスのサンプルを以下のページで公開しています。https://github.com/daisuke-yoshimoto/sample_java_error_handling上記のリポジトリのサンプルコードはシンプルさを重視しています。実際の開発・運用において必ずしも適切な実装ではありません。参考にされる場合は、十分ご注意ください。システムエラーのハンドリングビジネスロジック(JavaDelegateクラス)からExceptionクラスのサブクラスをスローした場合は、システムエラーが発生したとしてActivitiに判断され、リトライされます。リトライのパターンは、サービスタスクが同期(Asynchronous属性が無効)か非同期(Asynchronous属性が有効)かの設定によって異なります。サービスタスクが同期(Asynchronous属性が無効)で実行される場合ビジネスロジック(JavaDelegateクラス)から例外がスローされ、システムエラーが検知されると、一つ前のタスクまで戻ります(トランザクション全体がロールバックされる)。非同期の設定の場合、サービスタスクはジョブとして非同期スレッドで実行されます。この状態では、一つ前のタスクまでのトランザクションはすでに確定しているため、サービスタスクのジョブ内でシステムエラーが発生した場合でも一つ前のタスクまで戻ることはありません。ジョブが非同期スレッドにて、3度リトライされます。Explorerのジョブ一覧から手動で再実行できます。Explorer以外の場合は、APIから再実行する必要があります。Taskをご紹介します。Task」をご参照ください。http://www.activiti.org/userguide/#bpmnJavaServiceTaskXMLステップビジネスロジックの実装JavaDelegateインターフェースを実装したクラスを作成し、ビジネスロジックを作成します。Taskをフロー上に配置します。Project上で開発します。Projectを作成します。Projectに対してビルドパスを設定します。ProjectはMavenプロジェクトの形式になっていますが、eclipseのMavenプロジェクトの形式としては不完全でMaven経由のビルドパスが通らないため、直接jarファイルをビルドパスに追加することでeclipse上のクラスパスを解決します。Project上で右クリックし、プロパティ画面を表示します。JARS」を押下し、「activiti-engine-5.21.0.jar」を選択します。通常のMavenプロジェクトのような感じで、Javaクラスを追加します。クラスの追加時に、org.activiti.engine.delegate.JavaDelegateインターフェースを選択します。クラス内に任意の業務処理を記述します。任意の業務処理を記述します。}}引数として渡ってくるorg.activiti.engine.delegate.DelegateExecutionからは様々なプロセスの情報が取得することが可能です。http://activiti.org/javadocs/org/activiti/engine/delegate/DelegateExecution.htmlもちろん、変数操作を行うことも可能です。"aaa");JavaDelegateのインスタンスはプロセス定義ごとにキャッシュされるため、同一のプロセス定義から生成されたプロセスインスタンス間で共有されます。スレッドセーフな実装になるようにしてください。ビルド(パッケージング)とデプロイ作成したクラスを含むjarファイルをビルドします。ProjectはMavenプロジェクトの形式になっているので、Mavenのコマンドを実行するだけでjarファイルを作成可能です。ビルドしたjarファイルは、Activitiを動作させるWebアプリケーションに同梱します。Projectから生成したデプロイメントにクラスを同梱してデプロイするような仕組みも作成可能ですが、今回は紹介しません。http://activiti.org/javadocs/org/activiti/engine/ProcessEngineConfiguration.html#setClassLoader-java.lang.ClassLoader-ビジネスロジックを呼び出すフローの作成ここでは、「ビジネスロジックの実装」で作成したクラスを呼び出すだけのフローの作成方法をご紹介します。Diagramを作成し、フローのデザイナー画面を表示します。以下のアイコンを配置します。Event」カテゴリから「StartEvent」を配置します。Task」を配置します。Event」カテゴリから「EndEvent」を配置します。以下のように線を引きます。Task」へ線を引きます。Task」から「EndEvent」へ線を引きます。デザイナー上のアイコン以外の箇所をクリックします。users」に任意のユーザを設定します。taskを設定します。Task」のアイコンをクリックします。name属性に「ビジネスロジックの実装」で作成したクラス名を設定します。「General」タブのAsynchronous属性にて同期・非同期の設定を行います。Taskで設定したJavaクラスの処理はフロー上で手前に配置されているアクティビティと同一のスレッドから呼び出されます。Taskの処理の完了を待ちます。Taskで時間がかかる処理を行う場合には、Asynchronous属性をオンにして、処理が非同期スレッドにて実行されるようにしてください。Explorerにデプロイします。サンプルフローユーザタスクで入力した文字列が数値形式かどうかチェックして、数字でない場合はエラーを返すだけのサンプルを以下のページで公開しています。https://github.com/daisuke-yoshimoto/sample_java_service上記のリポジトリのサンプルコードはシンプルさを重視しています。実際の開発・運用において必ずしも適切な実装ではありません。参考にされる場合は、十分ご注意ください。Taskに対して1インスタンスのみ生成され、全てのプロセスインスタンスの間で共有されます。そのため、スレッドセーフに実装する必要があります。EL式】リスナーのEL式でプロセスの変数にシステムパラメータを書き込む(例)プロセスインスタンスIDを変数に格納する。開始イベントのリスナーに以下を追加する。プロセスの開始時に変数にプロセスインスタンスIDが格納される。Gatewayの設定でデフォルトフローが設定できるが、こちらで選択したフローは他のフローが選出されない場合有効である。デフォルトフローの条件は無視される。前回の入門記事では条件分岐のルートを紹介しましたが、今回は並行ルートを扱います。並行ルートとは、同時に異なるユーザタスクが割り当てられるルートのことです。ステップ並行ルートを実現するには、「ParallelGateway」のアイコンを利用します。「Gateway」カテゴリにある「ParallelGateway」を利用することで、並行なルートを引くことが可能です。http://www.activiti.org/userguide/#bpmnParallelGateway「ParallelGateway」から各「UserTask」へのシーケンスを引くことで、各「UserTask」ごとに並列にプロセスが動作します。各「UserTask」から「ParallelGateway」へシーケンスを引くことで、並行に実行されていたプロセスが結合します。各プロセスが完了するまで待ち合わせを行います。フローの作成では、実際に並行ルートを実現するフローを作成していきます。Diagramを作成し、フローのデザイナー画面を表示します。以下のアイコンを配置します。Event」カテゴリから「StartEvent」を配置します。「Gateway」カテゴリから「ExclusiveGateway」を配置します。「Task」カテゴリから「UserTask」を2つ配置します。「Gateway」カテゴリから「ExclusiveGateway」を配置します。Event」カテゴリから「EndEvent」を配置します。以下のように線を引きます。「StartEvent」から「ParallelGateway」へ線を引きます。「ParallelGateway」から2つの「UserTask」へそれぞれ線を引きます。2つの「UserTask」からそれぞれ「ParallelGateway」へ線を引きます。「ParallelGateway」から「EndEvent」へ線を引きます。デザイナー上のアイコン以外の箇所をクリックします。users」に「fozzie」を設定します。処理対象者を設定します。デザイナー上のユーザタスクの1つ目をクリックします。config」-「Assignee」に「kermit」を設定します。デザイナー上のユーザタスクの2つ目をクリックします。config」-「Assignee」に「gonzo」を設定します。Explorerにデプロイします。Explorerへログインします。「プロセス」からデプロイしたフローを選択します。「プロセスの開始」を押下し、プロセスを開始します。Explorerへログインします。「ケース」-「受信トレイ」にタスクがあります。「タスクの完了」を押下し、タスクを完了させます。Explorerへログインします。「ケース」-「受信トレイ」にタスクがあります。「タスクの完了」を押下し、タスクを完了させます。Explorerへログインします。「プロセス」-「マイ・インスタンス」から開始したフローが完了していることを確認します。注意ParallelGatewayに接続されるシーケンスの条件は、評価されません。条件の設定は、無視されます。[追記]この記事では、並列に動作しているプロセスをParallelGatewayで再度結合し待ち合わせを行っていますが、結合しない場合は各プロセスが終了まで並列に動作します。概要Activitiのプロセスでは、変数を利用してプロセスに関する入力データを扱う。ACT_RU_VARIABLE)にて管理される。beanなどが格納された場合は、バイナリデータとしてACT_GE_BYTEARRAYテーブルに格納される。変数には、スコープが存在する。Variablesプロセス全体で有効となる変数。ACT_RU_VARIABLEのカラムproc_inst_idとカラムexecution_idが一致するもの。ExecutionアクティブなExecution内でのみ有効な変数。説明が難しいが、Activitiでは、プロセスインスタンス上で現在アクティブな箇所をExecutionと定義している。以下のような並行ルートの場合は、並行ルートの処理中に3つのアクティブなExecutionが存在する。1つ目はプロセスインスタンス全体のExecution、2,3つ目はそれぞれの並行ルートのExecutionである。Executionスコープの変数とは、プロセスインスタンスのExecutionではない、個々のExecution内で有効となる変数である。ACT_RU_VARIABLEのカラムproc_inst_idとカラムexecution_idが一致しないもの。Variablesユーザタスク内でのみ有効な変数。ACT_RU_VARIABLEのカラムtask_id_が空でないもの。ACT_HI_VARINSTに格納される。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。