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]にあります。