Business Automation Manager Open Edition メモ - (6) Embedded形態でのルール開発(DMN編)

# はじめに
当記事では、前回同様Embedded(組み込み型)のルール開発の流れを確認しますが、ルール開発部分にはDMNを使用してみたいと思います。
DMN(Decision Model and Notation)はルールをグラフィカルに記述するための表記法で、OMGにより標準化が進められています。Business Centralで提供されていたルール開発支援機能の代替として利用できる機能と言えそうです。
※当記事で試す手順はスタンドアローンのJavaアプリケーションで実行するシナリオなので、前の記事で作成したBusiness CentralやKIE Serverは不要です。

## 関連記事
[Business Automation Manager Open Edition メモ - (1) 概要](https://qiita.com/tomotagwork/items/31f5ad04b0efa193809e)
[Business Automation Manager Open Edition メモ - (2) KIE Server, Business Central 構成](https://qiita.com/tomotagwork/items/92362b8a2d9f4cfd3219)
[Business Automation Manager Open Edition メモ - (3) Business Centralを使用したルール開発](https://qiita.com/tomotagwork/items/e0a680f62baf2900f7a1)
[Business Automation Manager Open Edition メモ - (4) KIEサーバー上のルール呼び出し](https://qiita.com/tomotagwork/items/092f221dd3a84214102b)
[Business Automation Manager Open Edition メモ - (5) Embedded形態でのルール開発(DRL編)](https://qiita.com/tomotagwork/items/c0a670845b499c6e2de3)
[Business Automation Manager Open Edition メモ - (6) Embedded形態でのルール開発(DMN編)](https://qiita.com/tomotagwork/items/c7d2ff45d102484a1df9)
[Business Automation Manager Open Edition メモ - (7) kogitoでのルール開発(スタンドアローン)](https://qiita.com/tomotagwork/items/1a16377d882e3886f69f)
[Business Automation Manager Open Edition メモ - (8) kogitoでのルール開発(OpenShiftへのデプロイ)](https://qiita.com/tomotagwork/items/8b23cf90d25505edf45a)

# 全体像
いわゆる組み込み型(Embedded)の形態、つまり、ルール部分と、ルールを呼び出すアプリが一体となっている形態を動かすことを目指します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/6e3182c2-b2f6-0fd4-c652-fdf878e2ce85.png)
開発、実行までの流れを確認することが目的なので、できるだけシンプルな形とします。ルール部分はDMNによる記述、アプリはStandAloneのJavaアプリケーションとします。


# 環境情報

今回はWindowsPC上で試します。以下のコンポーネントはセットアップ済みの想定です。

OS: Windows11

Java: OpenJDK 11

```
c:\>java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
```

ビルド管理ツール: Maven 3.8.6

```
c:\>mvn -v
Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: C:\x\apache-maven-3.8.6
Java version: 1.8.0_144, vendor: Oracle Corporation, runtime: C:\x\Java\jdk1.8.0_144\jre
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
```

ルール開発ツール: VS Code 1.73.1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/13f5ba6f-fa83-a04d-49d6-081ae5b243ce.png)

VS CodeのExtensionとしては以下のものを使用

Java,Maven関連
[Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)
[Debugger for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug)

DMN関連
[Red Hat Business Automation Bundle](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-extension-red-hat-business-automation-bundle)

※ここではWindows11環境での実行を試していますが、IBM BAM OE V8.0.1としてサポートしているOSはRHEL8, WindowsServer2016のみです。
参考: [System Requirements for IBM Business Automation Manager Open Editions 8.0.1](https://www.ibm.com/software/reports/compatibility/clarity-reports/report/html/softwareReqsForProduct?deliverableId=A0C4EFF0306311ED89D524E10733C3D5&osPlatforms=Linux|Windows&duComponentIds=S004|S005|C007|C008|C006&mandatoryCapIds=30|25&optionalCapIds=127|9|71|35|161|26)
Windows11でも動くだろうということで試しているものですのでご注意ください。また、droolsやkogitoなどオープンソースのプロジェクトでは基本的にRHELをベースに開発、テストが実施されているとのことで、Windows環境で実行する場合Windows固有の問題が発生することが多々あるようです。特に日本語を扱う必要がある場合は、実環境としてはLinuxでの利用を強くお勧めします。(もしくはMacの方がWindowsよりは問題が少ないと思われます。)

# Mavenを使用したDMNでのルール開発、実行の流れ
以下の記述を参考に、Embedded用にカスタマイズして試していきます。
[Learning IBM Business Automation Open Edition - 32. Business Automation projects in VSCode](https://timwuthenow.github.io/guided_exercises/tools/getting-started/)
[赤帽エンジニアブログ - 業務ルールをビジュアル化してそのまま実装！DMNをVSCodeで作成してみよう](https://rheb.hatenablog.com/entry/create_dmn_with_vscode)

## 事前準備
VS Code上で新規にワークスペースを作っておきます。

## Javaアプリケーション用のMavenプロジェクト作成

コマンド・プロンプトを開き、ワークスペースのフォルダに移動して以下のコマンド実行します。

```
c:\y\VSCode_workspace\BAMOE_DMN>mvn archetype:generate -DgroupId=com.sample.app -DartifactId=dmn-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.2.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.2.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.2.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: c:\y\VSCode_workspace\BAMOE_DMN
[INFO] Parameter: package, Value: com.sample.app
[INFO] Parameter: groupId, Value: com.sample.app
[INFO] Parameter: artifactId, Value: dmn-app
[INFO] Parameter: packageName, Value: com.sample.app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: c:\y\VSCode_workspace\BAMOE_DMN\dmn-app
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.970 s
[INFO] Finished at: 2022-12-05T14:26:43+09:00
[INFO] ------------------------------------------------------------------------
```


以下のフォルダ、ファイルが作成されます。(Javaアプリ用のMavenプロジェクトが作成されました)

```
c:\y\VSCode_workspace\BAMOE_DMN>tree dmn-app /f
フォルダー パスの一覧:  ボリューム Windows
ボリューム シリアル番号は 7E75-9120 です
C:\Y\VSCODE_WORKSPACE\BAMOE_DMN\DMN-APP
│  pom.xml
│
└─src
    ├─main
    │  └─java
    │      └─com
    │          └─sample
    │              └─app
    │                      App.java
    │
    └─test
        └─java
            └─com
                └─sample
                    └─app
                            AppTest.java
```

このdmn-appをVS Codeのワークスペースに追加します。

## 管理ファイルの作成

### kmodule.xml (KIE module descriptor)
`src/main/resources/META-INF/`以下にkmodule.xmlファイルを作成します。
とりあえず今回のサンプル実行ではデフォルトでよさそうなので、以下のようなファイルを作成します。

```xml:kmodule.xml
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
</kmodule>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/473f5559-42ae-4df0-e334-ef1b32f61742.png)


### pom.xml

pom.xmlに依存関係の設定等を追加していきます。


<details><summary><font color="blue">pom.xml</font></summary><div>

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.sample.app</groupId>
  <artifactId>dmn-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>dmn-app</name>

  <repositories>
    <repository>
      <id>jboss-ga-repository</id>
      <url>https://maven.repository.redhat.com/ga/</url>
    </repository>
  </repositories>

  <properties>
    <version.org.kie>7.67.0.Final-redhat-00008</version.org.kie> 
    <!-- <version.org.kie>8.29.0.Final-redhat-00012</version.org.kie> -->
    <version.org.drools>7.67.0.Final-redhat-00008</version.org.drools>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

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

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M6</version>
        <configuration>
          <argLine>-Dfile.encoding=UTF-8</argLine>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>
```

</div></details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/976c4c91-69dc-8d2a-c931-2e95eeda1bca.png)

※補足
依存関係のあるモジュールは https://maven.repository.redhat.com/ga/ に提供されていますので、リポジトリの定義を追加しています。(2022年11月点ではリポジトリとしてはRedHatさんが提供しているものしか無いようなのでそちらを使います。この時点ではIBMさんは別のリポジトリを立ててはいないようで、モノは同じということでRedHatさんのリポジトリを使えばよいようです。)
参考: [Learning IBM Business Automation Open Edition - Environment Setup - Maven](https://timwuthenow.github.io/guided_exercises/00_get_tools/env-setup/#maven)
>With IBM Business Automation Open Edition 8.0, the components are built around a Maven architecture predominantly. What this ultimately means is your workstation needs to be able to communicate with one to many different Maven Repositories. These labs will use two in particular, the Red Hat General Availability repository and Maven Central. You could easily replace the two repositories with a local environment one hosting the Maven dependencies as a mirror or based in a disconnected installation, but this is the easiest developer workflow for acquiring new dependencies. The reason we are pointing to the Red Hat Maven repository, at least in the short term, is that the builds for IBM Business Automation Open Edition 8.0 are being deployed there as they are the same binaries used within both the IBM and Red Hat products during the transition of Red Hat Process Automation Manager (RHPAM)/Red Hat Decision Manager (RHDM) from Red Hat into IBM Automation under the name of IBM Business Automation Open Edition 8.0 ( IBAMOE).


ルール実行のための依存関係として以下のモジュールを指定しています。
- [kie-dmn-core](https://maven.repository.redhat.com/ga/org/kie/kie-dmn-core/)
- [kie-api](https://maven.repository.redhat.com/ga/org/kie/kie-api/)
- [drools-scenario-simulation-api](https://maven.repository.redhat.com/ga/org/drools/drools-scenario-simulation-api/)
- [drools-scenario-simulation-backend](https://maven.repository.redhat.com/ga/org/drools/drools-scenario-simulation-backend/)

drools-scenario-xxxというモジュールは、表形式でテストシナリオを作成して実行するためのものです。
バージョンは7.xの最新のものを指定しています(7.67.0.Final-redhat-00017)。

maven-surefire-pluginで「-Dfile.encoding=UTF-8」を指定しているのはWindows環境で実施しているためです。末尾のメモに残していますが、テストシナリオ内に日本語文字列を含む場合にWindows環境でこの設定をしていないとエラーでうまくテスト実行できませんでした。


## DMNによるルール作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/155f1ed9-49d0-646a-2f72-6ddd78cb1c49.png)

### DMNファイル作成
`src\main\resources\test01\'以下に、CustomerLoyalty.dmnというファイルを新規に作成します。
dmnという拡張子を指定したファイルを作成すると、以下のようにDMNのエディターが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/430aefb5-1e93-4c9a-a3f5-42681b45453f.png)

ここにDMN表記でルールを作成していきます。

### データタイプ作成
まずデータオブジェクトの型となるデータタイプを定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/aa0ed581-835d-ce11-9a1a-421e5c85b932.png)

まず入力用のデータタイプとしてLoyaltyInという名前のデータタイプを定義します。
名前に"LoyaltyIn"を指定し, タイプから"Structure"を選択し、保存のアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c92baa6e-4148-c03e-95c3-00daa5448403.png)

rankというstring型のフィールドを定義して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1dec7fc2-2898-0942-e437-49dfd1696608.png)

※ここでは入力フィールドとしてrank一つだけ定義します。string型1つのみ保持するStructureはあまり意味がないですが、ここは手順を確認する目的なのでシンプルな型として定義しています。

次に出力用のデータタイプを作成するので、新規データタイプをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c7eeabfe-ff76-dcaf-6189-4f307db5620b.png)

出力用としてLoyaltyOutという名前のデータタイプを定義します。
名前に"LoyaltyOut"を指定し, タイプから"Structure"を選択し、保存のアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/867c65c6-b5db-dce5-4f2c-f05e7e841364.png)

LoyaltyOutには、number型のdiscountRate、string型のmessageを定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/48bcecc4-de97-a5fc-6e7e-a8c676db8252.png)

※データタイプ作成時には先にJavaクラスを作ってそれをDMNのデータタイプとしてimportするのがよさそうな気がします。この画面上では「import java classes」という機能がグレーアウトされていますが、この機能を有効化するとJavaのクラスを取り込んでデータタイプを作成することができるようです。
https://blog.kie.org/2022/05/dmn-types-from-java-classes.html
ただ、この機能は比較的新しい機能のようで、上の記事だとkie-apiの8.22.0.Betaで使えるもののようです。今回は7.xx使用しているのでここではこの機能は使用しないことにします。

### 入力データの配置

エディターに戻って、「DMN入力データ」をエディター内にドラッグ&ドロップし、名前をloyaltyに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5e219d6b-7b0e-9f7e-deb8-9a1175553d73.png)

画面右端のプロパティーアイコンをクリックしてプロパティー画面を表示し、データタイプとして先ほど定義したLoyaltyInを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/cf73c82c-b11e-2b9f-e327-0e3e127ba72a.png)

### DMNディシジョンの配置

「DMNデシジョン」をエディター内にドラッグ&ドロップし、名前をdecisionLoyaltyに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/8d03435f-801f-306e-64f6-dc75c045a652.png)

画面右端のプロパティーアイコンをクリックしてプロパティー画面を表示し、データタイプとして先ほど定義したLoyaltyOutを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c35fcf99-db1c-922a-b01a-b06698020861.png)

### 入力データとディシジョンの接続

loyaltyを選択して矢印アイコンを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5da0b34b-5992-d0bd-a380-26c70bb9cf4a.png)

decisionLoyaltyと矢印を接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/f5c6b685-79f9-b97a-945c-3aae3e2fbcca.png)

### ディシジョンの定義

ここでいよいよルールを定義していきます。
decisionLoyaltyをクリックして編集アイコンを選択します。、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/7fba2a5c-5ced-db78-8b0d-67f200f864b2.png)

「式の選択」をクリックし、プルダウンから「デシジョンテーブル」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/20113d14-5b07-6da1-b4b8-efe5903109cf.png)
※ここでは表形式でルールを作成することを想定しているため「デシジョンテーブル」を選択しています。

テーブルの雛形が表示されるので、ここにルールを指定していきます。左側の薄いブルーの列が入力値(判断の元になる値)で、右側の濃いブルーの列が出力値(判定結果)を意味します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/90794cb1-f3c5-c991-8f4c-34e5d615017c.png)

以下のように表を埋めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5899e137-c91e-f6c6-be8c-6a99ff103d5d.png)

### その他の設定

メインの画面に戻って、プロパティー画面で、Namespaceを以下のように指定します(末尾をtest01に変更)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/87c306ed-ded8-0bca-1742-28036aa24455.png)

一通りDMNファイルの編集が済んだので保存して終了します。

## ルールのテスト

### JUnit Runnerの作成

`src\test\java\testscenario\`以下に、ScenarioJunitActivatorTest.javaを作成し、以下のように編集します。

```java:ScenarioJunitActivatorTest.java
package testscenario;

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/f565d0d1-20e0-09a0-117d-d49422c1546f.png)

### テストシナリオ作成

`src\test\resources\test01\'以下にValidateCustomerLoyalty.scesimファイルを作成します。拡張子"scesim"を持つファイルを作成すると、テストシナリオエディターが開くので、DMNを選択してテスト対象のCustomerLoyalty.dmnを選択して「+Create」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1ea78ffd-89bc-c17b-b8f1-547e532d578d.png)

表のガラができるので、入力値と、結果として期待される期待値をセットしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/6aebd6a8-0c9b-d51d-a7d1-0c5cc0cb0f67.png)

### テスト実行
ScenarioJunitActivatorTest.javaを右クリック-Run Javaを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ac9844e1-26cf-540a-2340-76788b5d3b6c.png)

以下のようにテストが実行されて結果が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/6110ad38-45d3-8d66-85c6-bd75e42d09ee.png)

もしくは、左下のMavenのビューからtestを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5d861a8c-8b78-b940-cd27-4476f192dacb.png)


## ルール呼び出しJavaアプリケーション作成

参考: [Developing decision services in IBM Business Automation Manager Open Editions - 7.1. Embedding a DMN call directly in a Java application](https://access.redhat.com/documentation/en-us/ibm_business_automation_manager_open_editions/8.0/html-single/developing_decision_services_in_ibm_business_automation_manager_open_editions/index#dmn-execution-embedded-proc)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5a07785e-cca1-2b66-4a25-d9155ff1ef69.png)

### Factとなるデータオブジェクトの作成
Javaのクラスとしてデータオブジェクトを作成します。`src/main/java/test01/Loyalty.java`にFactとなるJavaアプリケーションを作成していきます。
これは、DMNで作成したデータ・タイプに合わせて作成していきます。

<details><summary><font color="blue">Loyalty.java</font></summary><div>

```java:Loyalty.java
package test01;

public class Loyalty {

    private String rank;

    public String getRank() {
      return rank;
    }

    public void setRank(String rank) {
      this.rank = rank;
    }

}
```

</div></details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/2a95263d-3908-57e6-cbd6-0db784497d05.png)


### ルール呼び出しロジック作成
`src/main/java/com/sample/app/App.java`にルール呼び出しを行うJavaアプリケーションを作成していきます。

<details><summary><font color="blue">App.java</font></summary><div>

```java:App.java
package com.sample.app;

import java.util.HashMap;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieRuntimeFactory;
import org.kie.dmn.api.core.DMNContext;
import org.kie.dmn.api.core.DMNDecisionResult;
import org.kie.dmn.api.core.DMNModel;
import org.kie.dmn.api.core.DMNResult;
import org.kie.dmn.api.core.DMNRuntime;

import test01.Loyalty;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        // Parse arguments :
        String strRank = args[0];

        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        DMNRuntime dmnRuntime = KieRuntimeFactory.of(kieContainer.getKieBase()).get(DMNRuntime.class);

        String namespace = "https://kiegroup.org/dmn/test01";
        String modelName = "CustomerLoyalty";

        DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName);

        DMNContext dmnContext = dmnRuntime.newContext();

        Loyalty loyalty = new Loyalty();
        //loyalty.setRank("gold");
        loyalty.setRank(strRank);

        dmnContext.set("loyalty", loyalty);

        DMNResult dmnResult = dmnRuntime.evaluateAll(dmnModel, dmnContext);
        DMNDecisionResult decisionResult_discount = dmnResult.getDecisionResultByName("decisionLoyalty");
        Object objResult = decisionResult_discount.getResult();
        //System.out.println("Result: " + objResult);

        if (objResult instanceof HashMap) {
            @SuppressWarnings("unchecked")
            HashMap<Object, Object> hashResult = (HashMap<Object,Object>)objResult;
            for (Object key : hashResult.keySet()) {
                System.out.println(key + " : " + hashResult.get(key));

            }
        }
        
        /*
        for (DMNDecisionResult dr : dmnResult.getDecisionResults()) {
            System.out.println("Decision: '" + dr.getDecisionName() + "', " +
                                "Result: " + dr.getResult());
        }
        */
    }
}
```

</div></details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/2c98c084-545b-35c8-6182-cffecab93134.png)

## ルール呼び出しJavaアプリケーションのデバッグ/実行

あとは一般的なJavaアプリと同様にデバッグやら実行をして動作確認をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/61428c20-1b0a-da8c-26ce-e082880e9c38.png)

入力値、"gold"に対して、ルール判定によりdiscountRate:0.2が返されることが確認できました。


# おまけ: エラーmemo
テストシナリオに日本語を含めるとうまく動かない事象が発生しました。その時のログを参考までに残しておきます。

例えば以下のようにGIVENの列に日本語の文字列を記入してテストしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/6b2a12f8-0554-d95e-05ab-7df1a608b432.png)

ScenarioJunitActivatorTest.javaを右クリックしてRun Javaだと一応動く。(テスト結果がNGになるのは想定内)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/31747c66-2534-cee6-c09a-ae24b6f9d12b.png)

ただMavenのtestを実行するとテスト実行そのものがExceptionを吐く(日本語を含まない場合はOK)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/2b9981c3-c560-59f0-cd0d-6b4bc23ac41e.png)

<details><summary><font color="blue">Exception時のログ</font></summary><div>

```ログ
PS C:\y\VSCode_workspace\BAMOE_DMN\dmn-app> & mvn test -f "c:\y\VSCode_workspace\BAMOE_DMN\dmn-app\pom.xml" 
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< com.sample.app:dmn-app >-----------------------
[INFO] Building dmn-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ dmn-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ dmn-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ dmn-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ dmn-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ dmn-app ---
[INFO] Surefire report directory: c:\y\VSCode_workspace\BAMOE_DMN\dmn-app\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.sample.app.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.034 sec
Running testscenario.ScenarioJunitActivatorTest
[Fatal Error] :618:38: 1バイトのUTF-8シーケンスのバイト1が無効です。
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.395 sec <<< FAILURE!
testscenario.ScenarioJunitActivatorTest  Time elapsed: 0.395 sec  <<< ERROR!
org.drools.scenariosimulation.backend.runner.ScenarioException: Issue on parsing file: C:\y\VSCode_workspace\BAMOE_DMN\dmn-app\target\test-classes\test01\ValidateCustomerLoyalty.scesim
        at org.drools.scenariosimulation.backend.runner.ScenarioJunitActivator.parseFile(ScenarioJunitActivator.java:85)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
        at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
        at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)        
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)    
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
        at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)        
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)    
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
        at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)        
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
        at org.drools.scenariosimulation.backend.runner.ScenarioJunitActivator.getChildren(ScenarioJunitActivator.java:62)
        at org.junit.runners.ParentRunner.getFilteredChildren(ParentRunner.java:426)
        at org.junit.runners.ParentRunner.getDescription(ParentRunner.java:351)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:359)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)   
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)  
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: org.xml.sax.SAXParseException; lineNumber: 618; columnNumber: 38; 1バイトのUTF-8シーケンスのバイ ト1が無効です。
        at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:262)
        at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
        at java.xml/javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:122)
        at org.drools.scenariosimulation.backend.util.DOMParserUtil.getDocument(DOMParserUtil.java:348)     
        at org.drools.scenariosimulation.backend.util.DOMParserUtil.cleanupNodes(DOMParserUtil.java:64)     
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.cleanUpUnusedNodes(ScenarioSimulationXMLPersistence.java:101)
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.internalUnmarshal(ScenarioSimulationXMLPersistence.java:202)
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.unmarshal(ScenarioSimulationXMLPersistence.java:143)
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.unmarshal(ScenarioSimulationXMLPersistence.java:133)
        at org.drools.scenariosimulation.backend.runner.ScenarioJunitActivator.parseFile(ScenarioJunitActivator.java:80)
        ... 44 more
Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 1バイトのUTF-8シーケンスのバイト1が無効です。
        at java.xml/com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:702)  
        at java.xml/com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:568)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1904)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanContent(XMLEntityScanner.java:1032)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2742)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:534)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:246)
        ... 53 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 618; columnNumber: 38; 1バイトのUTF-8シーケンスのバイ ト1が無効です。
        at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:262)
        at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
        at java.xml/javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:122)
        at org.drools.scenariosimulation.backend.util.DOMParserUtil.getDocument(DOMParserUtil.java:348)     
        at org.drools.scenariosimulation.backend.util.DOMParserUtil.cleanupNodes(DOMParserUtil.java:64)     
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.cleanUpUnusedNodes(ScenarioSimulationXMLPersistence.java:101)
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.internalUnmarshal(ScenarioSimulationXMLPersistence.java:202)
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.unmarshal(ScenarioSimulationXMLPersistence.java:143)
        at org.drools.scenariosimulation.backend.util.ScenarioSimulationXMLPersistence.unmarshal(ScenarioSimulationXMLPersistence.java:133)
        at org.drools.scenariosimulation.backend.runner.ScenarioJunitActivator.parseFile(ScenarioJunitActivator.java:80)
        ... 44 more
Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 1バイトのUTF-8シーケンスのバイト1が無効です。
        at java.xml/com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:702)  
        at java.xml/com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:568)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1904)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanContent(XMLEntityScanner.java:1032)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2742)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:534)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:246)
        ... 53 more


Results :

Tests in error:
  testscenario.ScenarioJunitActivatorTest: Issue on parsing file: C:\y\VSCode_workspace\BAMOE_DMN\dmn-app\ta[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test) on project dmn-app: There are test failures.
[ERROR]
[ERROR] Please refer to c:\y\VSCode_workspace\BAMOE_DMN\dmn-app\target\surefire-reports for the individual test results.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:   [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
```

</div></details>

Windows環境でデフォルトのEncodingがMS932になっててMaven上はUTF-8で扱おうとしていて、その辺の文字コードの不整合が影響しているのではないかと思われる。
pom.xmlに以下の設定を追加することで解消された。

```xml:pom.xml
...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M6</version>
        <configuration>
          <argLine>-Dfile.encoding=UTF-8</argLine>
        </configuration>
      </plugin>
    </plugins>
  </build>
...
```

もしくはmvnコマンド実行時に以下のようにfile.encodingで明示的にファイルのエンコーディングとしてUTF-8を明示指定する必要があります。
`mvn test -DargLine="-Dfile.encoding=UTF-8"`