3

I tried researching a lot online but unable to find the exact reason for my error

Here is my problem

I am trying to write an if-else condition in RHS (THEN) but my drools show the following error

[An error occurred when attempting to build drools rule set. Error: Unable to Analyse Expression if (

I know this clearly says that I can't write if inside THEN (RHS), but I was able to do it in drools version 6.5.0-FINAL

is it something that got introduced in the 6.5.0 version? please guide me in the right direction for this investigation

I cant create two rules for this I need an if-else condition inside THEN

my drools version is 5.5.0

rule "TEST"
when
     $aa : Age()
then
     if(//something)
     {
        //something
     }
     else
     {
     }
end
jagapathi
  • 1,635
  • 1
  • 19
  • 32

1 Answers1

7

This is perfectly valid going back to Drools 5.0 (can't speak to earlier, that's the earliest I ever used.) It is bad rule design -- whatever is restricting you to not adding a second rule is simply incorrect -- but you can have an if/else on the right hand side.

The reason it is bad rule design is that conditions should go on the conditional clause (left hand side, 'when') and the right hand side (then) should have the consequences. Drools optimizes the checking of conditions on the LHS, but executes the consequences on the RHS as-is. So by moving conditions to the RHS, you are causing your rules to be less performant because you're bypassing the optimization Drools provides.

The correct way would be -- as you probably figured out -- to have two rules like follows. (Since I don't know your particular use problem I'm going to make up something -- a difference in consequence depending on if the age is greater than or less than 18.)

rule "TEST - Under 18"
when
  Age( value < 18 )
then
  System.out.println("User is underage.");
end

rule "TEST - Adult"
when
  Age( value >= 18 )
then
  Sytem.out.println("User is an adult.");
end

As mentioned, you still can use an if-else if you must, but it is bad rule design and if I were doing your code review I'd send it back for revision. :)

rule "TEST WITH BAD PRACTICES"
when
  Age( $age: value )
then
  if ($age < 18) {
    System.out.println("User is underage.");
  } else  {
    System.out.println("User is an adult.");
  }
end

This rule is perfectly valid and it works. If it doesn't work for you, the problem is not with the rule, it's with something else in how you're loading or firing your rules that you have not shared. Maybe it's your dialect. Maybe it's how you're loading them. Maybe you have a typo in your 'if' like a missing quotation mark or hyphen, which you haven't shown us because you've not provided your actual rule.

That's something you'll have to investigate in your own environment (I suggest breakpoints and a debug session in your IDE.)


For completeness' sake, Drools 7 introduced the concept of conditional and named consequences. While many I know prefer the simplicity and streamlined-ness of the best practice of having multiple rules, this is an alternative way to provide conditional processing in a single rule.

Basically the idea is that if you have two extremely similar conditions, such that one builds off the other, you can use a syntax that is very similar to "goto" to trigger permutations of the right hand side. Here is how you might go about doing it for your situation:

rule "TEST with named consequences"
when
  Age( $age: value )
  if ( $age  < 18 ) break[underage]
then
  System.out.println("User is an adult.");
then[underage]
  System.out.println("User is underage.");
end
Roddy of the Frozen Peas
  • 14,380
  • 9
  • 49
  • 99
  • 1
    Thanks for the answer @roddy-of-the-frozen-peas , as of now I am using named consequences as my alternative, I am just curious why would my drools 5.5.0 version throw this kinda error, if drools is supporting the condition in RHS. As you mentioned that could be an issue with my MVEl dialect. – jagapathi Jul 12 '20 at 10:46
  • Not sure. At my last job we used Drools 5.0 and we had rules that had if/else in the RHS. My guess is that the issue is something specific to your rule or environment. – Roddy of the Frozen Peas Jul 12 '20 at 16:03
  • adding dialect "java" in my rule fixed my issue any idea why would this happen? – jagapathi Jul 13 '20 at 05:11
  • Not a clue. I've always used "mvel" dialect. Java dialect is supposed to be the default, so adding an explicit declaration should have been a "no-op". – Roddy of the Frozen Peas Jul 13 '20 at 05:38
  • 2
    @RoddyoftheFrozenPeas your avatar is of canned peas, not frozen! :D – cellepo Dec 17 '20 at 16:06
  • @cellepo - It's surprisingly hard to find an image of frozen peas that is readily recognizeable at such tiny resolution. :) – Roddy of the Frozen Peas Dec 17 '20 at 16:08
  • I really like the solution with break; it reduced the number of lines 2x. I wonder though if it's also not recommended as using breaks in classic programming languages. – xagaffar Jun 07 '23 at 08:28
  • Line count generally doesn't correlate to performance, though it may minimally correlate to the memory footprint of the rules. Using conditional and named consequences like this may cause issues with inheritance because the parent rule introduces branching paths that may cause unintended consequences for the child rules and be more difficult to debug. I personally have never benchmarked two rules vs a single rule with conditional/named consequences, but I don't imagine there would be a significant performance impact one way or the other. – Roddy of the Frozen Peas Jun 07 '23 at 12:36