業務ルールをビジュアル化してそのまま実装!DMNをVSCodeで作成してみよう

レッドハットのソリューションアーキテクトの森です。
Red Hat Decision Manager / Process Automation Manager は、VSCode 拡張機能のサポートが提供され、Visual Studio Code (VSCode) で BPMN モデル、 DMN モデル、及びテストシナリオを可視化し、設計できるようになりました。

今回は、VSCode で DMNモデルを用いて簡単なルールを作成して動かしてみたいと思います。

必要なセット

  • VSCode
  • Red Hat Business Automation Bundle (VSCode拡張機能)
  • KIE Server (RHDM/PAM に 含まれている、REST API でルールを実行できるサーバアプリ)
  • Java 11
  • Maven
  • Git

DMN について

DMN (Decision Model and Notation) は、業務的意思決定を説明してモデル化するための表記法です。OMG (Object Management Group)によって定義されています。 業務ルールを整理し定義する際に、DMNを使うことで、要件定義・設計・実装における認識の齟齬を低減し、開発効率と品質を向上することが期待されます。 DMNの基本については、こちらも合わせてご覧いただければと思います。

qiita.com

ルールの要件

今回は、ドライバーが交通違反をした時の罰則の判断(罰金・減点)と、免許停止の判断をサンプルとして作ってみます。

  • 違反の内容が 速度超過 で、超過速度が 10km/h 以上、30km/h 未満の場合、違反点数 3、罰金 500
  • 違反の内容が 速度超過 で、超過速度が 30km/h 以上の場合、違反点数 7、罰金 1000
  • 違反の内容が 駐車違反の場合、違反点数 1、罰金 100
  • 違反の内容が 飲酒運転の場合、違反点数 5、罰金 1000
  • 違反点数が 累計 20 以上の場合、免許停止となる

プロジェクトの作成

まずは Maven アーキタイプを使用して、新しいプロジェクトを作成します。

mvn archetype:generate \
    -DarchetypeGroupId=org.kie \
    -DarchetypeArtifactId=kie-kjar-archetype \
    -DarchetypeVersion=7.48.0.Final-redhat-00004

※ Red Hat Maven Repository(https://maven.repository.redhat.com/ga/) を ~/.m2/settings.xml に設定しておく必要があります。

設定例:

1) 以下の XML を settings.xml ファイルの <profiles> 要素へコピーします。

<!-- Configure the JBoss Enterprise Maven repository -->
<profile>
  <id>jboss-enterprise-maven-repository</id>
  <repositories>
    <repository>
      <id>jboss-enterprise-maven-repository</id>
      <url>https://maven.repository.redhat.com/ga/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>jboss-enterprise-maven-repository</id>
      <url>https://maven.repository.redhat.com/ga/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </pluginRepository>
  </pluginRepositories>
</profile>

2) 以下の XML を settings.xml ファイルの <activeProfiles> 要素へコピーします。

<activeProfile>jboss-enterprise-maven-repository</activeProfile>

※ 7.48.0.Final-redhat-00004 は RHDM 7.10 に対応しています。

デフォルトのGAV(group:artifact:version)を使用してプロジェクトを作成するかを聞かれますので、一旦そのままとしておきます。

f:id:ka_mori:20210616180113p:plain:w400

DNM ファイルの作成

次に、src/main/resource 配下のフォルダに、traffic-violation.dmn というファイルを作成します。

f:id:ka_mori:20210616175247p:plain:w400

ファイルを作成すると、以下のような DMN エディタが開きます。

f:id:ka_mori:20210616180940p:plain:w800

DMN エディタが開いたら、入力データノードを2つキャンバスに配置し、それぞれ、ドライバー情報, 違反情報 と名前を変更します。 (名前の変更はノードをダブルクリックするか、右側のプロパティパネルの Name を変更します)

続いて、罰則の内容を判断するデシジョンと、免許停止かどうかを判断するデシジョンを作成します。 デシジョンノードを2つキャンバスに配置し、それぞれ、罰則, 免許停止 と名前を変更します。

入力データノード 違反情報 から、デシジョンノード 罰則 へ、情報要件を用いて接続をします。

f:id:ka_mori:20210616181033p:plain:w500

以下のように各ノードを接続して下さい。

f:id:ka_mori:20210616181057p:plain:w400

データ構造の定義

次に、DMN で使用するデータ構造について定義をします。

エディタの上部メニューからデータタイプを選択し、中央の Add a custom Data Type をクリックして下さい。

