Search code examples
drools

Drool Rules: Arithmetic Operations


I'm trying to write a simple rule. To perform a set of calculations. I understand that the calculations can be handled via functions. But, The business logic involves calculations.

package com.sample.rules
import com.sample.rules.Test
rule "Calculate"
    when
        Test(calculate == true)
    then
        finalValue = Test(InitialValue) + 10;
        Test.setFinalValue(finalValue)
        System.out.println("FinalValue=" + Test.getFinalValue();
end

The Class file with variable

public class Test {
    private int finalValue;
    private int initialValue;
    private boolean calculate;


    public int getFinalValue() {
        return FinalValue;
    }
    public void setFinalValue(int FinalValue) {
        this.FinalValue = FinalValue;
    }
    public int getInitialValue() {
        return InitialValue;
    }
    public void setInitialValue(int InitialValue) {
        this.InitialValue = InitialValue;
    }

    public boolean isCalculate() {
        return calculate;
    }
    public void setCalculate(boolean calculate) {
        this.calculate = calculate;
    }
}

The App file is as shown below

public class CalculationApp {
    public static void main(String[] args) {        
         System.out.println( "Bootstrapping the Rule Engine ..." );       
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            KieSession kSession =  kContainer.newKieSession("ksession-rules");

            Test test = new Test();
            test.setInitialValue(20);
            test.setCalculate(true);
            kSession.insert(test);

            int fired = kSession.fireAllRules();
            System.out.println( "Number of Rules executed = " + fired );           
    }
}

The rule file throws an error :

Rule Compilation error finalValue cannot be resolved to a variable
Cannot make a static reference to the non-static method getInitialValue() from the type Test
finalValue cannot be resolved to a variable
Cannot make a static reference to the non-static method getFinalValue() from the type Test

While I found the answer by Trial and Error: I'm trying to understand the logic behind it. I mean, Assigning a variable (I understand variable has a different meaning) /assignment in the when condition is understandable, but the same the how does the Then part work. I mean, the item.setFinalValue(...) part.


Solution

  • Your rule has several problems, as indicated by the error.

    Rule Compilation error finalValue cannot be resolved to a variable

    finalValue cannot be resolved to a variable

    The first problem is that you never declare finalValue, just attempt to assign to it on the right hand side. To fix this, simply declare finalValue. Assuming it's an integer:

    int finalValue = ...
    

    This is identical to how it works in Java.

    However given what the original rule looks like, I think you're trying to pull the initial value from the Test object. To do that, you would do something like this:

    rule "Calculate"
    when
      Test( calculate == true,
            $initialValue: initialValue ) // assign the $initialValue variable
    then
      int finalValue = $initialValue + 10; // set finalValue by adding 10 to $initialValue
    

    Cannot make a static reference to the non-static method getInitialValue() from the type Test

    Cannot make a static reference to the non-static method getFinalValue() from the type Test

    Both of these errors indicate that you're trying to call instance methods without an object instance. This is once again the same as in Java, where if you have an instance method you must call it against an instance.

    Assuming these are methods on the Test class, you would change your rule to be:

    package com.sample.rules
    import com.sample.rules.Test
    
    rule "Calculate"
    when
      $test : Test( calculate == true,
                    $initialValue: initialValue )
    then
      int finalValue = $initialValue + 10;
      $test.setFinalValue(finalValue); // call against $test instance
      System.out.println("FinalValue=" + $test.getFinalValue()); // you were also missing a parenthesis
    end