1. 概要

簡単に言えば、Activitiはワークフローおよびビジネスプロセス管理プラットフォームです。

ProcessEngineConfiguration (通常は構成ファイルに基づく)を作成することで、すぐに始めることができます。 これから、 ProcessEngine –そして ProcessEngine、 ワークフローとBPM操作を実行できます。

APIは、プロセスへのアクセスと管理に使用できるさまざまなサービスを提供します。 これらのサービスは、プロセスの履歴、現在実行されているもの、およびデプロイされているがまだ実行されていないプロセスに関する情報を提供します。

これらのサービスを使用して、プロセス構造を定義し、プロセスの状態を操作することもできます。 実行、一時停止、キャンセルなど。

APIを初めて使用する場合は、Javaを使用したActivitiAPIの概要を確認してください。 この記事では、Spring Bootアプリケーション内でActivitiAPIを設定する方法について説明します。

2. SpringBootを使用したセットアップ

ActivitiをSpring BootMavenアプリケーションとしてセットアップして使用を開始する方法を見てみましょう。

2.1. 初期設定

いつものように、Mavenの依存関係を追加する必要があります。

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter-basic</artifactId>
</dependency>

APIの最新の安定バージョンは、ここにあります。 これは、v1.5.4までのSpringBootで動作します。 v2.0.0.M1ではまだ動作しません。

https://start.spring.ioを使用してSpringBootプロジェクトを生成し、依存関係としてActivitiを選択することもできます。

この依存関係と@EnableAutoConfigurationアノテーションをSpring Bootアプリケーションに追加するだけで、初期設定が実行されます。

  • データソースの作成(APIには、 ProcessEngine を作成するためのデータベースが必要です)
  • ProcessEngineBeanを作成して公開します
  • ActivitiサービスBeanを作成して公開する
  • SpringJobExecutorを作成する

2.2. プロセスの作成と実行

ビジネスプロセスを作成して実行する例を作成してみましょう。 プロセスを定義するには、BPMNファイルを作成する必要があります。

次に、BPMNファイルをダウンロードします。 このファイルをsrc/ main / resources /employeesフォルダーに配置する必要があります。 デフォルトでは、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タスクのリストを取得します

2つのユーザータスクABがあります。 プロセスを開始すると、最初のタスク 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. タスクの完了

ここで、タスク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のタスクを提供します。 これはUserTaskAです。 次の行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でのActivitiAPIの使用の概要について説明しました。APIの詳細については、ユーザーガイドを参照してください。 また、Activitiサービスを使用して、プロセスを作成し、プロセスに対してさまざまな操作を実行する方法についても説明しました。

Spring Bootを使用すると、データベースの作成、プロセスのデプロイ、または ProcessEngine の作成について心配する必要がないため、簡単に使用できます。

ActivitiとSpringBootの統合はまだ実験段階であり、SpringBoot2ではまだサポートされていないことに注意してください。

いつものように、私たちが見たすべての例の実装は、GitHubにあります。