0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

本記事では、DRL で実装されたプロジェクト内のルールのうち、一部を抽出して動かす方法について書いていきます。

サンプルコード

以下 2 パターンの実装例を紹介します。

  • 複数ある DRL ファイルのうち、1 ファイルに含まれるルールのみ動作させる
  • DRL ファイル内にある 1 つのルールのみ動作させる

コード全量は、GitHub にあげています。

データクラス

ルールに渡すデータクラスを定義します。
このクラスは、ルールの名称を Set で保持する構造にしています。

ExecutedRules.java
public class ExecutedRules {
    // これまで実行されたルール名のリスト
    private Set<String> result = new HashSet<>();

    public void recordRuleName(String ruleName) {
        this.result.add(ruleName);
    }

    public Set<String> getExecutedRules() {
        return result;
    }
...

DRL

検証に用いる DRL は、先述したExecutedRulesオブジェクトを受け取り、実行されたルール名をオブジェクトに記録する仕様とします。
決定表形式で仕様を表現すると、次のようになります。

条件 (when) 実行処理 (then)
Rule_A ExecutedRules が存在 ExecutedRules に Rule_A を記録する
Rule_B ExecutedRules が存在 ExecutedRules に Rule_B を記録する
Rule_C ExecutedRules が存在 ExecutedRules に Rule_C を記録する
Rule_D ExecutedRules が存在 ExecutedRules に Rule_D を記録する

これを 2 つのDRL ファイルで実装します。
1 つ目には、表の 1 行目~ 3 行目のルールを定義します。

Rule_A_B_C.drl
package org.example.partialexec;

rule "Rule_A"
    when
        $data : ExecutedRules()
    then
        $data.recordRuleName("Rule_A");
end

rule "Rule_B"
    when
        $data : ExecutedRules()
    then
        $data.recordRuleName("Rule_B");
end

rule "Rule_C"
    when
        $data : ExecutedRules()
    then
        $data.recordRuleName("Rule_C");
end

2 つ目の DRL ファイルには、4 行目のルールを定義します。

Rule_D.drl
package org.example.partialexec;

rule "Rule_D"
    when
        $data : ExecutedRules()
    then
        $data.recordRuleName("Rule_D");
end

このルールをそのまま動かすと、ExecutedRulesオブジェクトには、Rule_A, Rule_B, Rule_C, Rule_D の 4 件のルール名が記録されます。
動作確認用のテストコードは次のとおりです。

AllRuleTest.java
    @Test
    public void test_全ルール実行() {
        KieServices ks = KieServices.Factory.get();
        KieContainer kieContainer = ks.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession();

        try {
            var data = new ExecutedRules();
            kieSession.insert(data);
            kieSession.fireAllRules();

            // assert
            assertEquals(Set.of("Rule_A", "Rule_B", "Rule_C", "Rule_D"), data.getExecutedRules());

        } finally {
            kieSession.dispose();
        }
    }

1 DRL ファイルに含まれるルールのみを動かす

まず、Rule_A_B_C.drl に含まれるルールのみが動くように制御してみます。
KieFileSystem という仕組みを用いると、特定の DRL ファイルを指定したうえでルールを動作させることが可能です。

以下が動作確認用のテストコードです。

SingleFileTest.java
    @Test
    public void test_指定したDRLファイルのみ動かす() {
        // 動かしたいDRLファイル(1ファイルだけ)をクラスパスから読み込み、リソースとして追加
        KieServices ks = KieServices.Factory.get();
        KieFileSystem kfs = ks.newKieFileSystem();
        kfs.write(ResourceFactory.newClassPathResource("org/example/partialexec/Rule_A_B_C.drl"));
        ks.newKieBuilder(kfs).buildAll();

        KieContainer kContainer = ks.newKieContainer(ks.getRepository().getDefaultReleaseId());
        KieSession kieSession = kContainer.newKieSession();

        try {
            var data = new ExecutedRules();
            kieSession.insert(data);
            kieSession.fireAllRules();

            // assert
            assertEquals(Set.of("Rule_A", "Rule_B", "Rule_C"), data.getExecutedRules());

        } finally {
            kieSession.dispose();
        }
    }

本テストがパスするので、Rule_A_B_C.drl に含まれるルールのみ実行されたことがわかります。

DRL ファイル内のルール 1 件のみを動かす

次に、DRLファイルに含まれる 1 件のルールのみを抽出し動かしてみます。
これは、先述した決定表のうちの 1 行が相当します。

DRL ファイル内における「Rule_A」ルールのみを動かしたい場合、RuleNameEqualsAgendaFilterという仕組みを用い、動作させたいルール名称を指定します。

SingleLineTest.java
    @Test
    public void test_指定した単一ルールのみを動かす() {
        KieServices ks = KieServices.Factory.get();
        KieContainer kieContainer = ks.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession();

        try {
            var data = new ExecutedRules();
            kieSession.insert(data);

            // 「Rule_A」のみを実行
            kieSession.fireAllRules( new RuleNameEqualsAgendaFilter( "Rule_A" ) );

            // assert
            assertEquals(Set.of("Rule_A"), data.getExecutedRules());

        } finally {
            kieSession.dispose();
        }
    }

本テストがパスするので、「Rule_A」のみ実行されたことがわかります。

終わりに

本番環境で動かすルールのうち、一部を区分けして管理・実行したい場合は、過去記事で紹介したagenda-group, Rule Unitを使うのがよいと思います。

今回の方法は、プロジェクトが Rule Unit に移行しておらず、DRLの数も多い場合において、一部分のみを手元で検証したいときに役立つのではと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?