Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with executing all the rules in the easy-rules-2.0.0 #13

Closed
vinoct6 opened this issue May 21, 2015 · 18 comments
Closed

Problem with executing all the rules in the easy-rules-2.0.0 #13

vinoct6 opened this issue May 21, 2015 · 18 comments
Labels

Comments

@vinoct6
Copy link

vinoct6 commented May 21, 2015

I tried out the new version 2.0.0. All the registered rules does not seem to be triggered.
I'm pasting the code I have written, and I'm expecting all the rules to be executed, but it's not working this way. Let me know if I'm missing something.

  @Rule
  public class RuleA {
    @Condition
    public boolean when(){
        System.out.println("A is called");
        return true;
    }
    @Action
    public void then(){
        System.out.println("A is executed");
    }
}
@Rule
public class RuleB {
    @Condition
    public boolean when(){
        System.out.println("B is called");
        return true;
    }

    @Action
    public void then(){
        System.out.println("B is executed");
    }
}
@Rule
public class RuleC {
    @Condition
    public boolean when(){
        System.out.println("C is called");
        return true;
    }

    @Action
    public void then(){
        System.out.println("C is executed");
    }
}

The Main method for calling these rules:

public class Main {
    public static void main(String[] args) {
          RuleA a = new RuleA();
          RuleB b = new RuleB();
          RuleC c = new RuleC();

           RulesEngine rulesEngine = RulesEngineBuilder.aNewRulesEngine().build();
          rulesEngine.registerRule(a);
          rulesEngine.registerRule(b);
          rulesEngine.registerRule(c);

             rulesEngine.fireRules();
    }
}

Output printed in the console-------------------

May 21, 2015 10:18:26 AM org.easyrules.core.DefaultRulesEngine logEngineParameters
INFO: Rule priority threshold: 2,147,483,647
May 21, 2015 10:18:26 AM org.easyrules.core.DefaultRulesEngine logEngineParameters
INFO: Skip on first applied rule: false
May 21, 2015 10:18:26 AM org.easyrules.core.DefaultRulesEngine logEngineParameters
INFO: Skip on first failed rule: false
May 21, 2015 10:18:26 AM org.easyrules.core.DefaultRulesEngine applyRules
INFO: Rule 'rule' triggered.
A is called
A is executed
May 21, 2015 10:18:26 AM org.easyrules.core.DefaultRulesEngine applyRules
INFO: Rule 'rule' performed successfully.

Question:

Why aren't RuleB and RuleC executed in this case ?

@fmbenhassine
Copy link
Member

Hi,

Rules must have a unique name with in a rules engine registry.
Since you didn't specify a name for each rule, they have been assigned the same default name.
Hence, RuleB and RuleC have not been registered.

Try to give them different names and it should work fine.

Regards
Mahmoud

@vinoct6
Copy link
Author

vinoct6 commented May 21, 2015

A Rule has failed when the condition method returns false right ?

Consider this case:

@Rule(description="ruleA",name="ruleA")
public class RuleA {
    @Condition
    public boolean when(){
        System.out.println("A is called");
        return false;
    }

    @Action
    public void then(){
        System.out.println("A is executed");
    }
}
@Rule(description="ruleB",name="ruleB")
public class RuleB {

    @Condition
    public boolean when(){
        System.out.println("B is called");
        return true;
    }

    @Action
    public void then(){
        System.out.println("B is executed");
    }
}

The Main method

public static void main(String[] args) {
          RuleA a = new RuleA();
          RuleB b = new RuleB();
          RulesEngine rulesEngine = RulesEngineBuilder.aNewRulesEngine().withSkipOnFirstFailedRule(true).build();
          rulesEngine.registerRule(a);
          rulesEngine.registerRule(b);
          rulesEngine.fireRules();
    }

The console output

May 21, 2015 12:27:34 PM org.easyrules.core.DefaultRulesEngine logEngineParameters
INFO: Rule priority threshold: 2,147,483,647
May 21, 2015 12:27:34 PM org.easyrules.core.DefaultRulesEngine logEngineParameters
INFO: Skip on first applied rule: false
May 21, 2015 12:27:34 PM org.easyrules.core.DefaultRulesEngine logEngineParameters
INFO: Skip on first failed rule: true
A is called
May 21, 2015 12:27:34 PM org.easyrules.core.DefaultRulesEngine applyRules
INFO: Rule 'ruleA' has been evaluated to false, it has not been executed.
B is called
May 21, 2015 12:27:34 PM org.easyrules.core.DefaultRulesEngine applyRules
INFO: Rule 'ruleB' triggered.
B is executed
May 21, 2015 12:27:34 PM org.easyrules.core.DefaultRulesEngine applyRules
INFO: Rule 'ruleB' performed successfully.

Question

RuleA returned false. So we should be skipping the remaining rules right ? But RuleB seems to have been executed.

@fmbenhassine
Copy link
Member

A Rule has failed when the condition method returns false right ?

No, a rule fails when it executes with error (throw an exception)
In your case, RuleA didn't evaluated to true, it does not fail.

Try to throw an exception in RuleA action method (to make it fail) and RuleB will not be executed.

@vinoct6
Copy link
Author

