1. 概要

Flowable は、Javaで記述されたビジネスプロセスエンジンです。 このチュートリアルでは、ビジネスプロセスの詳細を確認し、FlowableJavaAPIを利用してサンプルのビジネスプロセスを作成およびデプロイする方法を理解します。

2. ビジネスプロセスを理解する

簡単に言えば、ビジネスプロセスは、定義された順序で完了すると、定義された目的を達成する一連のタスクです。 ビジネスプロセスの各タスクには、明確に定義された入力と出力があります。 これらのタスクは、人間の介入が必要な場合もあれば、完全に自動化されている場合もあります。

OMG(Object Management Group)は、企業がプロセスを定義および伝達するためのビジネスプロセスモデルおよび表記法(BPMN)と呼ばれる標準を定義しました。 BPMNは、業界で広くサポートされ、受け入れられるようになりました。 Flowable APIは、BPMN2.0プロセス定義の作成とデプロイを完全にサポートします。

3. プロセス定義の作成

公開する前に記事をレビューするための簡単なプロセスがあるとしましょう。

このプロセスの要点は、著者が記事を提出し、編集者がそれを受け入れるか拒否するかです。 承認された場合、記事はすぐに公開されます。 ただし、拒否された場合は、作成者に電子メールで通知されます。

BPMN 2.0 XML標準を使用して、プロセス定義をXMLファイルとして作成します。

BPMN2.0標準に従って単純なプロセスを定義しましょう。

<?xml version="1.0" encoding="UTF-8"?>
<definitions
    xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
    xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
    xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
    xmlns:flowable="http://flowable.org/bpmn"
    typeLanguage="http://www.w3.org/2001/XMLSchema"
    expressionLanguage="http://www.w3.org/1999/XPath"
    targetNamespace="http://www.flowable.org/processdef">
    <process id="articleReview"
      name="A simple process for article review." isExecutable="true">
        <startEvent id="start" />
        <sequenceFlow sourceRef="start" targetRef="reviewArticle" />
        <userTask id="reviewArticle" name="Review the submitted tutorial"
          flowable:candidateGroups="editors" />
        <sequenceFlow sourceRef="reviewArticle" targetRef="decision" />
        <exclusiveGateway id="decision" />
        <sequenceFlow sourceRef="decision" targetRef="tutorialApproved">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[${approved}]]>
            </conditionExpression>
        </sequenceFlow>
        <sequenceFlow sourceRef="decision" targetRef="tutorialRejected">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[${!approved}]]>
            </conditionExpression>
        </sequenceFlow>
        <serviceTask id="tutorialApproved" name="Publish the approved tutorial."
          flowable:class="com.baeldung.service.PublishArticleService" />
        <sequenceFlow sourceRef="tutorialApproved" targetRef="end" />
        <serviceTask id="tutorialRejected" name="Send out rejection email"
          flowable:class="com.baeldung.service.SendMailService" />
        <sequenceFlow sourceRef="tutorialRejected" targetRef="end" />
        <endEvent id="end" />
    </process>
</definitions>

さて、ここには標準のXMLのものである要素がかなりありますが、他の要素はBPMN2.0に固有のものです。

  • プロセス全体が「プロセス」と呼ばれるタグにラップされ、は「定義」と呼ばれるタグの一部になります。
  • プロセスは、イベント、フロー、タスク、およびゲートウェイで構成されます
  • イベントは、開始イベントまたは終了イベントのいずれかです
  • フロー(この例では、シーケンスフロー)は、イベントやタスクなどの他の要素を接続します
  • タスクは実際の作業が行われる場所です。 これらは、とりわけ「ユーザータスク」または「サービスタスク」である可能性があります
  • ユーザータスクでは、人間のユーザーがFlowableAPIを操作してアクションを実行する必要があります
  • サービスタスクは自動タスクを表します。これは、Javaクラスの呼び出し、またはHTTP呼び出しの場合もあります。
  • ゲートウェイは、「承認済み」の属性に基づいて実行されます。 これはプロセス変数と呼ばれ、後で設定する方法を説明します。

