Flowableの紹介

1. 概要

https://www.flowable.org/[Flowable]は、Javaで記述されたビジネスプロセスエンジンです。 このチュートリアルでは、ビジネスプロセスの詳細を説明し、Flowable Java APIを活用してサンプルビジネスプロセスを作成およびデプロイする方法を理解します。

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

簡単に言えば、*ビジネスプロセスとは、定義された順序で完了すると、定義された目標を達成する一連のタスクです*。 ビジネスプロセスの各タスクには、入力と出力が明確に定義されています。 これらのタスクは、人間の介入が必要な場合や、完全に自動化されている場合があります。
  • OMG(Object Management Group)は、企業がプロセスを定義および伝達するためのhttp://www.bpmn.org/[Business Process Model and Notation(BPMN)]と呼ばれる標準を定義しています*。 BPMNは業界で広くサポートされ、受け入れられるようになりました。 Flowable APIは、BPMN 2.0プロセス定義の作成とデプロイを完全にサポートしています。

3. プロセス定義の作成

公開する前に記事をレビューする簡単なプロセスがあるとしましょう。
このプロセスの要点は、著者が記事を提出し、編集者がその記事を受け入れるか拒否するかです。 受け入れられた場合、記事はすぐに公開されます。ただし、拒否された場合、作成者には電子メールで通知されます。
link:/uploads/Screenshot-2019-04-15-at-05.49.51-100x36.png%20100w []
  • BPMN 2.0 XML標準を使用して、プロセス定義をXMLファイルとして作成します。*

    BPMN 2.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の要素がかなりありますが、BPMN 2.0に固有のものもあります。
  • *プロセス全体は、「プロセス」と呼ばれるタグでラップされます。
    ターン、「定義」と呼ばれるタグの一部です

  • プロセスは、イベント、フロー、タスク、およびゲートウェイで構成されます

  • イベントは、開始イベントまたは終了イベントのいずれかです

  • フロー(この例ではシーケンスフロー)は、次のような他の要素を接続します
    イベントとタスク

  • タスクは、実際の作業が行われる場所です。これらは「ユーザータスク」または
    「サービスタスク」など

  • ユーザータスクでは、Flowable APIと対話するために人間のユーザーが必要です
    そして行動を起こす

  • サービスタスクは、自動タスクを表します。これは、
    Javaクラス、さらにはHTTP呼び出し

  • ゲートウェイは、属性「承認済み」に基づいて実行されます。 *これは知られています
    プロセス変数*として、後で設定する方法を見ていきます

    テキストエディタでプロセス定義ファイルを作成できますが、これが常に最も便利な方法とは限りません。 ただし、幸いなことに、Flowableにはhttps://www.flowable.org/docs/userguide/index.html#flowableDesigner[Eclipse plugin]またはhttps://www.flowableを使用してこれを行うためのユーザーインターフェイスオプションが付属しています。 org / docs / userguide / index.html#flowableApps [Webアプリケーション]。

4. Flowable APIの使用

BPMN 2.0標準に従ってXMLファイルで単純なプロセスを定義したので、それを送信して実行する方法が必要です。 * Flowableは、Flow Engineと対話するProcess Engine APIを提供します*。 Flowableは非常に柔軟性があり、このAPIを展開するいくつかの方法を提供します。
FlowableはJava APIであるため、必要なJARファイルを含めるだけで、任意のJavaアプリケーションにプロセスエンジンを含めることができます。 これらの依存関係を管理するためにMavenを非常にうまく活用できます。
さらに、Flowableには、Flowable over HTTPと対話するためのREST APIがバンドルされています。 これらのREST APIを使用して、Flowable APIを介して可能な限りほとんどすべてを実行できます。
最後に、* FlowableはSpringおよびSpring Bootとの統合を非常にサポートしています!*チ​​ュートリアルではFlowableとSpring Bootの統合を使用します。

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

Flowableからプロセスエンジンをラップし、Flowable APIとやり取りするREST APIを提供する簡単なアプリケーションを作成しましょう。 エクスペリエンスを向上させるために、REST 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>
必要な依存関係はすべてMaven Centralで利用できます。

5.2. プロセス定義

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

5.3. 構成

Spring Bootはアプリケーションの構成に対して非常に考え抜かれたアプローチを取っていることを知っているので、Spring Bootの一部としてFlowableにも当てはまります。 たとえば、*クラスパス上の唯一のデータベースドライバーとしてH2を検出すると、Flowableはそれを使用するように自動的に構成します*。
明らかに、構成可能なすべての側面は、https://www.flowable.org/docs/userguide/index.html#springBootFlowableProperties [application properties]を介してカスタムの方法で構成できます。 ただし、このチュートリアルでは、デフォルトのままにします!

5.4. Javaデリゲート

プロセス定義では、サービスタスクの一部として呼び出されるはずのいくつかのJavaクラスを使用しました。 *これらのクラスは_JavaDelegate_インターフェースを実装し、FlowableではJavaデリゲートとして知られています*。 これらの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. REST API

最後に、プロセスエンジンと対話し、定義したプロセスを操作するためのRESTエンドポイントを作成しましょう。
最初に、3つのエンドポイントを公開するRESTコントローラーを定義します。
@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クライアントを使用して、作成した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の標準的な単体テストのように見えるはずです。 現在、テストメソッドに関連するプロセスデプロイメントを作成および削除するために、Flowableによって_ @ Deployment_アノテーションが提供されています。

7. プロセスの展開について

このチュートリアルではプロセス展開の詳細については説明しませんが、重要ないくつかの側面を説明することは価値があります。
通常、プロセスはビジネスアーカイブ(BAR)としてアーカイブされ、アプリケーションにデプロイされます*。 展開中、このアーカイブは、プロセス定義などのアーティファクトをスキャンして処理されます。 _“。bpmn20.xml” ._で終わるプロセス定義ファイルの規則に気づいたかもしれません
チュートリアルではデフォルトのインメモリH2データベースを使用しましたが、実際にはこれは実際のアプリケーションでは使用できません。単純な理由により、インメモリデータベースはスタートアップ間でデータを保持せず、実際にはクラスター環境では使用できません! したがって、*実稼働グレードのリレーショナルデータベースを使用し、アプリケーションで必要な構成を提供する必要があります*。
BPMN 2.0自体にはバージョニングの概念はありませんが、* Flowableはプロセスのバージョン属性を作成し、データベースにデプロイされます*。 属性「id」で識別される同じプロセスの更新されたバージョンがデプロイされると、バージョンがインクリメントされる新しいエントリが作成されます。 「id」でプロセスを開始しようとすると、プロセスエンジンはデプロイされたプロセス定義の最新バージョンを取得します。
前に説明したデザイナーのいずれかを使用してプロセス定義を作成する場合、プロセスの視覚化は既に行われています。 *プロセス図を画像としてエクスポートし、XMLプロセス定義ファイルと一緒に配置できます。*標準のhttps://www.flowable.org/docs/userguide/index.html#providingProcessDiagram [命名規則]に準拠する場合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を使用しているため、幸運です!
    link:/spring-boot-actuators[Spring BootはActuator Endpointsを提供]を使用して、HTTP経由でアプリケーションメトリックを収集します。 これをhttps://prometheus.io/docs/visualization/grafana/[Prometheus and Grafana]などのツールスタックとシームレスに統合して、最小限の労力でプロダクショングレードの監視ツールを作成できます。
  • Flowableは、実行中のプロセスに関する情報を公開する追加のアクチュエータエンドポイントを提供します。*これは、JMXを介した情報収集ほどではありませんが、迅速、簡単、そして何よりも十分です。

10. 結論

このチュートリアルでは、ビジネスプロセスと、BPMN 2.0標準でビジネスプロセスを定義する方法について説明しました。 次に、プロセスをデプロイおよび実行するためのFlowable Process EngineとAPIの機能について説明しました。 これをJavaアプリケーション、特にSpring Bootに統合する方法を見ました。
さらに続けて、展開、視覚化、監視などのプロセスの他の重要な側面について説明しました。 言うまでもなく、ビジネスプロセスとFlowableのような強力なエンジンの表面に触れただけです。 Flowableには、十分なドキュメントが利用可能な非常に豊富なAPIがあります。 ただし、このチュートリアルは、このテーマへの興味をそそるものでした。
いつものように、例のコードが利用可能ですhttps://github.com/eugenp/tutorials/tree/master/spring-boot-flowable[over on GitHub]。