1. 序章

このクイックチュートリアルでは、DroolsをSpringと統合します。 Droolsを使い始めたばかりの場合は、この紹介記事をチェックしてください。

2. Mavenの依存関係

pom.xmlファイルに次の依存関係を追加することから始めましょう。

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.0.0.Final</version>
</dependency>
<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>7.0.0.Final</version>
</dependency>

最新バージョンは、 drools-core についてはこちら、kie-springについてはこちらをご覧ください。

3. 初期データ

ここで、この例で使用するデータを定義しましょう。 移動距離と夜間追加料金フラグに基づいて、乗車料金を計算します。

ファクトとして使用される単純なオブジェクトは次のとおりです:

public class TaxiRide {
    private Boolean isNightSurcharge;
    private Long distanceInMile;
    
    // standard constructors, getters/setters
}

運賃を表すために使用される別のビジネスオブジェクトも定義しましょう。

public class Fare {
    private Long nightSurcharge;
    private Long rideFare;
    
    // standard constructors, getters/setters
}

それでは、タクシー料金を計算するためのビジネスルールを定義しましょう。

global com.baeldung.spring.drools.model.Fare rideFare;
dialect  "mvel"

rule "Calculate Taxi Fare - Scenario 1"
    when
        taxiRideInstance:TaxiRide(isNightSurcharge == false && distanceInMile < 10);
    then
      	rideFare.setNightSurcharge(0);
       	rideFare.setRideFare(70);
end

ご覧のとおり、指定されたTaxiRideの合計運賃を計算するルールが定義されています。

このルールはTaxiRideオブジェクトを受け入れ、isNightSurcharge属性がfalseであり、 distanceInMile 属性値が10未満であるかどうかを確認し、計算します。運賃は70で、nightSurchargeプロパティを0に設定します。

計算された出力は、さらに使用するためにFareオブジェクトに設定されます。

4. 春の統合

4.1. SpringBeanの構成

それでは、Spring統合に移りましょう。

Spring bean構成クラスを定義します。これは、 TaxiFareCalculatorServicebeanとその依存関係のインスタンス化を担当します。

@Configuration
@ComponentScan("com.baeldung.spring.drools.service")
public class TaxiFareConfiguration {
    private static final String drlFile = "TAXI_FARE_RULE.drl";

    @Bean
    public KieContainer kieContainer() {
        KieServices kieServices = KieServices.Factory.get();

        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        kieFileSystem.write(ResourceFactory.newClassPathResource(drlFile));
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        KieModule kieModule = kieBuilder.getKieModule();

        return kieServices.newKieContainer(kieModule.getReleaseId());
    }
}

KieServices は、Kieが提供するすべてのサービスを取得するためのシングルポイントエントリとして機能するシングルトンです。 KieServices は、 KieServices.Factory.get()。を使用して取得されます。

次に、ルールエンジンを実行するために必要なすべてのオブジェクトのプレースホルダーであるKieContainerを取得する必要があります。

KieContainer は、 KieFileSystem、KieBuilder、KieModuleなどの他のBeanを使用して構築されています。

の作成に進みましょう KieModule これは、として知られているルール知識を定義するために必要なすべてのリソースのコンテナです。 KieBase。

KieModule kieModule = kieBuilder.getKieModule();

KieBase は、ルール、プロセス、関数、型モデルなど、アプリケーションに関連するすべての知識を含むリポジトリであり、KieModule内に隠されています。 KieBase は、KieContainerから入手できます。

KieModule が作成されたら、KieBaseが持つKieModuleを含むKieContainer の作成に進むことができます定義されています。 KieContainer は、次のモジュールを使用して作成されます。

KieContainer kContainer = kieServices.newKieContainer(kieModule.getReleaseId());

4.2. 春のサービス

結果を処理するためにFactオブジェクトをエンジンに渡すことにより、実際のビジネスロジックを実行するサービスクラスを定義しましょう。

@Service
public class TaxiFareCalculatorService {

    @Autowired
    private KieContainer kieContainer;

    public Long calculateFare(TaxiRide taxiRide, Fare rideFare) {
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.setGlobal("rideFare", rideFare);
        kieSession.insert(taxiRide);
        kieSession.fireAllRules();
        kieSession.dispose();
        return rideFare.getTotalFare();
    }
}

最後に、KieSessionKieContainerインスタンスを使用して作成されます。 KieSession インスタンスは、入力データを挿入できる場所です。 KieSession はエンジンと対話して、挿入されたファクトに基づいてルールで定義された実際のビジネスロジックを処理します。

グローバル(グローバル変数と同じように)は、情報をエンジンに渡すために使用されます。 setGlobal( “key”、value); を使用してグローバルを設定できます。この例では、 Fare オブジェクトをGlobalとして設定して、計算されたタクシー料金を保存しています。

セクション4で説明したように、ルールはで動作するデータを必要とします。 kieSession .insert(taxiRide); を使用して、Factをセッションに挿入しています。

入力Fact、の設定が完了したら、 fireAllRules()。を呼び出すことにより、エンジンにビジネスロジックの実行を要求できます。

最後に、 dispose()メソッドを呼び出して、メモリリークを回避するためにセッションをクリーンアップする必要があります。

5. 実際の例

これで、Springコンテキストを接続して、Droolsが期待どおりに機能することを実際に確認できます。

@Test
public void whenNightSurchargeFalseAndDistLessThan10_thenFixWithoutNightSurcharge() {
    TaxiRide taxiRide = new TaxiRide();
    taxiRide.setIsNightSurcharge(false);
    taxiRide.setDistanceInMile(9L);
    Fare rideFare = new Fare();
    Long totalCharge = taxiFareCalculatorService.calculateFare(taxiRide, rideFare);
 
    assertNotNull(totalCharge);
    assertEquals(Long.valueOf(70), totalCharge);
}

6. 結論

この記事では、DroolsSpringと簡単なユースケースとの統合について学びました。

いつものように、サンプルとコードスニペットの実装はGitHub利用できます。