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
Stopping the chain if a Rule returns false #77
Comments
My apologies for the delayed response. I was on vacation for a bit. I think what you are looking for was answered in this issue: #74 |
Hi Unfortunately I'm not using the POJO rules and the @then annotation. I need to dynamically create the various rules so I'm using the RuleBuilder.create(..) method, which doesn't look like I can return a RuleState from the then method. Is there another way of doing it ? Thanks D |
You can still do it! Pojo rules just use an adapter under the hood to convert to non-pojo rules. ;) I'll post an example of how it looks with non-pojo rules sometime tomorrow - it would be today, but I am otherwise committed. |
Here is an example RuleBook ruleBook = RuleBookBuilder.create()
.addRule(rule -> rule.withNoSpecifiedFactType()
.when(f->true)
.then(f -> System.out.println("breaking the rule chain here"))
.stop())
.addRule(rule -> rule.withNoSpecifiedFactType()
.when(f->true)
.then(f -> System.out.println("next rule"))
.stop()).build(); The first rule will execute and then it will break the rule chain after the rule is invoked. This shows how to break the rule chain when the rule evaluates to true. In order for a rule to perform any action, including breaking the rule chain, its 'when' condition must be true and its 'then' condition must be invoked. Of course, you could always have a rule that breaks the rule chain based on the inverse being evaluated in a 'when' statement and then having the stop() method set on that rule. A trivial example would be as follows. RuleBook ruleBook = RuleBookBuilder.create()
.addRule(rule -> rule.withNoSpecifiedFactType()
.when(f-> !isTrue)
.then(f -> {})
.stop()) //stops the rule chain if isTrue == false
.addRule(rule -> rule.withNoSpecifiedFactType()
.when(f->true)
.then(f -> System.out.println("next rule"))
.stop()).build(); |
closing due to inactivity |
Sorry for the late reply. Many thanks for the example, although its not quite what I was hoping for as the result of the when needs to evaluate to true to execute the then, which is where the rule is used to break the rule chain. However, I'd like to be able to break the rule chain if the when fails and only perform the then if the when is successful. Kind of like the the .orElse terminology of java 8. Would this be possible ? |
A related question was asked in Issue #79. In the interest of DRY, I will paraphrase the response :)
With that being said, adding in a feature that would allow for breaking the rule chain on a 'false' rule... that could happen. But it would be specific to the CoR implementation of RuleBook (currently, the only implementation). Future RuleBook implementations (future sate, there will be more than one packaged implementation), however, may have different execution sequences, where that would not be possible. |
That would be great. I don't think it would be unreasonable to simply have a setting to determine whether a rule chain should break on failure of a rule, that would suit my purposes entirely (well, certainly for the foreseeable future). What I'm trying to avoid is having to have a negative rule for each positive rule with the negative rule simply breaking the chain...it seems a little excessive :-). |
This update is on deck for the v0.8 release. v0.7 is planned for release to Maven Central on August 7. v0.8 is due to be released by the end of August and the SNAPSHOT release will be pushed on August 7. The v0.8 code is currently in the Issue67_EnhanceDSL branch which includes DSL related feature updates for v0.8. |
Here's what is planned: RuleBook ruleBook = RuleBookBuilder.create()
.addRule(
RuleBuilder.create(GoldenRule.class, true) //second param indicates that on failure this rule can stop the rule chain
.withFactType(String.class)
.when(facts -> false)
.then(someConsumer)
.stop() //signals that this rule stops the rule chain
.build())
.addRule(
RuleBuilder.create() //this rule will never be invoked since the above rule stopped the rule chain when its condition was false
.withFactType(String.class)
.when(facts -> true)
.then(someOtherConsumer)
.build())
.build(); Since this behavior is specific to sequential rules execution, it can only work with RuleBook implementations that use sequential rules execution (i.e. CoRRuleBook). So, the default behavior is still when a rule fails or its condition is not met, the rule chain continues. However, if a developer would like to make so that on a failure or failed rule condition, the rule breaks the rule chain, they may do so by specifying that in the creation of the rule (only available via RuleBuilder or the rule's constructor) using the optional boolean parameter. In that case, those rules that do not error and their condition is true will NOT break the rule chain; it will only break if the rule's condition evaluates false or the rule fails. |
This is updated in the 0.8-SNAPSHOT. One change was made, however. The above code would now look like this: RuleBook ruleBook = RuleBookBuilder.create()
.addRule(
RuleBuilder.create(GoldenRule.class, STOP_ON_FAILURE) //second param indicates that on failure this rule can stop the rule chain
.withFactType(String.class)
.when(facts -> false)
.then(someConsumer)
.stop() //signals that this rule stops the rule chain
.build())
.addRule(
RuleBuilder.create() //this rule will never be invoked since the above rule stopped the rule chain when its condition was false
.withFactType(String.class)
.when(facts -> true)
.then(someOtherConsumer)
.build())
.build(); |
This enhancement was released in v0.8. |
Cool, thanks, I'll take at this hopefully sometime this week, many thanks for that |
Hi
If I want to add a bunch of rules, where I want the result to contain success ONLY if all rules are successful, is this possible currently. So, lets say that I have two rules, the first one checks if a user is Male, the second checks whether the users age is less than 40. If the user happens to be female, then the first rule will return false, but the second rule will still process. If the second rule returns true (the user is less than 40), then the rulebook result is true, even though I actually want it to be false. Essentially I'd like to be able to stop the chain should a rule fail, but this doesn't look possible. Is there another way of doing this possibly ?
Thanks
Darrell
The text was updated successfully, but these errors were encountered: