ルールエンジン管理のメモ

ルールエンジン管理とは

RedHatのBRMS製品にDecision Managerなるミドルウェアがあり、最近業務で触ることがあったのでその内容をまとめておきます。(すぐ忘れそうなので...)

www.redhat.com

Decision ManagerのプロジェクトをKIEサーバにデプロイした後の動き

ここでは構築系の情報ではなく、デプロイ後の利用方法をメインにしたいと思います。

プロジェクト上で二つオブジェクトを作成して、それに合わせてルールを記載したようなプロジェクトを作りました。

オブジェクトは「アセットの追加」から「データオブジェクト」で作成しています。

  • Personオブジェクト
package com.myspace.myfirstprj;

/**
 * This class was automatically generated by the data modeler tool.
 */

public class Person implements java.io.Serializable {

    static final long serialVersionUID = 1L;

    private java.lang.String name;
    private int age;
    public Person() {
    }

    public java.lang.String getName() {
        return this.name;
    }

    public void setName(java.lang.String name) {
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(java.lang.String name, int age) {
        this.name = name;
        this.age = age;
    }

}
  • Placeオブジェクト
package com.myspace.myfirstprj;

/**
 * This class was automatically generated by the data modeler tool.
 */

public class Place implements java.io.Serializable {

    static final long serialVersionUID = 1L;

    private java.lang.String name;

    public Place() {
    }

    public java.lang.String getName() {
        return this.name;
    }

    public void setName(java.lang.String name) {
        this.name = name;
    }

    public Place(java.lang.String name) {
        this.name = name;
    }

}

f:id:akky97:20201119230154p:plain
ルール

「東京のマイク」は20歳、「名古屋のマイク」は34歳だよ、という謎ルールですが、こんな感じの表で条件とその条件に合致した場合の処理(と言っても値をセットするとか単純なこと)を書くことができます。

ソースだと以下の感じになってます。

package com.myspace.myfirstprj;

//from row number: 1
//東京のマイク
rule "Row 1 rule01"
    dialect "mvel"
    when
        person : Person( name == "マイク" )
        place : Place( name == "東京" )
    then
        person.setAge( 20 );
end

//from row number: 2
//名古屋のマイク
rule "Row 2 rule01"
    dialect "mvel"
    when
        person : Person( name == "マイク" )
        place : Place( name == "名古屋" )
    then
        person.setAge( 34 );
end

//from row number: 3
//東京のケン
rule "Row 3 rule01"
    dialect "mvel"
    when
        person : Person( name == "ケン" )
        place : Place( name == "東京" )
    then
        person.setAge( 25 );
end

//from row number: 4
//大阪のケン
rule "Row 4 rule01"
    dialect "mvel"
    when
        person : Person( name == "ケン" )
        place : Place( name == "大阪" )
    then
        person.setAge( 41 );
end

KIEサーバにデプロイしたWebAPIを呼ぶときのjson

Decision Central(Business Centralという表記になっていますが)から、デプロイボタンでKIEサーバへデプロイします。

f:id:akky97:20201119224605p:plain
デプロイ

これでWebAPIで呼べるのですが、複数オブジェクトの渡し方がわからず、うまく動かせませんでした。いろいろとドキュメントなどみながら試行錯誤した結果、Insertコマンドでオブジェクトを二つ渡すことで期待する動きになりました。

ファクトは一つのオブジェクト、と考えればそれぞれInsertする、ということになるのですね。返して欲しいファクトもそれぞれのInsertの中の”out-identifier”でこの中で指定できますし。

{
    "lookup": "myksession",
    "commands": [
        {
            "insert": {
                "object": {
                    "Person": {
                        "name": "マイク"
                    }
                },
                "out-identifier": "fact1"
            }
        },
        {
            "insert": {
                "object": {
                    "Place": {
                        "name": "名古屋"
                    }
                }
            }
        },
        {
            "fire-all-rules": ""
        }
    ]
}

これの結果が以下になっています。ちゃんとマイクは34歳になっています。

{
    "type": "SUCCESS",
    "msg": "Container MyFirstPrj successfully called.",
    "result": {
        "execution-results": {
            "results": [
                {
                    "value": 1,
                    "key": ""
                },
                {
                    "value": {
                        "com.myspace.myfirstprj.Person": {
                            "name": "マイク",
                            "age": 34
                        }
                    },
                    "key": "fact1"
                }
            ],
            "facts": [
                {
                    "value": {
                        "org.drools.core.common.DefaultFactHandle": {
                            "external-form": "0:1:163308650:163308650:1:DEFAULT:NON_TRAIT:com.myspace.myfirstprj.Person"
                        }
                    },
                    "key": "fact1"
                }
            ]
        }
    }
}

ルールにはないものはどうなる?

次にルールにはない、「大阪のマイク」をデータで入れてみます。

{
    "lookup": "myksession",
    "commands": [
        {
            "insert": {
                "object": {
                    "Person": {
                        "name": "マイク"
                    }
                },
                "out-identifier": "fact1"
            }
        },
        {
            "insert": {
                "object": {
                    "Place": {
                        "name": "大阪"
                    }
                }
            }
        },
        {
            "fire-all-rules": ""
        }
    ]
}

結果は以下の通りとなり、年齢は0歳になっています。年齢はint型になっているので、その初期値0ということになります。

{
    "type": "SUCCESS",
    "msg": "Container MyFirstPrj successfully called.",
    "result": {
        "execution-results": {
            "results": [
                {
                    "value": 0,
                    "key": ""
                },
                {
                    "value": {
                        "com.myspace.myfirstprj.Person": {
                            "name": "マイク",
                            "age": 0
                        }
                    },
                    "key": "fact1"
                }
            ],
            "facts": [
                {
                    "value": {
                        "org.drools.core.common.DefaultFactHandle": {
                            "external-form": "0:1:160820194:160820194:1:DEFAULT:NON_TRAIT:com.myspace.myfirstprj.Person"
                        }
                    },
                    "key": "fact1"
                }
            ]
        }
    }
}

まだまだ勉強不足ですが、うまく使いこなせると何かが効率的になりそうな気がするシステムだなと思いました。(帳票系とかと相性が良さそう?)