f:id:ka_mori:20210616181304p:plain:w600

  • Name: ドライバー情報
  • タイプ: Structure

と入力し、右側のチェックマークをクリックすると、ドライバー情報 という名前の Structure型 のデータが定義されます。

f:id:ka_mori:20210616181135p:plain:w800

以下の表に従って、3つの Structure型 を含むデータを定義して下さい。

Name タイプ
ドライバー情報 Structure
点数 number


Name タイプ
違反情報 Structure
タイプ string
制限速度 number
違反時速度 number


Name タイプ
罰則情報 Structure
罰金 number
点数 number

下記のように定義ができていればOKです。

f:id:ka_mori:20210620010156p:plain:w600

エディターに戻り、各ノードのデータタイプを定義していきます。

入力データノード ドライバー情報 をクリックし、右側のプロパティパネルの情報アイテムで、データタイプを ドライバー情報 に設定して下さい。

f:id:ka_mori:20210616181431p:plain:w800

他のノードも、下記の表に従って設定をします。

ノード データタイプ
ドライバー情報 ドライバー情報
違反情報 違反情報
罰則 罰則情報
免許停止 string

デシジョンの作成

2つのデシジョン、罰則, 免許停止 について、ルールの定義を行っていきます。

デシジョンノード 罰則 を選択し、編集 をクリックしてデシジョンエディタを開きます。

f:id:ka_mori:20210616181508p:plain:w400

式の選択をクリックし、デシジョンテーブルを選択します。

f:id:ka_mori:20210616181536p:plain:w200

条件列として、情報要件で接続した入力データノードの内容が、またアクション列として、デシジョンのデータタイプの内容が既に設定されています。

f:id:ka_mori:20210616181610p:plain:w600

違反情報.違反時速度 の列を、違反情報.違反時速度 - 違反情報.制限速度 に修正をして、 違反情報.制限速度 の列を削除します。

次に、罰則のルールの要件に従って条件とアクションを作成していきます。

下記の表のように各行を設定をして下さい。

f:id:ka_mori:20210616181630p:plain:w600

[10..30) は、10以上、30未満(10 ≦ x < 30)という意味になります。

続いて、デシジョンノード 免許停止 を選択し、編集 をクリックしてデシジョンエディタを開きます。

式の選択をクリックし、コンテキストを選択します。

f:id:ka_mori:20210616181721p:plain:w300

ContextEntry-1 をクリックして、Name に 累計点数 、データタイプ に number と入力します。

f:id:ka_mori:20210616181825p:plain:w300

累計点数 の右の式の選択をクリックして文字式を選択し、ドライバー情報.点数 + 罰則.点数 と入力します。

次に、<result> の右の式の選択をクリックして文字式を選択し、if 累計点数 >= 20 then "はい" else "いいえ" と入力します。

f:id:ka_mori:20210616182033p:plain:w600

こちらの記述式については、FEEL(Friendly Enough Expression Language) という言語で、簡単に計算等のロジックを記述できます。 DMN における FEEL の詳細は OMG の Decision Model and Notation specification を参照してみてください。

以上で、DMN の作成については完了です!

シナリオテスト

VSCode拡張機能を使って、DMN のテストシナリオを作成することができます。

テストシナリオを使用するには、プロジェクトに以下の依存関係を追加する必要があります。

  • junit:junit
  • org.drools:drools-scenario-simulation-backend
  • org.drools:drools-scenario-simulation-api

org.drools については、org.kie と バージョンを合わせる必要があります。 今回のサンプルでは、RHDM 7.10 を使用しており、7.48.0.Final-redhat-00004 となります。

プロジェクトの pom.xml を開き、次の依存関係を追加して下さい。

  <dependencies>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-scenario-simulation-api</artifactId>
      <version>${version.org.kie}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-scenario-simulation-backend</artifactId>
      <version>${version.org.kie}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

次に、src/test/java 配下のフォルダに、testscenario というフォルダを作成します。 そのフォルダの中に、下記の内容で ScenarioJunitActivatorTest.java というファイルを作成しておくことで、Junit と一緒にテストシナリオを実行できるようになります。

  package testscenario;

  @org.junit.runner.RunWith(org.drools.scenariosimulation.backend.runner.ScenarioJunitActivator.class)
  public class ScenarioJunitActivatorTest {
  }

f:id:ka_mori:20210616182127p:plain:w800

それでは、テストシナリオを作成していきます。

