I am working on a drool file with the below code:
rule "test rule"
#RuleNumber(1)
#RuleMessage("data mismatch")
when
$myObj : MyObj($localVal1: val1)
$dataMismatch: Boolean() from ($localVal1 == null)
eval $dataMismatch
then
//do something
end
I keep getting the error mismatched input '$dataMismatch' in rule, Parser returned a null Package
Does anyone know where am I going wrong?
Thanks!
Unless you get paid by lines of code written, you should use:
rule "test rule"
#RuleNumber(1)
#RuleMessage("data mismatch")
when
$myObj : MyObj(val1 == null)
then
//do something
end
(Looking into syntax errors cannot be done reliably without knowing the Drools version, which you haven't provided.)
Related
I'm trying to run this GitHub project using Drools 7.57.0.Final instead of 7.39.0.Final which was used in original project. And I found some issues. The issue that most triggers me is the one in the Section 6, Step 5. The problem lies in the Drools file VisaApplicationValidationWithAgendaAndSalience.drl. Here is the content with the "debug" statement that I have added:
package io.github.aasaru.drools.section06.step5
import io.github.aasaru.drools.domain.Passport;
import io.github.aasaru.drools.domain.Validation;
import io.github.aasaru.drools.domain.VisaApplication;
import java.time.LocalDate;
rule "Invalidate visa application with invalid passport"
dialect "mvel"
agenda-group "validate-application"
salience 20
when
$passport: Passport( validation == Validation.FAILED )
$visaApplication: VisaApplication( passportNumber == $passport.passportNumber,
validation != Validation.FAILED )
then
System.out.println( "Set " + $visaApplication + " invalid as " + $passport + " hasn't passed validation");
modify($visaApplication) {
setValidation( Validation.FAILED )
}
end
rule "Set application without validation info as passed"
dialect "mvel"
agenda-group "validate-application"
salience 10
when
$visaApplication: VisaApplication( validation == Validation.UNKNOWN )
then
System.out.println("debug >>>>>>>>>>>>> " + $visaApplication.validation);
System.out.println( $visaApplication + " is without validation info, consider OK for now" );
modify($visaApplication) {
setValidation( Validation.PASSED )
}
end
rule "Invalidate visa application where passport expires earlier than 6 months after visit end date"
dialect "mvel"
agenda-group "validate-application"
salience 20
when
$passport: Passport( validation != Validation.FAILED )
$visaApplication: VisaApplication( passportNumber == $passport.passportNumber,
$passport.expiresOn.isBefore(visitEndDate.plusMonths(6)),
validation != Validation.FAILED )
then
System.out.println( "Set " + $visaApplication + " invalid as " + $passport + " not valid 6 months after visit");
modify($visaApplication) {
setValidation( Validation.FAILED )
}
end
and here is the part of the console output that regards to the previous rules:
Set VisaApplication(#1, pass:CA-SARAH-1) invalid as Passport[no:CA-SARAH-1, name:Sarah Murphy] hasn't passed validation
Set VisaApplication(#4, pass:AU-JAMES-4) invalid as Passport[no:AU-JAMES-4, name:James Brown] not valid 6 months after visit
debug >>>>>>>>>>>>> FAILED
VisaApplication(#1, pass:CA-SARAH-1) is without validation info, consider OK for now
Set VisaApplication(#1, pass:CA-SARAH-1) invalid as Passport[no:CA-SARAH-1, name:Sarah Murphy] hasn't passed validation
debug >>>>>>>>>>>>> UNKNOWN
VisaApplication(#2, pass:CA-SIMON-2) is without validation info, consider OK for now
debug >>>>>>>>>>>>> UNKNOWN
VisaApplication(#3, pass:AU-EMILY-3) is without validation info, consider OK for now
As is obvious, the middle rule, the one with the salience 10, has been fired not only for the pattern validation == Validation.UNKNOWN but also for the pattern validation == Validation.FAILED! That is wrong and it happens in Drools 7.57.0.Final and doesn't happen in Drools 7.39.0.Final used by the original project. Is it a Drools bug or what? I'm pretty new to Drools so this really confuses me.
Second, why do I get the console output Set VisaApplication(#1, pass:CA-SARAH-1) ... twice? It seems to be a consequence of the reevaluation of the 1st rule, but this shouldn't have happened as this is the stateful and not the stateless session.
If you want to reproduce the console log, download the project, change Drools version to the latest one 7.57.0.Final, run the app io.github.aasaru.drools.section06.VisaIssue, and when asked,
enter 5 for the step and no when asked whether all passports should be considered as expired.
Congratulation, you found drools bug DROOLS-6542 - fixed in 7.60.0.Final
There is a workaround - remove mvel dialect for the rule "Invalidate visa application with invalid passport".
BTW, I'd like to propose you drools testing library which may save you great amount of time to mind complicated rules and simplify writing test scenarios. Here is how test may look like.
#DroolsSession(
resources = "classpath*:**/section06/step5/*",
showStateTransitionPopup = true)
public class Section6Step5Test {
#RegisterExtension
public DroolsAssert drools = new DroolsAssert();
#Test
public void test() {
ApplicationRepository.getPassports().forEach(drools::insert);
ApplicationRepository.getVisaApplications().forEach(drools::insert);
drools.getSession().getAgenda().getAgendaGroup("issue-visa").setFocus();
drools.getSession().getAgenda().getAgendaGroup("validate-application").setFocus();
drools.getSession().getAgenda().getAgendaGroup("validate-passport").setFocus();
drools.fireAllRules();
assertEquals(1, drools.getObjects(Visa.class).size());
}
}
Here is visualization popup of the test on 7.39.0.Final (or 7.57.0.Final without mvel dialect).
and the same on 7.57.0.Final (with mvel dialect)
while answers_right < 3:
ran_number_1 = random.randint(10, 99)
ran_number_2 = random.randint(10, 99)
solution = ran_number_1 + ran_number_2
print(f"What is {ran_number_1} + {ran_number_2}?")
user_answer = int(input("Your answer: "))
if user_answer == solution:
answers_right += 1
print(f"Correct. You've gotten {answers_right} correct in a row.")
elif user_answer != solution:
answers_right = 0
print(f"Incorrect. The expected answer is {solution}.")
if answers_right == 3:
print("Congratulations! You've mastered addition.")
I want to add an additional if statement in case someone types string and return a message that says "Invalid Response" instead of the Traceback Error.
Use of Exception handling in python may be solve your Problem and you can also generate your own error class for particular condition.
if x < 3:
raise Exception("Sorry, no numbers below 3")
Use of throw and raise keyword you can generate your own error.
for more referencelink here
The correct way to solve this problem is to look at the error type in your traceback, and use a try/except block. It will say something like TypeError: error stuff here or ValueError: error stuff also here.
The way you do a try/except is to:
try:
some_code()
that_might()
produce_an_error()
except some_error_type:
do_stuff()
except_some_other_error_type:
do_other_stuff()
So, to catch a ValueError and a TypeError, you might do:
try:
buggy_code()
except ValueError:
print("Woah, you did something you shouldn't have")
except TypeError:
print("Woah, you did something ELSE you shouldn't have")
If you then want the traceback, you can add in a lone "raise" statement below the excepts. For example:
try:
buggy_code()
except ValueError:
print("Woah, you did something you shouldn't have")
raise
except TypeError:
print("Woah, you did something ELSE you shouldn't have")
raise
Errors have evolved to be a lot more useful in modern times. They don't break the entire system anymore, and there are ways of handling them. Try/Except blocks like the above give you the tools to have code that only executes when a specific error or set of errors is raised.
This my When condition
$cla : cashliquidassets(
entity == "AU001",
asset_liability_indicator == "A",
product_group.contains('Loans','Bankofindia'),
product.contains("DS"),
counterparty_resident_indicator == "AU",
counterparty_type.contains("DS"),
related_entity == "Y"
)
I am getting an error at
Unable to Analyse Expression product_group.contains("Loans","Bankofindia")
Any Suggestions
Without your class model is hard to tell, but assuming that cashliquidassets.product_group is a String, you are trying to use an unexisting method String.contains(String, String).
One option would be to use an OR or and AND between 2 contains:
...
(product_group.contains('Loans') || product_group.contains('Bankofindia')),
...
or
...
product_group.contains('Loans'),
product_group.contains('Bankofindia'),
...
Another option could be to use the matches operator with a regular expression.
Hope it helps,
I am just curious as to why my Eclipse Drools compiler (6.5.0) requires semi-colons at the end of statements in the For loop, as below:
Map businessRulesRequest = $root.containsKey("BusinessRulesRequest") ? $root.get("BusinessRulesRequest") : null
Map quoteRequest = businessRulesRequest!=null && businessRulesRequest.containsKey("QuoteRequest") ? businessRulesRequest.get("QuoteRequest") : null
List resultsByKey = quoteRequest!=null && quoteRequest.containsKey("resultsByKey") ? quoteRequest.get("resultsByKey") : new ArrayList()
for (Map search : resultsByKey) {
Map searchInfo = (search.containsKey("searchInfo") ? search.get("searchInfo") : null);
String searchName = searchInfo!=null && searchInfo.containsKey("searchName") ? searchInfo.get("searchName").toString() : "";
List results = (searchName=="quotesMotor" && search.containsKey("results") ? search.get("results") : new ArrayList());
}
If I remove the semi-colons from the first or second lines in the For loop, I get an "unexpected token" error, but not if I remove it from the last line in the loop.
Is it due to Drools evaluating RHS lines as a single statement and so they must be separated inside any loops?
Note: I understand it is not best practice to code assuming semi-colons are not required, however I came across this issue while experimenting and am just interested to know the reason for the compiler error. Thanks.
I guess the answer is because of MVEL itself. Drools may be delegating the entire chunk of code to MVEL to evaluate and execute.
According to this guide, in MVEL the use of a semi-colon is not mandatory in cases where you have 1 statement, or in the last statement of a script.
Hope it helps,
In drools we have when and then. If a condition is satisfied, then we go to the then condition and update a status, like obj.setStatus("transaction success", "review required").
But when the when condition is not satisfied, then I want to update obj.setStatus("transaction Failed", "review not required").
How is this possible in Drools?
The best way would be to initialize obj.status to "failed". After all rules have fired, you'll either still have this or the updated status showing "success".
If you need a rule firing, you can write a rule catching the unmodified fact:
rule "catch failures"
salience -999999
when
$obj: MyFact( status == null ) // no initial value
then
modify( $obj ){ setStatus("transaction Failed", "review not required") }
end
There is not a single rule. If we do like that then our rules size will be increase.
//FailureMessage :- Equipment breakdown coverage size is greater than 0
rule "CPP_ReviewLossControl"
ruleflow-group "CPPReview"
lock-on-active
when
$commPolicy : CommlPolicyInfoBean();
$STPRulesResponseBean:STPRulesResponseBean();
$lobInfo: LOBInfoBean("CPP".equalsIgnoreCase(lob) && losses.size() >= 3) from $commPolicy.getLobs();
then
System.out.println("Creating Loss history task for AMR");
$STPRulesResponseBean.getResultMap().put("CPP_ORD_LOSS_CNTRL",true);
end
//FailureMessage :-Business category should be General Framing, Window or Window Framing, Stucco and/or EIFS application including masonry/drywall contractors., Roofing, Exterior Siding/Water Proofing/Caulking, Any other exterior finishing work.
rule "CPP_ReviewBusinessCategory"
ruleflow-group "CPPReview"
lock-on-active
when
$STPRulesResponseBean:STPRulesResponseBean();
$commlPolicyInfoBean : CommlPolicyInfoBean();
$lobInfo: LOBInfoBean("CPP".equalsIgnoreCase(lob)) from $commlPolicyInfoBean.getLobs();
AccountInfoBean(businessCategoryCode =="23" && (primaryActivities contains ("23813") || primaryActivities contains ("23831") || primaryActivities contains "23816")) from $commlPolicyInfoBean.getAccountInfo()
then
System.out.println("Creating Business category");
$STPRulesResponseBean.getResultMap().put("CPP_REV_SPL_RISK",true);
end
and there is setFocus also.