Java Activiti User Guide Digest

JavaActivitiUserGuideDigest

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 46

DownloadJava Activiti User Guide Digest
Open PDF In BrowserView PDF
2018/7/4

Java Activiti User Guide Digest - @//メモ

Java Activiti User Guide Digest
1. Introduction

2018-0703

2. Getting Started

2018

3. Configuration

July

3.18. Event handlers

3.16. Loggin
4. The Activiti API

Week 27

4.1~4.3 ワークフローを実⾏するコンソールアプリ

Day 03
Tue

4.3.4.プロセスの Suspend と Activate
4.4 Query API
4.5.Variables
4.7 Unit Test

⽬次

4.9 The process engine in a web application
6. Deployment

FrontPage
・さくらVPS
・Fedora13
・SuSe10
・Docker
・Ansible
・Java
・Scala
・Python
・Ruby
・Lisp
・Computer
・GIS
・HTML
・Culture
・Random
・Link

7.標準 BPMN 2.0
8.Activiti 拡張 BPMN 2.0
8.2.Event
8.3 Sequence Flow
8.4 Gateways
8.5 Task
8.15.12.Execution listener
8.5.13. Task listener
8.5.14 Multi-instance (for each)
8.6. Sub-Processes and Call Activities
9. Form
11.History
13. Activiti Explorer 14. Modeler
15. REST API

↑

訪問者

本家 : http://www.activiti.org/userguide/

total: 5611
today: 21

1. Introduction

yesterday: 11

†

now: 4
↑

更新
最新の10件

Activiti 本体 Apache License V2
Activiti Modeler LGPL 2.1
http://activiti.org/download.html
https://github.com/Activiti/Activiti
JDK6+
Eclipse designer plugin

2018-07-02
Python
http://www.eclipse.org/downloads/ (最新の Mars でも OK だった)
CuPy on
http://activiti.org/designer/update/ (Plugin Repository)
MacBookPro
↑
Python
†
2018-06-28
2. Getting Started
Thought 逆
伝搬について
Tutorial
の整理
2018-06-25
Java6 + Tomcat + Activiti-Explorer
Random
Demo database setup flag
Memorandum
2018Q1
Activiti Explorer や Rest API では、後述する標準の activiti.cfg.xml の代わりに db.properties,
2018-06-24
engine.properties でアプリケーションの設定を⾏う
Mac 数式の⼊
WEB-INF/classes/db.properties
った資料を作
る
db=h2
OmniGraffle+LaTeXiT 1
2
jdbc.driver=org.h2.Driver
2018-06-23
3
jdbc.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
Mac
4
jdbc.username=sa
2018-06-12
5
jdbc.password=
Books 深層
学習 Deep
WEB-INF/classes/engine.properties
Learning
2018-06-07
1
# demo data properties
Thought テ
2
create.demo.users=true
ンソル
3
create.demo.definitions=true
2018-05-30
4
create.demo.models=true
Culture
5
create.demo.reports=true
Python
6
Matplotlib
7
# engine properties
https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

1/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

8
9
10
11
12
13
14
15
16
17

⼈気の10件

engine.schema.update=true
engine.activate.jobexecutor=false
engine.asyncexecutor.enabled=true
engine.asyncexecutor.activate=true
engine.history.level=full

FrontPage(431163)
Maven
Eclipseとの
連携(72491)
# email properties
Jakarta
#engine.email.enabled=true
log4j.xml
#engine.email.host=localhost
に設定するロ
#engine.email.port=1025
グレベルの整
理(67255)
VBAの基本構
⽂(60656)
3. Configuration †
Win32 Trac
Lightning(54708)
独⾃の Workflow アプリ ⇒ ProcessEngine? を使ってワークフローを操作
Jakarta
POI(45451)
JavaSE RSA
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
暗号(41483)
Java(40691)
デフォルト設定では Classpath にある activiti.cfg.xml または activiti-context.xml の設定に基づいて
OpenAM
ProcessEngine? が作られる
Wordpress
(設定内容をプログラム内で明⽰的に設定することも可。後述)
との SAML
連携(37622)
activity.cfg.xml
OpenAM イン
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/resources/activiti.cfg.xml
ストール

↑

(37126)

↑

MenuBar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63













-->








Spring の bean.xml 形式だが、⽂法を借りているだけ。Activiti に Spring が必須ではない
JNDI から Datasource を lookup して利⽤することも可能
Activiti Explorer、 Activity Rest API は、db.properties で接続先を設定するようになっている。→
内部的には、その他の ProcessEngine 作成⽅法
その他の ProcessEngine 作成⽅法
1. 設定ファイルを明⽰する
ProcessEngine processEngine
= ProcessEngineConfiguration
.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()
2. プログラム中で設定を⾏う (Activiti-Explorer、Activiti-Rest はこのやり⽅)
デフォルト設定
ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
デフォルト設定に個別設定を追加
ProcessEngine processEngine
= ProcessEngineConfiguration
.createStandaloneInMemProcessEngineConfiguration()
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
.setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
.setAsyncExecutorEnabled(true)
.setAsyncExecutorActivate(false)
.buildProcessEngine();
ProcessEngine? は、Singleton。設定ファイルを読み直すには
ProcessEngine.destory();
ProcessEngine.init();
を実⾏する必要あり
↑

3.16. Loggin

†

Activiti は SLF4J にログを書いている
SLF4J は、出⼒先がないときは NOP-logger にログを送っているので、結果的にログは出ない
SLF4J 推奨の logback を Classpath に追加すれば logback からログが出る
pom.xml

ch.qos.logback
logback-classic

log4j でログを出⼒させるときには SLF4J-log4j ブリッジを Classpath に追加すれば良い
pom.xml

org.slf4j
slf4j-log4j12

Activiti Explorer、 Activity Rest API はこの⽅式
Spring (commons-loggin) に統合したいときは
pom.xml

org.slf4j
jcl-over-slf4j

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

3/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

Activiti は、SLF4J の Mapped Diagnostic Contexts に、実⾏中のワークフローの情報を詰め込んでいるので、
ログ出⼒の設定(logback.xmlなど)で適宜拾うことができる → 【留意点あり】

true

%date [%thread] %highlight(%-5level) %-20logger{20} %mdc{mdcProcessDefinitionID} %msg %



processDefinition Id as mdcProcessDefinitionID
processInstance Id as mdcProcessInstanceID
execution Id as mdcexecutionId
【留意点】
実装は、http://activiti.org/javadocs/org/activiti/engine/logging/LogMDC.html
Activiti の本体コードを⾒てみると、タスク開始時に⼀律 MDC にタスク情報が設定されて、終了時にクリア
されるわけではないらしい。最初そう思ってうまく⾏かず、⾊々調べてみた。
どうやら、例外発⽣時に MDC にプロセス情報が設定されるようだ。きっと、障害解析⽤の仕組みなんだろう
業務ログとしてこういう情報が欲しければ、⾃前で 3.18. Event handler を作って MDC にタスク情報を格
納する必要あり
LogMDC.putMDCExecution(ActivityExecution? e) の引き数は、Activiti の内部クラス
org.activiti.engine.impl.pvm.delegate.ActivityExecution? であり、ユーザプログラムからは取
得できない。LogMDC を強制初期化するようなユーザプログラム (イベントハンドラ) は作ることが出来ない
↑

3.18. Event handlers

†

ProcessEngine? の起動・停⽌、JOB の開始・終了イベントをフックできる
3.18.6. Supported event types
EventListener? は ProcessEngine? のインスタンスのもちもの。DBを共有して同じJOBを⼆つの
ProcessEneigne? をまたいで実⾏した場合、それぞれの EventLister? はそれぞれの ProcessEngine? (の
実⾏環境にある activiti.cfg.xml) に定義されているもの
EventListener? 実装
インタフェース org.activiti.engine.delegate.event.ActivitiEventListener? を実装する
3.18.1. Event listener implementation
EventListener? 定義
activiti.cfg.xml に定義する
全イベントを拾う 3.18.2. Configuration and setup
1
2
3
4
5
6
7
8








特定のイベントだけを拾う
1
2
3
4
5
6
7
8
9
10
11
12












処理中でイベントリスナを設定 3.18.3. Adding listeners at runtime
特定のプロセスだけ拾う 3.18.4. Adding listeners to process definitions
↑

4. The Activiti API

†

http://activiti.org/javadocs/index.html
アプリの中では ProcessEngine? のインスタンスは⼀つだけにする。Thread Safe になっている。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
何回 ProcessEngines?.getDefaultProcessEngine?(); を呼び出しても返ってくるインスタンスは同じ (設
定ファイルを毎回読まない)
設定ファイルを読み直すには
https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

4/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

ProcessEngine.destory();
ProcessEngine.init();
を実⾏する必要あり
ProcessEngine? から getXXXService() で、Service API を取得できる
RuntimeService?

processEngine.getRuntimeService?()

プロセス管理

RepositoryService? processEngine.getRepositoryService?() BPMN 管理。配備とか
TaskService?

processEngine.getTaskService?()

ユーザ操作の実現 (エミュレーション)

ManagementService? processEngine.getManagementService?() Activiti ⾃体の管理
IdentityService?

processEngine.getIdentityService?()

認証

HistoryService?

processEngine.getHistoryService?()

タスク処理の記録をDBに永続化

FormService?

processEngine.getFormService?()

タスク開始・終了時のユーザ確認

http://activiti.org/javadocs/org/activiti/engine/ProcessEngine.html
どのサービスもStateless ⇒ JOB管理DBが共有でもクラスタで同時実⾏可能
Exception

org.activiti.engine.ActivitiException? の⼦
http://activiti.org/javadocs/org/activiti/engine/ActivitiException.html
It's RuntimeException?.
↑

4.1~4.3 ワークフローを実⾏するコンソールアプリ

†

↑

開発環境

†

https://eclipse.org/ 最新版(2015時点)のMarsでOK
plugin
Name

Activiti BPMN 2.0 designer

Location http://activiti.org/designer/update/

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

5/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

BPMN を GUI で編集するために Activiti BPMN 2.0 designer が必要ないのであれば Eclipse でなくてもい
い。プログラム本体を作るだけなら Java の Maven Project が扱えればどんな IDE でもいい。
↑

サンプルプロジェクト

†

普通の Maven Project
pom.xml
https://github.com/kagyuu/ActivitiExam/blob/master/pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21


4.0.0
com.snail.exam
ActivitExam
0.0.1-SNAPSHOT


org.activiti
activiti-engine
5.19.0


ch.qos.logback
logback-classic
1.1.3


com.h2database
h2

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

6/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

1.4.190






org.apache.felix
maven-bundle-plugin
2.3.7
true



org.apache.maven.plugins
maven-compiler-plugin
3.3

1.8
1.8







Alfresco Maven Repository
https://maven.alfresco.com/nexus/content/groups/public/




レポジトリに Alfresco (Activiti開発元) のレポジトリを追加
依存ライブラリに Activiti Engine を設定する
その他に、ログ出⼒⽤に logback、テスト⽤ DB に H2
↑

activiti.cfg.xml

†

ここでは、テスト⽤の Table をロードする設定(StandaloneInMemProcessEngineConfiguration?)を使う
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/resources/activiti.cfg.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46













-->







↑

テスト⽤BPMN (VacationRequest?.bpmn20.xml)

†

ActivitiExplorerのデモアプリ で使った休暇申請のワークフローを /src/main/resources/org/activiti/test に
配置

↑

Java コンソールアプリ

†

BMMNの配備(DB格納) → プロセス開始 (休暇申請) → 否決 → 再申請
の流れをやってみる
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/MyProcess.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

package com.snail.exam;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import
import
import
import
import
import
import
import
import
import
import

org.activiti.engine.ProcessEngine;
org.activiti.engine.ProcessEngines;
org.activiti.engine.RepositoryService;
org.activiti.engine.RuntimeService;
org.activiti.engine.TaskService;
org.activiti.engine.repository.ProcessDefinition;
org.activiti.engine.runtime.ProcessInstance;
org.activiti.engine.task.Task;
org.apache.commons.lang3.time.DateUtils;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class MyProcess {
private static final Logger log = LoggerFactory.getLogger(MyProcess.class);
public static void main(String[] args) {
try {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

8/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

// ----- 4.3.1. Deploying the process
log.info("--- #1. Deploying the process");
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
.deploy();
log.info("Number of process definitions {}", repositoryService.createProcessDefinitionQ
for (ProcessDefinition p : repositoryService.createProcessDefinitionQuery().list()) {
log.info("PROCESS DEF [id={},name={},key={}]", p.getId(), p.getName(), p.getKey())
}
// ----- 4.3.2. Starting a process instance
log.info("--- #2. Starting a process instance");
// VacationRequest.bpmn20.xml L3-10
// -------------------------------------------------------------------------// 
//
^^^^^^^^^^^^^^^
//

//
^^^^^^^*1
^^^^^^^^^^^^ $employeeName = the use
//

//

//

//

// arguments : 
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationReq
log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery()
for (ProcessInstance p : runtimeService.createProcessInstanceQuery().list()) {
log.info("PROCESS INSTANCE [id={},pid={},pname={},pkey={}]"
, p.getId()
, p.getProcessDefinitionId()
, p.getProcessDefinitionName()
, p.getProcessDefinitionKey());
}
// ----- 4.3.3. Completing tasks (Reject Request)
// VacationRequest.bpmn20.xml L11-21
// -------------------------------------------------------------------------//
${employeeName} would like to take ${numberOfDays} day(s) of vac
//
(Motivation: ${vacationMotivation}).
//

//

//

//

//

//
 tasks = taskService.createTaskQuery().taskCandidateGroup("management").list
for (Task task : tasks) {
if (task.getProcessDefinitionId().startsWith("vacationRequest")){
if (task.getTaskDefinitionKey().equals("handleRequest")) {
// Description is .
log.info("TASK REJECT REQ [{}]", task.getDescription());
// Do task (reject application)
Map taskVariables = new HashMap();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

9/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

}

}

}

// ----- 4.3.3. Completing tasks (Adjust rejected request)
// VacationRequest.bpmn20.xml L22-23
// -------------------------------------------------------------------------// 
// 
// Your manager has disapproved your vacation request for ${n
//
Reason: ${managerMotivation}
log.info("--- #4. Completing tasks (Adjust rejected request)");
taskService = processEngine.getTaskService();
tasks = taskService.createTaskQuery().active().list();
for (Task task : tasks) {
if (task.getProcessDefinitionId().startsWith("vacationRequest")){
if (task.getTaskDefinitionKey().equals("adjustVacationRequestTask")) {
// Description is .
log.info("ADJUST REJECT REQ [{}]", task.getDescription());
}
}
}

}

}

} catch (Throwable th) {
log.error("ERROR", th);
}

実⾏ログ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

16-03-24 00:24:21 [INFO
16-03-24 00:24:21 [INFO
16-03-24 00:24:21 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:22 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
16-03-24 00:24:23 [INFO
Reason: We have

]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
a

Initializing process engine using configuration 'file:/Users/atsushi/E
initializing process engine for resource file:/Users/atsushi/EclipseWo
Loading XML bean definitions from resource loaded through InputStream
performing create on engine with resource org/activiti/db/create/activ
performing create on history with resource org/activiti/db/create/acti
performing create on identity with resource org/activiti/db/create/act
ProcessEngine default created
initialised process engine default
--- #1. Deploying the process
Processing resource org/activiti/test/VacationRequest.bpmn20.xml
Number of process definitions 1
PROCESS DEF [id=vacationRequest:1:4,name=Vacation request,key=vacation
--- #2. Starting a process instance
Number of process instances: 1
PROCESS INSTANCE [id=5,pid=vacationRequest:1:4,pname=Vacation request,
--- #3. Completing tasks (Reject Request)
TASK REJECT REQ [Kermit would like to take 4 day(s) of vacation (Motiv
--- #4. Completing tasks (Adjust rejected request)
ADJUST REJECT REQ [Your manager has disapproved your vacation request
tight deadline!]

I got it.
↑

BPMNの配備 (RepositoryService?)
1
2
3
4
5

†

log.info("--- #1. Deploying the process");
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
.deploy()
↑

プロセス開始 (RuntimeService?)
1
2
3
4
5
6
7
8

†

Map variables = new HashMap();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("startDate", DateUtils.parseDate("1999-12-31", "yyyy-MM-dd"));
variables.put("vacationMotivation", "I'm really tired!");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variabl

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

10/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

http://activiti.org/javadocs/org/activiti/engine/RuntimeService.html
プロセスIDを指定してプロセスを開始する。⼊⼒値がある場合には Map 形式で投⼊する
RuntimeService?.startProcessInstanceByKey?(String processDefinitionId?, Map
variables) でプロセスを開始する
processDefinitionId? : BPMN の process id

variables : BPMN の  に定義された⼊⼒値






↑

タスク実⾏ (TaskService?)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

†

TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
if (task.getProcessDefinitionId().startsWith("vacationRequest")){
if (task.getTaskDefinitionKey().equals("handleRequest")) {
// Description is .
log.info("TASK REJECT REQ [{}]", task.getDescription());

}

}

}

// Do task (reject application)
Map taskVariables = new HashMap();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);

プロセスが開始されたり、タスクが実⾏されたら、後続処理は ユーザによる⼊⼒待ちまで ProcessEngine? が実⾏す
る
ユーザの⼊⼒待ちになっているタスクのリストから、今回実⾏するタスクを選んで実⾏する
manager 決済のタスクのうち
プロセスID が vacationRequest で始まり
タスクが名が handleRequest なもの
※ プロセスIDには、プロセス名に version と ⼀意ID がつく。今回の場合 "vacationRequest:1:4" となる
→ cf. 6.Deployment
http://activiti.org/javadocs/org/activiti/engine/TaskService.html
TaskServcie?.complete(String taskId, Map variables) でタスクを実⾏する。⼊⼒値が
ある場合には Map 形式で投⼊する
taskId : TaskService?.crateTaskQeury?(). ... .list() で取得したタスクのID
variables : BPMN の  に定義された⼊⼒値

${employeeName} would like to take ${numberOfDays} day(s) of vacation
(Motivation: ${vacationMotivation}).







 は task.getDescription() で取得できる
log.info("TASK REJECT REQ [{}]", task.getDescription());
↑

4.3.4.プロセスの Suspend と Activate

†

https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/MyProcess2.java

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

11/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

package com.snail.exam;
import java.util.HashMap;
import java.util.Map;
import
import
import
import
import
import
import
import
import

org.activiti.engine.ActivitiException;
org.activiti.engine.ProcessEngine;
org.activiti.engine.ProcessEngines;
org.activiti.engine.RepositoryService;
org.activiti.engine.RuntimeService;
org.activiti.engine.runtime.ProcessInstance;
org.apache.commons.lang3.time.DateUtils;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class MyProcess2 {
private static final Logger log = LoggerFactory.getLogger(MyProcess2.class);
public static void main(String[] args) {
try {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// ----- 4.3.1. Deploying the process
log.info("--- #1. Deploying the process");
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
.deploy();
// ----- 4.3.4. Suspending and activating a process
log.info("--- #2. Suspend Process");
repositoryService.suspendProcessDefinitionByKey("vacationRequest");
// ----- 4.3.2. Starting a process instance
log.info("--- #3. Starting a process instance (will fail)");
Map variables = new HashMap();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("startDate", DateUtils.parseDate("1999-12-31", "yyyy-MM-dd"));
variables.put("vacationMotivation", "I'm really tired!");
// the process to run
// id
: 
// arguments : 
RuntimeService runtimeService = processEngine.getRuntimeService();
try {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacation
} catch (ActivitiException e) {
log.error("ERROR", e);
}
// ----- 4.3.4. Suspending and activating a process
log.info("--- #5. Activate Process");
repositoryService.activateProcessDefinitionByKey("vacationRequest");
log.info("--- #6. Starting a process instance (will success)");
try {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacation
log.info("{} was started", processInstance.getProcessDefinitionId());
} catch (ActivitiException e) {
log.error("ERROR", e);
}

}

}

} catch (Throwable th) {
log.error("ERROR", th);
}

実⾏ログ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

16-03-25 01:12:03 [INFO ] Initializing process engine using configuration 'file:/Users/atsushi/E
16-03-25 01:12:03 [INFO ] initializing process engine for resource file:/Users/atsushi/EclipseWo
16-03-25 01:12:03 [INFO ] Loading XML bean definitions from resource loaded through InputStream
16-03-25 01:12:04 [INFO ] performing create on engine with resource org/activiti/db/create/activ
16-03-25 01:12:04 [INFO ] performing create on history with resource org/activiti/db/create/acti
16-03-25 01:12:05 [INFO ] performing create on identity with resource org/activiti/db/create/act
16-03-25 01:12:05 [INFO ] ProcessEngine default created
16-03-25 01:12:05 [INFO ] initialised process engine default
16-03-25 01:12:05 [INFO ] --- #1. Deploying the process
16-03-25 01:12:05 [INFO ] Processing resource org/activiti/test/VacationRequest.bpmn20.xml
16-03-25 01:12:06 [INFO ] --- #2. Suspend Process
16-03-25 01:12:06 [INFO ] --- #3. Starting a process instance (will fail)
16-03-25 01:12:06 [INFO ] Processing resource org/activiti/test/VacationRequest.vacationRequest.
16-03-25 01:12:06 [INFO ] Processing resource org/activiti/test/VacationRequest.bpmn20.xml
16-03-25 01:12:06 [ERROR] ERROR
org.activiti.engine.ActivitiException: Cannot start process instance. Process definition Vacatio
at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java
at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java
at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:24) ~[act

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

12/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

20
21
22
23
24
25
26
27
28
29
30

at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInte
at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31) ~[act
at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40) ~[a
at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35) ~[a
at org.activiti.engine.impl.RuntimeServiceImpl.startProcessInstanceByKey(RuntimeServiceImpl.
at com.snail.exam.MyProcess2.main(MyProcess2.java:49) ~[classes/:na]
16-03-25 01:12:06 [INFO ] --- #5. Activate Process
16-03-25 01:12:06 [INFO ] --- #6. Starting a process instance (will success)
16-03-25 01:12:06 [INFO ] Processing resource org/activiti/test/VacationRequest.vacationRequest.
16-03-25 01:12:06 [INFO ] Processing resource org/activiti/test/VacationRequest.bpmn20.xml
16-03-25 01:12:06 [INFO ] vacationRequest:1:4 was started
↑

4.4 Query API

†

タスクの検索
TaskQuery? と NativeTaskQuery? を使うことができる
TaskQuery?
1
2
3
4
5

List tasks = taskService.createTaskQuery()
.taskAssignee("kermit")
.processVariableValueEquals("orderId", "0815")
.orderByDueDate().asc()
.list();

NativeTaskQuery?
1
2
3
4
5
6
7
8
9

List tasks = taskService.createNativeTaskQuery()
.sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAM
.parameter("taskName", "gonzoTask")
.list();
long count = taskService.createNativeTaskQuery()
.sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, "
+ managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID
.count();

クラス図

NativeTaskQuery? の列名

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

13/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

その他の Query

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

14/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

代表的な TaskQuery? によるタスクの検索と同様に、ProcessEngine? から Service を取得して、Service から
Query を取得して、検索を⾏う。
どんな検索ができるかは Javadoc を参照
http://activiti.org/javadocs/org/activiti/engine/query/Query.html
↑

4.5.Variables

†

プロセス変数は ACT_RU_VARIABLE に格納される
アクセス⽅法
BPMN の中の EL 式
${myVar}
${myBean.myProperty} ⇔ Object も⼊れられるようだけど、⽂字列にしといたほうが無難だよね
暗黙オブジェクト
${execution}

DelegateExecution?

${task}

DelegateTask?

${authenticatedUserId?} String
Java Service Task の execution
JavaDelegate?#execution(DelegateExecution? execution)
Object execution.getVariable(String variableName);
void execution.setVariable(String variableName, Object value);
Map execution.getVariables();
RuntimeService?
Object execution.getVariable(String executionId, String variableName);
void execution.setVariable(String executionId, String variableName, Object value);
Map execution.getVariables(String executionId);
TaskSerivce?
Object execution.getVariable(String taskId, String variableName);
void execution.setVariable(String taskId, String variableName, Object value);
Map execution.getVariables(String taskId);
変数をたくさん取り出すときには、Map getVariables() を使って⼀気に取り出す。変数は RDB
のテーブルから取り出しているので、⼀気に読み書きしたほうが効率的
変数スコープ
getVariable() と getVariableLocal?() があって、変数スコープがあるようだけどよう分からん
こんな BPMN を作ってみた

B,C で setVariablesLocal?() した変数は、D,E で⾒られなかたりするのかな...と思ったけどそうでもないら
しい
各 Task では、現在の Variable を表⽰して、⾃分のタスク名の変数を setVariable() setVariableLocal?
() する
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/VariableTask.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

package com.snail.exam;
import java.util.ArrayList;
import java.util.List;
import
import
import
import

org.activiti.engine.delegate.DelegateExecution;
org.activiti.engine.delegate.JavaDelegate;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class VariableTask implements JavaDelegate {
private static final Logger log = LoggerFactory.getLogger(VariableTask.class);
@Override
public void execute(DelegateExecution execution) throws Exception {
String id = execution.getCurrentActivityName();
log.info(id);
// Dump variables
List keys = new ArrayList(execution.getVariableNames());
keys.sort((o1,o2)->{return o1.compareTo(o2);});
keys.forEach((key)->{
log.info("@{} EXEC SCOPE {} = {}", id, key, execution.getVariable(key));
});
List keysLocal = new ArrayList(execution.getVariableNamesLocal());

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

15/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

keysLocal.sort((o1,o2)->{return o1.compareTo(o2);});
keysLocal.forEach((key)->{
log.info("@{} LOCAL SCOPE {} = {}", id, key, execution.getVariableLocal(key));
});

}

}

// Update variables
execution.getVariableNames().forEach((name)->{
execution.setVariable(name, id);
});
execution.getVariableNamesLocal().forEach((name)->{
execution.setVariableLocal(name, id);
});
execution.setVariable(id + "_EXEC", id);
execution.setVariable(id + "_LOCAL", id);

実⾏結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21
16-05-21

23:38:30
23:38:30
23:38:30
23:38:31
23:38:31
23:38:31
23:38:31
23:38:31
23:38:31
23:38:31
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32
23:38:32

[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO

]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]

Initializing process engine using configuration 'file:/Users/atsus
initializing process engine for resource file:/Users/atsushi/Eclip
Loading XML bean definitions from resource loaded through InputStr
performing create on engine with resource org/activiti/db/create/a
performing create on history with resource org/activiti/db/create/
performing create on identity with resource org/activiti/db/create
ProcessEngine default created
initialised process engine default
--- #1. Deploying the process
Processing resource org/activiti/test/VariableProcess.bpmn
TaskA
@TaskA EXEC SCOPE start = Start
@TaskA LOCAL SCOPE start = Start
TaskB
@TaskB EXEC SCOPE TaskA_EXEC = TaskA
@TaskB EXEC SCOPE TaskA_LOCAL = TaskA
@TaskB EXEC SCOPE start = TaskA
TaskC
@TaskC EXEC SCOPE TaskA_EXEC = TaskB
@TaskC EXEC SCOPE TaskA_LOCAL = TaskB
@TaskC EXEC SCOPE TaskB_EXEC = TaskB
@TaskC EXEC SCOPE TaskB_LOCAL = TaskB
@TaskC EXEC SCOPE start = TaskB
TaskD
@TaskD EXEC SCOPE TaskA_EXEC = TaskC
@TaskD EXEC SCOPE TaskA_LOCAL = TaskC
@TaskD EXEC SCOPE TaskB_EXEC = TaskC
@TaskD EXEC SCOPE TaskB_LOCAL = TaskC
@TaskD EXEC SCOPE TaskC_EXEC = TaskC
@TaskD EXEC SCOPE TaskC_LOCAL = TaskC
@TaskD EXEC SCOPE start = TaskC
TaskE
@TaskE EXEC SCOPE TaskA_EXEC = TaskD
@TaskE EXEC SCOPE TaskA_LOCAL = TaskD
@TaskE EXEC SCOPE TaskB_EXEC = TaskD
@TaskE EXEC SCOPE TaskB_LOCAL = TaskD
@TaskE EXEC SCOPE TaskC_EXEC = TaskD
@TaskE EXEC SCOPE TaskC_LOCAL = TaskD
@TaskE EXEC SCOPE TaskD_EXEC = TaskD
@TaskE EXEC SCOPE TaskD_LOCAL = TaskD
@TaskE EXEC SCOPE start = TaskD
TaskF
@TaskF EXEC SCOPE TaskA_EXEC = TaskE
@TaskF EXEC SCOPE TaskA_LOCAL = TaskE
@TaskF EXEC SCOPE TaskB_EXEC = TaskE
@TaskF EXEC SCOPE TaskB_LOCAL = TaskE
@TaskF EXEC SCOPE TaskC_EXEC = TaskE
@TaskF EXEC SCOPE TaskC_LOCAL = TaskE
@TaskF EXEC SCOPE TaskD_EXEC = TaskE
@TaskF EXEC SCOPE TaskD_LOCAL = TaskE
@TaskF EXEC SCOPE TaskE_EXEC = TaskE
@TaskF EXEC SCOPE TaskE_LOCAL = TaskE
@TaskF EXEC SCOPE start = TaskE
@TaskF LOCAL SCOPE TaskA_EXEC = TaskE
@TaskF LOCAL SCOPE TaskA_LOCAL = TaskE
@TaskF LOCAL SCOPE TaskB_EXEC = TaskE
@TaskF LOCAL SCOPE TaskB_LOCAL = TaskE
@TaskF LOCAL SCOPE TaskC_EXEC = TaskE
@TaskF LOCAL SCOPE TaskC_LOCAL = TaskE
@TaskF LOCAL SCOPE TaskD_EXEC = TaskE
@TaskF LOCAL SCOPE TaskD_LOCAL = TaskE
@TaskF LOCAL SCOPE TaskE_EXEC = TaskE
@TaskF LOCAL SCOPE TaskE_LOCAL = TaskE
@TaskF LOCAL SCOPE start = TaskE

よくわからない。Local のことは忘れて、プロセス・インスタンのスコープで変数が保持されると思っておいたほう
が良さそう
↑

4.7 Unit Test

†

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

16/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

public class MyBusinessProcessTest {
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
@Deployment
public void ruleUsageExample() {
RuntimeService runtimeService = activitiRule.getRuntimeService();
runtimeService.startProcessInstanceByKey("ruleUsage");
TaskService taskService = activitiRule.getTaskService();
Task task = taskService.createTaskQuery().singleResult();
assertEquals("My Task", task.getName());

}

}

taskService.complete(task.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());

@Deployment で BPMN を配備することもできる
@Deplpyment(resources = {"org/activiti/examples/bpmn/executionListener/ExecutionListenersFieldInjectionProc

↑

4.9 The process engine in a web application
1
2
3
4
5
6
7
8
9
10
11
12

†

@WebServletContextListener
public class ProcessEnginesServletContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
ProcessEngines.init();
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
ProcessEngines.destroy();
}
}

コンソールアプリと同じように ProcessEngines?.getDefaultProcessEngine?() で ProcessEngine? を取得する
が、アプリ再起動で確実に設定ファイルが反映されるように ServletContextListener? で ProcessEngine?.init(),
ProcessEngine?.destroy() を実⾏する
↑

6. Deployment

†

BPMN の配備
ActivitiExplorer? で [Import]

RepositoryService? API を使う
repositoryService
.createDeployment()
.addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
.deploy();
配備されたプロセス定義の名称
{processDefinitionKey}:{processDefinitionVersion}:{generated-id}

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

17/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

processDefinitionKey? プロセス名
processDefinitionVersion? バージョン
generated-id は、⾃動採番の UID
独⾃ Java プログラム (Jata Task、Listener) の配備
実⾏環境の Classpath に⼊れる
tomcat なら ${tomcat.home}/lib とか
↑

7.標準 BPMN 2.0

†

Eclipse の Activiti Desinger または、Activiti Explorer で作る
拡張⼦ .bpmn20.xml または .bpmn
BPMNの基本構造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43







Write monthly financial report for publication to shareholders.



accountancy






Verify monthly financial report composed by the accountancy department.
This financial report is going to be sent to all the company shareholders.



management








https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

18/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

ルート要素は 
その下に、    がくる
 処理フロー定義
 エラー定義 (  の中で、エラーを発⽣するときに指定する )
 シグナル定義 (  の中で、(全インスタンスに) シグナルを発⾏・受信するときに指定す
る。承認者が退職したので処理中フローを全部差し戻しとか )
 メッセージ定義 (  の中で、メッセージを発⾏・受信するときに指定する。同時並⾏し
て実施中のサブフローを中⽌とか )
 の下に    がくる

 開始点
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("financialReport");
でプロセスを開始すると、 からプロセスが始まる
 終了点
プロセスは  までいくと終了する。終了したプロセスの実⾏履歴は History Service
(processEngine.getHistoryService?()) で取得できる

 ユーザタスク
ユーザ⼊⼒画⾯
potentialOwner> で、実⾏可能なユーザ(または ロール)を指定できる。
実⾏権限ロールの⼈がタスクを個⼈指定で処理要求したいときには
List tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
for (Task task : tasks) {
if (....) {
taskService.claim(task.getId(), "fozzie");
}
}
プログラムでタスクを終わらせたい場合には
https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

19/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

List tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
for (Task task : tasks) {
if (....) {
taskService.complete(task.getId());
}
}

 フロー
sorceRef と targetRef に   の id を設定して、処理の流れを作る
条件分岐は、sequenceFlow の⼀種
↑

8.Activiti 拡張 BPMN 2.0

†

BPMN 規格⾃体に、BPMN を拡張できる仕様が備わっている
↑

8.2.Event

†

Event は、Eclipse Activiti Designer のパレットから Drag&Drop すれば良い

Event の設定は、Activiti Designer 上の properties で編集すると BPMN (XML) に反映される

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

20/46

2018/7/4

Java Activiti User Guide Digest - @//メモ


 の⼦要素にすると、指定したタイマーによって Event が発効する
Note. timers are only fired when the job or async executor is enabled (i.e.
jobExecutorActivate? or asyncExecutorActivate? needs to be set to true in the
activiti.cfg.xml, since the job and async executor are disabled by default).
https://en.wikipedia.org/wiki/ISO_8601 (⽇本語Wikipedia には、Duration、Intervals の記述な
し)

 の⼦要素にすると、エラーの発⽣を契機に Event が発効する
 の⼦要素にすると、その  に到達した時に指定されたエラーでフローを終了する
Java の Exception の発⽣を検知して  に跳ぶのではなく、その  に到達した時に指定
されたエラーでフローを終了する

シグナルは、全プロセスインスタンスに送られる。
承認担当者が、不正処理で馘になったので、処理中のワークフローを全部差し戻しとか
 でシグナルを発効する。
activiti:async="true" をつけると⾮同期になる
シグナルが発⾏すると、全プロセスインスタンスで  からのフローが始まる
プログラムからシグナルを強制発効する
RuntimeService.signalEventReceived(String signalName);
RuntimeService.signalEventReceived(String signalName, String executionId);
引き数が⼆つある⽅は、特定のインスタンスのみにシグナルを発効する。テストとかで使うのかな
シグナルを発⾏したプロセスインスタンスもプロセスを受信しちゃうんで、プロセスを発⾏した後に何かすることは出
来ないことに留意する

メッセージは、特定のプロセスに送られる。
BPMNのフローからメッセージを送ることはできない
 の⼦要素にすると、メッセージの受信を契機に Event が発効する
 の⼦要素にすると、メッセージ受信を契機にそこからフローが始まる
プログラムからメッセージを発効する
RuntimeService.messageEventReceived(String messageName, String executionId);
RuntimeService.messageEventReceived(String messageName, String executionId, HashMap

フローをはじめる (メッセージ受信を契機に実⾏できるフローがあるだけでは、勝⼿にフローは実⾏されないことに
注意。どこかの Process Engine が実⾏する必要がある)
ProcessInstance.startProcessInstanceByMessage(String messageName);
ProcessInstance.startProcessInstanceByMessage(String messageName, Map processVariab
ProcessInstance.startProcessInstanceByMessage(String messageName, String businessKey, Map がメッセージ契機なプロセスの⼀覧)
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.messageEventSubscription("newCallCenterBooking")
.singleResult();
https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

21/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

あるメッセージを契機に特殊処理が⾛るプロセスの⼀覧 ( でメッセージを待っているプロ
セスインスタンスの⼀覧)
Execution execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("paymentReceived")
.variableValueEquals("orderId", message.getOrderId())
.singleResult();
JMSなどを使って、外部システムのイベントを契機にフローを動かしたい時とかに使う

 の⼦要素
平⾏して動いているフローが有った場合には強制終了して、プロセスインスタンスを完全に終了させる

Task に張り付いて、Task 内のイベントに基づいてフローを開始する
 をつけると、主処理とは別に Task 終了後⼀定時間してから起動するフローを書ける

 をつけると、Task / Sub process があるエラーで終わった場合に起動するフロー
を書ける

 をつけると、当該タスクの実効待中にシグナルを受信した時のフローを書ける

 をつけると、当該タスクの実効待中にメッセージを受信した時のフローを書ける

↑

8.3 Sequence Flow

†

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

22/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

Sequence Flow は、Eclipse Activiti Designer では、遷移元の Event、Task、Gatewayをシングルクリック
した後に、[→] (Create Connection) を遷移先に Drag すればできる。あるいは、シングルクリックメニューから
遷移先を作ると、⾃動的に Sequence Flow で結ばれている

Sequence Flow は、Event、Task、Gateway を結びつける


sourceRef 属性 : 遷移元
targetRef 属性 : 遷移先
↑

8.4 Gateways

†

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

23/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

Gateway は、Eclipse Activiti Designer のパレットから Drag&Drop すれば良い



排他の分岐
⾏き先の  は、 ⼦要素を持ち、評価式が true になる最初の
 に進む (⼀つの Flow にしか進まない)
 の xsi:type は、現時点では tFormalExpression? (EL式) しか設定できない
1
2



https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

24/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

3
4
5
6
7
8
9
10
11
12
13


${input == 1}


${input == 2}


${input == 3}


評価式は Eclipse Activiti Designer で、 をクリックして properties ペインで設定で
きる

この設定から⽣成される bpmn (xml) は

 100}]]>




並⾏実⾏の分岐
⾏き先の  は、すべて同時に動き出す
 が⾏き先な場合は、並⾏実⾏されている処理の待ち合わせになる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18















https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

25/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

19
20





⾏き先の  は、 ⼦要素を持ち、その評価式が true になる すべての
 が同時に動き出す (複数の Flow が並⾏実⾏される)
 が⾏き先な場合は、並⾏実⾏されている処理の待ち合わせになる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24





${paymentReceived == false}

${shipOrder == true}












⾏き先の  の、さらに⾏先は、 になっており、最初に受信した
イベントが⾏き先の  に進む (⼀つの Flow にしか進まない)
10分待ってシグナルが来なかったら次へ進むなど
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18










https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

26/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41






PT10M











↑

8.5 Task

†

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

27/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

↑

8.5.1. User Task

†


ユーザの実⾏するタスク

配下の document に説明を書く。プログラムからは task.getDescription(); で取得可能
期限: activiti:dueDate 要素に ISO8601 date-time 形式 (yyyy-MM-ddThh:mm:ss) または time-duration
形式 (PT50M) で設定する
実⾏権限:
BPMN2.0規格では、 タグの配下に、 または  タグを⼊れ⼦
にして、そこでタスクを実⾏できるユーザやグループを定義する。この形式でも activiti は正しく動作する
activiti では、独⾃拡張として  タグに activiti:assignee、activiti:candidateUsers、
activiti:candidateGroups を定義できる
Eclipse Activiti Designer では、期限や権限は properties で編集できる。編集すると BPMN (XML) に反映さ
れる

↑

8.5.2. Script Task

†

JSR-223 (Java Scripting API) で、BPMN内に定義された⽂字列のスクリプトを実⾏する。
https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

28/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

例
1
2
3
4
5
6
7
8





フラグを⽴てるくらいなら使ってもいいかもね
ここに、がっつり処理ロジックを書いてもなかなかテストできないし、実⾏時に Syntax Error が起きるかもしれんし
プロセス変数の変更・設定
1
2
3
4



groovy を使う場合には、pom.xml に
1
2
3
4
5


org.codehaus.groovy
groovy-all
2.x.x


を追記する必要あり
↑

8.5.3. Java Task

†

Javaコードを実⾏する
例
1
2
3



(Activiti が Spring コンテナ上で動いている場合には、Spring が管理している Bean を lookup したり、その
任意のメソッドを実⾏できる。
JavaSE環境で実⾏するときには上記のように、クラス名をパッケージ名付きで指定する)
呼び出される Java コード
1
2
3
4
5
6
7
8
9

public class MyJavaDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
String var = (String) execution.getVariable("input");
var = var.toUpperCase();
execution.setVariable("input", var);
}
}
JavaDelegagte? を実装する
処理ロジックは void execute(DelegateExecution? execution) に記述する
DelegateExecution? からプロセススコープの (ACT_RU_VARIABLE テーブルに格納されている) 変数を取得・
変更できる cf. 4.5.Variables

パラメータの Injection
1
2
3
4
5
6
7
8
9
10
11
12




${genderBean.getGenderString(gender)}


Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}



