Boolean value in when section using Drools 7.21 - java

I am trying to migrate Drools from version 5.2 to 7.21. I rebuilded the code to KIE API and all looked fine, but now I get a problem in DRL files. In "when" section in Drools file I need to use statement "finished != true". In v5.2 it worked fine, but in v7.21 not...
My code:
rule"..."
when
element : Operation( person.id == $person.getId(), finished != true )
then
(...)
end
I've done some tests, and the results are wierd:
finished != true -> it doesn't work and all objects with "finished == true" are in the results too
finished == false -> like above
finished -> it's working fine and only the objects with "finished == true" are in the results
finished == true -> like above
I need to use finished != true or something similar. How can I fix it? Is it an error in new Drools version?

I found a workaround which is working for me. If someone have better way to do it, please share it here.
rule"..."
when
$booleanTrue : Boolean(booleanValue == true) from 1 == 1
element : Operation( person.id == $person.getId(), finished != $booleanTrue )
then
(...)
end

Simply use below:
rule"..."
when
element : Operation( person.id == $person.getId(), finished)
then
(...)
end
Or
rule"..."
when
element : Operation( person.id == $person.getId(), !finished)
then
(...)
end

Related

Why does this Drools scenario cause an infinite loop?

I'm working on writing a rule set in Drools and the following situation causes an infinite loop by retriggering the rule:
rule "My Rule"
when
a1:ObjectA()
b1:ObjectB(field1 > 0 || a1.field1 in (1,2,3))
ObjectB(field2 > 10)
then
modify( b1 ) { setField3(5) };
end
The following rule change doesn't result in an infinite loop, i.e., when a1 is no longer referenced within ObjectB:
rule "My Rule"
when
b1:ObjectB(field1 > 0 || field4 in (1,2,3))
ObjectB(field2 > 10)
then
modify( b1 ) { setField3(5) };
end
Another scenario which doesn't cause an infinite loop is when I change the || to an && in the second when line:
rule "My Rule"
when
a1:ObjectA()
b1:ObjectB(field1 > 0 && a1.field1 in (1,2,3))
ObjectB(field2 > 10)
then
modify( b1 ) { setField3(5) };
end
From the Drools docs I understand that calling modify(){} will "trigger a revaluation of all patterns of the matching object type in the knowledge base," but since the field I'm modifying, field3, isn't used in the LHS conditions, I didn't think it should reevaluate. However, I am faily certain it has to do with referencing a1.field1 within ObjectB, but I can't find a concrete reason why. Thanks in advance!
It matters at the object level, not the field level. Since you modify a1, the rule is re-evaluated because it relies on the ObjectA objects in working memory. Note that the docs indicate it will "trigger a reevaluation of all patterns of the matching object type in the knowledge base." Not the parameter values.
One way you could avoid this would be to add a constraint like field3 != 5 on the left hand side. That is:
rule "My Rule"
when
a1: ObjectA( field3 != 5 ) // <-- if field3 is already 5, don't fire the rule
b1: ObjectB(field1 > 0 || a1.field1 in (1,2,3))
exists(ObjectA(field2 > 10))
then
modify( a1 ) { setField3(5) };
end
Basically you need to make the rule no longer eligible for re-fire.
Alternatively, depending on your structure you could try to use no-loop, but that only keeps the rule from refiring when immediately triggered by the right hand side. If you have multiple modifications/updates/etc going on, you could get into a "broader" looping scenario where multiple rules cause reevaluation. (Example: Rule A does a re-evaluate, no-loop keeps A from firing again; then B causes re-eval, so A can trigger because no-loop does not apply.)

How to select 2 different attributes from an event in Drools

I am trying to write a drools rule that check if two events happens from the same stream. I have a compliance rules class which contains logic (in the working memory) to be compared with events coming from entry point. all I need is to detect the occurrence of two events, for example I want to detect that event A occurred and after that B occurred. I wrote this role in drools syntax
$comrule : Comprules ( pattern == "response" , isBefore == false)
Event (task == $comrule.antecedent) from entry-point StoreOne
Event (task == $comrule.consequent) from entry-point StoreOne
the problem is this technique doesn't work. the only one working is when I wrote this
Event (task == $comrule.antecedent) from entry-point StoreOne
not Event (task == $comrule.consequent) from entry-point StoreOne
I read the drools documentation but I couldn't find any solve to this problem
any help will be appreciated
The typical pattern for checking that two Events occur in the right order is this:
Comprules( pattern == "response", !isBefore, $a: antecedent, $b: consequent )
$one: Event( task == $a ) from entry-point StoreOne
$two: Event( task == $b, this after $one ) from entry-point StoreOne
Using not tests for the absence of a fact, which would be the situation after $one has arrived while $two still is absent.

