SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

近未来の技術トレンドを先取り! 「Tech-Sketch」出張所

オープンソースのワークフローエンジン「Activiti」チュートリアル

近未来の技術トレンドを先取り! 「Tech-Sketch」出張所 第9回

5)交通費申請照会画面:[承認]ボタン押下処理の実装

 tutorial.action.paperwork.TransportationInquiryAction#doApproveメソッド内を、以下のようにコーディングしてください。

// ----------------------------------------------------------------------
// TODO ActivitiのAPIを使って承認処理を実装してください。
// ----------------------------------------------------------------------

// [STEP1] この申請に関して、実行可能かつアクティブなタスクを取得します。
Task task = taskService
    .createTaskQuery()
    .taskAssignee(userLoginDto.userId)
    .processInstanceBusinessKey(
        transportationInquiryForm.transportationId)
    .active()
    .singleResult();

if (task == null) {
    saveError("errors.haita");
    return "transportationInquiry.jsp";
}

// [STEP2] フロー分岐の情報(flowCtrl=APPROVE)を設定し、タスクを完了します。
Map<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("flowCtrl", "APPROVE");
taskService.complete(task.getId(), variableMap);

// [STEP3] このプロセスの終了状態に応じて、承認状況を設定します。
HistoricProcessInstance historicProcessInstance = historyService
    .createHistoricProcessInstanceQuery()
    .processInstanceId(task.getProcessInstanceId())
    .finished()
    .singleResult();
if (historicProcessInstance == null) {
    // 完了していない→「01:申請中」のまま
    transportation.approvalState = "01";
} else {
    // 完了している→「02:承認済み」とする
    transportation.approvalState = "02";
}

// ----------------------------------------------------------------------
// ここまで
// ----------------------------------------------------------------------

コードの解説

[STEP1]

 taskService(ActivitiのAPI)を使用して、ログインしているユーザーが実行可能かつアクティブなタスクを取得しています。

 TaskQueryというタスクに関する情報を、さまざまな条件で取得することができるAPIを使用しています。

 「流れるようなインターフェース」と呼ばれる"文章を記述していくようにメソッドを呼び出していく手法"でコーディングします。

  • taskAssignee(userLoginDto.userId)=「ログインユーザーが実行可能なタスク」という条件
  • processInstanceBusinessKey(transportationInquiryForm.transportationId)=「この申請データと紐づくタスク」という条件
  • active()=「現在アクティブなタスク」という条件
  • singleResult()=「条件に一致するタスクを1件取得する」というメソッドの実行

 「if (task == null) { ・・・」の部分は、他のユーザーによって承認/却下が行われた場合にアクティブなタスクを取得できない可能性があることを考慮しています。

[STEP2]

 「承認」「却下」によってシーケンスフローが分岐しますので、どちらのシーケンスフローに流れるべきかの情報をflowCtrlという変数名で設定しています。

 プロセス定義ファイル上のシーケンスフローの条件プロパティに「${flowCtrl='APPROVE'}」と「${flowCtrl='REJECT'}」を設定しましたが、この条件をMapで設定しています。

 taskService#completeは、タスクを完了させるメソッドです。

 第1引数にタスクIDを、第2引数に上で設定したMapを渡しています。

[STEP3]

 交通費申請テーブルにある「承認状況」のカラムを適切に更新するために、historyService(ActivitiのAPI)を使用して、この交通費申請プロセスの完了状態をチェックしています。

 庶務確認タスクで承認されても、マネージャー承認待ちのときは、「申請中」という承認状況のままにしたいためです。

 ここでは、HistoricProcessInstanceQueryのAPIを使って、Activiti側で管理されているプロセスの情報を取得し、完了状態をチェックしています。

  • processInstanceId(task.getProcessInstanceId())=「今承認したタスクのプロセスID」を指定
  • finished()=「完了したプロセス」という条件
  • singleResult()=「条件に一致するタスクを1件取得する」というメソッドの実行

6)交通費申請照会画面:[却下]ボタン押下処理の実装

 tutorial.action.paperwork.TransportationInquiryAction#doRejectメソッド内を以下のようにコーディングしてください。

// ----------------------------------------------------------------------
// TODO ActivitiのAPIを使って却下処理を実装してください。
// ----------------------------------------------------------------------