フィールド変数 text1、text2 に BPMN で指定した値を設定できる
エラー処理
1
2
3
4






https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

29/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

5



例外が発⽣したら、エラーコード myErrorCode1 で終了
Exception の種類によってエラーコードを変える
1
2
3
4
5
6



org.activiti.SomeException



Exception の親クラスを指定 (どの⼦クラスの例外が起きても、指定されたエラーコードをで終了する)
1
2
3
4
5
6



org.activiti.SomeException


↑

8.5.6. Email Task

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

†





















activiti.cfg.xml で、SMTP サーバーの設定が必要
Activiti Explorer / REST API では、WEB-INF/classes/engine.properties
設定できるのは
activiti:field name="" 設定内容
to

TO

from

FROM

subject

SUBJECT

cc

CC

bcc

BCC

charset

⽇本語なら iso-2022-jp やね

html

HTML Mail 平⽂+EL式 で指定

text

Text Mail 平⽂+EL式 で指定

htmlVar

HTML Mail の全⽂が格納されているプロセス変数名

textVar

Text Mail の全⽂が格納されているプロセス変数名

ignoreException

例外を無視

exceptionVariableName? ignoreException=true のとき、発⽣した Exception を格納するプロセス変数名
Eclipse Activiti Designer から設定可能

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

