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.
</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.
<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.
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:
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.
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.
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
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.