Regular expression in Drools

I keep getting compile errors when I try to write my rules.
I am trying to translate this condition into drools
if(model.type.series != null && model.type.series.name.mathes(".*FANR.*") ||
model.type.series.name.matches(".*SANA.*"))
//do something....
This is what I have...
rule "Rule 01" salience 0
when
m : model(type.series != null,
type.series.name.matches(".*FANR.*") ||
type.series.name.matches(".*SANA.*")
a : Result(state == Result.GOOD )
then
a.setState(RESULT.BAD);
....
end
What I was trying to do is to use regular expression to match the part of the string where the 'name' is String type. As I am fair new to drools I don't see where it can cause problems, any help would be appreciated
Use correct Drools syntax, according to the matches operator, as described in the Drools manual.
rule FANRorSANA
when
$n: model($v: type.series.name matches ".*(FANR|SANA).*")
then
And you can use the power of regular expressions for testing alternatives.

How to change operators dynamically in rule file

I want to evaluate facts dynamically using drool engine. Rule conditions attributes & their conditional operators are stored in database and load in to WM when engine start.
So I want to use that operator in rule file as below.
$dynCx : DynCustomer()
$attrib : Attribute() from $dynCx.attributes
$offer : Offer($ofCode : offer_code, $domainName : domainName )
$rdef : OfferRuleDef($entity : entity,
$code : code,
$value : value,
$atrName : attributeName,
$atrVal : attributeVal,
$op : operation,
$entity == $domainName,
$code == "OFFER_CODE",
$value == $ofCode,
$atrName == $attrib.name,
$atrVal $op $attrib.value
)
but I'm getting below error
Caused by: java.lang.RuntimeException: [59,14]: [ERR 102] Line 59:14 mismatched input '$op' in rule "Evaluate Generic Offer Eligibility"
[0,0]: Parser returned a null Package
How we can achieve this?
Operators can't be resolved at runtime, so you can't write that kind of rule. Based on the version you are using and the number of operators you envision, you have a few options.
1) Write a rule for each operator:
OfferRuleDef( ..., operator == "==", attributeVal == $attrib.value )
to avoid excessive code repetition, consider that rules can "extend" each other.
2) In recent versions, create a static helper function and pass the three values:
OfferRuleDef( ..., MyHelper.applyOperator($attrValue, $op, $attrib.value) )

Error while traversing Null array in DRools rule

I am using arrayList in .drl rule file.
In one rule i am checking list is null or not and setting setFocus(2nd rule) .
in 2nd rule i am getting the element from list, bt in this rule i am getting list is null error.
I want to check list is null or not and getting particular element from that arraylist in one rule.
rule "Rule chesks client had already received Notifications or Not"
salience 10
no-loop true
when
event : Event($listOfClientNotifications : clientNotifications)
eval($listOfClientNotifications < 1)
then
event.setMessage("list is null");
end
2nd rule:
rule "Rule chesks "
salience 05
no-loop true
when
event : Event($listOfClientNotifications : clientNotifications)
value : ClientNotifications() from $listOfClientNotifications; // <<< !!!
then
event.setMessage("Value "+**value.getMessage()**);
end
This <<< !!! is where the null error occurs.
Testing a list (correctly!) against null in one rule doesn't avoid running into a NPE in another rule. Rule evaluations are not, repeat not, synchronized with rule executions, salience and activations groups notwithstanding.
This is a correct check:
rule "check list is null"
when
event : Event(clientNotifications == null)
then
event.setMessage("list is null");
end
Guard against running into NPE
rule "use notifications from list"
when
event : Event($listOfClientNotifications : clientNotifications != null)
value : ClientNotifications() from $listOfClientNotifications;
then
event.setMessage("Value "+ value.getMessage()); // strange, but maybe?
end

Categories