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).
Related
Say I have a rule file like below. Below rules are built on 2 properties Instrument and maverickModelMappingId. Can Drools tell me how many rules use the field "Instrument"? My use case is that I want to know if I am deleting an attribute or a field, how many rules and which rules are going to be affected.
package abc.modelMapping.ruleEngine;
dialect "java"
declare FRONTOFFICESYSTEM
Instrument : String
maverickModelMappingId : String
end
rule "rule_MurexCredit_Rule_3"
salience 3
no-loop true
when
$frontOfficeSystem : FRONTOFFICESYSTEM("Default swap".equalsIgnoreCase(Instrument))
then
$frontOfficeSystem.setMaverickModelMappingId("001282");
System.out.println("001282 "+"MurexCredit_Rule_3+");
end
rule "rule_MurexCredit_Rule_2"
salience 2
no-loop true
when
$frontOfficeSystem : FRONTOFFICESYSTEM("Euro credit index option".equalsIgnoreCase(Instrument))
then
$frontOfficeSystem.setMaverickModelMappingId("001283");
System.out.println("001283 "+"MurexCredit_Rule_2+");
end
rule "rule_MurexCredit_Rule_1"
salience 1
no-loop true
when
$frontOfficeSystem : FRONTOFFICESYSTEM("Credit index".equalsIgnoreCase(Instrument))
then
$frontOfficeSystem.setMaverickModelMappingId("001282");
System.out.println("001282 "+"MurexCredit_Rule_1+");
end
This is not possible with Drools, as of the current version (7.33.0.Final). As mentioned in the comments, the better solution will be to use your IDE's search tools -- or other find/grep solution -- to search the text of the rule file(s) for references to the given attribute or method.
In the below rules I expect Rule2 is fire because I am modifying customer name to mahesh. But when I execute Rule2 is not firing but Rule3 is firing. Am I missing anything here
rule "Rule1"
lock-on-active true
salience 95
when
$c:Customer($customerName:customerName)
then
System.out.println($customerName+" =======2========");
modify($c){
setCustomerName("mahesh");
}
System.out.println($customerName);
end
rule "Rule2"
lock-on-active true
salience 85
when
$c1:Customer($customerName:customerName=="mahesh");
then
System.out.println($customerName+" Rules Name is 1 - " + drools.getRule().getName());
$c1.setCustomerName("mahesh456");
update($c1);
end
rule "Rule3"
lock-on-active true
when
$c:Customer($customerName:customerName)
then
System.out.println($customerName+ "***** ");
end
What lock-on-active does is to prevent a rule to be activated if the agenda group where the rule is defined is already active.
In your case, because you was already executing the rules (fireAllRules) the MAIN agenda group (which is the group that both of your rules belong to) was already active. This mean that the second rule activation is going to be cancelled by Drools.
You can find here a more in depth explanation.
Hope it helps,
I want to run a rule that calls Java method and passes the fact (or rather, its logical value) from another rule, although I don't know if the java methods are at all important for this problem. It's not easy to describe so I'll try to show it based on an example:
rule "Some rule determining fact"
when
... //some conditions
then
insert(new SomeCondition(callSomeJavaMethodReturningBoolean()))
end
rule "Some rule using SomeCondition"
when
SomeCondition($value: value)
... //some other conditions
then
insert(callJavaMethodUsingSomeCondition($value))
end
The problem here is that the first rule doesn't always fire, so SomeCondition is not always definded and second rule isn't evaluated.
My second try was to create two separate rules like this:
rule "Some rule determining fact"
when
... //some conditions
then
insert(new SomeCondition(callSomeJavaMethodReturningBoolean()))
end
rule "SomeConditionTrueRule"
when
SomeCondition(value == true)
... //some other conditions
then
insert(callJavaMethodUsingSomeCondition(true))
end
rule "SomeConditionFalseRule"
when
not SomeCondition() or SomeCondition(value == false)
... //some other conditions
then
insert(callJavaMethodUsingSomeCondition(false))
end
This doesn't work as intended either, because it first evaluates SomeConditionFalseRule before even evaluating my first rule. I'll appreciate any suggestions on how to solve this problem. Drools version used is 6.5.0 if that matters. Also, I want to avoid using salience if possible since I've read it is a bad practice (correct me if I'm wrong).
In this case, you need to separate the 2 groups of rules (the ones inserting SomeCondition objects and the ones executing the java code).
The easiest way would be to use a lower salience in the second group:
rule "Some rule determining fact"
when
... //some conditions
then
insert(new SomeCondition(callSomeJavaMethodReturningBoolean()))
end
rule "SomeConditionTrueRule"
salience -1
when
SomeCondition(value == true)
... //some other conditions
then
insert(callJavaMethodUsingSomeCondition(true))
end
rule "SomeConditionFalseRule"
salience -1
when
not SomeCondition() or SomeCondition(value == false)
... //some other conditions
then
insert(callJavaMethodUsingSomeCondition(false))
end
A more robust approach would be to use 2 agenda-groups and to activate them one after the other.
But the idea is that the rules executing the java code give time to the rules determining what needs to be executed to come up with the final decision.
In the case I've presented above, as soon as you create your session, you will have an activation (A1) for SomeConditionFalseRule but the activation will not be executed until you call fireAllRules(). If you then insert the necessary facts to make SomeConditionTrueRule true, you will have now an activation (A2) for it.
At this point, the agenda will look like this: | A1 | A2 |.
When calling fireAllRules(), Drools will pick the activation in the agenda with the higher salience (by default, rules have a salience of 0). In this case, A2 will be picked and executed.
The execution of A2 will insert a new Fact that will make A1 invalid and it will create a new activation (A3) for SomeConditionTrueRule. Drools will then proceed to remove A1 from the agenda, so the rule SomeConditionFalseRule will not be executed.
The agenda after A2 is executed will look like this: | A3 |
Hope it helps,
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.
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.