src/test/resources 配下のフォルダに、org/kie/businessapp というフォルダを作成し、その中に Violation_Scenarios.scesim というファイルを作成します。

テストシナリオのエディタが開きますので、下記を指定します。

  • Source type: DMN
  • Choose a valid DMN asset from the list: traffic-violation.dmn

f:id:ka_mori:20210616182156p:plain:w400

入力と期待値については、列が既に設定されています。 いくつかのパターンで、シナリオを作成してみて下さい。

テストを実行するには、ターミナルから mvn test を実行するか、ScenarioJunitActivatorTest.java ファイルを右クリックして、Run java を選択します。

f:id:ka_mori:20210616182222p:plain:w800

テストの結果が問題なければ、mvn clean install を実行して、プロジェクトがコンパイルできることを確認します。

KIE Server の準備

ルールを実行するための KIE Server を準備します。 Red Hat Customer Portal にログインして、下記ファイルをダウンロードします。

1) jboss-eap-7.3.0.zip を解凍します。解凍したファイルを格納したフォルダを、仮に $EAP_HOME としておきます。

2) rhdm-7.10.0-kie-server-ee8.zip$EAP_HOME フォルダ内に解凍します。

3) $EAP_HOME/SecurityPolicy フォルダ配下のファイルを、$EAP_HOME/bin/ に移動します。

mv SecurityPolicy/* $EAP_HOME/jboss-eap-7.3/bin/

4) $EAP_HOME/kie-server.war フォルダを、$EAP_HOME/standalone/deployments/に移動します。

mv kie-server.war/ $EAP_HOME/jboss-eap-7.3/standalone/deployments/

5) kie-server.war を自動デプロイするための .dodeploy ファイルを作成します。

touch $EAP_HOME/jboss-eap-7.3/standalone/deployments/kie-server.war.dodeploy

6) KIE Server REST 機能にアクセス可能なユーザを追加します。パスワードは 8 文字以上で、数字と、英数字以外の文字をそれぞれ 1 文字以上使用する必要があります。ただし & の文字は使用できません。<USERNAME><PASSWORD> 書き換えて実行してください。

$EAP_HOME/jboss-eap-7.3/bin/add-user.sh -a --user <USERNAME>  --password <PASSWORD> --role kie-server,admin

7) EAP を起動します。

$EAP_HOME/jboss-eap-7.3/bin/standalone.sh -c standalone-full.xml

8) 設定したユーザとパスワードを使用して、ブラウザから http://localhost:8080/kie-server/services/rest/server にアクセスできればOKです。

デプロイ

今回は、KIE Server REST API を使用して、DMN を含むプロジェクトをデプロイしていきます。

まず、ブラウザで KIE Server REST API を開きます。(デフォルトの設定でローカル上に起動している場合は、 http://localhost:8080/kie-server/docs

f:id:ka_mori:20210616182241p:plain:w800

KIE Server and KIE containers のメニューから、[PUT] /server/containers/{containerId} を開き、Try it out をクリックします。

下記の内容を入力します。

  • containerId: mybusinessapp
  • body:
{
  "container-id": "mybusinessapp",
  "release-id": {
    "group-id": "org.kie.businessapp",
    "artifact-id": "mybusinessapp",
    "version": "1.0"
  }
}
  • Parameter content type: application/json

f:id:ka_mori:20210616182305p:plain:w800

Execute をクリックし、下記のような実行結果が出力されればOKです。

f:id:ka_mori:20210616182330p:plain:w600

それでは、KIEServer へデプロイした DMN を実行してみましょう。

f:id:ka_mori:20210616182400p:plain:w800

DMN models のメニューから、[POST] /server/containers/{containerId}/dmn を開き、Try it out をクリックします。

  • containerId: mybusinessapp
  • body:
{
  "dmn-context": {
    "ドライバー情報": {
      "点数": 17
    },
    "違反情報": {
      "タイプ": "速度超過",
      "制限速度": 100,
      "違反時速度": 120
    }
  }
}
  • Parameter content type: application/json
  • Response content type: application/json

f:id:ka_mori:20210616182424p:plain:w800

正しく実行できていれば、下記のような出力が帰ってくるはずです。

f:id:ka_mori:20210616182444p:plain:w600

いかがでしたでしょうか?

VSCode拡張機能 を使うことで、BPMN モデル、DMN モデル の開発がしやすくなっていると思います。

ぜひ試してみて下さい。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。