Search code examples
drools

Binding variables to different data types in case of 'or' in the rule LHS


How can I bind variables to different types of facts matched in an or group in the rule LHS ?

For instance, if I have the following rule-file:

package com.sample

rule "Rule1"
    when
         object1: ObjectType1( id == 1) or
         object2: ObjectType2( id == 2)
    then
        System.out.println(object1.getId());
        System.out.println(object2.getId());
end

and I use this driver code:

package com.sample;

import org.kie.api.runtime.KieSession;

public class DroolsTest {

  public static final void main(String[] args) {
    try {
      String ruleFilePath = "src/main/resources/rules/ruleFile.drl";
      KieSession kSession = KSessionUtil.buildKSession(ruleFilePath);

      ObjectType1 o1 = new ObjectType1(1);
      ObjectType2 o2 = new ObjectType2(2);

      kSession.insert(o1);
      kSession.insert(o2);

      kSession.fireAllRules();

      System.out.println("Bye");
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }
}

ObjectType1.java:

package com.sample;

public class ObjectType1 {
  public ObjectType1(int i) {
    super();
    this.id = i;
  }

  public int getId() {
    return id;
  }

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

  public int id;
}

ObjectType2.java:

package com.sample;

public class ObjectType12 {
  public ObjectType2(int i) {
    super();
    this.id = i;
  }

  public int getId() {
    return id;
  }

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

  public int id;
}

I get a syntax error from the Drools Eclipse plugin:

object1 cannot be resolved.
object2 cannot be resolved.

If I change the or in the rule LHS to and, the error goes away.

I am using Drools 6.2.0.


Solution

  • The tricky part is how Drools deals with or operands between patterns. In your example, Drools will decompose your rule into 2 independent rules:

    rule "Rule1_A"
    when
         object1: ObjectType1( id == 1)
    then
        System.out.println(object1.getId());
        System.out.println(object2.getId());
    end
    
    
    rule "Rule1_B"
    when
         object2: ObjectType2( id == 2)
    then
        System.out.println(object1.getId());
        System.out.println(object2.getId());
    end
    

    As you can see, the error becomes now more evident.

    A side-effect of the way Drools deals with or is also that there is no short-circuit in this operation: if both objects are present in your session, the rule will be executed twice.

    Hope it helps,