はじめに
前回までの記事では、Business Centralを使用してルールを開発し、KIE Serverにルールをデプロイするまでの流れを見てみました。ここではKIE Serverにデプロイされたルールを呼び出すやり方を見ていきます。
ルール実行方法はいくつかやり方がありますが、ここではJavaのクライアントアプリケーションからKIE APIと呼ばれるJavaのAPIを使用して呼び出す方法と、REST APIを使用する方法を試してみます。
関連記事
Business Automation Manager Open Edition メモ - (1) 概要
Business Automation Manager Open Edition メモ - (2) KIE Server, Business Central 構成
Business Automation Manager Open Edition メモ - (3) Business Centralを使用したルール開発
Business Automation Manager Open Edition メモ - (4) KIEサーバー上のルール呼び出し
Business Automation Manager Open Edition メモ - (5) Embedded形態でのルール開発(DRL編)
Business Automation Manager Open Edition メモ - (6) Embedded形態でのルール開発(DMN編)
Business Automation Manager Open Edition メモ - (7) kogitoでのルール開発(スタンドアローン)
Business Automation Manager Open Edition メモ - (8) kogitoでのルール開発(OpenShiftへのデプロイ)
KIE APIを使用したJavaクライアント・アプリケーションからのルール呼び出し
基本的にはこの辺の記述を参考に。
Developing decision services in IBM Business Automation Manager Open Editions - Chapter 29. Executing rules
全体像
環境情報
ルール呼び出しを行うJavaのクライアント・アプリケーションを作成するのに、VS Code、Mavenを使用しますので、関連するコンポーネントを導入、設定しておきます。
今回はWindowsPC上で試します。以下のコンポーネントはセットアップ済みの想定です。
OS: Windows11
Java: OpenJDK11
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: 11, vendor: Oracle Corporation, runtime: C:\x\openjdk11
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
VS CodeのExtensionとしては以下のものを使用
Java,Maven関連
Extension Pack for Java
Debugger for Java
事前準備
VS Code上で新規にワークスペースを作っておきます。
Javaアプリケーション用のMavenプロジェクト作成
コマンド・プロンプトを開き、ワークスペースのフォルダに移動して以下のコマンド実行します。
c:\y\VSCode_workspace\BAMOE_client>mvn archetype:generate -DgroupId=com.sample.app -DartifactId=my-client-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
[INFO] Scanning for projects...
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.4/maven-install-plugin-2.4.pom
...
[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_client
[INFO] Parameter: package, Value: com.sample.app
[INFO] Parameter: groupId, Value: com.sample.app
[INFO] Parameter: artifactId, Value: my-client-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_client\my-client-app
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.628 s
[INFO] Finished at: 2022-12-02T09:45:58+09:00
[INFO] ------------------------------------------------------------------------
以下のフォルダ、ファイルが作成されます。(Javaアプリ用のMavenプロジェクトが作成されました)
c:\y\VSCode_workspace\BAMOE_client>tree my-client-app /f
フォルダー パスの一覧: ボリューム Windows
ボリューム シリアル番号は 7E75-9120 です
C:\Y\VSCODE_WORKSPACE\BAMOE_CLIENT\MY-CLIENT-APP
│ pom.xml
│
└─src
├─main
│ └─java
│ └─com
│ └─sample
│ └─app
│ App.java
│
└─test
└─java
└─com
└─sample
└─app
AppTest.java
このmy-appをVS Codeのワークスペースに追加します。
"フォルダーを開く"を選択
mvnコマンドで作成されたmy-client-appフォルダを選択し、以下のポップアップが出たら「はい」を選択。
VS CodeでMavenプロジェクトを扱う準備が整いました。
pom.xml編集
以下のようにpom.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>my-client-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-client-app</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<version.org.kie>7.67.0.Final-redhat-00017</version.org.kie>
</properties>
<repositories>
<repository>
<id>Redhat GA</id>
<url>https://maven.repository.redhat.com/ga/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- KIE Server Client -->
<dependency>
<groupId>org.kie.server</groupId>
<artifactId>kie-server-client</artifactId>
<version>${version.org.kie}</version>
</dependency>
</dependencies>
</project>
データオブジェクトの取り込み
ルールの実行を行う際にFactとして設定する必要のあるデータオブジェクトを取り込みます。
まず、Business Centralから対象のデータオブジェクト(Loyalty)を選択し、ダウンロードをクリックします。
データオブジェクトの実装となるJavaのソースがダウンロードされるので、パッケージ名に沿ったフォルダを作成して配置します。
(`com\testspace01\customerloyalty01\以下に配置)
Loyalty.java
package com.testspace01.customerloyalty01;
/**
* This class was automatically generated by the data modeler tool.
*/
public class Loyalty implements java.io.Serializable {
static final long serialVersionUID = 1L;
private java.lang.String rank;
private java.lang.Double discount_rate;
private java.lang.String message;
public Loyalty() {
}
public java.lang.String getRank() {
return this.rank;
}
public void setRank(java.lang.String rank) {
this.rank = rank;
}
public java.lang.Double getDiscount_rate() {
return this.discount_rate;
}
public void setDiscount_rate(java.lang.Double discount_rate) {
this.discount_rate = discount_rate;
}
public java.lang.String getMessage() {
return this.message;
}
public void setMessage(java.lang.String message) {
this.message = message;
}
public Loyalty(java.lang.String rank, java.lang.Double discount_rate,
java.lang.String message) {
this.rank = rank;
this.discount_rate = discount_rate;
this.message = message;
}
}
ルール呼び出しロジック作成
お膳立てが整ったので、ルール呼び出しを行うJavaのクライアント・コードを書いていきます。ここでは単純なStand AloneのJavaアプリケーションとして作成します。
App.javaソース
package com.sample.app;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.kie.api.KieServices;
import org.kie.api.command.BatchExecutionCommand;
import org.kie.api.command.Command;
import org.kie.api.command.KieCommands;
import org.kie.api.runtime.ExecutionResults;
import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.api.model.ServiceResponse;
import org.kie.server.client.CredentialsProvider;
import org.kie.server.client.KieServicesClient;
import org.kie.server.client.KieServicesConfiguration;
import org.kie.server.client.KieServicesFactory;
import org.kie.server.client.RuleServicesClient;
import org.kie.server.client.credentials.EnteredCredentialsProvider;
import com.testspace01.customerloyalty01.Loyalty;
/**
* Hello world!
*
*/
public class App
{
private static final String KIE_SERVER_URL = "http://localhost:18080/kie-server/services/rest/server";
private static final String CONTAINER_ID = "CustomerLoyalty01";
// Credentials
private static final String USERNAME = "rhpamAdmin";
private static final String PASSWORD = "xxxxxxxxxx";
public static void main( String[] args )
{
// Parse arguments :
String strRank = args[0];
// Define KIE services configuration and client:
CredentialsProvider credentialsProvider = new EnteredCredentialsProvider(USERNAME, PASSWORD);
KieServicesConfiguration kieServicesConfig = KieServicesFactory.newRestConfiguration(KIE_SERVER_URL, credentialsProvider);
Set<Class<?>> extraClassList = new HashSet<>();
extraClassList.add(Loyalty.class);
kieServicesConfig.addExtraClasses(extraClassList);
kieServicesConfig.setMarshallingFormat(MarshallingFormat.JSON);
KieServicesClient kieServicesClient = KieServicesFactory.newKieServicesClient(kieServicesConfig);
RuleServicesClient rulesClient = kieServicesClient.getServicesClient(RuleServicesClient.class);
// Set up the fact model:
Loyalty loyalty = new Loyalty();
loyalty.setRank(strRank);
// Insert Person into the session:
KieServices kieServices = KieServices.Factory.get();
KieCommands commandFactory = kieServices.getCommands();
List<Command<?>> commands = new ArrayList<>();
commands.add(commandFactory.newInsert(loyalty, "loyalty"));
// Fire all rules:
commands.add(commandFactory.newFireAllRules());
commands.add(commandFactory.newGetObjects("objects"));
commands.add(commandFactory.newDispose());
BatchExecutionCommand batchExecutionCommand = commandFactory.newBatchExecution(commands);
// Use rule services client to send request:
ServiceResponse<ExecutionResults> response = rulesClient.executeCommandsWithResults(CONTAINER_ID, batchExecutionCommand);
ExecutionResults results = response.getResult();
Object obj;
Loyalty loyalty_result;
Collection<String> identifiers = results.getIdentifiers();
for (String str: identifiers) {
obj = results.getValue(str);
//System.out.println("id: " + str);
//System.out.println("objects:" + obj);
if (obj instanceof Loyalty) {
loyalty_result = (Loyalty)obj;
System.out.println("id: " + str);
System.out.println("Rank: " + loyalty_result.getRank());
System.out.println("Discount Rate: " + loyalty_result.getDiscount_rate());
System.out.println("Message: " + loyalty_result.getMessage());
}
}
}
}
ルール呼び出し実行
引数でRankを指定するようにしているので、launch.jsonでargsを指定します。
{
// IntelliSense を使用して利用可能な属性を学べます。
// 既存の属性の説明をホバーして表示します。
// 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Launch Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "Launch App",
"request": "launch",
"mainClass": "com.sample.app.App",
"projectName": "my-client-app",
"args": ["ゴールド"]
}
]
}
ターミナル部分で結果を確認します。Rank "ゴールド"指定に対して Discount Rate: 0.2が返されたことが確認できます。
REST APIを使用したルール呼び出し
全体像
ここではcurlコマンドでRESTのAPIを発行してみます。
登録されているルール・コンテナの確認
ルールプロジェクトは"コンテナ"と呼ばれる単位でサーバーにデプロイされているので、そのコンテナの情報を取得してみます。
※ここで言う"コンテナ"というのはあくまでKie Server上で管理しているルールプロジェクトの単位を表す概念で、DockerやKubernetesなどで扱われる"コンテナ"とは別物ですのでご注意ください。
以下のようにコンテナ情報を取得するREST APIをcurlから発行してみます。
curl -u rhpamAdmin:xxxxxxx -X GET "http://localhost:8080/kie-server/services/rest/server/containers" -H "accept: application/json"
結果例
{
"type" : "SUCCESS",
"msg" : "List of created containers",
"result" : {
"kie-containers" : {
"kie-container" : [ {
"container-id" : "CustomerLoyalty01_1.0.0-SNAPSHOT",
"release-id" : {
"group-id" : "com.testspace01",
"artifact-id" : "CustomerLoyalty01",
"version" : "1.0.0-SNAPSHOT"
},
"resolved-release-id" : {
"group-id" : "com.testspace01",
"artifact-id" : "CustomerLoyalty01",
"version" : "1.0.0-SNAPSHOT"
},
"status" : "STARTED",
"scanner" : {
"status" : "DISPOSED",
"poll-interval" : null
},
"config-items" : [ {
"itemName" : "KBase",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "KSession",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "MergeMode",
"itemValue" : "MERGE_COLLECTIONS",
"itemType" : "BPM"
}, {
"itemName" : "RuntimeStrategy",
"itemValue" : "SINGLETON",
"itemType" : "BPM"
} ],
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1670127503601
},
"content" : [ "Container CustomerLoyalty01_1.0.0-SNAPSHOT successfully created with module com.testspace01:CustomerLoyalty01:1.0.0-SNAPSHOT." ]
} ],
"container-alias" : "CustomerLoyalty01"
}, {
"container-id" : "CustomerLoyalty02_1.0.0-SNAPSHOT",
"release-id" : {
"group-id" : "com.testspace02",
"artifact-id" : "CustomerLoyalty02",
"version" : "1.0.0-SNAPSHOT"
},
"resolved-release-id" : {
"group-id" : "com.testspace02",
"artifact-id" : "CustomerLoyalty02",
"version" : "1.0.0-SNAPSHOT"
},
"status" : "STARTED",
"scanner" : {
"status" : "DISPOSED",
"poll-interval" : null
},
"config-items" : [ {
"itemName" : "KBase",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "KSession",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "MergeMode",
"itemValue" : "MERGE_COLLECTIONS",
"itemType" : "BPM"
}, {
"itemName" : "RuntimeStrategy",
"itemValue" : "SINGLETON",
"itemType" : "BPM"
} ],
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1670127508170
},
"content" : [ "Container CustomerLoyalty02_1.0.0-SNAPSHOT successfully created with module com.testspace02:CustomerLoyalty02:1.0.0-SNAPSHOT." ]
} ],
"container-alias" : "CustomerLoyalty02"
}, {
"container-id" : "integrate-rest_1.0.0-SNAPSHOT",
"release-id" : {
"group-id" : "com.ad364",
"artifact-id" : "integrate-rest",
"version" : "1.0.0-SNAPSHOT"
},
"resolved-release-id" : {
"group-id" : "com.ad364",
"artifact-id" : "integrate-rest",
"version" : "1.0.0-SNAPSHOT"
},
"status" : "STARTED",
"scanner" : {
"status" : "DISPOSED",
"poll-interval" : null
},
"config-items" : [ {
"itemName" : "KBase",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "KSession",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "MergeMode",
"itemValue" : "MERGE_COLLECTIONS",
"itemType" : "BPM"
}, {
"itemName" : "RuntimeStrategy",
"itemValue" : "SINGLETON",
"itemType" : "BPM"
} ],
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1670127511327
},
"content" : [ "Container integrate-rest_1.0.0-SNAPSHOT successfully created with module com.ad364:integrate-rest:1.0.0-SNAPSHOT." ]
} ],
"container-alias" : "integrate-rest"
}, {
"container-id" : "integrate-kie_1.0.0-SNAPSHOT",
"release-id" : {
"group-id" : "com.ad364",
"artifact-id" : "integrate-kie",
"version" : "1.0.0-SNAPSHOT"
},
"resolved-release-id" : {
"group-id" : "com.ad364",
"artifact-id" : "integrate-kie",
"version" : "1.0.0-SNAPSHOT"
},
"status" : "STARTED",
"scanner" : {
"status" : "DISPOSED",
"poll-interval" : null
},
"config-items" : [ {
"itemName" : "KBase",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "KSession",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "MergeMode",
"itemValue" : "MERGE_COLLECTIONS",
"itemType" : "BPM"
}, {
"itemName" : "RuntimeStrategy",
"itemValue" : "PER_PROCESS_INSTANCE",
"itemType" : "BPM"
} ],
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1670127505351
},
"content" : [ "Container integrate-kie_1.0.0-SNAPSHOT successfully created with module com.ad364:integrate-kie:1.0.0-SNAPSHOT." ]
} ],
"container-alias" : "integrate-kie"
}, {
"container-id" : "aaaaaPrj01_1.0.0-SNAPSHOT",
"release-id" : {
"group-id" : "com.testspace01",
"artifact-id" : "aaaaaPrj01",
"version" : "1.0.0-SNAPSHOT"
},
"resolved-release-id" : {
"group-id" : "com.testspace01",
"artifact-id" : "aaaaaPrj01",
"version" : "1.0.0-SNAPSHOT"
},
"status" : "STARTED",
"scanner" : {
"status" : "DISPOSED",
"poll-interval" : null
},
"config-items" : [ {
"itemName" : "KBase",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "KSession",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "MergeMode",
"itemValue" : "MERGE_COLLECTIONS",
"itemType" : "BPM"
}, {
"itemName" : "RuntimeStrategy",
"itemValue" : "SINGLETON",
"itemType" : "BPM"
} ],
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1670127512909
},
"content" : [ "Container aaaaaPrj01_1.0.0-SNAPSHOT successfully created with module com.testspace01:aaaaaPrj01:1.0.0-SNAPSHOT." ]
} ],
"container-alias" : "aaaaaPrj01"
}, {
"container-id" : "Prj01_1.0.0-SNAPSHOT",
"release-id" : {
"group-id" : "com.myspace",
"artifact-id" : "Prj01",
"version" : "1.0.0-SNAPSHOT"
},
"resolved-release-id" : {
"group-id" : "com.myspace",
"artifact-id" : "Prj01",
"version" : "1.0.0-SNAPSHOT"
},
"status" : "STARTED",
"scanner" : {
"status" : "DISPOSED",
"poll-interval" : null
},
"config-items" : [ {
"itemName" : "KBase",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "KSession",
"itemValue" : "",
"itemType" : "BPM"
}, {
"itemName" : "MergeMode",
"itemValue" : "MERGE_COLLECTIONS",
"itemType" : "BPM"
}, {
"itemName" : "RuntimeStrategy",
"itemValue" : "SINGLETON",
"itemType" : "BPM"
} ],
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1670127509716
},
"content" : [ "Container Prj01_1.0.0-SNAPSHOT successfully created with module com.myspace:Prj01:1.0.0-SNAPSHOT." ]
} ],
"container-alias" : "Prj01"
} ]
}
}
}
"container-alias" : "CustomerLoyalty01"
と設定されているコンテナが登録されているのが確認できます。
ルール実行
以下のcurlコマンドでルールの実行を試してみます。
curl -u rhpamAdmin:xxxxxxxx -X POST "http://localhost:8080/kie-server/services/rest/server/containers/instances/CustomerLoyalty01" \
-H "accept: application/json" \
-H "content-type: application/json" \
-d '
{
"commands":[
{
"insert":{
"object":{
"com.testspace01.customerloyalty01.Loyalty":{
"rank":"プラチナ"
}
},
"return-object":false
}
},
{
"fire-all-rules":{
}
},
{
"get-objects": {
"out-identifier": "objects"
}
},
{
"dispose": {}
}
]
}
'
以下のような結果が返されます。
{
"type" : "SUCCESS",
"msg" : "Container CustomerLoyalty01 successfully called.",
"result" : {
"execution-results" : {
"results" : [ {
"value" : [{"com.testspace01.customerloyalty01.Loyalty":{
"rank" : "プラチナ",
"discount_rate" : 0.3,
"message" : null
}}],
"key" : "objects"
} ],
"facts" : [ ]
}
}
}
Rank:"プラチナ"に対して、discount_rate: 0.3 が返されたことが確認できます。
うーん、RESTで呼び出せるとはいえ、この呼び出し方を見ると、POSTメソッドを使ってルール実行に特化した作法でJSONデータを組み立てないといけないので、ちょっとイケてないですね...。
(JSONのデータ構造の中に、純粋な業務データではないサービス実装に依存する情報が組み込まれてしまっています...)