I'm using JBoss Drools to write some business rules. I got a problem on the "not exists" rule.Here is my code.
rule "ATL 27R-A12 Subfleet A319-100 Departure configuration list has flap 1"
salience 20
no-loop true
when
AircraftConfig(aircraftType=="A319-100")
RunwayInfo(airport3lCode== "ATL", runwayId == "27R-A12" )
not (exists (DepartureConfiguration( flap == 1 )))
then
throw new RuleNotMatchException("The configurations do not match the rule of this runway.");
end
My facts contains:An AircraftConfig, an RunwayInfo and several DepartureConfigurations. I want to fire the rule when there are no DepartureConfiguration which flap=1. I mean, if there are three DepartureConfigurations, one of them has the flap=1, the others are flap=2 or flap=3, then this rule will not fire.
How could I make this work?
The keyword for checking for the non-existence of a fact is not, not not exists. Change the last line of your condition to:
not DepartureConfiguration( flap == 1 )
Actually, I made some conflict in my rules. I used to think the rules should be ran from the top to the end of the drl file. I solved my problem by adding a rule flow. Also thanks to you guys who give me suggestions.
Related
I am using guided rule in business central, Modiying the fact in action part with no-loop true .
Still the looping is happening .
when I use lock-on-active the rule do not run at all.
Please help.
rule "today true and close time is before 15pm"
dialect "mvel"
salience 120
ruleflow-group "gogo"
no-loop true
lock-on-active true
when
v : VendorWorkingDays( eval( vendorWD contains(java.time.LocalDate.now().plusDays(1).getDayOfWeek().toString()) )&& todayFlag == true && eval( closeTime.isBefore(java.time.LocalTime.parse("15:00:00")) ))
then
modify( v ) {
setTodayOneE( "NA" ),
setTodayOneM( "Available" ),
setTodayOneFlag( true )
}
System.out.println("today true and close time is before 15pm");
end
You may want to take a look at this other question: what is the difference between no-loop and lock-on-active in drools
In your case, the use of modify is causing the rules related to the VendorWorkingDays to be re-evaluated. The use of no-loop only works for when you have a single rule looping. I guess that in your case, you may have multiple rules involved in the infinite loop.
The use of lock-on-active will prevent the execution of this rule if the VendorWorkingDays is being inserted into the session (or modified) from another rule.
There is a link to a blog post in the question I mentioned that will give you a better explanation about these two attributes (the blog post is quite old, but the principles are still more or less valid for the latest version of Drools).
I run a rule that contains a few patterns, I want to know which pattern failed:
I've tried to debug the code (drools 7.18.0), and didn't found the relevant place.
rule example:
rule "Trigger"
agenda-group "Trigger"
salience 100
when
$pcase : PCaseMgr()
D1($id: id, type != null, type == "AAA")
D2(aId == $id)
then
$pcase.printAnalyticsRuleLog(">>>>>>>>>>>>>>>>>>> In Trigger");
end
in the example above, if D1 pattern is passed, and D2 pattern is failed, where in the code (of drools 7.18.0) can i see if the pattern was failed?
You can't. Because of the algorithm Drools uses internally, patterns are decomposed into nodes and nodes can be shared among multiple rules in your knowledge base. If you really need to know why a rule was not fire, then you can create other rules that will tell you that. In your example, you could create something like this:
rule "No Trigger because of No D2"
agenda-group "Trigger"
salience 100
when
$pcase : PCaseMgr()
D1($id: id, type != null, type == "AAA")
not D2(aId == $id)
then
$pcase.printAnalyticsRuleLog(">>>>>>>>>>>>>>>>>>> No Trigger because no D2");
end
Hope it helps,
I am using decision tables and would like to trigger one rule per input item.
I am using decision have set the Sequential = true and defined all rules as part of the same ACTIVATION-GROUP.
When I trigger the drools rules engine using below it just evaluates for the first input item and others are ignored. The behavior I want is to evaluate at most 1 rule per input item (rule order defined by the Salience).
kieStatelessSession.execute(inputList)
I can get this working by sending one item at a time to the kieStatelessSession, but would prefer to execute all at once.
I am using Drools verison 6.5.0.FINAL and Java 7.
There is no out of the box support in Drools for what you are trying to achieve. If you want your rules to be evaluated once for each fact, you will need to code it yourself.
One approach could be to have another type of facts to mark when one of the inputs is processed:
declare Marker
fact : Object
end
//Bellow are the rules that should be coming from your decision table.
//Each rule will do whatever it needs to do, and then it will create a
//Marker fact for the fact that was processed.
//These rules now include a "not" Conditional Element to avoid a fact to be
//evaluated more than once.
rule "Rule 1"
salience 100
when
$fact: Object(...) //your conditions
not Marker(fact == $fact)
then
//... Your logic
insert(new Marker($fact));
end
...
rule "Rule 50"
salience 50
when
$fact: Object(...) //your conditions
not Marker(fact == $fact)
then
//... Your logic
insert(new Marker($fact));
end
Hope it helps,
relative new comer to drools and rules engines.
I have three rules that essentially check if different instances of the same object exist, if they don't, they create one and insert it into the working memory. After performing a series of other related rules, theres a rule that checks for validity of the models.
The goal here is to have three different instances of the same object that represent three different entities and proceed as long as 2 of them are in a valid state.
They're defined as follows:
rule "SetupA"
salience 80
lock-on-active
when
not InvalidModel(name == "A-Name")
then
InvalidModel invalidA = new InvalidModel();
invalidA.setName("A-Name");
insert(invalidA);
end
rule "SetupB"
salience 80
lock-on-active
when
not InvalidModel(name == "B-Name")
then
InvalidModel invalidB = new InvalidModel();
invalidB.setName("B-Name");
insert(invalidB);
end
rule "SetupC"
salience 80
lock-on-active
when
not InvalidModel(name == "C-Name")
then
InvalidModel invalidC = new InvalidModel();
invalidC.setName("C-Name");
insert(invalidC);
end
rule "VALIDATE_MODEL_FOR_ANY_INVALID_FLAGS"
salience -10
when
$invalidList: List(size > 1) from collect(InvalidModel(isNotFound || isFlagged || isNotActive))
then
setDecision(result, "Denied");
end
However, what's happening is that it seems like these rules are matched on every request to this ruleset which I interpret as the facts not existing in the Working Memory. I'd expect the rules to be fired once, when each of the facts for the respective names dont exist, and then to not fire again as there is nothing that would remove them from the working memory. However, my audit log of the rules that fire show that for every request those rules get fired.
Furthermore, the fourth rule's condition seems to not be performing as expected as it returns a response like such
=============== DEBUG MESSAGE: illegal bytecode sequence - method not verified ================
My ask is for some guidance on where my logic/drools language structure may have gone astray. Thanks for your time.
As an exercise in teaching myself drools I'm working on rules for bidding in the bridge card game. The rules work independently of each other (enforced by use of drools.halt() in the rules) but when I try to extend the example by removing the halt() calls, I get behavior I didn't expect. In the example below I am commenting out the halt() in the first rule, and adding the size() condition to the 2nd rule to replace it, trying to prevent the 2nd rule from firing. I would not expect the 2nd rule to fire because the consequence of the first rule added a bid to the Auction's collection, and so subsequently in rule 2 the count should not be zero. I've tried explicitly adding the 'update' or 'modify' directives in the first rule, but that didn't make any difference.
rule "rule1"
salience 100
when
$auction : Auction( $currentBidder : currentBidder != null )
$hand : Hand( owner.equals($currentBidder), getTotalPoints(getLongestSuit()) >= 13 )
then
$auction.bid($currentBidder, new Bid(1, $hand.getLongestSuit()));
//drools.halt();
end
rule "rule2"
salience 1
when
$auction : Auction( $currentBidder : currentBidder != null, getPlayerBids().size() == 0 )
Hand(owner.equals($currentBidder))
then
$auction.bid($currentBidder, new Pass());
drools.halt();
end
When you change an object, you need to tell the engine you updated it. So try adding update($action); at the end of the first rule.