Looping on in-lined code but not when moved to function

39 views
Skip to first unread message

thomamt

unread,
Jun 17, 2022, 11:08:22 AM6/17/22
to Drools Usage
Drools version 7.70.0.Final

Hi,

the simplified example below highlights the problem I'm seeing. 

The code below is looping on [AfterMatchFiredEvent]: Subtraction rule whereas if I move the subtract operation to a drl declared function it behaves fine. Anyone know why that should be the case?

rule "Subtraction rule"    
agenda-group "math-agenda"
  when
    $fact : MathFact( bigDecimal1 != null, bigDecimal2 != null );
  then        
    BigDecimal result = $fact.getBigDecimal1().subtract($fact.getBigDecimal2());

    modify($fact) {
    setResult(result);
  };
end

Thanks

Toshiya Kobayashi

unread,
Jun 21, 2022, 12:13:15 AM6/21/22
to Drools Usage
Hi,

Could you share a simple reproducer (a maven project)? I tried the rule but couldn't reproduce the issue (loop) on my end.

Regards,
Toshiya

2022年6月18日土曜日 0:08:22 UTC+9 thomamt:

thomamt

unread,
Jun 21, 2022, 6:31:51 AM6/21/22
to Drools Usage
Hi Toshiya,

thanks for taking a look.

I had a go on a brand new project which I can share if you want but I think you should be able to recreate with the code below, it is more subtle than I realised. Obviously I can work around this easily but curious whether the problematic pattern outlined below is something that I should just be avoiding in general or whether it highlights anything else to be aware of? Thanks. 

Below I have an 'init' rule and then three variations of the subtract, two of which work fine, the final one causes looping.

rule "init"
when
    not MathFact(  );
then
    MathFact fact = new MathFact();
    fact.setBigDecimal1(BigDecimal.valueOf(10));
    fact.setBigDecimal2(BigDecimal.valueOf(5));
    insert(fact);
end

// Works
rule "subtract"

when
    $fact : MathFact( bigDecimal1 != null, bigDecimal2 != null );
then
    // Notice the entire calculation is on one line.
    BigDecimal result = $fact.getBigDecimal1().subtract($fact.getBigDecimal2());
       
    System.out.println("\nMathFact.result: " + result);
 
    modify($fact) {
        setBigDecimalResult(result);
    };
end

// Works
rule "subtract"

when
    $fact : MathFact( bigDecimal1 != null, bigDecimal2 != null );
then
    // Notice the calculation is split over lines but starts on the same as the assignment.
    BigDecimal result = $fact.getBigDecimal1().subtract(
        $fact.getBigDecimal2());
       
    System.out.println("\nMathFact.result: " + result);
 
    modify($fact) {
        setBigDecimalResult(result);
    };
end

// Looping!
rule "subtract"

when
    $fact : MathFact( bigDecimal1 != null, bigDecimal2 != null );
then
    // Notice the calculation is split over lines and this time starts on the line after assignment.
    BigDecimal result =
        $fact.getBigDecimal1().subtract($fact.getBigDecimal2());
       
    System.out.println("\nMathFact.result: " + result);
 
    modify($fact) {
        setBigDecimalResult(result);
    };
end

Toshiya Kobayashi

unread,
Jun 21, 2022, 10:57:18 PM6/21/22
to Drools Usage
Thank you for the detailed information, Andrew.

I reproduce the issue and filed a JIRA.

https://issues.redhat.com/browse/DROOLS-7031

The problem is that Drools failed to analyse the line and mistakenly considered that "bigDecimal1 is modified" so re-evaluated the rule repeatedly.

Workarounds are:

A) Write the statement without a line break.

B) Use executable-model (executable-model analyzes better respecting Java statement)

Thanks!
Toshiya

2022年6月21日火曜日 19:31:51 UTC+9 thomamt:

thomamt

unread,
Jun 22, 2022, 3:57:49 AM6/22/22
to Drools Usage
Thanks for the explanation Toshiya and for filing the Jira. Will take note of the workarounds, appreciate it, thanks again.

Andrew

Reply all
Reply to author
Forward
0 new messages