Alfresco Process Services入門
alfresco
Alfresco社員
2017年3月31日2:23 PM
はじめに
ご存じのように、AlfrescoではAlfresco Content ServicesとAlfresco Process Services(Activiti搭載)の2つの主力製品を取り扱っています。どちらの製品にも、無料版のCommunityバージョンと有料版のEnterpriseバージョンがあります。Enterpriseバージョンは、通常のサポートパッケージに加え、保証、追加の拡張機能、管理、 モデリングなどを装備し、ほとんどの本番環境に求められる必要な要素を網羅しています。
Activitiとは
Activitiは、Javaで実装されたオープンソースのBPMNプロセスエンジンで、設計、実装、デプロイ、ワークフローの実行に使用できます。これらのワークフローは、通常、組織におけるビジネスプロセスの管理と自動化に使用されます。
Activitiは、2010年にTom BaeyensとJoram Barrezによって作成されました。2人は以前所属していたJBossでjBPMワークフローエンジンを開発した開発者でもあります。jBPMはApacheライセンスを使っておらず、BPMN 2.0という新しいワークフロー定義の規格をサポートしていないという問題がありました。当時、AlfrescoのECM製品は、jBPMエンジンを組み込むことで、かなり前からワークフローをサポートしていました。AlfrescoのオープンソースワークフローエンジンであるActivitiを構築するためにAlfrescoがTomとJoramの雇用を決めたことは当然のことでした。
成功しているすべてのオープンソースプロジェクトと同様、より大規模な組織で採用されることにより、サポート、拡張性に関する主な機能、管理、レポート作成、高度な設計ツールなどが求められるようになりました。これが、2014年にAlfresco Process Servicesが誕生した経緯です。
Alfresco Process Servicesのコアワークフローエンジンは、BPMN 2.0ワークフロー定義を実行するApache認定のオープンソース製品です。以下は、Alfresco Process Services製品で利用できる追加機能の一例です(機能はこれに限定されず、新機能も高い頻度でリリースされます)。
- ユーザータスク管理 - グループタスクのリスト、動的なフォームの添付、MS Officeドキュメントのプレビュー、UIのローカライズ
- フォーム設計 - フォームライブラリ、マルチタブフォーム、豊富なフォームコントロール、データ駆動型コントロール(REST)、条件付き表示のサポート
- プロセスデザイナー - ステップベースのエンドユーザー向けプロセスデザイナー、DMN準拠のデシジョンテーブル、アプリケーション/モデル/ステンシルセットの共有、アプリケーション/フォーム/モデル/ステンシルセットのエクスポートとインポート、自動文書生成
- プロセス分析(Communityバージョンでは一切サポートなし) - プロセスヒートマップ、プロセス概要レポート、タスクのパフォーマンスレポート、SLAレポート
- システム管理 - プロセスエンジン設定用の管理UIおよびクラスタファーム構成、LDAPおよびAD同期、マルチテナントサポート
- アプリケーション統合 - Alfresco One ECM、BoxおよびGoogleドライブ、SharePoint
ご覧のとおり、大規模なビジネスプロセスプロジェクトに着手しようとしている場合に有用な機能や必要な機能が豊富に搭載されています。商用サポートやリリースプログラムの管理は言うまでもありません。
BPMN 2.0とは
ビジネスプロセスモデリング表記法バージョン2.0は、Object Management Group(OMG)が管理するワークフロー定義の規格です。グラフィカルな表現(図形と図のXMLシリアル化)とプロセスの実行に使用されるプロセス定義(XMLシリアル化)の両方をカバーしています。プロセスを視覚的に表現することは、エンドユーザーからプロセスの実装を行う開発者まで、プロジェクトのすべての関係者が話し合うことができるため、非常に有用です。
BPMNグラフィカルモデリング要素
BPMN要素には、フローオブジェクト、データ、接続オブジェクト、スイムレーン、アーティファクトの5つの基本的なカテゴリがあります。
フローオブジェクトは、ビジネスプロセスの挙動の定義に使用される主なグラフィカル要素です。
- イベント-
- アクティビティ-
- ゲートウェイ-
データは、以下の4つの要素で表されます。
- データオブジェクト
- データ入力
- データ出力
- データストア
フローオブジェクトを互いに接続したり、他の情報に接続したりする方法は4つあります。以下は、4つの接続オブジェクトです。
- シーケンスフロー -
- メッセージフロー -
- アソシエーション -
- データアソシエーション -
アーティファクトは、プロセスに関する追加情報の提供に使用されます。
- グループ -
- テキスト注釈 -
下図はプロセスのグラフィカルモデルの例です。
プロセスモデルは左側から解釈または解読します(より具体的には、通常図表の左側にある開始オブジェクト(の記号)を探します)。開始オブジェクトの次に最初のアクティビティがあり、注文フォーム内のデータを受け取ります。次に 排他ゲートウェイがあり(つまり、フローは一方向にのみ遷移可能)、注文を受け付けるか却下するかのいずれかを決定します。注文を却下すると、注文はクローズされ、プロセスは終了します。
注文を受け付けると、注文が処理されます。フローは並列実行に分かれて、注文の発送と請求書処理を同時に行うことができます。 次に進むのが並列ゲートウェイです。プロセスエンジンは、並列ゲートウェイで並列実行パスが両方とも完了するまで待機します。これが完了すると、注文はクローズし、プロセスは終了します。
このようにプロセスをグラフィカルに表現すると、プロジェクトの関係者全員が理解できるため、非常に有用です。また、グラフィカルモデルに変更を加える場合、XMLを変更してエンジンにデプロイし、問題を発見してやり直すのに比べ、コストがかかりません。グラフィカルモデリングツールは、通常、プロセス検証機能を備えているため、つじつまが合わないことがあると直ちに確認できます。また、グラフィカルモデリングツールでは一般的にプロセスのXML表現も可能なので、好みに応じてXMLで作業できます。
BPMNプロセスのXMLシリアル化
ここまでに、グラフィカルな記号でプロセスをモデリングする方法を学習しました。ここからは、実際にプロセスエンジンが実行できる表現へと変換する方法について掘り下げる必要があります。BPMNの場合、それがXMLです。後でBPMNグラフィカルエディタを使用すると、ここで説明するXMLの詳細がわかるようになります。手作業でXMLをコーディングするよりもグラフィカルビューを使って作業する方が容易であり、エラーも発生しにくくなります。しかし、スクリプトを書く場合などの一部のケースでは、XMLで直接作業した方が簡単な場合があります。
Alfrescoをある程度使用していた経験があり、jBPMを用いて数多くのjPDL(XML)プロセスの設計と実装を行ってきた場合、jPDLとBPMN 2.0の2つのプロセス定義言語間の違いについても確認してみる価値があるでしょう。
確認するすべてのBPMN 2.0の構文について、対応するjPDLの構文がある場合は併せて確認します。jPDLの知識があれば、これによりBPMN 2.0への移行がスピードアップする可能性があります。これは、古いjBPMワークフローをどのように新しいActivitiエンジンで動作するかについて理解するうえでも有用です。
名前空間、リソース、コラボレーションの定義
XML 名前空間などを定義するファイル冒頭の構文です。
BPMN 2.0
jPDL
プロセス定義の開始
実際のプロセス定義の開始を定義する構文です。
BPMN 2.0
jPDL
開始イベント
プロセスの最初のイベントです。
記号:
注:開始イベントには複数の種類があります。上記は 開始イベントといい、エンドユーザーが手動でプロセスを開始する場合や、スクリプトがプロセスを開始する場合があるなど、何がプロセスをトリガーするのかがわからない場合に使用します。他に、プロセスが受信メッセージによってトリガーされる場合に使用されるメッセージ開始イベント、タイマーの終了時にプロセスをトリガーするタイマー開始イベントなど、さまざまな開始イベントがありますが、ここでは割愛します。
BPMN 2.0
jPDL
コネクタオブジェクト
コネクタオブジェクトはワークフローの異なるノード間に設定される遷移を表し、プロセス中に取ることができるルートを設定します。
記号:
注:XMLによるプロセスの定義では、要素の順序は重要ではありません。シーケンスフロー要素とタスク要素の順序は不規則でも構いません。つまり、シーケンスフロー要素は自己完結型であり、どのステップ(sourceRef)からどのステップ(targetRef)へ遷移するかを順序に依存せず、コネクタで明示的に指定する必要があります。
BPMN 2.0
jPDL
ユーザータスクの定義
プロセスを続行する前に、実際のユーザーが何らかの作業を行う必要があるアクティビティです。
記号:
BPMN 2.0
jPDL
排他ゲートウェイ
プロセスには判断ノードがあり、フローはここで可能な遷移先の1つを選択します。
記号:
BPMN 2.0
jPDL
並列ゲートウェイ
プロセスが複数の並列実行パスに分岐する、または複数の並列実行パスが1つに合流するノードです。
記号:
BPMN 2.0
jPDL
包含ゲートウェイ
プロセスが 排他ゲートウェイと並列ゲートウェイの組み合わせとして機能するノードです。
排他ゲートウェイのように送信シーケンスフローの条件を定義することが可能で、 包含ゲートウェイによってこれを評価します。評価結果が「true」になるものについてフローが並列して進められ、各シーケンスフローに対して並列実行を1つ作成します。
並列シーケンスフローの合流時、 包含ゲートウェイは並列ゲートウェイと同じように動作し、各受信シーケンスフローを待機します。ただし、 包含ゲートウェイはすべての並列実行パスを待機せず、評価結果が「true」になり、選択されたパスのみを待機することが並列ゲートウェイと主に異なります。
記号:
BPMN 2.0
jPDL
サポートされていません。
サービスタスク
ユーザーの介入なく処理を実行することが想定されるノードです。データをフェッチするための外部アプリケーションの呼び出し、データベースへの格納、電子メールの送信などがあります。
記号:
BPMN 2.0
jPDL
タイマー
特定の時間、実行を待機し、その後実行を継続するプロセスノードです。
記号:
以下の例では、何かを発行する前に少しの間待機することを決断できます。
BPMN 2.0
jPDL
マルチインスタンス
複数のアクティビティを並列して、または順次に、発生させることが可能なノードです。
記号:
注:マルチインスタンスノードの目的は、判断ゲートウェイを使用してフローをプロセスの1つ前のポイントに戻すなど、複数の要素を用いて手動でループ挙動を定義しなければならない状況を回避することにあります。代わりに、ユーザータスクなどのアクティビティにおけるループ特性を定義し、Activitiを呼び出す回数(つまり、渡されたコレクションのサイズ)と、完了したと判断するタイミングをプロセスエンジンにより把握します。
BPMN 2.0
以下のマルチインスタンスの定義の例では、reviewerList変数に含まれる各ユーザーに対してユーザータスクを開始します。
jPDL
foreach要素を用いて、jPDLで同様のマルチインスタンスの挙動を実現できます。
Activiti BPMN拡張機能
他の規格と同様に、規格から少し逸脱して優れた新機能を実装し、ユーザーの手間を軽減したいと考える状況があります。規格から逸脱する場合、使用しているプロセス定義は言うまでもなく別のBPMN 2.0準拠のエンジンでは動作しなくなります。
規格は一般的に、異なる企業間の妥協策であるため、必ず違う方法でやりたいことがでてきます。BPMN 2.0の仕様を読んでいると、実際に構成が少し面倒に見えることがあります。物事をできるだけ簡単にするため、ActivitiではActiviti BPMN拡張機能を導入しました。これらの拡張機能は、BPMN 2.0の仕様には含まれない新しい構成または構成を簡略化する方法です。
Activiti拡張機能は、プロセスの特定の要素を定義する明瞭でわかりやすい方法として、BPMN規格の将来のバージョンに組み込むことができるように定義されています。BPMN 2.0 規格はアプリケーションプログラミングインターフェイス(API)、ルールモデリング、データモデリングなどに対応していないため、実際にこれらの拡張機能が最終的なシステム実装に必要になると予測しています。
Activiti拡張機能は、activiti: 名前空間で明示されます。これらの拡張機能の一部は、標準のBPMN 2.0に簡単に変換することができます。Activiti 名前空間は、プロセス定義ファイルで次のように追加されます。
ユーザーの割り当て
ユーザーのタスクへの割り当ては、繰り返し行う必要がある作業です。そのため、本当に簡単でわかりやすいことが望ましいといえます。
Activiti拡張機能では、以下の新しい構成が採用されています。
- activiti:assignee - 単一ユーザーをタスクに割り当てる
- activiti:candidateUsers - ユーザープールからユーザーを割り当てる
- activiti:candidateGroups - グループプールからグループを割り当てる
以下に例を示します。
これを標準のBPMN 2.0構文と組み合わせると、以下のようになります。
サービスタスクの実装
このActiviti拡張機能は、特定のサービスタスクと実行するコードをリンクするのに使用します。
Activiti拡張機能では、以下の新しい構成が採用されています。
- activiti:class - クラスが指すコードを実行する
例:
タスクリスナーと実行リスナー
このActiviti拡張機能により、タスクの実行時、または遷移の発生時に、簡単にコードを実行できます。
Activiti拡張機能では、以下の新しい構成が採用されています。
- activiti:taskListener - タスクの作成時、割り当て時、または完了時にコードを実行する
- activiti:executionListener - 遷移の実行時にコードを実行する
タスクリスナーの例:
実行リスナーの例:
式
SpringのBeanとして実装されているJavaDelegateの呼び出しを可能にします。Unified Expression Language(UEL)式をサポートし、プロセス定義がSpringのバッキングBeanと通信できるようにします。
Activiti拡張機能では、以下の新しい構成が採用されています。
- activiti:delegateExpression - 一致するSpringのBean IDを見つけ、JavaDelegateを実行する
- activiti:expression - UEL式を評価し、SpringのBeanメソッドを呼び出す
Delegateの例:
UEL式の例:
フォーム
ユーザータスクと特定のフォーム定義を連携します。
Activiti拡張機能では、以下の新しい構成が採用されています。
- activiti:formKey - フォーム定義を指す
例:
Alfresco Oneが組み込まれたActivitiの例:
まとめ
Activiti BPMN拡張機能はいたるところで使用されるので、拡張機能の意味を理解しておくのに越したことはありません。ここでは主な拡張機能のみを見てきましたが、他にもさまざまな拡張機能があります。詳しくはこちらを参照してください。
Alfresco Process Servicesのインストール
Alfresco Process Servicesのアーキテクチャ
下図は、Alfresco Process Servicesプラットフォームのアーキテクチャを示したものです。
このように、すべてJavaベースであり、Apache Tomcatなどの標準のJava Webコンテナで動作します。ユーザーインターフェイスは、数多くのいわゆるActivitiアプリケーションで構成されています。開発者や設計者向けの中心的なアプリケーションはKickstart Appで、ビジネスプロセスの設計や実装に使用します。
Task Appは、ビジネスプロセスのエンドユーザーがタスクの完了やワークフローインスタンスの管理に使用するアプリケーションです。Identity Managementアプリケーションは、ユーザープロファイルの管理に使用します。管理者の場合、グループや権限の管理にこのアプリケーションを使用します。
ビジネスプロセスを実装する際、ビジネスプロセス用のカスタムアプリケーションを作成します。アプリケーションには、ビジネスプロセスモデルが使用するあらゆるフォーム、デシジョンテーブル、データモデルが含まれます。
各種Activitiエンジンは、BPMN 2.0で定義された実行中のワークフロー、フォームの実行、DMN規格に準じたルール処理、検索などを実装します。すべて、Java仮想マシン(JVM)で動作します。
Alfresco Process Servicesアプリケーションについて
サーバー起動中、作業する主なアプリケーションを試すことができるようになりました。http://localhost:8080/activiti-appにアクセスすると、次のログイン画面が開きます。
admin@app.activiti.com/adminでログインします。ログインに成功すると、次のようなトップページが開きます。
トップページには、ユーザーが利用可能な数多くのアプリケーションを表示したダッシュボードが表示されます。Administrator(管理者)としてログインすると、利用できるすべてのアプリケーションが表示されます。各種アプリケーションは、特定のユーザーやグループに限定することができます。以下のタスクを実行するために、既成のアプリケーションを使用します。
- Kickstart App - 基本的には、プロセスを設計してある程度実行し、アプリケーションとして他のユーザーと共有するワークベンチ
- Task App - プロセスインスタンスが実行されると、ログインユーザー(この場合はAdministrator)に割り当てられたすべてのタスクを表示
- Identity Management - グループ、テナント、ユーザーなどのセットアップに使用するアプリケーション
- Analytics App - パフォーマンスやスループット統計データを伴う各種プロセスレポート
ビジネスプロセスの実装
以降のセクションでは、Alfresco Process Servicesを用いたビジネスプロセスの実装について説明します。シンプルな請求書支払い承認プロセスを構築してみましょう。
初期設計
ビジネスプロセスを設計する場合、スイムレーン図から始めると効果的な場合があります。スイムレーン図により、どの関係者(ユーザー、グループ、システム)がワークフローで何を行うかを簡単に把握できるためです。また、開発者、設計者、ビジネスアナリスト、エンドユーザーといったさまざまな関係者がいる場合、スイムレーン図を用いることで話し合いが行いやすくなります。
この段階でのActivitiの使用は任意です。スイムレーン図はさまざまなダイアグラムツールで作成できます。ただし、ワークフローエンジンの観点では、スイムレーン図には明示的な実行の意図がないことに留意してください。
以下に、シンプルな請求書支払い承認プロセスのスイムレーン図を示します。
ご覧のとおり、このワークフローはTeam Assistant(チームアシスタント)が請求書を受け取るところから始まります。ワークフローを開始すると同時に、Approver(承認者)となる担当者を割り当てます。金額に応じて承認を行う担当者が異なる場合があるため、手動による割り当てが必要になります。
次に、Approve Invoice (請求書承認)タスクが選択したApproverに割り当てられ、Approverは請求書を承認するか、請求書の目的をさらに明確にすることを要求します。請求書の詳細が要求される場合、Clarify Invoice(請求書の詳細)タスクが開始者、つまりTeam Assistantに割り当てられます。請求書の詳細を説明できない場合、プロセスは終了します。
請求書の支払いが承認されると、プールされた新しいタスクであるPrepare Payment(支払い準備)がAccounting(経理)グループに割り当てられます。同時にEscalate Timer(エスカレートタイマー)が起動します。仮にこれを15日後に期限切れになるように設定していると、15日後までに何も実行しない場合、エスカレートされたPrepare Paymentタスクが再度送られます。通常、請求書には支払い期限が記載されているため、Prepare Paymentタスクを未処理のままにすることはできません。
Prepare Paymentタスクが完了すると、プロセス実行は、File Invoice(請求書の保管)タスクに遷移し、その後Send Payment Approved Email(支払い承認メールの送信)タスクに進みます。Eメール送信サービスのタスクでは、プロセス開始時に開始者と請求書送信元企業の両方のEメールアドレスが提供されていた場合、両者にEメールを送信します。これでプロセスは終了となります。
設計と実装
実装したいプロセスがレイアウトされたスイムレーン図が用意できました。スイムレーン図は、クライアントの組織の誰でも作成することができます。プロセスの実装にActivitiを使用することを知っている必要もありません。
この時点で行う必要があるのは、設計に目を通し、あいまいな点を修正することです。プロセス設計のつじつまがあっており、やり残しがないことを確認する必要があります。初期設計を行う担当者は、ワークフロー定義のすべての要素や、BPMN 2.0によって何が可能かについて知らない可能性があります。そのため、BPMN 2.0に直接変換できるよう、スイムレーン図の矛盾を解消するまでには、複数のバージョンが発生する可能性があります。
BPMNエディタを使用している場合、多くのユーザーはプロセスのモデリングにスイムレーンを使用しません。これは単純に、スイムレーンがエディタ領域のスペースを占めてしまい、すべてをスイムレーンに一致させる作業が増えることになるためです。
BPMNエディタとフォームエディタは非常に強力なツールなので、設計はもちろん、作業しながら実際にワークフローを実装できます。これらのエディタ外で設定する必要があるのは、Javaサービスタスク、リスナー、カスタムRESTエンドポイントなどを実装する必要がある場合のみです。
カスタムステンシルの作成
ステンシルとは、Activitiプラットフォーム全体で使用するもので、基本的にドメイン固有の要素を再利用する1つの手段です。非技術系のユーザーでも、コンポーネントのAPIの知識を使わずにカスタムコンポーネントを自身のワークフローに組み込むことができます。
ステンシルには以下の3種類があります。
- プロセスエディタステンシル - BPMNエディタのカスタマイズに使用
- フォームエディタステンシル - フォームエディタのカスタマイズに使用
- ステップエディタステンシル - ステップエディタのカスタマイズに使用
入門ガイドでステンシルについて説明する必要があるのかと考えるかもしれませんが、説明は必要です。一度プロセスモデルとフォームモデルを作成すると、BPMNエディタとフォームエディタ用に使用したステンシルの切り替えができなくなります。
そのため、カスタムプロセスステンシルとカスタムフォームステンシルを作成し、それらに使用するエディタをベースとすることをお勧めします。その結果、カスタムエディタステンシルを利用する際に、プロセス全体を作り直したり、フォームをゼロから再設計したりすることなく、エディタにカスタムコンポーネントを組み込むことができます。
では、カスタムステンシルとは何でしょうか。以下の例でステンシルの用途について説明しますが、ステンシルとは基本的にカスタムエディタを作成する手段の1つです。
エンタープライズREST APIを呼び出してユーザー情報をフェッチするのに使用できるサービスタスクがあると仮定します。サービスタスクは、com.mycompany.activiti.service.UserProfileServiceImplで、Javaで実装されます。そして、userId、endpointURLなどを渡す必要があります。基本的に、このサービスを使用したいビジネスユーザーは、多くのビジネスユーザーが知る必要のない詳細をかなり知っておく必要があります。サービスタスク、サービスタスク実装クラス名、パラメータ名などの使い方を知っている必要があります。
BPMNエディタで以下のようにビジネスユーザーが既製のコンポーネントを使用できれば、とても便利ではないでしょうか。
ここで、ユーザーはどのフィールドが呼び出されているか、クラス名は何かなどについて知る必要はありません。このカスタムサービスタスクをキャンバスにドラッグ&ドロップするだけで、カスタムプロパティを設定できます。エンドユーザーにわかりやすくするため、サービスタスクのデフォルトプロパティの多くも削除されています。BPMNエディタのカスタムステンシルを使用することで、これがすべて可能です。
カスタムコントロールを追加することで、同様の方法でフォームエディタをカスタマイズできます。デフォルトのフォームエディタには存在しないImage Hyperlinkコントロールを追加したいと仮定します。フォームエディタのカスタムステンシルを作成することで、以下のようにフォームエディタで利用できるようになります。
コントロールに必要な特定のデータを収集するため、次のようにコントロールに新しいプロパティタブを設けることも可能です。
このように、ステンシルは非常に有用であるため、プロセスやフォームのベースとなるベーシックなカスタムステンシルをいくつか作成してみましょう。カスタムステンシルは空になりますが、カスタムコンポーネントをエディタに追加する必要が考えられる場合に備えることができます。
ステンシルはApp Designerを用いて作成します(既製のステンシルをインポートする場合、こちらからZIPをダウンロード)。
このアプリケーションをクリックすると、次のページが表示されます。
画面上部のStencilsメニューアイテムをクリックし、次にCreate a new Stencil now!ボタンをクリックします。
ステンシルの名前を「My Company Process Editor」に指定し、Create new stencilボタンをクリックします。エディタの種類はデフォルトで「BPMN editor」に設定されているため、変更の必要はありません。
これにより、デフォルトのBPMNエディタが表示されます。画面右上のStencil Editorボタンをクリックすると、エディタをカスタマイズできます。今回はカスタマイズを行わず、この記事ではデフォルトのエディタレイアウトを維持します。ただし、将来必要になる場合に備えて、新しいコンポーネントを追加する用意はできています。
同じように、フォームエディタステンシルを追加します。
ここでは、Editor typeドロップダウンから「Form editor」を選択します。これで以下のように2つのステンシルが作成されました。
プロセスモデルの作成
エディタのベースとなるカスタムステンシルの作成が完了し、顧客のビジネスプロセスも明確になりました。次に、Activitiでプロセスを作成します。プロセスの作成にはApp Designerを使用します(この手順を簡単に確認したい場合は、こちらから入手可能なZIPファイル経由でインポートできます)。
このアプリケーションをクリックすると、次のページが表示されます。
ここでプロセスの設計、ユーザータスク用フォームの作成、デシジョンテーブル、データモデル、これをすべて含む新しいアプリケーションの定義を行うことができます。ほとんどの場合、プロセス定義から開始することをお勧めします。フォームが必要な場合は、 Kickstart Appページを使用して作成することができます。
画面右上のCreate Processボタンをクリックして、Web版のBPMN 2.0デザイナーを起動します。最初に開くダイアログで、プロセスの名前と説明の入力が求められます。
上図のように名前と説明を入力します。「BPMN editor」を選択したままにするので、馴染みのあるBPMN 2.0の図形を使用してプロセスを設計します。「Step Editor」を選択する場合は、より簡略化されたステップベースのアプローチでビジネスプロセスを設計することになります。
ステンシルには、先ほど定義したプロセスエディタのカスタムステンシルを選択することが重要です。Stencilドロップダウンから「My Company Process Editor」を選択します。将来的に役に立つことが見込まれるため、カスタムコンポーネントをこのステンシルに追加し、今後のプロセス定義で使用します。
Create new modelボタンをクリックして新しいプロセスモデルを作成します。BPMNエディタが次のように表示されます。
最初は開始イベントのみで、多くは表示されていません。BPMNエディタの左側に、自由に作業に使用できるBPMN要素がすべて表示されています。基本的な要素についてはこの記事で既に説明していますが、ご覧のとおり、他にも数多くの要素を使用できます。画面中央は、プロセスを作成するメイン領域です。先ほどお話したとおり、この時点では開始イベントのみが表示されています。
画面下部には、要素やノードに関連する情報が表示されます。いずれかの要素の外側をクリックすると、プロセス全体に関連する情報やプロパティが表示されます。
これは、リスナー、信号、変数、フォーム、IDなど、何かをセットアップする際に使用する場所です。実際に、一切XMLに触ることなく、BPMNエディタから多くのことを実行できます。
開始イベント
開始イベントなど(実際にその他にクリック可能な要素がない場合)、プロセス定義の要素をクリックすると、次のようにプロパティセクションにその要素が表示されます(Activitiオンラインユーザーガイドの「Start Events」)。
追加する各要素に対して、IDを設定しておくと便利です。これを行わない場合、ActivitiがIDを生成しますが、それでも問題はありません。ただし、要素により読みやすいIDを設定すると、生成されたプロセス定義XMLがより読みやすくなります。開始イベント要素のIDプロパティをクリックし、startInvoiceProcessというIDを設定します。画面は次のように表示されます。
このケースでは、開始イベントに一貫性のある対応する名前を設定しました。
使用可能なプロパティは、クリックした要素によって異なります。開始イベントは関連するフォームを持つことができるため、Referenced formなど、フォームに関連する新しいプロパティが表示されます。Approverを選択できる開始イベントに実際にフォームを連携し、請求書送付元の会社のEメールアドレスを指定して、請求書ファイルをアップロードします。Referenced formプロパティをクリックします。
これにより次のダイアログが表示されます。
複数のフォームの定義を開始した場合、ここでフォームが開かれます。この時点では、まだフォームは定義されていません。そのため、New formボタンをクリックして、新しいフォームを作成します。
名前を入力します。このワークフロー定義をベースにしたワークフローインスタンスを開始すると表示される最初のフォームであるため、ここでは「Start Invoice Approval Form」と設定します。次に役に立つ説明を入力します。
一番下にStencilドロップダウンが表示されます。先ほど作成した「My Company Form Editor」というフォームのカスタムステンシルが選択されていることを確認します。これでカスタムコントロールを追加して、将来使用することができます。
Create formボタンをクリックして、フォームの定義を開始します。
BPMNエディタではなく、フォームエディタが表示されます。フォームエディタでは、デフォルトでDesignモードが開くので、画面中央のキャンバスにコントロールの追加を開始できます。それでは、ユーザー選択、会社Eメールアドレスのテキストフィールド、さらに、承認を受ける請求書をアップロードできるように添付フィールドを追加してみましょう。
ここでは、基本的にフォームキャンバスへのコンロトールのドラッグ&ドロップのみを行いました。次にコントロールにラベルを設定します。これを行うには、コントロールにカーソルを置き、ペンをクリックします。このケースでは、デフォルトの1列複数行のレイアウトを使用しました。列数と各列の行数はカスタマイズ可能です。列幅やタブなども指定できます。
以下はApproverのラベルとIDです。
ラベルを入力すると、IDが自動的に生成されます。使用されたIDを覚えておくと、後にプロセスで参照できるので便利です。Company Emailのテキストコントロールは次のようになります。
以下は添付コントロールの請求書ファイルプロパティです。
フォームが完成したら、画面左上の検証ボタンをクリックします。
すべて緑であれば、フォームは有効です。検証ボタン横のディスクのアイコンをクリックして、フォームを保存します。
フォームを保存してフォームエディタを閉じ、BPMNエディタに戻るため、Save and close editorボタンをクリックします。開始イベントをクリックすると、作成したフォームがイベントに連携されます。
Activiti Web環境を離れることなく、フォームを作成し、プロセスモデルの要素に連携できました。今のところXMLには一切触っていません。
Approve Invoiceユーザータスク
ワークフロー定義の次のノードはApprove Invoiceユーザータスクです(Activitiオンラインユーザーガイドの「User Task」)。画面左側にあるナビゲータで Activitiesセクションを開くと、User Taskをプロセス定義キャンバスにドラッグ&ドロップできます。
次に、開始イベントをクリックし、遷移を表す矢印を選択して、開始イベントと新しいユーザータスクを接続します。
次に、ユーザータスクをダブルクリックして、「Approve Invoice」という名前を入力します。次の図が完成します。
この時点で、プロセスモデルを検証して保存します。
画面左上の検証ボタンをクリックし、次にその左にある保存ボタンをクリックします。検証前に承認タスクでやるべきことがあるため、検証は実際に失敗することになります。以下は検証エラーが表示された状態です。
検証に失敗しても、プロセスを保存できます。保存すると、プロセスはMy processes下に表示されます。
BPMNエディタに戻るには、単純にプロセスモデルをクリックします。
次に、右上にあるVisual Editorボタンをクリックします。Approve Invoiceタスクのプロパティを更新する必要があるので、タスクをクリックします。次に、タスクのIDとして「approveInvoice」と記入します。次のように表示されます。
このユーザータスクでは、Approverが作業内容に関する情報を参照し、確認のために請求書ファイルをダウンロードできるフォームが必要になります。Referenced formプロパティをクリックします。
「Approve Invoice」フォームという新しいフォームを作成します。
Create formボタンをクリックしてから、フォームエディタで次のようにフォームを設計します。
最初の情報であるDisplay textフィールドには、次のプロパティが表示されます。
ここでは、まずテキスト表示フィールドのNameを入力しました。これにより、IDが生成されました。次に、Text to displayへの入力を行いましたが、1か所で下にあるForm fieldドロップダウンからCompany Emailのフォームフィールド値を選択して挿入しています。${companyemail}変数には、開始フォームで入力したCompany Emailの値が代入されます。
変数名を覚えている場合は、テキストに${...}変数/フィールドプレースホルダを明示的に入力し、ドロップダウンリストから選択するのと同じ最終効果を持たせることも可能です。ドロップダウンからの選択は、変数を素早く正しい構文で挿入する手段にすぎません。
表示値フィールドには次のプロパティが表示されます。
フィールドにラベルを設定しておいたので、開始フォームでアップロードした請求書ファイルとして表示されるフォームフィールド値を選択しました。
最後は複数行のCommentsフィールドです。Approverが、請求書が却下され、請求書の詳細を説明する必要があるなどのメッセージを開始者に伝えたり、経理部に請求書の支払いに関するメッセージを伝えたりする際にこのフィールドを使用します。
ユーザータスクには、タスクの完了時にユーザーがクリックするCompleteボタンがデフォルトで表示されます。今回はこのボタンは不要なので、代わりにApprove(承認)ボタンとReject(却下)ボタンの2つを表示します。これらのボタンは、請求書を支払うかどうかについてのApproverによる決定を示します。これらの決定をタスク結果と呼びます。フォームエディタには、これらを設定するための専用のタブがあります。
Use custom outcomes for this formラジオボタンをクリックします。
上図のように、 2つのタスク結果が標準フィールドで指定されます。これらのボタンには任意の名前を付けることが可能で、BPMNエディタにより、関連する条件に正しい変数名が付いていることが確認されます。なお、必要に応じてボタンを増やすこともできます。
これでApprove Invoiceフォームが完成しました。フォームを保存して、BPMNエディタに戻ります。
すべてのユーザータスクは、ユーザーまたはユーザーのグループに割り当てる必要があります。上図のとおり、Approve Invoiceタスクはまだ誰にも割り当てられていません。何も行わないと、BPMNエディタによって、デフォルトでプロセスの開始者に割り当てられます。
これを修正するには、Assignmentプロパティをクリックします。
このダイアログは、これまで見てきたものよりも少々扱いにくくなっています。行うことは基本的に、最初の開始フォームでApproverとして選んだユーザーを担当者に設定することです。これを行うには、まずIdentity storeタブ(1)をクリックします。次に、AssignmentドロップダウンでAssign to single userを選択します(2)。次に、Form fieldタブ(3)をクリックします。最後に、Form fieldドロップダウンからApproverを選択します(4)。
BPMNエディタでは、プロセスの他のフォームで使用されているすべての担当者フォームフィールドの識別と選択が可能です。さらにFixed valuesセクションでは、フォームフィールドだけでなく、権限に対応する変数プレースホルダを利用することもできます。
ここで割り当て構成を保存します。プロパティセクションが次のように表示されます。
これでApprove Invoiceユーザータスクが完成しました。ワークフローの次の要素に進むことができます。
承認結果の 排他ゲートウェイ
2つの結果(承認または却下)を設定したため、Approve Invoiceタスクに続いて排他ゲートウェイが必要になります(Activitiオンラインユーザーガイドの「Exclusive Gateway」)。 排他ゲートウェイを次のように追加します。
ゲートウェイの後は、請求書却下または請求書承認のいずれかに進みます。それぞれの実行パスには、後に続くユーザータスクが1つあります。
Clarify Invoiceユーザータスク
却下のパスから始めましょう。これには、ワークフローの開始者に割り当てられるClarify Invoiceユーザータスクが含まれます。
新しいタスクにIDを設定し、記号をダブルクリックして名前を入力しました。さらに、矢印で 排他ゲートウェイと接続しました。プロパティを見てわかるように、この新しいタスクは自動的に開始者に戻るよう設定されます。
そのため、割り当ての詳細をセットアップする必要はありません。ただし、請求書ファイルへのリンクとApproverがこの時点で請求書を却下した理由に関するコメントで構成されるフォームが必要です。Clarify InvoiceタスクのReferenced Formプロパティをクリックし、次のように名前と説明を入力します。
フォーム名はタスクインボックスやフォームページでエンドユーザーに向けて表示されることもあるため、有用な名前を選ぶことをお勧めします。また、変数/フィールドプレースホルダを活用して、ユーザーがタスクを開かなくても簡単に内容を特定できるようにすることが可能です。この記事で後ほど、タスク名を動的に設定する方法を紹介します。
次に、次のようにフォームを設計します。
ここで、Approverからのコメントと請求書ファイルへのリンクを表示します。その結果、開始者はClarificationという複数行テキストフィールドに問題に対する回答を記入することができます。回答はApproverに送り返され、再度Approve Invoiceタスクが実行されます。
Comments表示値フィールドには次のプロパティが表示されます。
Form fieldを選択した後に、ラベルを変更することに留意してください。
Invoice file表示値フィールドには、次のプロパティが表示されます。
最終的な新しいClarification複数行テキストフィールドは以下のとおりです。
このタスクには、請求書の詳細が説明され承認タスクに戻される(Clarified)、または支払いが却下される(Rejected)という2つの結果があります。そのため、Outcomesタブで、次の2つの結果を入力します。
これでClarify Invoiceフォームが完成しました。フォームを保存して、BPMNエディタに戻ります。
Clarify Invoiceタスクに複数の結果があるため、タスクに続く 排他ゲートウェイが必要です。
確認結果の 排他ゲートウェイ
このゲートウェイは、Clarify Invoiceユーザータスクのすぐ後に続き、却下(Rejected)の実行パスは直接終了イベントに進みます。承認(Clarified)の実行パスは、Approve Invoiceユーザータスクへと戻ります。これをモデリングすると、次のようになります。
ここでは、シーケンスフロー(遷移)名の設定も行いました。その結果、図表が読みやすくなりました。さらに、 排他ゲートウェイに続くシーケンスフローに屈曲点を追加して、図表の見た目を少し整えました。BPMNエディタで下図に示したボタンをクリックすると、屈曲点を追加できます。
ゲートウェイ後のシーケンスフローは、それぞれにフロー条件を設定するまで、実際に機能しません。フロー条件は、特定のシーケンスフローを選択するかどうかを決定します。では、Clarifiedシーケンスフローから始めましょう。Clarifiedシーケンスフローをクリックして、プロパティを表示します。
フロー条件を設定する必要がない特別なケースがあります。他のすべてのシーケンスのフロー条件がfalseの場合、このシーケンスフローを選択するというケースです。これをデフォルトフローと呼び、Default flowプロパティをクリックすることでシーケンスフローをデフォルトフローに設定できます。ただし、今回はこの機能を使用しません。
Flow conditionプロパティをクリックして、次のとおり入力します。
まず、フロー条件をSimpleに設定し(1)、ベースとしてForm outcome(2)を選択します。次にClarify Invoiceフォームを選択します(3)。結果が「Clarified」と等しくなるように設計します(equal(4)とClarified(5)を 選択)。
次に、Payment Rejected(支払い却下)シーケンスフローをクリックします。
次のように設定します。
さらに、最初のゲートウェイからのRejectedシーケンスフローのフロー条件もセットアップする必要があります。
次のとおり設定します。
このフロー条件は、Approve Invoiceユーザータスクの結果に基づいていることに留意してください。
説明メッセージ付きApprove Invoiceユーザータスク
Clarify Invoiceタスクの Clarified結果からApprove Invoiceタスクに遷移する場合、Approve Invoiceフォームに説明メッセージを表示すると便利です。Approve Invoiceタスク、Referenced formの順にクリックし、フォームの更新を開始します。
Open formを選択し、Commentsフィールドの下にClarificationテキスト用の表示値フィールドを追加します。
以下はClarificationフィールドのプロパティです。
基本的に、Clarificationフォームフィールドの値が表示されます。説明文がない場合(開始イベントからのフロー)はこのフィールドを非表示にしたいため、Visibilityタブで次のとおり設定します。
更新したApprove Invoiceフォームを保存し、フォームエディタを閉じます。これでApproved Invoiceフローを進める準備が完了しました。
Prepare Paymentユーザータスク
Approved Invoiceフローにおける最初のタスクは、経理グループに割り当てられるPrepare Paymentタスクです。このタスクをモデリングする前に、Accountingというユーザーグループを実際に作成する必要があります。Activitiのインストールは、Active Directory(AD)またはLDAPサーバーに連結させるのがおそらく最も一般的です。次に、Assignmentプロパティの設定を開始することになります。
しかしここでは、このグループを手動で作成します。プロセスモデルを保存し、エディタを終了して、BPMNエディタを閉じます。次に、画面左上のAlfresco Activitiアイコンをクリックし、トップページに戻ります。
ここで、Identity managementアプリケーションをクリックして、新しいグループを作成します。
このアプリケーションで、Organization タブ、Create groupボタンを順にクリックします。
グループにAccountingという名前を付け、+ add userをクリックして、自身(Administrator)を単独のメンバーとして追加します。
Prepare Paymentタスクを続行する準備ができました。BPMNエディタに戻ると、プロセスは次のように表示されます。
新しいPrepare Paymentユーザータスクを追加します。その結果、プロセスモデルが次のように表示されます。
タスクにpreparePaymentというIDを設定します。ユーザータスクにAllow email notificationsというプロパティが追加され、デフォルトで有効になっています。これは、タスクがユーザーに割り当てられるたび、ユーザーにEメールが送信されることを意味します。そのため、ユーザーはActivitiにログインすることなく、タスクを割り当てられたことを知ることができます。これはグループへの割り当てでも同様です。
今回のケースでは、Prepare Paymentタスクは先ほど作成したAccountingグループに割り当てられ、プールタスクになります。つまり、Accountingグループのすべてのユーザーがタスクを完了するのではなく、この内の1人がタスクを完了します。タスクを完了しようとしているユーザーが申し出ると、グループの他のすべてのユーザーからタスクが消去されます。
下に示したAssignmentプロパティをクリックします。
デフォルトでワークフローの開始者に設定されるため、変更する必要があります。
Candidate groups、Accountingグループを順に選択します。ここで、開始者、担当者、候補グループ、候補ユーザー、プールタスク、さらにはタスクオーナーなどが登場します。少々混乱するかもしれませんので、解説しておきます。
- Initiator(開始者) - ワークフローインスタンスを開始するユーザー。
- Owner(オーナー) - ユーザータスクの責任者であるユーザー。たとえば、Prepare Paymentタスクを作成したときに、(プールタスクのため)担当者がいない場合、オーナーが開始者に設定されます。
- Assignee(担当者) - ユーザータスクの完了を割り当てられたユーザー。
- Candidate User(候補ユーザー) - ユーザータスクを要求し、担当者になることができるユーザー。
- Candidate Group(候補グループ) - ユーザータスクを要求し、担当者になることができるユーザーのグループ。プールタスクを参照してください。
- Involved User(関係ユーザー) - ユーザータスクにリンクされている関係ユーザー。1つのタスクに担当者は1人しか割り当てられませんが、関係するユーザーは複数割り当てることができます。
- Pooled Task(プールタスク) - 作成した際に、誰も割り当てられていないタスク。候補グループの誰かが担当者になることを申し出る必要があります。
- Queued Task(キュータスク) - 候補ユーザーまたはグループのみが存在し、担当者が未定のユーザータスクです。
オーナーと関係ユーザーは、プロセス定義において実行時に意味を持たない暗黙の概念と考えることができます。
ここでプロセスモデルを検証および保存すると、足りないパーツがあるかが明確になります。
排他ゲートウェイに警告があります。ゲートウェイからPrepare Paymentタスクへの遷移に対して、フロー条件が設定されていませんでした。次のとおり設定します。
Approve Invoiceタスクが承認された場合、Prepare Paymentタスクに遷移しなければなりません。現在、Prepare Paymentタスク用に定義されたフォームもないため、Accountingユーザーはどの請求書の支払いを行うのかがわかりません。次のようにタスク用の新しいフォームをセットアップします。
レイアウトは次のようになります。
AccountingチームのいずれかのユーザーがPrepare Paymentタスクを完了したら、請求書ファイルをファイリングし、Eメールを請求書送付元の会社に送信します。これらはすべてシステムによって実行されるサービスタスクであり、人間の手は介在しません。ただし、特定の期間までにタスクが完了していない場合にこのタスクをエスカレートするタイマーを最初に定義する必要があります。
Prepare Paymentタスクタイマー
タイマーは、「ESCALATED: Prepare Payment」という新しい名前でPrepare Paymentタスクを再送信するトリガーとして使用されます。タイマーは、ユーザータスクアクティビティの境界イベントとして定義されます。境界イベントはアクティビティに付加され、アクティビティの実行中、タイマーの時間切れなどのトリガー をリッスンします(Activitiオンラインユーザーガイドの「Timer Events」)。
次のとおり、タイマーをPrepare Paymentユーザータスクに追加します。
タイマーには時間を設定する必要があります。タイマーをクリックしてプロパティを表示します。
ここでは、タイマーの長さを「PT2M」に設定しました。これは2分後に時間切れになることを意味します。時間の構文一覧については、こちらのページを参照してください。タイマーの終了時にPrepare Paymentタスクに戻るようにタイマーから遷移(シーケンスフロー)を追加する必要もあります。
タイマーが終了すると、アクティビティ(つまり、Prepare Paymentユーザータスク)は自動的にキャンセルされます。これは、タイマープロパティのCancel activityにチェックが入っているためです。これで、請求書のファイリングに進む準備が完了しました。
File Invoiceサービスタスク
このタスクは、請求書の支払い準備が完了したら、記録管理の目的で請求書をシステムにファイリングするという考えが背景にあります。このタスクの初回の実装では、 ロギングを複数回実行します。次に、ファイルシステムにファイルを書き込むようタスクを変更し、後で記録管理モジュールで設定されたAlfresco ECMコンテンツリポジトリにファイルを格納する別のバージョンを実装します。
次のように、左側のActivitiesセクションからService taskを選択して、File Invoiceサービスタスクを追加します。
さらに、サービスタスクにfileInvoiceというIDを設定しました。この時点では、サービスタスクは明らかに完了していません。コードの呼び出しを行う必要があります。サービスタスクからコードを呼び出す方法はいくつかあります。プロパティを少しスクロールダウンすると、次の情報を確認できます。
これらのプロパティには、次のような意味があります(この情報に関する完全版マニュアルは、こちらのページを参照してください)。
- Class(クラス):org.activiti.engine.delegate.JavaDelegateインターフェイスを実施するクラスのフルパッケージパスを含むクラス名を設定します。その結果、サービスタスクにヒットすると、Activitiは実行メソッドを呼び出します。
- 例:activiti:class="org.alfresco.activiti.service.task.MyServiceTask"
- スレッドセーフか?いいえ。このデリゲートクラスを使用する各サービスタスクに対して、クラスインスタンスが1つ作成されます。ただし、これらはプロセスインスタンス間で共有されます。
- Delegate expression(デリゲート式):JavaDelegateからSpringのBeanを作成し、デリゲート式としてSpring Bean名を設定することも可能です。
- 例:activiti:delegateExpression="${someBeanName}"
- スレッドセーフか?いいえ。SpringのBeanはデフォルトでシングルトンなので、複数のサービスタスクからデリゲート式(Bean)を使用する場合、同一のBeanインスタンスを使用します。これは、Beanの@Scope(BeanDefinition.SCOPE_PROTOTYPE)を使用して設定します。
- Expression(式):標準のJava POJO インスタンスをプロセス変数として使用することもできます。式からその中のあらゆるメソッドを呼び出し、必要に応じてパラメータを渡します。
- 例:activiti:expression="${myVariable.doStuff(param1)}"
- スレッドセーフか?はい。すべてのプロセスインスタンスには独自の変数インスタンスがあります。
多くの場合、サービスタスク実装にもパラメータを渡すことになります。今回のケースでは、Company EmailとInvoice Fileを渡します。これは、ClassまたはDelegate expressionを使用していれば、Class fieldsプロパティで実行できます。まず、クラスorg.alfresco.training.activiti.task.FileInvoiceServiceTaskDelegateをJavaデリゲートとして設定します。
Class fieldsをクリックして追加を開始します。
companyEmailクラスを次のとおり設定します。
会社Eメールアドレスと請求書ファイルに設定した変数名を覚えていない場合は戻って確認します。invoiceToBeApprovedクラスを次のとおり設定します。
これにより、次のBPMN 2.0 XMLに変換されます。
<serviceTask id="fileInvoice" name="File Invoice" activiti:class="org.alfresco.training.activiti.task.FileInvoiceServiceTaskDelegate"> <extensionElements> <activiti:field name="companyEmail"> <activiti:expression><![CDATA[${companyemail}]]></activiti:expression> </activiti:field> <activiti:field name="invoiceToFile"> <activiti:expression><![CDATA[${invoicetobeapproved}]]></activiti:expression> </activiti:field> </extensionElements> </serviceTask>
次のステップは、FileInvoiceServiceTaskDelegateクラスの実装です。これには、Mavenベースの拡張プロジェクトが必要です。これは、このクラスが使用するすべての依存関係をMavenとartifacts.alfresco.comからプルするのが最も簡単であるためです。最良の開始方法は、Activitiプロジェクトテンプレートを提供するSDK 3 beta 5を使用する方法です。ただし、SDK 3を使用するには、エンタープライズアカウントでartifacts.alfresco.comにログインして、Alfresco Process Services アーティファクトをダウンロードする必要があります。
この記事では、最初にダウンロードしたトライアルライセンスを使用します。そのため、ここではクラス実装を紹介し、サーバーのクラスパスを置くことができるActiviti Extension JARへの次のリンクを提供します。(クラスのソースコードはこちら)
package org.alfresco.training.activiti.task; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.JavaDelegate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FileInvoiceServiceTaskDelegate implements JavaDelegate { private static Logger logger = LoggerFactory.getLogger(FileInvoiceServiceTaskDelegate.class); /** * Injected class fields */ private Expression companyEmail; private Expression invoiceToFile; public void execute(DelegateExecution execution) throws Exception { logger.debug("Storing the invoice file somewhere safe!"); String emailAddress = (String) companyEmail.getValue(execution); logger.debug("The invoice was sent in from: " + emailAddress); // We will deal with the invoiceToFile field later on } public void setCompanyEmail(Expression companyEmail) { this.companyEmail = companyEmail; } public void setInvoiceToFile(Expression invoiceToFile) { this.invoiceToFile = invoiceToFile; } }
このサービスタスクは、実際のところログメッセージの印刷以上に有用な機能は果たしません。しかし、ある種のエンタープライズアーカイブシステムにファイルを保存します。ここで重要なことは、JavaDelegateインターフェイスを実装してデリゲートを使用したサービスタスクの実装を実現し、このインターフェイスでexecuteメソッドを実施することです。
executeメソッドは、DelegateExecutionの1つのパラメータを利用します。これにはJavaデリゲートを呼び出すプロセスインスタンスに関する情報が含まれます。実行コンテキストにアクセスできない場合、Process Instance ID、Process Definition ID、Tenant ID、Activity IDなどのインスタンス情報を入手できません。
このメソッドは、サービスタスクに到達したときに、Activitiワークフローエンジンによって呼び出されます。後ほど、サービスタスクから請求書ファイルを抽出して保存する方法を見ていきますが、その実装を開始する前にワークフローを試してみましょう。
Send Approved Emailタスク
承認された請求書のルートの最終ステップは、ワークフローの開始者と請求書送付元の会社へのEメールの送信です。
Activitiは既製のEメール送信サービスタスクを備えているので、簡単に実行できます。Mail taskをキャンバスにドラッグ&ドロップし、それをFile InvoiceサービスタスクとEnd Processノードに接続します。
次に、Send Approval Emailタスクのプロパティのリストをスクロールダウンし、関連するメールプロパティ(From、To、Subjectなど)を入力します。
この時点で生成したBPMN 2.0 XMLを見ると、次のように見えるはずです。
<serviceTask id="sendApprovalEmail" name="Send Approval Email" activiti:type="mail"> <extensionElements> <activiti:field name="to"> <activiti:expression><![CDATA[${emailBean.getProcessInitiator(execution)}]]> </activiti:expression> </activiti:field> <activiti:field name="from"> <activiti:string><![CDATA[activiti@mycompany.com]]></activiti:string> </activiti:field> <activiti:field name="subject"> <activiti:string><![CDATA[Invoice Approved for Payment]]></activiti:string> </activiti:field> <activiti:field name="cc"> <activiti:expression><![CDATA[${companyemail}]]></activiti:expression> </activiti:field> <activiti:field name="text"> <activiti:string><![CDATA[Invoice Approved for Payment]]></activiti:string> </activiti:field> </extensionElements> </serviceTask>
これで、最後のステップであるこのワークフローの実装は完了です。
プロセスモデル用のBPMN 2.0 XMLの生成
最後の2つのサービスタスクについて説明する際に、BPMN 2.0 XMLをいくつか提示しました。これをどこで入手したのか知りたいユーザーもいるかと思います。現在のプロセスモデルのBPMN 2.0 XMLはいつでもダウンロードできます。
Kickstart Appに移動します。
次にプロセスモデルをクリックします。
画面右上のExport to BPMN 2.0ボタンをクリックします。
これにより、現在のプロセスモデルがBPMN 2.0 XMLとしてダウンロードされます。
ビジネスプロセス用アプリケーションの生成
ここまでの作業でビジネスプロセスのソートが完了しましたが、まだ実際に動作することはできません。まず、Activitiアプリケーションに組み込む必要があります。次にこのアプリケーションを公開し、公開したバージョンからワークフローを実行する必要があります。プロセスアプリケーションを使用して、さまざまなユーザー間でプロセスを共有することも可能です。他のActivitiユーザーにこのプロセスを実行してもらいたい場合は、対象のユーザーとアプリケーションを共有する必要があります。
Kickstart Appから起動し、画面上のAppsメニューアイテムをクリックします。
アプリケーション管理ページが表示されます。
画面右上のCreate Appボタンをクリックします。
新しいアプリケーションの名前(App definition name )と説明(Description )を入力し、Create new app definition をクリックします。
ここでは、Edit included modelsをクリックして、先ほど作成したプロセス定義を追加します。ご覧のとおり、アプリケーションは必要に応じて複数のプロセスモデルをホストすることができます。
次に、アプリケーションのアイコンとテーマを変更します。ここでも、他のユーザーとのアプリケーションの共有を設定できます。共有を設定するには、Add another person またはAdd another groupをクリックします。今回のケースでは、自分だけがワークフローを起動するため、他のユーザーと共有する必要はありません。
最後に、画面左上の保存ボタンをクリックします。
この時点でActivitiのホームボタンをクリックしてもこのアプリケーションは表示されず、引き続きデフォルトのアプリケーションが表示されます。
これは、アプリケーションがまだ公開されていないためです。アプリケーションを公開するには、Kickstart App、Appsメニューアイテム、Invoice Approval Appを順にクリックします。
ここで、画面右上のPublishボタンをクリックすると、アプリケーションが公開されます。トップページに戻ると、ダッシュボードに新しいアプリケーションが表示されます。
これで、Invoice Approvalワークフローを埋め込んだInvoice Approvalアプリケーションが使用できるようになりました。
ビジネスプロセスの実行
Invoice Approvalワークフローの設計と実装のために行ったすべての作業をテストしてみましょう。ただし、まずはクラスパスにFile Invoiceサービスタスククラスがあることを確認する必要があります。こちらからコピーし、tomcat/webapps/activiti-app/WEB-INF/libに置くと、以下のようになります。
martin@gravitonian:/opt/activiti15/tomcat/webapps/activiti-app/WEB-INF/lib$ cp ~/src/sdk3/alfresco-sdk-tests/activiti-jar-blog/target/activiti-jar-blog-1.0-SNAPSHOT.jar .
注意:tomcat/libにJARを置いただけでは機能しません。
また、Eメールサーバー(SMTP)が設定されており、Activitiが最後のMailタスクでEメールを送信できるようになっていることを確認する必要があります。確認には、Fake SMTPサーバーを使用します(こちらからダウンロード)。以下のように開始します。
martin@gravitonian:~/apps/fakeSMTP$ java -jar fakeSMTP-1.13.jar
次にポートを「2525」に設定し、Start serverボタンをクリックしてSMTPサーバーを起動します。
ここで、ローカルSMTPサーバー経由でEメールを送信するようActivitiを設定します。次のファイルを開きます。
martin@gravitonian:/opt/activiti15/tomcat/lib$ gedit activiti-app.properties
以下のSMTPサーバープロパティを設定します。
email.host=localhost email.port=2525 email.useCredentials=false
martin@gravitonian:/opt/activiti15$ /opt/activiti15/tomcat/bin/catalina.sh stop martin@gravitonian:/opt/activiti15$ /opt/activiti15/h2/stop-h2.sh Shutting down TCP Server at tcp://localhost martin@gravitonian:/opt/activiti15$ ./start-activiti.sh
Approved Invoiceフローの実行
ここで、Invoice Approval Appをクリックします。次の画面が表示されます。
Administratorにタスクが割り当てられている場合は、ここに表示されます。
プロセスインスタンスの開始
プロセスインスタンスがまだ動作していないので、まず+STARTメニューアイテムをクリックする必要があります。
これで、「開始フォーム」で定義したすべてのフィールドが表示されました。Approverを選択し(Administratorを選択)、次に架空のEメールを指定して、請求書の見本となるファイルをアップロードします。画面は次のように表示されます。
START PROCESSボタンをクリックし、プロセスインスタンスを開始します。
ここで、ワークフローインスタンスのアクティブなタスク(つまり、Approve Invoiceタスク)や、これまでに完了したタスク、プロセス変数などを確認できます。また、SHOW DIAGRAMをクリックすると、現在プロセスフローのどこにいるかを視覚的に確認できます。
現在のタスクには緑色の枠線が表示されます。
Approve Invoiceタスクの完了
Tasksメニューアイテムをクリックします。
これにより、Administratorに割り当てられたタスクがすべて表示されます。
ここではInvoice Approvalフォームが表示されます。companyEmail変数が変換された状態で情報テキストが表示されます。タスクの結果もAPPROVEボタンおよびREJECTボタンで反映されています。請求書を却下する場合、このページでコメントを入力できます。入力したコメントは、請求書を明確にする際に開始者に対して提示されます。しかし、今回はApprovedフローに進みます。最初に請求書ファイルをクリックしてプレビューを表示します。
Activiti UIを使用できる状態で請求書を表示できるので、非常に便利で時間の節約にもなります。請求書に問題がないので、APPROVEボタンをクリックします。
REST APIを用いたプロセスインスタンスの確認
この時点で、多くのソリューションの基礎であるREST APIを少々見た方が有用かもしれません。
まず、アプリサーバー情報を取得します。
API呼び出し(GET):http://localhost:8080/activiti-app/api/enterprise/app-version
結果:
作業中のプロセスインスタンスをフェッチします。
API呼び出し(GET):http://localhost:8080/activiti-app/api/enterprise/process-instances/65001
結果:
この場合、プロセスIDは65001で、Activiti Webappの多くのURLに表示されています。
この時点でプロセス変数を設定します。
API呼び出し(GET):http://localhost:8080/activiti-app/api/enterprise/process-instances/65001/variables
結果:
プロセスインスタンスの現在のアクティブタスクを取得します。
API呼び出し(POST):http://localhost:8080/activiti-app/api/enterprise/tasks/query
結果:
POSTによる呼び出しでは、ChromeのPostmanなどのツールを使用します。上記の呼び出しでは、Authorizationタブで許可証明書を作成しました。
Prepare Paymentタスクの完了
プロセスインスタンスを進めていきます。フローの次のタスクはPrepare Paymentなので、Administratorに割り当てられたタスクはもうありません。Processesメニューアイテムをクリックします。
Prepare Paymentタスクは、作成したAccountingグループのプールタスクです。このグループにAdministratorを追加しました。そのため、メニューでTasksをクリックするとタスクが表示されそうですが、タスクは表示されません。
これは、このタスクがまだ誰にも割り当てられていないプールタスクであるためです。このタスクはAccountingグループのメンバーであれば誰でも取得できます。担当者など、各種タスクの説明で触れましたが、キュータスクは割り当てが行われていないタスクなので、左のメニューでQUEUEDTASKSをクリックします。
これでタスクが表示されます。まず、他のグループメンバーのQUEUED TASKSリストからこのタスクを削除します。これはCLAIMボタンをクリックして、申し出ることで実行できます。
これで、この請求書の支払い準備が可能になりました。この時点でこのタスクへの申し出が誤りであり、他のメンバーが処理を行うべきと判断した場合、REQUEUEボタンを押して、タスクをキュータスクに戻すことができます。
タスクを実行することに問題がない場合は、タスク完了時にCOMPLETEボタンをクリックします。その結果、Eメールが次のようにFake SMTPクライアントに送信されます。
これでビジネスプロセスインスタンスが完了します。完了したビジネスプロセスは、ProcessesページのCOMPLETEDの下に表示されます。ここでは、ビジネスプロセスで行われたすべてのステップと実施者の監査ログをダウンロードできます。
Rejected Invoiceフローの実行
Rejected invoiceのパスが機能するかも確認してみましょう。新しいInvoice Approvalワークフローインスタンスを起動し、Approve InvoiceタスクでREJECTをクリックします。
請求書に関する懸念事項をコメントに入力し、 いずれかのREJECTボタンをクリックします。この時点で、Clarify Invoiceタスクが開始者に割り当てられます。Processesメニューアイテムをクリックし、次に画面左側のRUNNINGリンクをクリックすると次の画面が表示されます。
Clarify Invoiceタスクがアクティブタスクに加わり、ワークフローインスタンスを開始したAdministratorに正しく割り当てられたことが確認できます。画面右上のSHOW DIAGRAMボタンをクリックすると、ワークフローパスのどこにいるのかを確認できます。
ダイアグラムビューを閉じ、ACTIVE TASKSリストでClarify Invoiceタスクをクリックします。
ApproverからのメッセージがCommentsフィールドに表示されています。Clarificationにメッセージを入力し、CLARIFIEDボタンをクリックすると、再度Approve InvoiceタスクがApproverに割り当てられます。画面上部のメニューでTasksをクリックし、画面左側のナビゲーションでMY TASKSをクリックします。
追加された説明メッセージが表示されます。APPROVEをクリックして、ワークフローのApprovedパスに進みます。次にQUEUED TASKSをクリックし、プールされたPrepare Paymentタスクを確認します。タスクの実行を申し出、完了します。
これでワークフローインスタンスが終了します。
ビジネスプロセスの改善
すべてのプロセスやアプリケーションがそうであるように、新しいビジネス要件などによって状況は頻繁に変化します。このセクションでは、プロセスにいくつかの更新を行い、再公開を行います。その後、新しいバージョンのプロセスを試します。
File Invoiceタスクを更新してファイルを保存
File Invoiceサービスタスクの初回の実装では、わずかな ロギングしか行わず、Stringクラスフィールドに容易にアクセスできることが示されました。ここでは、サービスタスク実装から請求書ファイルにアクセスし、ファイルシステムまたは必要に応じて別のシステムに保存していきます(こちらで最新のサービスタスク実装用のソースコードを入手できます)。
次のように、渡されるExpression変数を用いて請求書ファイルにアクセスすることはできません。
public void setInvoiceToFile(Expression invoiceToFile) { this.invoiceToFile = invoiceToFile; }
実際、invoicetobeapprovedプロセス変数には、ファイルのDB IDのみが含まれています。これはパフォーマンス上の理由によるものです。実際のファイルにアクセスする際に使用する、RelatedContentServiceという専用のActivitiサービスがあります。このサービスは、次のようにサービスタスク実装につながっている必要があります。
public class FileInvoiceServiceTaskDelegate implements JavaDelegate { private static Logger logger = LoggerFactory.getLogger(FileInvoiceServiceTaskDelegate.class); /** * Used to access content files related to the workflow instance */ @Autowired RelatedContentService relatedContentService;
ただし、これはクラスにつながっているSpring Beanであるため、システムによるスキャンと検出が可能なSpring Beanである必要があります。このためには、2つのことを行う必要があります。1つは、Spring Componentとして注釈する必要があるサービスクラスの 設定、もう1つは、実際にスキャンされるJavaパッケージでの定義です。サービスタスク実装が定義されるJavaパッケージは、現在スキャンされていません。クラスは次のように更新する必要があります。
package com.activiti.extension.bean; import com.activiti.service.runtime.RelatedContentService; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.JavaDelegate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class FileInvoiceServiceTaskDelegate implements JavaDelegate { private static Logger logger = LoggerFactory.getLogger(FileInvoiceServiceTaskDelegate.class); /** * Used to access content files related to the workflow instance */ @Autowired RelatedContentService relatedContentService;
Bean用にスキャンされる新しいパッケージ、com.activiti.extension.beanに注目してください。また、クラスは@Componentで注釈が付けられています。これで次のようにコンテンツを取得できます。
package com.activiti.extension.bean; import com.activiti.content.storage.api.ContentObject; import com.activiti.domain.runtime.RelatedContent; import com.activiti.service.runtime.RelatedContentService; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.JavaDelegate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; @Component public class FileInvoiceServiceTaskDelegate implements JavaDelegate { private static Logger logger = LoggerFactory.getLogger(FileInvoiceServiceTaskDelegate.class); private static final String INVOICE_FILE_VAR_NAME = "invoicetobeapproved"; @Autowired RelatedContentService relatedContentService; private Expression companyEmail; public void setCompanyEmail(Expression companyEmail) { this.companyEmail = companyEmail; } public void execute(DelegateExecution execution) throws Exception { logger.info("Storing the invoice file somewhere safe!"); String emailAddress = (String) companyEmail.getValue(execution); logger.info("The invoice was sent in from: " + emailAddress); List<RelatedContent> contentList = relatedContentService.getFieldContentForProcessInstance( execution.getProcessInstanceId(), INVOICE_FILE_VAR_NAME, 1, 0).getContent(); if (contentList != null) { for (RelatedContent relCon : contentList) { logger.info("Content file: " + relCon.getName() + ", created: " + relCon.getCreated()); ContentObject co = relatedContentService.getContentStorage().getContentObject( relCon.getContentStoreId()); // Get the InputStream and do stuff with the file // co.getContent() } } } }
ここでプロセス定義を更新し、SpringのBeanとなった新しいタスク実装を使用します。Kickstart Appをクリックし、次に、Invoice Approval Process Modelにカーソルを置くと表示されるVisual Editorボタンをクリックします。
これによりBPMNエディタが直接表示されます。
File Invoiceタスクをクリックし、Class名を削除して、Spring Bean名をDelegate expressionプロパティに式として入力します(例:${fileInvoiceServiceTaskDelegate})。Component注釈で指定していない場合、Beanの名前がクラス名(最初の文字は小文字)になります。
モデルを保存し、BPMNエディタを閉じます。
重要!プロセスモデルのバージョン1で動作するプロセスインスタンスがある場合、サーバーを停止し、File Invoiceサービスタスク実装が更新された新しい拡張JARを組み込むと問題が発生します。バージョン1のプロセスインスタンスは、org.alfresco.training.activiti.task.FileInvoiceServiceTaskDelegateクラスがクラスパスで引き続き使用できると想定しています。使用できない場合、プロセスインスタンスは失敗またはクラッシュします。そのため、一定期間、両方のサービスタスク実装を共存させなければならない可能性があります。
タスク名を更新して請求書名を反映しエスカレーション
このワークフローを実際に本番環境にデプロイすると、どのタスクがどの請求書に関連しているかをユーザーが判断することは困難でしょう。ユーザーは、タスク名から関連する請求書を判断することができません。また、Prepare Paymentタスクがエスカレーションされると、ユーザーはタスク名を確認できません。
タスクがエスカレーションされた場合に、その名前がはっきりわかれば(例:ESCALATED - Prepare Payment...)、迅速な対応が必要なタスクであることがユーザーにとって明確になります。
タスクの名前を変更するには、 nameタスクプロパティを更新する必要があります。これは、一般的にいわゆるタスクリスナーを介して行います(この情報に関する完全版マニュアルは、こちらのページを参照してください)。
タスクリスナーは、サービスタスクのタスクデリゲートクラスと同じように実装されます。ただし、タスクの周期イベントにおいて1回以上実行することができます。
- Create:タスクが作成されるとき
- Assignment:タスクがユーザーに割り当てられるとき
- Completed:ユーザーがタスクを完了するとき
- Deleted:タスクインスタンスが削除されるとき
今回は複数のユーザータスクのタスク名に請求書ファイル名を使用するため、プロセスの最初にこのファイル名を引き出すのが合理的です。たとえば、Approveタスクに入ったときにこれを行い、この名前をプロセス変数に設定すると、Clarify InvoiceユーザータスクやPrepare Paymentユーザータスクで再度使用できます。
Approve Invoiceタスクをクリックし、Task listenersプロパティをクリックします。
以下のダイアログが開き、タスクリスナーを追加できます。
今回のケースでは、タスクが作成(Create)されたときにタスク名を更新します。スクリプトを用いてタスク名を設定できます。これは、org.activiti.engine.impl.bpmn.listener.ScriptTaskListenerというビルトインのタスクリスナー実装を用いて実行できます。
次に、スクリプトコードがscriptという名前でフィールドを通じて挿入されます。また、使用するスクリプト言語を指定するlanguageというフィールドも必要です。今回のケースではJavascriptを使用します。ただし、Groovyなど、他のスクリプト言語を使用する可能性もあります。
Javaではなく、スクリプトで作業を開始する場合、両方のメリットとデメリットについて考える価値があります。
Java
メリット:デバッグとテストが簡単で、ほとんどの場合高速であり、コードの再利用、コード補完、保護が容易。アクティブなプロセスインスタンス用にコードを変更できます。
デメリット:開始に手間がかかるため、拡張プロジェクトが必要です。JRebelなどを使用しない限り、新しいバージョンをインストールするためにサーバーを停止する必要があります。
スクリプト
メリット:非常に簡単に始められ、BPMNエディタから離れる必要がありません。他のツールが不要で、サーバーの再起動も不要です。
デメリット:スクリプトの変更をアクティブプロセスインスタンスが使用できず、セキュリティリスクになる可能性があります(ただし、いわゆるセキュアスクリプトリスナーが最近リリースされ、特定のセキュリティリスクに対処できるようになっています)。問題のデバッグが困難で、ランタイム中最初にエラーを確認したようにエラーが発生しやすく、テストの作成が容易ではありません。
この結果として生じたBPMN 2 XMLは、以下のようなものです。
<userTask id="approveInvoice" name="Approve Invoice" activiti:async="true" activiti:exclusive="false" activiti:assignee="${taskAssignmentBean.assignTaskToAssignee('approver', execution)}" activiti:formKey="3"> <extensionElements> ... <activiti:taskListener event="create" class="org.activiti.engine.impl.bpmn.listener.ScriptTaskListener"> <activiti:field name="script"> <activiti:string> <![CDATA[ var execution = task.getExecution(); var contentList = relatedContentService.getFieldContentForProcessInstance( execution.getProcessInstanceId(), 'invoicetobeapproved', 1, 0).getContent(); var invoiceFileName = ' - [UNKNOWN]'; if (typeof contentList != 'undefined' && contentList.length > 0) { invoiceFileName = ' - [' + contentList.get(0).getName() + ']'; } execution.setVariable('invoiceFileName', invoiceFileName); task.name = "Approve Invoice " + invoiceFileName;]]> </activiti:string> </activiti:field> <activiti:field name="language"> <activiti:string><![CDATA[javascript]]></activiti:string> </activiti:field> </activiti:taskListener> ... </extensionElements> </userTask>
ここでは、最初にタスクオブジェクトからexecution環境のインスタンスを取得しています。JavaScriptの実行オブジェクトはタスクリスナーから直接アクセスできません。次に、RelatedContentService Spring Beanを使用して、渡すフィールドのコンテンツを取得します。開始フォームで作成したinvoicetobeapprovedというフィールドです。Activiti ServiceのBeanの多くには、直接スクリプトコードでアクセスできます。通常、Beanクラス名(最初の文字は小文字)がBeanインスタンスのIDとして機能します。
コンテンツオブジェクトからファイル名を取得すると、ファイル名はinvoiceFileNameというプロセス変数に保存され、後でそれを必要とするユーザータスクで使用されます。最後に行うのはタスク名の更新で、請求書ファイル名がタスク名に含まれるようにします。
Prepare Paymentタスクリスナーは次のように表示されます。
タスクリスナーの設定はApprove Invoiceタスクと同じですが、唯一スクリプトのみが異なります。また、タスクがエスカレーションされたかを確認し、エスカレーションされた場合はタスク名に「ESCALATED」という接頭辞が付きます。BPMN 2.0 XMLでは次のようになります。
<userTask id="preparePayment" name="Prepare Payment" activiti:candidateGroups="1001" activiti:formKey="1001"> <extensionElements> <activiti:taskListener event="create" class="org.activiti.engine.impl.bpmn.listener.ScriptTaskListener"> <activiti:field name="script"> <activiti:string><![CDATA[ var execution = task.getExecution(); var isEscalated = execution.getVariable('preparePaymentEscalated'); var invoiceFileName = execution.getVariable('invoiceFileName'); var taskDescription = "Prepare Payment for " + invoiceFileName; if (typeof isEscalated != 'undefined' && isEscalated == true) { taskDescription = "ESCALATED: " + taskDescription; } task.name = taskDescription;]]> </activiti:string> </activiti:field> <activiti:field name="language"> <activiti:string><![CDATA[javascript]]></activiti:string> </activiti:field> </activiti:taskListener> ... </extensionElements> </userTask>
スクリプトでは、preparePaymentEscalatedというプロセス変数が使用できると仮定し、タスクがエスカレーションされた場合にこれを示すためtrueに設定されていることがわかります。変数は明らかにどこかに設定する必要があります。最もわかりやすい場所は、タイマー終了時のタイマーからの遷移です。
これを行うには、いわゆる実行リスナーを使用する必要があります(この情報に関する完全版マニュアルは、こちらのページを参照してください)。
Escalate taskタイマーからPrepare Paymentユーザータスクへの遷移をクリックし、次にExecution Listenersプロパティをクリックします。
ダイアログが表示され、遷移が行われる際に実行リスナーが実行されるよう設定できます。
「take」に設定されているEventプロパティと、新しいクラス(org.activiti.engine.impl.bpmn.listener.ScriptExecutionListener)に注目してください。スクリプトはシンプルで、preparePaymentEscalated変数を「true」に設定するだけです。
BPMN 2.0 XMLでは次のようになります。
<sequenceFlow id="sid-E174B2BB-83BF-4443-893A-A411488FE30A" name="Escalate" sourceRef="escalatePreparePayment" targetRef="preparePayment"> <extensionElements> <activiti:executionListener event="take" class="org.activiti.engine.impl.bpmn.listener.ScriptExecutionListener"> <activiti:field name="script"> <activiti:string><![CDATA[execution.setVariable('preparePaymentEscalated', true);]]></activiti:string> </activiti:field> <activiti:field name="language"> <activiti:string><![CDATA[javascript]]></activiti:string> </activiti:field> </activiti:executionListener> ... </extensionElements> </sequenceFlow>
Clarify Invoiceタスクは、タスク名に請求書ファイル名を表示すように設定することもできます。
新バージョンのInvoice Approvalアプリケーションの公開
更新した新しいプロセス定義を使用できるようにするには、新しいバージョンのInvoice Approvalアプリケーションを公開し、さらに新しいバージョンのInvoice Approvalプロセスも間接的に公開する必要があります。下図では、バージョン2のInvoice Approvalアプリケーションを扱っていることがわかります。
バージョン2を公開するには、画面右上のPublishボタンをクリックします。
更新したプロセスの実行
新しいプロセスを実行するには、すべての新しい要素で拡張JARを更新する必要があります。これと同じようにJARを構築してコピーします(JARを構築できない場合は、こちらからコピーしてください)。
martin@gravitonian:/opt/activiti15/tomcat/webapps/activiti-app/WEB-INF/lib$ cp ~/src/sdk3/alfresco-sdk-tests/activiti-jar-blog/target/activiti-jar-blog-1.0-SNAPSHOT.jar .
次に新しいプロセスを開始します。請求書ファイル情報を含むApproveタスク名が次のように表示されます。
どの請求書とタスクが関連しているのかがわかりやすくなっています。このタスクを完了し、少し待つと、Prepare Paymentタスクが新しいタスク名でエスカレーションされるのが確認できます。
プロセスを完了すると、Filingサービスタスクから以下のようなログが表示されます。
03:42:11,135 [http-nio-8080-exec-1] INFO com.activiti.extension.bean.FileInvoiceServiceTaskDelegate - Storing the invoice file somewhere safe! 03:42:11,136 [http-nio-8080-exec-1] INFO com.activiti.extension.bean.FileInvoiceServiceTaskDelegate - The invoice was sent in from: some@company.com 03:42:11,139 [http-nio-8080-exec-1] INFO com.activiti.extension.bean.FileInvoiceServiceTaskDelegate - Content file: invoice - 2016-10-039.pdf, created: 2016-10-25 15:35:03.798
まとめ
この記事では、Activitiビジネスプロセス管理製品のエンタープライズエディションであるAlfresco Activitiの使い方を紹介してきました。Activitiでビジネスプロセスを設計および実装できるWebツールが非常に強力であることも見てきました。Web UIから作業することで、ほとんどの場合手動でXMLをコーディングするよりも大幅に時間を節約でき、エラーも発生しにくくなります。
この記事の最初から最後までの手順に従った読者の多くが、初期設計と実装の終了後、非常に速やかにプロセスの実行を実現できたはずです。ほとんどがWeb UIから操作でき、実行時ではなく設計や実装中にすべてを検証できることがいかに強力であるか、私自身も驚きました。
この記事では、確かに基本的な要素のみを取り扱っており、デシジョンテーブル、データモデル、RESTステップ、フォーム/信号/メッセージ/サブプロセス/イベントへのJavaScriptの埋め込みなどについては触れませんでした。こうした要素も説明すると、入門ガイドの範疇ではなくなるためです。
リックソフト株式会社 は、日本でトップレベルのAtlassian Platinum Solution Partnerです。
大規模ユーザーへの対応実績が認められたEnterpriseの認定をうけ、高度なトレーニング要件をクリアし、小規模から大規模のお客様まで対応可能な実績を示したパートナー企業です。
Copyright © Ricksoft Co., Ltd. プライバシーポリシー お問い合わせ