我正在使用Drools 6.1.0.FINAL和无状态会话来解雇所有规则。
我的.drl文件中有以下2个简单规则。
rule "Null Check"
when
$paymentHolder : PaymentHolder(pmtRequest.requestDetails == null
|| pmtRequest.requestDetails.paymentData == null
|| pmtRequest.requestDetails.paymentData.accountDetails == null
|| pmtRequest.requestDetails.paymentData.payments == null
|| pmtRequest.requestDetails.paymentData.payments.payment == null
|| pmtRequest.requestDetails.paymentData.payments.payment.get(0).tenderDetails == null
|| pmtRequest.requestDetails.paymentData.payments.payment.get(0).tenderDetails.paymentCardDetails == null
|| pmtRequest.requestDetails.paymentData.payments.payment.get(0).tenderDetails.paymentCardDetails.authorizationInfo == null)
then
System.out.println("Some Manadatory data is null ");
// populate error code and error message
List<ErrorHolder> errors = $paymentHolder.getErrors();
ErrorHolder erroHolder = new ErrorHolder();
errors.add(erroHolder);
erroHolder.setErrorCode(com.wdpr.payment.exception.ErrorCode.MANDATORY_DATA_MISSING);
// drools.halt();
// kcontext.getKieRuntime().halt();
end
rule "Amount is -ve"
when
$paymentHolder : PaymentHolder(errors.size() == 0)
$paymentHolder(pmtRequest.getRequestDetails()!.getPaymentData().getPayments().getPayment().get(0).getAmount().getAmount() < 0)
then
//System.out.println(paymentHolder.getProcessId());
System.out.println("Amount is -ve");
//throw new com.wdpr.payment.exception.PaymentPlatformException(com.wdpr.payment.exception.ErrorCode.DATA_RANGE_INVALID, "Data Range Invalid - Amount", null);
end
我想在下面实现
我试过了。
尝试在内部抛出一个运行时异常然后在第一个规则中阻塞,但是由于NullPointerException它仍然是第二个失败的规则。
添加了drools.halt()和kcontext.getKieRuntime()。halt()但是没有用,仍然是下一个规则。
所以我在我的第一个规则中的自定义erroHolder中添加了一些错误代码,并在第二个规则中检查了相同的条件,这样它就不会被执行但仍然会被执行并抛出NullPointerException。
< / LI> 醇>如果我删除第二条规则,那么第一条规则将完美执行并打印出sysout。但是,当我使用这两条规则运行我的.drl时,它会让我低于NPE
栈跟踪
Exception in thread "main" java.lang.RuntimeException: Error while creating KieBase[Message [id=1, level=ERROR, path=com/my/payment/rules/validation.drl, line=40, column=0
text=[ERR 102] Line 40:53 mismatched input '!.' in rule "Amount is -ve"], Message [id=2, level=ERROR, path=com/my/payment/rules/validation.drl, line=0, column=0
text=Parser returned a null Package]]
at org.drools.compiler.kie.builder.impl.KieContainerImpl.getKieBase(KieContainerImpl.java:349)
at org.drools.compiler.kie.builder.impl.KieContainerImpl.newStatelessKieSession(KieContainerImpl.java:540)
at org.drools.compiler.kie.builder.impl.KieContainerImpl.newStatelessKieSession(KieContainerImpl.java:528)
at com.my.payment.workflow.DroolsRuleProcessor.runRules(DroolsRuleProcessor.java:58)
at com.my.payment.workflow.DroolsRuleProcessor.main(DroolsRuleProcessor.java:81)
我的java代码段
// some code
final StatelessKieSession kSession = this.kContainer.newStatelessKieSession(rulesSession);
// provide the necessary data and execute rules.
kSession.execute(paymentHolder);
注意:我不想使用显着和激活组
有人可以帮助我实现我的目标。
答案 0 :(得分:1)
解决方案很简单(虽然它可能不会让你满意)。要在评估访问包含对象的字段的约束时避免使用NPE,请确保该字段不为null,或者将测试与null结合使用。
// (#1) either:
class PmtRequest {
// guarantee non-null requestDetails
List<rRequestDetail> requestDetails = new ArrayList<>();
// (#2) or:
when
$paymentHolder: PaymentHolder(errors.size() == 0,
pmtRequest != null &&
pmtRequest.getRequestDetails() ... )
then ...
使用深度嵌套的约束,这会越来越不方便,这就是为什么建议不要编写此类访问,而是将包含的对象作为事实插入或在顶级对象中添加方法以访问包含的对象。
还有另一种选择(#3):在规则执行中使用两个会话。新的PaymentHolder事实必须先传递包含nun-null测试的第一个会话才能插入第二个会话。
恕我直言,一种可靠的方法是将#1与#3组合在一起。
(问题的根源在于,在设计规则和应用程序之前,需要考虑规则评估的工作方式。所有约束在事实插入时进行评估< / em>。来自Drools手册:条件评估不依赖于特定的评估序列或时间点,而是在发动机的使用寿命期间的任何时间连续发生。)