流口水的LHS中的异常捕获

2022-09-03 07:56:42

我有一个问题,其中流口水规则的当子句抛出一个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并覆盖exitrearactionFired方法,以将要触发的规则添加到列表中。我希望列表中的最后一个会是抛出错误的那个,但遗憾的是它没有以这种方式工作。

我现在尝试在所有规则之前添加“始终正确”的规则。它们记录其后出现的规则的名称。问题是当“WHEN”子句中存在异常时,不会记录任何内容。就好像在发生上述异常时不会触发任何规则一样。

问题都在于动态流口水生成代码。我想采取双管齐下的方法来修复生成代码,并捕获本文中列出的异常。

附注:我确实检查了构建器中的错误。我没有从下面的代码收到任何错误。

KnowledgeBuilderErrors errors = builder.getErrors();

if (!errors.isEmpty()) {
    for (KnowledgeBuilderError error : errors) {
        ...
    }
}

答案 1

根据我的理解,在进行fireAllRules()方法之前,应遵循以下步骤:

  1. 向包/知识生成器添加规则
  2. 验证规则中没有错误
  3. 在工作内存中注入规则

当然,可以在没有步骤 2 的情况下触发规则,但这种做法可能会导致本问题中提到的问题。如果我是你,我会按照下面的逻辑来解决这个问题:

第 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));
}

使用上述方法,您不会执行有错误的规则,也不会出现上述情况。但是,我仍然认为您应该更多地关注生成错误规则的代码段,以及上面描述的方法,仅用于跟踪和持久保存此类事件。


答案 2

推荐