// [STEP1] この申請に関して、実行可能かつアクティブなタスクを取得します。
Task task = taskService
    .createTaskQuery()
    .taskAssignee(userLoginDto.userId)
    .processInstanceBusinessKey(
        transportationInquiryForm.transportationId)
    .active()
    .singleResult();

if (task == null) {
    saveError("errors.haita");
    return "transportationInquiry.jsp";
}

// [STEP2] フロー分岐の情報(flowCtrl=REJECT)を設定し、タスクを完了します。
Map<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("flowCtrl", "REJECT");
taskService.complete(task.getId(), variableMap);

// ----------------------------------------------------------------------
// ここまで
// ----------------------------------------------------------------------

コードの解説

[STEP1]

 taskService(ActivitiのAPI)を使用して、ログインしているユーザーが実行可能かつアクティブなタスクを取得しています。

  • taskAssignee(userLoginDto.userId)=「ログインユーザーが実行可能なタスク」という条件
  • processInstanceBusinessKey(transportationInquiryForm.transportationId)=「この申請データと紐づくタスク」という条件
  • active()=「現在アクティブなタスク」という条件
  • singleResult()=「条件に一致するタスクを1件取得する」というメソッドの実行
[STEP2]

 ここでは、「却下」のシーケンスフローに流れたいため、flowCtrl='REJECT'をMapに設定しています。

7)交通費申請照会画面:[承認][却下]ボタン非表示処理の実装

 交通費申請データの承認/却下を実行できるユーザーは、申請データごと異なります。

 承認/却下を実行できないユーザーが本画面を表示したときは、[承認][却下]ボタンを非表示にする処理を実装してみましょう。

 tutorial.action.paperwork.TransportationInquiryAction#indexメソッド内を以下のようにコーディングしてください。

// ----------------------------------------------------------------------
// TODO ActivitiのAPIを使って[承認][却下]ボタンを
// 非表示にする処理を実装してください。
// ----------------------------------------------------------------------

// この申請に関して、実行可能かつアクティブなタスクを取得します。
Task task = taskService
    .createTaskQuery()
    .taskAssignee(userLoginDto.userId)
    .processInstanceBusinessKey(
        transportationInquiryForm.transportationId)
    .active()
    .singleResult();
if (task == null) {
    // アクティブなタスクがない→[承認][却下]ボタンは非表示とします。
    transportationInquiryForm.approvable = false;
} else {
    // アクティブなタスクがある→[承認][却下]ボタンを表示します。
    transportationInquiryForm.approvable = true;
}

// ----------------------------------------------------------------------
// ここまで
// ----------------------------------------------------------------------

コードの解説

 画面表示が行われる前に、ログインユーザーが[承認][却下]を実行可能かをチェックし、ボタンの表示/非表示を制御しています。

 transportationInquiryForm.approvableのプロパティは、JSP側で参照しています。

/transportation/src/main/webapp/WEB-INF/view/paperwork/transportationInquiry/transportationInquiry.jsp
<c:if test="${approvable}" >
  <input type="submit" class="input-button" name="doApprove" value="承認" />
  <input type="submit" class="input-button" name="doReject" value="却下" />
</c:if>

8)交通費申請アプリ(完成版)の動作確認

 以下のテストケースをもとに動作確認をしましょう。

  • kagawaで申請→messiで承認→xaviで承認
    • 承認状況は、「申請中」→「承認済み」と遷移することを確認
    • [承認][却下]ボタンの表示制御が正しいことを確認
  • kagawaで申請→messiで承認→xaviで却下
    • 承認状況は、「申請中」→「却下」と遷移することを確認
    • [承認][却下]ボタンの表示制御が正しいことを確認
  • kagawaで申請→messiで却下
    • 承認状況は、「申請中」→「却下」と遷移することを確認
    • [承認][却下]ボタンの表示制御が正しいことを確認

次のページ
4.業務データとActiviti側のデータを跨いだトランザクション管理の実現

この記事は参考になりましたか?

近未来の技術トレンドを先取り! 「Tech-Sketch」出張所連載記事一覧

もっと読む

この記事の著者

佐藤 政美(TIS株式会社)(サトウ マサミ)

TIS株式会社 コーポレート本部 戦略技術センター所属。 TISのアプリケーション開発基盤『Xenlon~神龍』の開発および導入支援を中心に活動中。オープンソースのライブラリを活用し、アプリケーションを素早く構築することに興味があり、「開発現場に喜ばれるモノを提供したい!」と日々、Xenlonの改良・機能...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7495 2013/11/27 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー