The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Kogitoを使用してアプリケーションにルール・エンジン機能を追加する

このガイドでは、QuarkusアプリケーションがKogitoを使用してルール付きのDRLファイルを追加する方法を説明します。

Kogitoは、よく知られたオープンソース・プロジェクトであるDrools(ビジネス・ルール用)とjBPM(ビジネス・プロセス用)から生まれた、次世代のビジネス・オートメーション・ツールキットです。Kogitoは、ビジネス・オートメーションに新しいアプローチを提供することを目的としており、主なメッセージは、ビジネス・ナレッジ(プロセス、ルール、決定、予測)をドメイン固有の方法で公開することです。

前提条件

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 11+ がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.8.1+

  • 動作するコンテナランタイム(Docker, Podman)

  • 使用したい場合、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

アーキテクチャ

この例では、1つのRESTエンドポイントを提供する非常にシンプルなマイクロサービスを構築します:

  • /find-approved

このエンドポイントは、DRLファイルのRule Unitに挿入されたクエリに基づいて自動的に生成されます。これは、ビジネス・ルールの実行が副作用を伴わないステートレス呼び出し(「純粋な関数呼び出し」とも呼ばれる)の例です。返される出力値は、提供された入力に一意に基づいています。

ビジネスルール

ビジネスルールとは、意思決定ロジックを再利用可能なパーツに外部化し、宣言的な方法で簡単に使用できるようにするものです。ルールの書き方には、デシジョンテーブル、デシジョンツリー、ルールなど、さまざまな方法があります。この例では、DRL (Drools Rule Language)によるルール形式に注目します。

ソリューション

次のセクションで紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。

Gitリポジトリをクローンする: git clone https://github.com/quarkusio/quarkus-quickstarts.git 、または archive をダウンロードする。

このソリューションは kogito-drl-quickstart directory にあります。

Mavenプロジェクトの作成

まず、新しいプロジェクトを用意します。以下のコマンドで新しいプロジェクトを作成します:

CLI
quarkus create app org.acme:kogito-drl-quickstart \
    --extension=kogito-quarkus-rules,resteasy-reactive-jackson \
    --no-code
cd kogito-drl-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストール方法については、Quarkus CLIガイドをご参照ください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.11.1.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=kogito-drl-quickstart \
    -Dextensions="kogito-quarkus-rules,resteasy-reactive-jackson" \
    -DnoCode
cd kogito-drl-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

このコマンドはMavenプロジェクトを生成し、アプリケーションにビジネス・オートメーションの機能を追加するために必要な依存関係と構成をすべて備えた kogito-quarkus-rules エクステンションをインポートします。また、KogitoがRESTサービスを公開するのに必要な resteasy-jackson エクステンションをインポートします。

すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリで以下のコマンドを実行することで、 kogito-quarkus-rules エクステンションをプロジェクトに追加することができます:

CLI
quarkus extension add 'kogito-quarkus-rules'
Maven
./mvnw quarkus:add-extension -Dextensions="kogito-quarkus-rules"
Gradle
./gradlew addExtension --extensions="kogito-quarkus-rules"

これにより、 pom.xml に以下が追加されます:

pom.xml
<dependency>
    <groupId>org.kie.kogito</groupId>
    <artifactId>kogito-quarkus-rules</artifactId>
</dependency>
build.gradle
implementation(“org.kie.kogito:kogito-quarkus-rules”)

アプリケーションの作成

Let’s start from the application domain model. This application will approve Loan Applications, so we have a class with all the details of the wanted Loan:

package org.acme.kogito.model;

public class LoanApplication {

   private String id;
   private Applicant applicant;
   private int amount;
   private int deposit;
   private boolean approved = false;

   public LoanApplication() {

   }

   public LoanApplication(String id, Applicant applicant,
                      	int amount, int deposit) {
       this.id = id;
       this.applicant = applicant;
       this.amount = amount;
       this.deposit = deposit;
   }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Applicant getApplicant() {
        return applicant;
    }

    public void setApplicant(Applicant applicant) {
        this.applicant = applicant;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public int getDeposit() {
        return deposit;
    }

    public void setDeposit(int deposit) {
        this.deposit = deposit;
    }

    public boolean isApproved() {
        return approved;
    }

    public void setApproved(boolean approved) {
        this.approved = approved;
    }
}

そして、申請者の詳細を記載した別のクラスを用意します:

package org.acme.kogito.model;

public class Applicant {

   private String name;
   private int age;

   public Applicant() {
   }

