Migration Guide

Migrate to Drools 8

This guide explains how to migrate Drools 7 projects to Drools 8 projects.

Firstly, Drools 8 supports Drools 7 APIs and DRL syntax, so basically you don’t need to change your Java codes and rule assets. However, there are some cautions in pom.xml.

Typical Drools 6 or early 7 projects have pom dependencies like this.

Traditional pom.xml
  </dependencied>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-core</artifactId>
      <version>${version.org.drools}</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-compiler</artifactId>
      <version>${version.org.drools}</version>
    </dependency>
  </dependencied>

But since Drools 7.45.0, drools-engine and drools-engine-classic have been introduced as aggregator dependencies. The dependencies drools-engine-classic, drools-mvel are deprecated starting with Drools 8. Hence, use drools-engine.

    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-engine</artifactId>
      <version>${version.org.drools}</version>
    </dependency>

Drools 8 made some module refactoring, so you may find some difficulty in collecting dependencies. This aggregator dependency would help.

Rule Unit

As introduced in First Rule Project, using Rule Units is a recommended style for implementing rules in Drools 8. It will require some modifications to your codebase, but if you are going to develop cloud-native applications, Rule Units are strongly recommended, because Kogito also works with Rule Units.

Rule Unit pom.xml
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-ruleunits-engine</artifactId>
      <version>${version.org.drools}</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-model-compiler</artifactId>
      <version>${version.org.drools}</version>
    </dependency>

drools-ruleunits-engine is required for Rule Unit APIs. drools-model-compiler is required to generate executable model that is also recommended in Drools 8.

Regarding related Java API usage, in Drools 7, you create a KieSession from rule assets. Then insert facts and fire rules.

Traditional Java code
        KieServices ks = KieServices.Factory.get();
        KieContainer kcontainer = ks.getKieClasspathContainer();
        KieBase kbase = kcontainer.getKieBase();
        KieSession ksession = kbase.newKieSession();
        try {
            ksession.insert(new Measurement("color", "red"));
            ksession.insert(new Measurement("color", "green"));

            ksession.fireAllRules();
        } finally {
            ksession.dispose();
        }

Using Rule Unit APIs, the resulting Java snippet would be like this:

Rule Unit Java code
        MeasurementUnit measurementUnit = new MeasurementUnit();
        RuleUnitInstance<MeasurementUnit> instance = RuleUnitInstanceFactory.instance(measurementUnit);
        try {
            measurementUnit.getMeasurements().add(new Measurement("color", "red"));
            measurementUnit.getMeasurements().add(new Measurement("color", "green"));

            instance.fire();
        } finally {
            instance.dispose();
        }

In Rule Unit, instantiate RuleUnitInstance instead of KieSession. Add facts to DataSource property instead of insert. Generic KIE API calls (e.g. KieServices, KieContainer, KieBase …​ ) are no longer needed. Instead, one more class Unit has to be defined.

Rule Unit Class
public class MeasurementUnit implements RuleUnitData {

    private final DataStore<Measurement> measurements;
    private final Set<String> controlSet = new HashSet<>();

    public MeasurementUnit() {
        this(DataSource.createStore());
    }

    public MeasurementUnit(DataStore<Measurement> measurements) {
        this.measurements = measurements;
    }

    public DataStore<Measurement> getMeasurements() {
        return measurements;
    }

    public Set<String> getControlSet() {
        return controlSet;
    }
}

This Unit class associates rules (DRL) and inserted facts (DataSource), so it helps you to manage the relationship.

DRL syntax style also changes.

Traditional DRL
global java.util.Set controlSet;

rule "will execute per each Measurement having ID color"
when
	Measurement( id == "color", $colorVal : val )
then
	controlSet.add($colorVal);
end
Rule Unit DRL
unit MeasurementUnit;

rule "will execute per each Measurement having ID color"
when
	/measurements[ id == "color", $colorVal : val ]
then
	controlSet.add($colorVal);
end

Firstly, declare unit. Don’t need to declare global, because controlSet is a field of MeasurementUnit. Traditional global usage would become the Unit’s field. In addition, the main difference is OOPath notation in LHS. It is described in detail at Rule conditions in DRL. You should change from the class name (Measurement) to the DataSource property name in the Unit class (measurements).

These changes are not negligible, but hopefully, as this migration guide demonstrated, they are not so difficult to implement either.