我遇到一个问题,即drools规则的when子句抛出 MethodNotFoundException 。我正在寻找一种方法来确定在运行时哪个规则能够将其从要使用的规则列表中删除。
规则示例
Rule "FooBar"
when
$V1 : Foo ( ) AND
$V2 : FooBar( ) from $V1.getGoodMethod() AND
$V3 : FooBarBar( status == "FooBar" ) from $V2.getBadMethod()
reply : FooFooBar()
then
reply.getList().add("FooBar");
end
因此, FooBar 上的 getBadMethod 并不存在。我想知道它是什么规则,并将其从要使用的规则列表中删除。
尝试和失败的解决方案:
我尝试扩展DefaultAgendaEventListener并重写beforeActivationFired方法,将要触发的规则添加到列表中。我希望列表中的最后一个是抛出错误的那个,但遗憾的是它并没有那样解决。
我现在尝试添加"始终为真"我所有规则之前的规则。它们记录了它之后的规则的名称。问题是当" WHEN"条款没有记录。当上述例外情况发生时,似乎没有规则被触发。
问题在于动态drools生成代码。我想采取双管齐下的方法来修复生成代码,并捕获像本文中列出的异常。
旁注:我会检查构建器中的错误。我从以下代码中没有收到任何错误。
KnowledgeBuilderErrors errors = builder.getErrors();
if (!errors.isEmpty()) {
for (KnowledgeBuilderError error : errors) {
...
}
}
答案 0 :(得分:5)
根据我的理解,在执行fireAllRules()方法之前,应遵循以下步骤:
当然,没有第2步就可以使用fireRules,但是这种做法可能导致此问题中提到的问题。 如果我是你,我会按照以下逻辑来解决你的问题:
第1步:
private RuleBase initialiseDrools() throws IOException, DroolsParserException {
PackageBuilder packageBuilder = readRules();
return addRulesToWorkingMemory(packageBuilder);
}
第2步:
private PackageBuilder readRules() throws DroolsParserException, IOException {
PackageBuilder packageBuilder = new PackageBuilder();
PackageBuilder intermPackageBuilder = null;
listOfReader = dynamicRuleReader(); // Here goes your application code
for(Reader reader : listOfReader){
try{
intermPackageBuilder = new PackageBuilder();
intermPackageBuilder.addPackage(reader);
assertNoRuleErrors(intermPackageBuilder); // This is the core step.
// Above line throws an exception, every time a rules fails. You can persist this exception for production debugging
packageBuilder.addPackage(reader);
}catch(DroolsParserException | IOException e){
logger.error("Rules contain error, so skip adding them to the Package Builder");
}
}
return packageBuilder;
}
第3步:
public void shouldFireAllRules() throws IOException, DroolsParserException {
RuleBase ruleBase = initialiseDrools();
WorkingMemory workingMemory = ruleBase.newStatefulSession();
int expectedNumberOfRulesFired = 2; // Idealy this number should be equal to the number of total rules injected in the Working memory
int actualNumberOfRulesFired = workingMemory.fireAllRules();
assertThat(actualNumberOfRulesFired, is(expectedNumberOfRulesFired));
}
使用上述方法,您将不会执行有错误的规则,并且不会出现上述情况。 但是,我仍然认为你应该更多地关注产生错误规则的代码片段,以及上述方法只是为了跟踪和持久存在这些事件。