Search code examples
droolsdslrule-engine

If condition in THEN clause drools


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

Solution

  • 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