春のアクティビティー入門
1概要
簡単に言えば、** Activitiはワークフローとビジネスプロセス管理プラットフォームです。
ProcessEngineConfiguration
(通常は設定ファイルに基づく)を作成することですぐに始めることができます。これから、
ProcessEngine
を取得することができます – そして
ProcessEngineを通して
ワークフローとBPM操作を実行することができます。
APIは、プロセスへのアクセスと管理に使用できるさまざまなサービスを提供します。これらのサービスは、プロセスの履歴、現在実行されているプロセス、および展開されているがまだ実行されていないプロセスに関する情報を提供してくれます。
サービスはまた、プロセス構造を定義し、プロセスの状態を操作するために、すなわち実行、中断、取り消しなどのために使用することができる。
あなたがこのAPIを初めて使うのであれば、**
はじめに
を参照してください。この記事では、Spring Bootアプリケーション内でActiviti APIを設定する方法について説明します。
2 Spring Bootによるセットアップ
ActivitiをSpring Boot Mavenアプリケーションとして設定して使用を開始する方法を見てみましょう。
2.1. 初期設定
いつものように、Mavenの依存関係を追加する必要があります。
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
</dependency>
APIの最新安定版はhttps://mvnrepository.com/artifact/org.activiti/activiti-engine[ここ]にあります。
v1.5.4までのSpring Bootで動作します。まだv2.0.0.M1では動作しません。
https://start.spring.io
を使用してSpring Bootプロジェクトを生成し、依存関係としてActivitiを選択することもできます。
この依存関係と
@ EnableAutoConfiguration
アノテーションをSpring Bootアプリケーションに追加するだけで、初期設定が行われます。
-
データソースの作成(APIにはデータベースを作成するためのデータベースが必要です。
ProcessEngine
)
**
ProcessEngine
Beanを作成して公開する
-
ActivitiサービスBeanを作成して公開する
-
Spring Job Executorを作成する
** 2.2. プロセスの作成と実行
ビジネスプロセスを作成して実行する例を作成しましょう。
プロセスを定義するために、BPMNファイルを作成する必要があります。これにはhttps://activiti.alfresco.com/activiti-app/editorを使用してプロセス定義を作成できます。
次に、BPMNファイルをダウンロードするだけです。このファイルを
src/main/resources/processes
フォルダーに配置する必要があります。デフォルトでは、Spring Bootはこのフォルダを調べてプロセス定義をデプロイします。
1つのユーザータスクを含むデモプロセスを作成します。
ユーザタスクの担当者がプロセスの開始者に設定されます。
このプロセス定義のBPMNファイルは次のようになります。
<process id="my-process" name="say-hello-process" isExecutable="true">
<startEvent id="startEvent" name="startEvent">
</startEvent>
<sequenceFlow id="sequence-flow-1" sourceRef="startEvent" targetRef="A">
</sequenceFlow>
<userTask id="A" name="A" activiti:assignee="$INITIATOR">
</userTask>
<sequenceFlow id="sequence-flow-2" sourceRef="A" targetRef="endEvent">
</sequenceFlow>
<endEvent id="endEvent" name="endEvent">
</endEvent>
</process>
これで、このプロセスを開始する要求を処理するためのRESTコントローラを作成します。
@Autowired
private RuntimeService runtimeService;
@GetMapping("/start-process")
public String startProcess() {
runtimeService.startProcessInstanceByKey("my-process");
return "Process started. Number of currently running"
+ "process instances = "
+ runtimeService.createProcessInstanceQuery().count();
}
ここで、
runtimeService.startProcessInstanceByKey(“ my-process”)
は、キーが
“ my-process”
であるプロセスの実行を開始します。
runtimeService.createProcessInstanceQuery()。count()
は、プロセスインスタンスの数を取得します。
パス“/start-process”
を押すたびに、新しい
ProcessInstance__が作成され、現在実行中のプロセスの数が増えます。
JUnitテストケースは私達にこの挙動を示しています:
@Test
public void givenProcess__whenStartProcess__thenIncreaseInProcessInstanceCount()
throws Exception {
String responseBody = this.mockMvc
.perform(MockMvcRequestBuilders.get("/start-process"))
.andReturn().getResponse().getContentAsString();
assertEquals("Process started. Number of currently running"
+ " process instances = 1", responseBody);
responseBody = this.mockMvc
.perform(MockMvcRequestBuilders.get("/start-process"))
.andReturn().getResponse().getContentAsString();
assertEquals("Process started. Number of currently running"
+ " process instances = 2", responseBody);
responseBody = this.mockMvc
.perform(MockMvcRequestBuilders.get("/start-process"))
.andReturn().getResponse().getContentAsString();
assertEquals("Process started. Number of currently running"
+ " process instances = 3", responseBody);
}
3プロセスで遊ぶ
Spring Bootを使ってActivitiで実行中のプロセスができたので、上記の例を拡張して、プロセスにアクセスして操作する方法を説明しましょう。
3.1. 与えられた
ProcessInstance
の
Tasks
のリストを取得する
2つのユーザータスク
A
と
B
があります。プロセスを開始すると、最初のタスク
A
が完了するのを待ってからタスク
B
が実行されます。
特定の
processInstance
に関連するタスクを表示するためのリクエストを受け付けるハンドラメソッドを作成しましょう。
Task
のようなオブジェクトは直接レスポンスとして送信することはできません。したがって、カスタムオブジェクトを作成して
Task
をカスタムオブジェクトに変換する必要があります。このクラスを
TaskRepresentation
と呼びます。
class TaskRepresentation {
private String id;
private String name;
private String processInstanceId;
//standard constructors
}
ハンドラメソッドは次のようになります。
@GetMapping("/get-tasks/{processInstanceId}")
public List<TaskRepresentation> getTasks(
@PathVariable String processInstanceId) {
List<Task> usertasks = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.list();
return usertasks.stream()
.map(task -> new TaskRepresentation(
task.getId(), task.getName(), task.getProcessInstanceId()))
.collect(Collectors.toList());
}
ここで、
taskService.createTaskQuery()。processInstanceId(processInstanceId).list()
は
TaskService
を使用し、指定された
processInstanceId
に関連するタスクのリストを取得します。作成したプロセスの実行を開始すると、先ほど定義したメソッドに要求を送信することでタスク
A
を取得することがわかります。
@Test
public void givenProcess__whenProcessInstance__thenReceivedRunningTask()
throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.get("/start-process"))
.andReturn()
.getResponse();
ProcessInstance pi = runtimeService.createProcessInstanceQuery()
.orderByProcessInstanceId()
.desc()
.list()
.get(0);
String responseBody = this.mockMvc
.perform(MockMvcRequestBuilders.get("/get-tasks/" + pi.getId()))
.andReturn()
.getResponse()
.getContentAsString();
ObjectMapper mapper = new ObjectMapper();
List<TaskRepresentation> tasks = Arrays.asList(mapper
.readValue(responseBody, TaskRepresentation[].class));
assertEquals(1, tasks.size());
assertEquals("A", tasks.get(0).getName());
}
3.2.
Task
を完成させる
これで、タスク
A
を完了したときに何が起こるかがわかります。与えられた
processInstance
に対してタスク
A
を完了するためのリクエストを処理するハンドラメソッドを作成します。
@GetMapping("/complete-task-A/{processInstanceId}")
public void completeTaskA(@PathVariable String processInstanceId) {
Task task = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.singleResult();
taskService.complete(task.getId());
}
taskService.createTaskQuery()。processInstanceId(processInstanceId).singleResult()
は、タスクサービスに対してクエリを作成し、指定された
processInstance
のタスクを取得します。これが
UserTask A
です。次の行
taskService.complete(task.getId)
がこのタスクを完了します。したがって、これでプロセスは終了し、
RuntimeService
には
ProcessInstances
が含まれていません。これはJUnitテストケースを使用して確認できます。
@Test
public void givenProcess__whenCompleteTaskA__thenNoProcessInstance()
throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.get("/start-process"))
.andReturn()
.getResponse();
ProcessInstance pi = runtimeService.createProcessInstanceQuery()
.orderByProcessInstanceId()
.desc()
.list()
.get(0);
this.mockMvc.perform(MockMvcRequestBuilders.get("/complete-task-A/" + pi.getId()))
.andReturn()
.getResponse()
.getContentAsString();
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
assertEquals(0, list.size());
}
このようにしてActivitiサービスをプロセスと連携させることができます。
4結論
この記事では、Spring BootでのActiviti APIの使用の概要について説明しました。また、Activitiサービスを使用してプロセスを作成し、そのプロセスに対してさまざまな操作を実行する方法も見ました。
Spring Bootは、データベースの作成、プロセスのデプロイ、または
ProcessEngine
の作成について心配する必要がないため、使いやすくなっています。
ActivitiとSpring Bootの統合はまだ実験段階にあり、Spring Boot 2ではまだサポートされていません。
いつものように、私たちが見たすべての例の実装はhttps://github.com/eugenp/tutorials/tree/master/spring-activiti[over on GitHub]にあります。