30/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

⽇本語メールもOK (charset = iso-2022-jp にしておけば、あとは (commons-mailが) やってくれる)

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

31/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

⽇本語部分は、iso-2022-jp (JISコード) の base64 になっている

↑

8.5.8. Camel Task (つかえない)

†

結局 Camel を実⾏する Java Class (Spring 管理下の Bean) を呼び出せるだけ
こうだったらよかったのに <実際にはこうなっていません!>
1
2
3
4
5
6
7









→ 普通の Java Task から Camel を呼び出せば良いんでないかい
↑

8.5.9. Manual Task

†

ユーザが Done を押すだけのタスク (ユーザがシステム外で何かやったことを確認するためのタスク)
1


↑

8.5.10. Java Receive Task

†

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

32/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

シグナル待ちタスク
1



シグナル発⾏
1
2
3
4
5
6
7
8

ProcessInstance pi = runtimeService.startProcessInstanceByKey("receiveTask");
Execution execution = runtimeService.createExecutionQuery()
.processInstanceId(pi.getId())
.activityId("waitState")
.singleResult();
assertNotNull(execution);
runtimeService.signal(execution.getId());
↑

8.5.11. Shell Task (つかえない)
1
2
3
4
5
6
7
8
9
10

†












ちゃんと動くけど、つかえない
Activiti Designer が未対応で、対応予定もなし → https://forums.activiti.org/content/eclipseactiviti-designer-and-shell-tasks
Activiti Desinger で bpmn を編集すると  タグが消えてしまう!
→ Java Task で実装するのが良いだろう
↑

8.15.12.Execution listener

†

プロセス開始、終了時の処理 (event="start/end")
bpmn
1
2
3
4
5
6
7
8
9
10


...



...



com.foo.ExecutionListenerOne?
1
2
3
4
5
6
7
8
9
10

import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.ExecutionListenerExecution;
public class ExecutionListenerOne implements ExecutionListener {

}

public void notify(ExecutionListenerExecution execution) throws Exception {
execution.setVariable("variableSetInExecutionListener", "firstValue");
execution.setVariable("eventReceived", execution.getEventName());
}

旧バージョン (< 5.3) との互換性のため、
org.activiti.engine.impl.pvm.delegate.ExecutionListener? もあるが、そちらは使わない
イベントハンドラには、ExecutionListner? ではなく、JavaTask?
(org.activiti.engine.delegate.JavaDelegate?を継承したクラス) を指定してもよい
Flow 通過時の処理 (event なし)
bpmn
1
2
3
4
5
6


...





https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

33/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

7
8
9
10



...


Flow には、event 属性がない (無視される)。Flow には start も end も無いんで
Flow のほかに、Gateway にも同様に Listener を設定できる
Task開始、終了時の処理 (event="start/end")
bpmn
1
2
3
4
5
6
7
8
9
10


...






...


bpmn から executionListener への Field Injection
bpmn
1
2
3
4
5
6
7
8
9
10
11







...


com.foo.FieldInjectedExecutionListener?
1
2
3
4
5
6
7
8
9
10
11
12
13
14

import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.ExecutionListenerExecution;
import org.activiti.engine.delegate.Expression;
public class FieldInjectedExecutionListener implements ExecutionListener {
private Expression fixedValue;
private Expression dynamicValue;

}