どのテキストエディタでもプロセス定義ファイルを作成できますが、これが常に最も便利な方法であるとは限りません。 ただし、幸いなことに、Flowableには、EclipseプラグインまたはWebアプリケーションのいずれかを使用してこれを行うためのユーザーインターフェイスオプションも付属しています。 代わりにIntelliJを使用している場合は、IntelliJプラグインも利用できます。

4. FlowableAPIの操作

BPMN 2.0標準に従ってXMLファイルで単純なプロセスを定義したので、それを送信して実行する方法が必要です。 Flowableは、FlowableEnginesと対話するためのProcessEngineAPIを提供します。 Flowableは非常に柔軟性があり、このAPIをデプロイするためのいくつかの方法を提供します。

FlowableはJavaAPIであるため、必要なJARファイルを含めるだけで、任意のJavaアプリケーションにプロセスエンジンを含めることができます。 これらの依存関係を管理するためにMavenを非常にうまく活用できます。

さらに、Flowableには、FlowableoverHTTPと対話するためのバンドルされたAPIが付属しています。 これらのAPIを使用して、FlowableAPIを介して他の方法で可能なことをほぼすべて実行できます。

最後に、 Flowableは、SpringおよびSpring Bootとの統合を優れた方法でサポートしています!チュートリアルでは、FlowableおよびSpring Bootの統合を利用します。

5. ProcessEngineを使用したデモアプリケーションの作成

次に、Flowableからプロセスエンジンをラップし、FlowableAPIと対話するためのHTTPベースのAPIを提供する単純なアプリケーションを作成しましょう。 エクスペリエンスを向上させるために、APIの上にWebまたはモバイルアプリケーションを配置することもできますが、このチュートリアルではそれをスキップします。

Spring Bootアプリケーションとしてデモを作成します。

5.1. 依存関係

まず、Mavenからプルする必要のある依存関係を見てみましょう。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.4.1</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

必要な依存関係はすべてMavenCentralで利用できます。

5.2. プロセス定義

Spring Bootアプリケーションを起動すると、「resources / employees」フォルダーの下にあるすべてのプロセス定義が自動的に読み込まれます。したがって、上記で作成したプロセス定義を使用してXMLファイルを作成しましょう。 「article-workflow.bpmn20.xml」という名前を付けて、そのフォルダーに配置します。

5.3. 構成

Spring Bootはアプリケーション構成に対して非常に意見の分かれるアプローチを取っていることを認識しているので、それはSpring Bootの一部としてのFlowableにも当てはまります。 たとえば、クラスパス上の唯一のデータベースドライバーとしてH2を検出すると、FlowableはH2を使用するように自動的に構成します

明らかに、構成可能なすべての側面は、アプリケーションプロパティを介してカスタム方法で構成できます。 ただし、このチュートリアルでは、デフォルトを使用します。

5.4. Javaデリゲート

プロセス定義では、サービスタスクの一部として呼び出されることになっているJavaクラスをいくつか使用しました。 これらのクラスはJavaDelegateインターフェースを実装し、FlowableではJavaDelegatesとして知られています。 次に、これらのJavaデリゲートのダミークラスを定義します。

public class PublishArticleService implements JavaDelegate {
    public void execute(DelegateExecution execution) {
        System.out.println("Publishing the approved article.");
    }
}
public class SendMailService implements JavaDelegate {
    public void execute(DelegateExecution execution) {
        System.out.println("Sending rejection mail to author.");
    }
}

もちろん、記事を公開したりメールを送信したりするには、これらのダミークラスを実際のサービスに置き換える必要があります。

5.5. HTTPAPI

最後に、プロセスエンジンと対話し、定義したプロセスを操作するためのエンドポイントをいくつか作成しましょう。

まず、3つのエンドポイントを公開するコントローラーを定義します。

@RestController
public class ArticleWorkflowController {
    @Autowired
    private ArticleWorkflowService service;
 
    @PostMapping("/submit")
    public void submit(@RequestBody Article article) {
        service.startProcess(article);
    }
 
    @GetMapping("/tasks")
    public List<Article> getTasks(@RequestParam String assignee) {
        return service.getTasks(assignee);
    }
 