   public Applicant(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public String getName() {
       return name;
   }

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

   public int getAge() {
       return age;
   }

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

次に、生成されたプロジェクトの src/main/resources/org/acme/kogito/queries フォルダ内にルールファイル loan-rules.drl を作成します。

package org.acme.kogito.queries;

unit LoanUnit; // no need to using globals, all variables and facts are stored in the rule unit

import org.acme.kogito.model.Applicant;
import org.acme.kogito.model.LoanApplication;

rule LargeDepositApprove when
   $l: /loanApplications[ applicant.age >= 20, deposit >= 1000, amount <= maxAmount ] // oopath style
then
   modify($l) { setApproved(true) };
end

rule LargeDepositReject when
   $l: /loanApplications[ applicant.age >= 20, deposit >= 1000, amount > maxAmount ]
then
   modify($l) { setApproved(false) };
end

// ... more loans approval/rejections business rules ...

// approved loan applications are now retrieved through a query
query FindApproved
   $l: /loanApplications[ approved ]
end

このファイルには、ローンが承認されるべきかどうかを決定するためのルールの例があります。このサービスでは、申請者の年齢が20歳以上で、銀行口座に1,000通貨以上の預金があることを求めています。ローンの金額は maxAmount を超えてはいけません。

この例では、Kogitoに導入された新しい概念であるルール・ユニットを使用しています。これは、ルールのセットと、それらのルールが照合されるファクトをカプセル化するのに役立ちます。

挿入されたファクトは、タイプセーフのエントリーポイントである DataStore に挿入されます。すべてを機能させるには、RuleUnitとDataStoreの両方を定義する必要があります。

package org.acme.kogito.queries;

import org.acme.kogito.model.LoanApplication;
import org.kie.kogito.rules.DataSource;
import org.kie.kogito.rules.DataStore;
import org.kie.kogito.rules.RuleUnitData;

public class LoanUnit implements RuleUnitData {

   private int maxAmount;
   private DataStore<LoanApplication> loanApplications;

   public LoanUnit() {
   	this(DataSource.createStore(), 0);
   }

   public LoanUnit(DataStore<LoanApplication> loanApplications, int maxAmount) {
   	this.loanApplications = loanApplications;
   	this.maxAmount = maxAmount;
   }

   public DataStore<LoanApplication> getLoanApplications() { return loanApplications; }

   public void setLoanApplications(DataStore<LoanApplication> loanApplications) {
   	this.loanApplications = loanApplications;
   }

   public int getMaxAmount() { return maxAmount; }
   public void setMaxAmount(int maxAmount) { this.maxAmount = maxAmount; }
}

これで完了です。ローン申請を検証するためのRESTエンドポイントが、このRule Unitから自動的に生成されます。

アプリケーションの実行と使用

Devモードでの動作

マイクロサービスをdevモードで実行するには:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

JVMモードでの動作

「開発モード」で遊び終わったら、標準のJavaアプリケーションとして実行することができます。

まず、コンパイルします:

CLI
quarkus build
Maven
./mvnw clean package
Gradle
./gradlew build

それから実行してください:

java -jar target/quarkus-app/quarkus-run.jar

ネイティブモードでの実行

同じデモをネイティブコードにコンパイルすることができます。修正は必要ありません。

これは、生成されたバイナリにランタイム技術が含まれており、最小限のリソースオーバーヘッドで実行できるように最適化されているため、本番環境にJVMをインストールする必要がないことを意味します。

コンパイルには少し時間がかかるので、このステップはデフォルトでは無効になっています。以下のコマンドでネイティブ実行可能ファイルをビルドしてみましょう:

CLI
quarkus build --native
Maven
./mvnw package -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native

コーヒーを飲み終わると、このバイナリは以下のように直接実行出来るようになります:

target/kogito-drl-quickstart-1.0.0-SNAPSHOT-runner

アプリケーションのテスト

アプリケーションをテストするには、JSONペイロードとして期待される入力を提供して、エンドポイントにリクエストを送るだけです。

curl -X POST http://localhost:8080/find-approved \
    -H ‘Content-Type: application/json’\
    -H ‘Accept: application/json’ \
    -d ‘{“maxAmount”:5000,
          “loanApplications”:[
          {“id”:”ABC10001”,”amount”:2000,”deposit”:1000,
            “applicant”:{“age”:45,”name”:”John”}},
          {“id”:”ABC10002”,”amount”:5000,”deposit”:100,
            “applicant”:{“age”:25,”name”:”Paul”}},
          {“id”:”ABC10015”,”amount”:1000,”deposit”:100,
            “applicant”:{“age”:12,”name”:”George”}}
]}’

レスポンスでは、承認されたアプリケーションのリストが返されます:

[{“id”:”ABC10001”,
    “applicant”:{“name”:”John”,”age”:45},
    “amount”:2000,”deposit”:100,”approved”:true}]