vinoct6 commented May 21, 2015

Thank you very much and thanks for updating the framework in a short period of time. :)

@fmbenhassine
Copy link
Member

You are welcome!

Do not hesitate to ask me if you need further support.

@salvitas
Copy link

Hi @benas ,

But if the condition is false, then the action is never executed even if we have an Exception thrown, right?

@fmbenhassine
Copy link
Member

Hi @salvitas

Yes, since (the code of) the action is not executed, it can not throw an exception.

Regards
Mahmoud

@salvitas
Copy link

So...I am trying to use this library to build a simple engine but i am not sure what the proper approach would be, cause i have set up the parameter skipOnFirstFailedRule = true, but because the condition is false, the action never gets executed and therefore the engine does not stop , because there is no failure!
is there a way of firing the action no matter what the condition value is (true or false)?
The idea is create a set of rules, then fire them and if the condition is false i would like to throw an exception and stop execution, if all are true then the logic can continue as success.
Does it makes sense?
Thanks for your thoughts.

@fmbenhassine
Copy link
Member

but because the condition is false, the action never gets executed and therefore the engine does not stop , because there is no failure!

I think there is a little confusion about what a failure means here, just like the previous comment.
I'll try to explain it differently.

A rule is said to be triggered when its condition evaluates to true.
A rule is said to be executed when it is triggered and (all of) its action(s) are successfully executed.
A rule is said to be failed when it is triggered and (one of) its action(s) throws an exception.

When a rule is not triggered (its condition evaluates to false), the engine will simply move to the next registered rule. This is called forward chaining in production systems and Easy Rules is of this type.

is there a way of firing the action no matter what the condition value is (true or false)?

No, this is not how rule based systems are intended to work.

The idea is create a set of rules, then fire them and if the condition is false i would like to throw an exception and stop execution, if all are true then the logic can continue as success.
Does it makes sense?

Yes I see. It's a bit tricky, but in production systems, there is no "ELSE" part. All rules have only two parts: "IF" (LHS) and "THEN" (RHS).
In your case, you can design a rule with the negation of the condition, throw an exception in the action and set the skipOnFirstFailedRule to true. This will stop execution as required. Do you see?

Hope this helps
Kind regards
Mahmoud

@ssozonoff
Copy link

Except for this approach dumps exceptions all over the place even though the behaviour is normal.
Basically all the rules leading up to the final rule need to throw an exception if the Condition is "not met" in order for rules processing to halt. If the last rule is executed it means all the conditions were met.

@fmbenhassine
Copy link
Member

Don't use exceptions for flow control. If you can't design your requirement as a set of ordered rules (IF/THEN (with no else) statements), don't use a production system.

@ssozonoff
Copy link

Thanks for your reply but it puzzles me a little. Maybe as you mention I am looking for a different type of rules engine... but the requirement is simple. If Rule1 fails dont move on to Rule2. From my understanding the only way to accomplish this is throwing an exception in the @action.

I am not looking for an ELSE. I simply want the rule chain to break as soon as a @condition is not met.

@fmbenhassine
Copy link
Member

fmbenhassine commented Sep 6, 2016

Sorry, no offense in my last comment. But I see the confusion here:

If Rule1 fails dont move on to Rule2

What does "fails" means to you?

In Easy Rules, a rule is said to be failed when it is triggered and (one of) its action(s) throws an exception (I tried to summarize definitions in my previous comment) . So in Easy Rules, implementing "If Rule1 fails dont move on to Rule2" is done by setting the skipOnFirstFailedRule parameter (given that rules priorities are correctly defined)

I simply want the rule chain to break as soon as a @condition is not met

That's fine, in this case, probably Easy Rules needs to add a parameter like skipOnFirstNonTriggeredRule (according to what does triggered means in Easy Rules). Do you agree?

@ssozonoff
Copy link

For me a Rule failing means that the Condition was not met. For you it means that an exception was thrown in the @action portion. Ultimately we just need a simple way to break out of the Rule chain on the first occurence of a non met condition. "skipOnFirstNonTriggeredRule" is a possibility.

@fmbenhassine
Copy link
Member

For me a Rule failing means that the Condition was not met.

I see, but this is a common confusion indeed (same here with drools). When the condition of the rule is met, the rule is triggered (or fired) but it can execute successfully or with a failure.

Anyway, I see your point. Please open an issue with your feature request and an example. I'll plan it for next release. Many thanks upfront.

Kind regards
Mahmoud

@shefworx
Copy link

shefworx commented Oct 4, 2016

Hi Mahmoud,

I am also keen to know when the skipOnFirstNonTriggeredRule will be released. Can you please let me know as I also have a need for this feature?

Thanks
Shaheem

@fmbenhassine
Copy link
Member

Hi @shefworx

Adding "skipOnFirstNonTriggeredRule" was forgotten in this closed issue.
I've planned it for next release in issue #52.

Kind regards
Mahmoud

@niketa741
Copy link

Hello @benas / @vinoct6 / @salvitas / @ssozonoff / @shefworx ,
I am working with org.jeasy rules in a project and I want to exit in between if one of the particular rules is executed. Can you please help me with a solution to this problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

6 participants