    @PostMapping("/review")
    public void review(@RequestBody Approval approval) {
        service.submitReview(approval);
    }
}

私たちのコントローラーは、レビューのために記事を送信し、レビューする記事のリストをフェッチし、最後に記事のレビューを送信するためにエンドポイントを公開します。 ArticleおよびApprovalは、リポジトリにある標準のPOJOです。

実際には、ほとんどの作業をArticleWorkflowServiceに委任しています。

@Service
public class ArticleWorkflowService {
    @Autowired
    private RuntimeService runtimeService;
 
    @Autowired
    private TaskService taskService;

    @Transactional
    public void startProcess(Article article) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("author", article.getAuthor());
        variables.put("url", article.getUrl());
        runtimeService.startProcessInstanceByKey("articleReview", variables);
    }
 
    @Transactional
    public List<Article> getTasks(String assignee) {
        List<Task> tasks = taskService.createTaskQuery()
          .taskCandidateGroup(assignee)
          .list();
        return tasks.stream()
          .map(task -> {
              Map<String, Object> variables = taskService.getVariables(task.getId());
              return new Article(task.getId(), (String) variables.get("author"), (String) variables.get("url"));
          })
          .collect(Collectors.toList());
    }
 
    @Transactional
    public void submitReview(Approval approval) {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("approved", approval.isStatus());
        taskService.complete(approval.getId(), variables);
    }
}

さて、ここのコードのほとんどはかなり直感的ですが、重要なポイントを理解しましょう:

  • RuntimeService は、特定の送信のプロセスをインスタンス化します
  • TaskService を使用して、タスクを照会および更新します
  • Springでサポートされているトランザクションですべてのデータベース呼び出しをラップする
  • 作成者やURLなどの詳細をMapに保存し、プロセスインスタンスとともに保存します。 これらはプロセス変数と呼ばれ、前に見たように、プロセス定義内でアクセスできます。

これで、アプリケーションとプロセスエンジンをテストする準備が整いました。 アプリケーションを起動すると、 curl またはPostmanなどのRESTクライアントを使用して、作成したエンドポイントと対話できます。

6. ユニットテストプロセス

Flowableは、ビジネスプロセスの単体テストを作成するためにJUnit 5を含むさまざまなバージョンのJUnitをサポートします。SpringとのFlowable統合は、これにも適切にサポートされます。 Springのプロセスの典型的な単体テストを見てみましょう。

@ExtendWith(FlowableSpringExtension.class)
@ExtendWith(SpringExtension.class)
public class ArticleWorkflowUnitTest {
    @Autowired
    private RuntimeService runtimeService;
 
    @Autowired
    private TaskService taskService;
 
    @Test
    @Deployment(resources = { "processes/article-workflow.bpmn20.xml" })
    void articleApprovalTest() {
        Map<String, Object> variables = new HashMap<>();
        variables.put("author", "[email protected]");
        variables.put("url", "http://baeldung.com/dummy");
 
        runtimeService.startProcessInstanceByKey("articleReview", variables);
        Task task = taskService.createTaskQuery().singleResult();
 
        assertEquals("Review the submitted tutorial", task.getName());
 
        variables.put("approved", true);
        taskService.complete(task.getId(), variables);
 
        assertEquals(0, runtimeService.createProcessInstanceQuery().count());
    }
}

これは、 @Deployment のようないくつかの注釈を除いて、Springの標準的な単体テストのように見えるはずです。 現在、 @Deployment アノテーションは、テストメソッドを中心としたプロセス展開を作成および削除するためにFlowableによって提供されています。

7. プロセスの展開を理解する

このチュートリアルではプロセス展開の詳細については説明しませんが、重要ないくつかの側面について説明することは価値があります。

通常、プロセスはビジネスアーカイブ(BAR)としてアーカイブされ、アプリケーションにデプロイされます。 デプロイ中に、このアーカイブは、プロセス定義などのアーティファクトがないかスキャンされ、処理されます。 「。bpmn20.xml」で終わるプロセス定義ファイルの規則に気付いたかもしれません。