public void notify(ExecutionListenerExecution execution) throws Exception {
execution.setVariable("var", fixedValue.getValue(execution).toString() + dynamicValue.ge
}

旧バージョン (< 5.3) との互換性のため、org.activiti.engine.impl.pvm.delegate.Expression もある
が、そちらは使わない
bpmn からプロセススコープの変数を Injection できる (ACT_RU_VARIABLE テーブルに格納されているプロセス固
有の変数 cf. 4.5.Variable
Unit Test では、RuntimeService? でプロセスを開始するときに、変数を設定してあげればいい
1
2
3
4
5
6
7
8
9
10
11
12
13
14

@Deployment(resources = {"org/activiti/examples/bpmn/executionListener/ExecutionListenersFieldIn
public void testExecutionListenerFieldInjection() {
Map variables = new HashMap();
variables.put("myVar", "listening!");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionListeners
Object varSetByListener = runtimeService.getVariable(processInstance.getId(), "var");
assertNotNull(varSetByListener);
assertTrue(varSetByListener instanceof String);

}

// Result is a concatenation of fixed injected field and injected expression
assertEquals("Yes, I am listening!", varSetByListener);
↑

8.5.13. Task listener

†

User Task のイベント処理
event="create" (タスクが作られたとき)
event="assignment" (誰かにアサインされたとき)
event="complete" (完了したとき)
event="delete" (棄却されたとき)
bpmn
1



https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

34/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

2
3
4
5
6
7
8
9
10

...




...

event="create"/>



com.foo.MyTaskCreateListener?
1
2
3
4
5
6
7
8
9

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
public class MyTaskCreateListener implements TaskListener {

}

public void notify(DelegateTask delegateTask) {
// Custom logic goes here
}
↑

8.5.14 Multi-instance (for each)

†

Task/Subprocessの繰り返し実⾏
まぁ、使うとしても JavaTask? だけだろうね
User Task とかで使うと複雑になりすぎる
Mail Task にも使えるけど... ⼤量の嫌がらせメール送るとか ...
bpmn

縦線は並列実⾏、横線はシーケンシャル実⾏
1
2
3
4
5
6
7
8
9
10
11






10






 の属性、⼦要素
property

note

isSequential

true(並列実⾏可) / false(逐次実⾏)

loopCardinality

繰り返し数 (${}でプロセス変数の参照も可能)

completionCondition 終了条件 ${EL式} でプロセス変数を評価する
タスク側では、⾃分が何番⽬の繰り返しなのかをプロセス変数で参照可能
property

note

nrOfInstancfes?

インスタンス数

nrOfActiveInstances?

起動中のインスタンス数

nrOfCompletedInstances? 終了したインスタンス数
loopCounter

現在実⾏中のインスタンス番号

サンプル実装
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/MultiInstanceProcess.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14

package com.snail.exam;
import
import
import
import
import
import
import

org.activiti.engine.ProcessEngine;
org.activiti.engine.ProcessEngines;
org.activiti.engine.RepositoryService;
org.activiti.engine.RuntimeService;
org.activiti.engine.runtime.ProcessInstance;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class MultiInstanceProcess {
private static final Logger log = LoggerFactory.getLogger(MyProcess.class);

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

35/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

public static void main(String[] args) {
try {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/MultiInstance.bpmn")
.deploy();
log.info("Deployed");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("MultiExa
log.info("Complete");

}

}

} catch (RuntimeException th) {
log.error("ERROR", th);
}

https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/MyJavaTask.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

package com.snail.exam;
import java.util.Map;
import
import
import
import

org.activiti.engine.delegate.DelegateExecution;
org.activiti.engine.delegate.JavaDelegate;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class MyJavaTask implements JavaDelegate {
private static final Logger log = LoggerFactory.getLogger(MyJavaTask.class);

}

public void execute(DelegateExecution execution) throws Exception {
log.info("This is MyJavaTask");
for(Map.Entry entry : execution.getVariables().entrySet()) {
log.info("{}={}", entry.getKey(), entry.getValue());
}
}

実⾏結果 (10回実⾏された)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18

23:49:36
23:49:36
23:49:36
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:37
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38

[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO

]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]

Initializing process engine using configuration 'file:/Users/atsushi/E
initializing process engine for resource file:/Users/atsushi/EclipseWo
Loading XML bean definitions from resource loaded through InputStream
performing create on engine with resource org/activiti/db/create/activ
performing create on history with resource org/activiti/db/create/acti
performing create on identity with resource org/activiti/db/create/act
ProcessEngine default created
initialised process engine default
Processing resource org/activiti/test/MultiInstance.bpmn
Deployed
This is MyJavaTask
nrOfActiveInstances=10
loopCounter=0
nrOfInstances=10
nrOfCompletedInstances=0
This is MyJavaTask
nrOfActiveInstances=9
loopCounter=1
nrOfInstances=10
nrOfCompletedInstances=1
This is MyJavaTask
nrOfActiveInstances=8
loopCounter=2
nrOfInstances=10
nrOfCompletedInstances=2
This is MyJavaTask
nrOfActiveInstances=7
loopCounter=3
nrOfInstances=10
nrOfCompletedInstances=3
This is MyJavaTask
nrOfActiveInstances=6
loopCounter=4
nrOfInstances=10
nrOfCompletedInstances=4
This is MyJavaTask
nrOfActiveInstances=5
loopCounter=5
nrOfInstances=10
nrOfCompletedInstances=5
This is MyJavaTask
nrOfActiveInstances=4
loopCounter=6

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

36/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18
16-05-18

23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38
23:49:38

[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO

]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]

nrOfInstances=10
nrOfCompletedInstances=6
This is MyJavaTask
nrOfActiveInstances=3
loopCounter=7
nrOfInstances=10
nrOfCompletedInstances=7
This is MyJavaTask
nrOfActiveInstances=2
loopCounter=8
nrOfInstances=10
nrOfCompletedInstances=8
This is MyJavaTask
nrOfActiveInstances=1
loopCounter=9
nrOfInstances=10
nrOfCompletedInstances=9
Complete
↑

8.6. Sub-Processes and Call Activities

†

ひとかたまりの Activiti を Sub-Process としてまとめることができる

Activiti Explorer では、[Container] から SubProcess? と EventSubProcess? を選ぶことができる

通常の sub process は、Task と同じように扱うことができる。sub process 全体にエラーイベントを貼り付け
ることもできる
event sub process は、Process 中のどこかで発⽣したイベントを契機に開始する
現時点では sub process にする意味はあまりない。
各業務共通の Sub-Processes を「共通bpmnファイル」にくくりだして、各業務bpmnファイル から参照する ...
というのなら意味がありそう
現時点ではそういう使い⽅に対応する予定なし ⇒ https://forums.activiti.org/content/how-includeother-bpmn-files
↑

9. Form

†

Activiti Explorer は、bpmn 上の User Task や Start Event からユーザ⼊⼒画⾯を作ってくれる

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

37/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

User Task や Start Event には、⼊⼒項⽬を指定できる
1
2
3
4
5
6
7
8
9
10








property note
id

key項⽬。⼊⼒値は id をキーにしてプロセススコープの変数として保持される ((ACT_RU_VARIABLE テ
ーブルに格納される)

name

表⽰するラベル

type

"string","long","enum","date","boolean"

value

初期値。プロセススコープの変数 (ACT_RU_VARIABLE テーブルに格納されているプロセス固有の変数)
を EL式で参照可能

readable "true"/"false"
writable "true"/"false"
required "true"/"false"
type="enum" の時には次のように候補を定義する
1
2
3
4
5
6
7
8










GUI は Activiti Explorer 前提なら From の話はここまでで OK
⾃前のワークフローGUIを作りたい時、bpmn 上の Form ⼊出⼒定義から動的に画⾯を作りたくなるだろう
FormService? にはそのための API がある
StartFormData FormService.getStartFormData(String processDefinitionId)
TaskFormdata FormService.getTaskFormData(String taskId)
StartFromData? を検索するキーは、processDefinitionId? (プロセス定義のID)。TaskFormData? を検索する
キーは taskId (実⾏中のタスクのID)。考えて⾒れば当たり前。
StartFormData?.getFormProperties?()、TaskFromData?.getFormProperties?() で
List が返ってくる
1
2
3
4
5
6
7
8
9
10

public interface FormProperty {
FormService#submitStartFormData(String, java.util.Map)}
String getId();
String getName();
FormType getType();
String getValue();
boolean isReadable();
boolean isWritable();
boolean isRequired();
}

 に定義できる⼊出⼒項⽬  の属性と同じね
⼊出⼒項⽬の型は FormType? 型で返される FormType?.getName() を使えば型名を⽂字列で取得できる
string (org.activiti.engine.impl.form.StringFormType?)
long (org.activiti.engine.impl.form.LongFormType?)
enum (org.activiti.engine.impl.form.EnumFormType?)
date (org.activiti.engine.impl.form.DateFormType?)
boolean (org.activiti.engine.impl.form.BooleanFormType?)
https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

38/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

Vacation Request を読み込むサンプル
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/FormProcess.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

package com.snail.exam;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import
import
import
import
import
import
import
import
import
import
import
import
import
import

org.activiti.engine.ProcessEngine;
org.activiti.engine.ProcessEngines;
org.activiti.engine.RepositoryService;
org.activiti.engine.RuntimeService;
org.activiti.engine.TaskService;
org.activiti.engine.form.FormProperty;
org.activiti.engine.form.StartFormData;
org.activiti.engine.form.TaskFormData;
org.activiti.engine.repository.ProcessDefinition;
org.activiti.engine.runtime.ProcessInstance;
org.activiti.engine.task.Task;
org.apache.commons.lang3.time.DateUtils;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class FormProcess {
private static final Logger log = LoggerFactory.getLogger(FormProcess.class);
public static void main(String[] args) {
try {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// ----- 4.3.1. Deploying the process
log.info("--- #1. Deploying the process");
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
.deploy();
// ----- 9. Forms (Read Start Form)
ProcessDefinition processDef = processEngine.getRepositoryService().createProcessDef
.processDefinitionKey("vacationRequest").singleResult();
log.info("Vaction Request PID={}", processDef.getId());
StartFormData startForm = processEngine.getFormService().getStartFormData(processDef
for (FormProperty prop : startForm.getFormProperties()) {
log.info("id={}, name={}, type={}, value={}, readable={}, required={}, writable=
, prop.getId(), prop.getName(), prop.getType(), prop.getValue()
, prop.isReadable(), prop.isRequired(), prop.isWritable());
}
// ----- 4.3.2. Starting a process instance
log.info("--- #3. Starting a process instance");
Map variables = new HashMap();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("startDate", DateUtils.parseDate("1999-12-31", "yyyy-MM-dd"));
variables.put("vacationMotivation", "I'm really tired!");
// the process to run
// id
: 
// arguments : 
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacation
// Fetch all tasks for the management group
TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery().processDefinitionKeyLike("vacationR
for (Task task : tasks) {
TaskFormData taskForm = processEngine.getFormService().getTaskFormData(task.getI
for (FormProperty prop : taskForm.getFormProperties()) {
log.info("id={}, name={}, type={}, value={}, readable={}, required={}, writa
, prop.getId(), prop.getName(), prop.getType(), prop.getValue()
, prop.isReadable(), prop.isRequired(), prop.isWritable());
}

}

// Do task (reject application)
Map taskVariables = new HashMap();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);

} catch (Throwable th) {
log.error("ERROR", th);
}

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

39/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

88
89

}

}

実⾏結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

16-05-19 01:22:08 [INFO ] Initializing process engine using configuration 'file:/Users/atsushi/E
16-05-19 01:22:08 [INFO ] initializing process engine for resource file:/Users/atsushi/EclipseWo
16-05-19 01:22:08 [INFO ] Loading XML bean definitions from resource loaded through InputStream
16-05-19 01:22:09 [INFO ] performing create on engine with resource org/activiti/db/create/activ
16-05-19 01:22:09 [INFO ] performing create on history with resource org/activiti/db/create/acti
16-05-19 01:22:09 [INFO ] performing create on identity with resource org/activiti/db/create/act
16-05-19 01:22:09 [INFO ] ProcessEngine default created
16-05-19 01:22:09 [INFO ] initialised process engine default
16-05-19 01:22:09 [INFO ] --- #1. Deploying the process
16-05-19 01:22:09 [INFO ] Processing resource org/activiti/test/VacationRequest.bpmn20.xml
16-05-19 01:22:10 [INFO ] Vaction Request PID=vacationRequest:1:4
16-05-19 01:22:10 [INFO ] id=numberOfDays, name=Number of days, type=org.activiti.engine.impl.fo
value=null, readable=true, required=true, writable=true,
16-05-19 01:22:10 [INFO ] id=startDate, name=First day of holiday (dd-MM-yyy), type=org.activiti
value=null, readable=true, required=true, writable=true,
16-05-19 01:22:10 [INFO ] id=vacationMotivation, name=Motivation, type=org.activiti.engine.impl.
readable=true, required=false, writable=true,
16-05-19 01:22:10 [INFO ] --- #3. Starting a process instance
16-05-19 01:22:10 [INFO ] id=vacationApproved, name=Do you approve this vacation, type=org.activ
value=null, readable=true, required=true, writable=true,
16-05-19 01:22:10 [INFO ] id=managerMotivation, name=Motivation, type=org.activiti.engine.impl.f
value=null, readable=true, required=false, writable=true,
↑

11.History

†

History Entities
HistoricProcessInstance?

プロセスに関する情報

HistoricVariableInstance? プロセス変数に関する情報
HistoricActivityInstance? 操作に関する情報
HistoricTaskInstance?

タスク情報

HistoricDetail?

Form Submit項⽬、プロセス変数の変更履歴

設定 ⇒ activiti.cfg.xml
1
2
3
4
5



...


history
level

note

none

何も記録しない

*1
activity ユーザ操作をすべて査証 可
能

Prcess
Instance

Activity
Instance

そ
From
Variable(最 Variable(変
の
Properties 終状態)
更履歴)
他

✔

✔

✔

✔

audit

デフォルト設定。プロセス変
数の変更履歴を査証*2可能

✔

✔

✔

✔

✔

full

すべてを記録

✔

✔

✔

✔

✔

✔

API
HistoricProcessInstance?
String

getBusinessKey?()

The user provided unique reference to
this process instance.

String

getDeleteReason?()

Obtains the reason for the process
instance's deletion.

Long

getDurationInMillis?()

The difference between?getEndTime?()?
and?getStartTime?()?.

Date

getEndTime?()

The time the process was ended.

String

getId()

The process instance id (== as the id
for the run21:28:09process instance).

String

getName()

The name for the process instance.

String

getProcessDefinitionId?()

The process definition reference.

Map getProcessVariables?()

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

Returns the process variables if
requested in the process instance
query. ※ なんか何にも⼊っていない Map が返
される。プロセス変数は
40/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

HistoricVariableInstance? からとればいい
だろう
String

getStartActivitId?()

The start activit.

Date

getStartTime?()

The time the process was started.

String

getStartUserId?()

The authenticated user that started
this process instance.

String

The process instance id of a potential
getSuperProcessInstanceId?() super process instance or null if no
super process instance exists.

String

getTenantId?()

The tenant identifier for the process
instance.

HistoricVariableInstance?
Date

getCreateTime?()

Returns the time when the variable was created.

String getId()

The unique DB id

Date

Returns the time when the value of the variable was
last updated.

getLastUpdatedTime?()

String getProcessInstanceId?() The process instance reference.
String getTaskId?()
Object getValue()
String getVariableName?()
String getVariableTypeName?()
HistoricActivityInstance?
String getActivityId?()

The unique identifier of the activity in the
process

String getActivityName?()

The display name for the activity

String getActivityType?()

The XML tag of the activity as in the process
file

String getAssignee()

Assignee in case of user task activity

String getCalledProcessInstanceId?()

The called process instance in case of call
activity

Long

getDurationInMillis?()

Difference between?getEndTime?()?and?
getStartTime?().

Date

getEndTime?()

Time when the activity instance ended

String getExecutionId?()

Execution reference

String getId()

The unique identifier of this historic activity
instance.

String getProcessDefinitionId?()

Process definition reference

String getProcessInstanceId?()

Process instance reference

Date

Time when the activity instance started

getStartTime?()

String getTaskId?()

The corresponding task in case of task activity

String getTenantId?()

Returns the tenant identifier for the historic
activity

HistoricDetail?
String getActivityInstanceId?()

The activity reference in case this detail is related
to an activity instance.

String getExecutionId?()

The identifier for the path of execution.

String getId()

The unique DB id for this historic detail

String getProcessInstanceId?()

The process instance reference.

String getTaskId?()

The identifier for the task.

Date

getTime()

The time when this detail occurred

int

getRevision()?

(Query の検索結果が HistoricVariableUpdate? extends
HistoricDetail? 型のとき)the revision of Process
variable

Object getValue()?

(Query の検索結果が HistoricVariableUpdate? extends
HistoricDetail? 型のとき)Process variable

String getVariableName?()?

(Query の検索結果が HistoricVariableUpdate? extends
HistoricDetail? 型のとき)

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

41/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

String getVariableTypeName?()?

(Query の検索結果が HistoricVariableUpdate? extends
HistoricDetail? 型のとき)

String getPropertyId?()

(Query の検索結果が HistoricFormProperty? extends
HistoricDetail? 型のとき) the id or key of the Form
property

String getPropertyValue?()

(Query の検索結果が HistoricFormProperty? extends
HistoricDetail? 型のとき)the Formsubmitted value

HistoricTaskInstance?
Date

getClaimTime?()

Time when the task was claimed.

String getDeleteReason?()

The reason why this task was deleted {'completed',
'deleted', any other user defined string }.

Long

getDurationInMillis?()

Difference between getEndTime?() and getStartTime?() in
milliseconds.

Date

getEndTime?()

Time when the task was deleted or completed.

Date

getStartTime?()

Time when the task started.

Long

getWorkTimeInMillis?()

Difference between getEndTime?() and getClaimTime?() in
milliseconds.

サンプルプログラム (Vacation Request)
おなじみの Vacation Request
start で休暇申請

manager が承認する

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

42/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

サンプルコード
https://github.com/kagyuu/ActivitiExam/blob/master/src/main/java/com/snail/exam/HistoryProcess.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

package com.snail.exam;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import

org.activiti.engine.HistoryService;
org.activiti.engine.ProcessEngine;
org.activiti.engine.ProcessEngines;
org.activiti.engine.RepositoryService;
org.activiti.engine.RuntimeService;
org.activiti.engine.TaskService;
org.activiti.engine.history.HistoricActivityInstance;
org.activiti.engine.history.HistoricDetail;
org.activiti.engine.history.HistoricFormProperty;
org.activiti.engine.history.HistoricProcessInstance;
org.activiti.engine.history.HistoricTaskInstance;
org.activiti.engine.history.HistoricVariableInstance;
org.activiti.engine.history.HistoricVariableUpdate;
org.activiti.engine.repository.ProcessDefinition;
org.activiti.engine.runtime.ProcessInstance;
org.activiti.engine.task.Task;
org.apache.commons.lang3.time.DateUtils;
org.slf4j.Logger;
org.slf4j.LoggerFactory;

public class HistoryProcess {
private static final Logger log = LoggerFactory.getLogger(HistoryProcess.class);
public static void main(String[] args) {
try {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// ----- 4.3.1. Deploying the process
log.info("--- #1. Deploying the process");
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment().addClasspathResource("org/activiti/test/Va
.deploy();
log.info("Number of process definitions {}", repositoryService.createProcessDef
for (ProcessDefinition p : repositoryService.createProcessDefinitionQuery().lis
log.info("PROCESS DEF [id={},name={},key={}]", p.getId(), p.getName(), p.ge
}
// ----- 4.3.2. Starting a process instance
log.info("--- #2. Starting a process instance");
Map variables = new HashMap();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("startDate", DateUtils.parseDate("1999-12-31", "yyyy-MM-dd"));

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

43/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

variables.put("vacationMotivation", "I'm really tired!");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vac
log.info("Number of process instances: " + runtimeService.createProcessInstance
for (ProcessInstance p : runtimeService.createProcessInstanceQuery().list()) {
log.info("PROCESS INSTANCE [id={},pid={},pname={},pkey={}]", p.getId(), p.g
p.getProcessDefinitionName(), p.getProcessDefinitionKey());
}
log.info("--- #3. Completing tasks (Accept Request)");
// Fetch all tasks for the management group
TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery().taskCandidateGroup("management
.processDefinitionKey("vacationRequest").list();
for (Task task : tasks) {
if (task.getTaskDefinitionKey().equals("handleRequest")) {
// Description is .
log.info("TASK ACCEPT REQ [{}]", task.getDescription());

}

}

// Do task (reject application)
Map taskVariables = new HashMap();
taskVariables.put("vacationApproved", "true");
taskVariables.put("managerMotivation", "Okay, refresh yourself!");
taskService.complete(task.getId(), taskVariables);

// ----- 11. History
log.info("--- #4. History");
HistoryService historyService = processEngine.getHistoryService();
// 11.1.1. HistoricProcessInstanceQuery
List historicPorcessInstances = historyService.createH
.finished().orderByProcessInstanceDuration().desc().listPage(0, 10);
log.info("TERMINATED PROCESS = {}", historicPorcessInstances.size());
historicPorcessInstances.forEach(p -> {
log.info("PROCESS INSTANCE [id={},pid={},name={},variables_size={}]"
, p.getId()
, p.getProcessDefinitionId()
, p.getName()
, p.getProcessVariables().size());
p.getProcessVariables().forEach((k,v) -> {
log.info("{} = {}", k, v);
});
});
// 11.1.2. HistoricVariableInstanceQuery
List historicVariableInstances = historyService.creat
.orderByVariableName().asc().list();
log.info("VARIABLE SIZE = {}", historicVariableInstances.size());
historicVariableInstances.forEach(p -> {
log.info("VARIABLE [id={},pid={},task={},type={},name={},value={}]"
, p.getId()
, p.getProcessInstanceId()
, p.getTaskId()
, p.getVariableTypeName()
, p.getVariableName()
, p.getValue());
});
// 11.1.3. HistoricActivityInstanceQuery
List historicActivityInstances =historyService.create
.finished()
.orderByHistoricActivityInstanceEndTime().desc().list();
log.info("ACTIVITY SIZE = {}", historicActivityInstances.size());
historicActivityInstances.forEach(p -> {
log.info("ACTIVITY [id={},name={},task={},asignee={}]"
, p.getActivityId()
, p.getActivityName()
, p.getTaskId()
, p.getAssignee()
);
});
// 11.1.4. HistoricDetailQuery
List historicDetails = historyService.createHistoricDetailQuery
log.info("DETAIL SIZE = {}", historicDetails.size());
historicDetails.forEach(p -> {
if (p instanceof HistoricFormProperty) {
log.info("FORM [pid={},taskid={},property_id={},value={}]"
, p.getProcessInstanceId()
, p.getTaskId()
, ((HistoricFormProperty)p).getPropertyId()
, ((HistoricFormProperty)p).getPropertyValue()
);
} else if (p instanceof HistoricVariableUpdate) {
log.info("VARIABLE [pid={},taskid={},revision={},name={},value={}]"
, p.getProcessInstanceId()
, p.getTaskId()

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

44/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

}

});

}

, ((HistoricVariableUpdate)p).getRevision()
, ((HistoricVariableUpdate)p).getVariableName()
, ((HistoricVariableUpdate)p).getValue()
);

// 11.1.5. HistoricTaskInstanceQuery
List historicTaskInstances = historyService.createHistori
.finished()
.orderByHistoricTaskInstanceDuration().desc()
.listPage(0, 10);
log.info("TASK SIZE = {}", historicTaskInstances.size());
historicTaskInstances.forEach(p -> {
log.info("TASK [id={},name={},time={},asignee={}]"
, p.getId()
, p.getName()
, p.getCreateTime()
, p.getAssignee()
);
});
} catch (Throwable th) {
log.error("ERROR", th);
}

}

実⾏結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23

21:34:18
21:34:18
21:34:18
21:34:19
21:34:19
21:34:19
21:34:19
21:34:19
21:34:19
21:34:19
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21
21:34:21

[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO

]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]

Initializing process engine using configuration 'file:/Users/atsus
initializing process engine for resource file:/Users/atsushi/Eclip
Loading XML bean definitions from resource loaded through InputStr
performing create on engine with resource org/activiti/db/create/a
performing create on history with resource org/activiti/db/create/
performing create on identity with resource org/activiti/db/create
ProcessEngine default created
initialised process engine default
--- #1. Deploying the process
Processing resource org/activiti/test/VacationRequest.bpmn20.xml
Number of process definitions 1
PROCESS DEF [id=vacationRequest:1:4,name=Vacation request,key=vaca
--- #2. Starting a process instance
Number of process instances: 1
PROCESS INSTANCE [id=5,pid=vacationRequest:1:4,pname=Vacation requ
--- #3. Completing tasks (Accept Request)
TASK ACCEPT REQ [Kermit would like to take 4 day(s) of vacation (M
--- #4. History
TERMINATED PROCESS = 1
PROCESS INSTANCE [id=5,pid=vacationRequest:1:4,name=null,variables
VARIABLE SIZE = 6
VARIABLE [id=6,pid=5,task=null,type=string,name=employeeName,value
VARIABLE [id=15,pid=5,task=null,type=string,name=managerMotivation
VARIABLE [id=9,pid=5,task=null,type=integer,name=numberOfDays,valu
VARIABLE [id=10,pid=5,task=null,type=date,name=startDate,value=Fri
VARIABLE [id=14,pid=5,task=null,type=string,name=vacationApproved,
VARIABLE [id=8,pid=5,task=null,type=string,name=vacationMotivation
ACTIVITY SIZE = 5
ACTIVITY [id=theEnd1,name=null,task=null,asignee=null]
ACTIVITY [id=sendApprovalMail,name=Send confirmation e-mail,task=n
ACTIVITY [id=requestApprovedDecision,name=Request approved?,task=n
ACTIVITY [id=handleRequest,name=Handle vacation request,task=12,as
ACTIVITY [id=request,name=null,task=null,asignee=null]
DETAIL SIZE = 0
TASK SIZE = 1
TASK [id=12,name=Handle vacation request,time=Mon May 23 21:34:21

HistoricProcessInstance? から Variable が取れないとか、謎仕様になっているけどまぁいいか
activiti.cfg.xml で  にすると DETAIL が表⽰される。
でも Form Property ではなくプロセス変数
1
2
3
4
5
6
7
8

16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23
16-05-23

22:06:05
22:06:05
22:06:05
22:06:05
22:06:05
22:06:05
22:06:05
22:06:05

[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO
[INFO

]
]
]
]
]
]
]
]

DETAIL SIZE = 7
VARIABLE [pid=5,taskid=null,revision=0,name=vacationMotivation,valu
VARIABLE [pid=5,taskid=null,revision=0,name=numberOfDays,value=4]
VARIABLE [pid=5,taskid=null,revision=0,name=startDate,value=Fri Dec
VARIABLE [pid=5,taskid=null,revision=0,name=vacationApproved,value=
VARIABLE [pid=5,taskid=null,revision=0,name=managerMotivation,value
VARIABLE [pid=5,taskid=null,revision=0,name=employeeName,value=null
VARIABLE [pid=5,taskid=null,revision=0,name=employeeName,value=Kerm

プロセス変数周りは、細かい所⾊々と謎仕様が多いけどまぁいいか。⼀通りのことはできるし、必要になったら(プロ
セス監視画⾯をつくろうとか思い⽴ったら)もうちょっと細かい所検証する必要あり。まぁその時は REST API 使う
だろうけど
↑

13. Activiti Explorer 14. Modeler

†

→ Java Activiti Explorer
↑

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

45/46

2018/7/4

Java Activiti User Guide Digest - @//メモ

15. REST API

†

→ Java Activiti REST API
Java#Activiti
*1

audit

*2

audit

Last-modified: 2018-01-30 (⽕) 01:18:32 (154d)
Site admin: kagyuu
PukiWiki 1.4.6 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji. Powered by PHP 5.3.3. HTML convert time: 3.017 sec.

https://hondou.homedns.org/pukiwiki/index.php?Java%20Activiti%20User%20Guide%20Digest

ISBN10

ISBN13
→

4061426060

9784061426061

46/46



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.4
Linearized                      : No
Warning                         : Invalid xref table
EXIF Metadata provided by EXIF.tools

Navigation menu