チュートリアルではデフォルトのインメモリH2データベースを使用しましたが、これは実際のアプリケーションでは使用できません。これは、インメモリデータベースが起動時にデータを保持せず、実際にはデータを保持するという単純な理由からです。クラスター環境では使用できません! したがって、実稼働グレードのリレーショナルデータベースを使用し、アプリケーションで必要な構成を提供する必要があります。

BPMN 2.0自体にはバージョン管理の概念はありませんが、 Flowableは、データベースにデプロイされるプロセスのバージョン属性を作成します。 属性「id」で識別される同じプロセスの更新されたバージョンがデプロイされると、バージョンがインクリメントされた新しいエントリが作成されます。 「id」でプロセスを開始しようとすると、プロセスエンジンはデプロイされたプロセス定義の最新バージョンをフェッチします。

前に説明したデザイナーの1つを使用してプロセス定義を作成する場合、プロセスの視覚化はすでに完了しています。 プロセス図を画像としてエクスポートし、XMLプロセス定義ファイルと一緒に配置できます。 Flowableが提案する標準の命名規則に準拠すると、この画像はプロセス自体と一緒にプロセスエンジン。 さらに、APIを介してこの画像を取得することもできます。

8. プロセスインスタンスの履歴の閲覧

ビジネスプロセスの場合、過去に何が起こったかを理解することが非常に重要になることがよくあります。 これは、単純なデバッグまたは複雑な法的監査の目的で必要になる場合があります。

Flowableは、プロセスの実行中に発生したことを記録し、データベースに保持します。さらに、Flowableは、この履歴をAPIを介してクエリおよび分析できるようにします。 Flowableがこれらを記録するエンティティは6つあり、HistoryServiceにはそれらすべてをクエリするメソッドがあります。

完了したプロセスインスタンスをフェッチするための簡単なクエリを見てみましょう。

HistoryService historyService = processEngine.getHistoryService();
List<HistoricActivityInstance> activities = historyService
  .createHistoricActivityInstanceQuery()
  .processInstanceId(processInstance.getId())
  .finished()
  .orderByHistoricActivityInstanceEndTime()
  .asc()
  .list();

ご覧のとおり、記録されたデータをクエリするAPIはかなり構成可能です。この例では、終了したプロセスインスタンスをIDでクエリし、終了時刻の昇順で並べ替えています。

9. 監視プロセス

監視は、ビジネスクリティカルなアプリケーションの重要な側面であり、組織のビジネスプロセスを処理するアプリケーションにとってはさらに重要です。 Flowableには、プロセスをリアルタイムで監視できるようにするためのいくつかのオプションがあります。

Flowableは、JMX を介してアクセスできる特定のMBeanを提供し、監視用のデータを収集するだけでなく、他の多くのアクティビティも実行します。 これは、標準のJavaディストリビューションと一緒に存在するjconsoleを含む任意の標準のJMXクライアントと統合できます。

監視にJMXを使用すると、多くのオプションが開きますが、比較的複雑で時間がかかります。 ただし、Spring Bootを使用しているので、運が良かったです。

Spring Bootは、HTTPを介してアプリケーションメトリックを収集するためのアクチュエータエンドポイントを提供します。 これをPrometheusやGrafanaなどのツールスタックとシームレスに統合して、最小限の労力で本番環境グレードの監視ツールを作成できます。

Flowableは、実行中のプロセスに関する情報を公開する追加のアクチュエータエンドポイントを提供します。これは、JMXを介して情報を収集するほど良くはありませんが、迅速、簡単、そして何よりも十分です。

10. 結論

このチュートリアルでは、ビジネスプロセスと、BPMN2.0標準でそれらを定義する方法について説明しました。 次に、プロセスをデプロイして実行するFlowableプロセスエンジンとAPIの機能について説明しました。 これをJavaアプリケーション、特にSpringBootに統合する方法を見てきました。

さらに続けて、展開、視覚化、監視など、プロセスの他の重要な側面について説明しました。 言うまでもなく、私たちはビジネスプロセスの表面とFlowableのような強力なエンジンをかじったところです。 Flowableには非常に豊富なAPIがあり、十分なドキュメントが利用可能です。 ただし、このチュートリアルでは、このテーマに興味をそそられるはずです。

いつものように、例のコードはGitHubから入手できます。