【问题标题】:Drools 6.5 Executing Specific Rule Using a Custom Agenda Filter Not WorkingDrools 6.5 使用自定义议程过滤器执行特定规则不起作用
【发布时间】:2017-08-08 13:33:38
【问题描述】:

我需要使用关联值执行特定规则,并尝试实现自定义议程过滤器一次只执行一个特定规则,但它似乎执行所有规则。我正在使用我这样定义的无状态会话:

   @Bean
     @ConditionalOnMissingBean(KieSession.class)
     public StatelessKieSession kieSession() throws IOException {   
         return kieContainer().newStatelessKieSession();
     } 

我迭代Map并执行每条规则的逻辑如下:

for (Map.Entry<Long, String> entry : ruleIdsAndData.entrySet()){

    List<Object> facts = new ArrayList<Object>();
    facts.add(entry.getValue());

    Map<String, String> ruleResponse = new HashMap<String, String>();
    kieSession.setGlobal("ruleResponse", ruleResponse);                     

    TrackingAgendaEventListener agendaEventListener = new TrackingAgendaEventListener();
    kieSession.addEventListener(agendaEventListener);

    String ruleName = myRuleService.retrieveRuleNameById(entry.getKey());               
    log.debug("Attempting to fire the following rule : " + ruleName);

    facts.add(new FireAllRulesCommand(new RuleNameEqualsAgendaFilter(ruleName)));   
    kieSession.execute(facts);

    log.debug("RuleResponse after rule has fired is : " + ruleResponse);                                                            
}

RuleNameEqualsAgendaFilter 类看起来像这样:

import lombok.extern.slf4j.Slf4j;
import org.kie.api.runtime.rule.AgendaFilter;
import org.kie.api.runtime.rule.Match;

    @Slf4j
    public class RuleNameEqualsAgendaFilter implements AgendaFilter {

        private final String ruleName;

        private final boolean accept;

        public RuleNameEqualsAgendaFilter(final String name) {
            this(name, true);
        }

        public RuleNameEqualsAgendaFilter(final String name, final boolean accept) {
            this.ruleName = name;
            this.accept = accept;
        }

        public String getName() {
            return ruleName;
        }

        public boolean isAccept() {
            return accept;
        }

        public boolean accept( Match match) {
            log.debug("Comparing : " + match.getRule().getName() + " to ruleName : " + this.ruleName);
            if (match.getRule().getName().equals(this.ruleName)) {
                return this.accept;
            } else {
                return !this.accept;
            }
        }
    }

知道为什么这会执行与我在ruleName 中指定的规则不同的规则吗?

【问题讨论】:

  • 是什么让你说每次调用都执行所有规则?
  • 如果我将我的 ruleName 硬编码到以下行,控制台输出会显示另一个 ruleName:facts.add(new FireAllRulesCommand(new RuleNameEqualsAgendaFilter("myHardCodedRuleName")));我想知道上面的配置是否可以,或者我应该传递一个命令列表并使用 CommandFactory.newBatchExecution....
  • 谁在创建这些日志? TrackingAgendaEventListener 在做什么?
  • 请在您的问题中编辑此内容、控制台输出和控制台输出的生成方式。 - 日志行“Comparing : ...”应该对所有匹配规则可见。
  • 我的应用程序正在本地生成控制台输出,而 TrackingAgendaEventListener 当前未使用。我看不到我添加到 RuleNameEqualsAgendaFilter 的行“比较.....”的任何日志记录

标签: drools kie


【解决方案1】:

在这里您将事实添加到列表中:

List<Object> facts = new ArrayList<Object>();
facts.add(entry.getValue());

在这里你添加另一个对象,一个 FireAllRulesCommand:

facts.add(new FireAllRulesCommand(new RuleNameEqualsAgendaFilter(ruleName))); 

然后你打电话给

kieSession.execute(facts);

插入所有事实,然后调用fireAllRules。所以 AgendaFilter 只是 WM 中的一个事实。

使用有状态会话,插入事实并以 AgendaFilter 作为参数调用 fireAllRules。

【讨论】:

  • 非常感谢,当我使用 statefulSession 时,它现在正在激活议程过滤器,因此我可以看到正确的日志记录。如果我有 2 条规则并且只有 1 条执行,而另一个没有,那么当我期望 2 条执行时。如果您多次调用 session.insert 或 session.fireAllRules(...) ,将会话更改为 statefulSession 不会导致仅执行 1 条规则?
  • 当我将第二个 ruleName 传递给议程过滤器时,它不会记录,但第一个会记录,所以我的第一个规则会被执行,但第二个规则不会
  • 不确定我是否理解这些 cmets。 - 请注意,您必须在调用 fireAllRules 之前和之后重新创建和处理有状态会话,以获得与无状态会话相同的结果。
  • 嗨 laune,我的要求很简单。我需要迭代一个 Map 或一批规则,并使用其关联值单独执行每个规则。将我的无状态会话更改为有状态会话后,议程过滤器为我的第一个规则运行了一次,但没有在我的第二个规则上运行。对于第一条规则,我只能看到一个日志语句“比较.....”。我有什么理由会看到这种行为吗?
  • 另外,我在启动时将规则从数据库加载到会话中,因此每次我想执行规则时都无法重新创建会话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-25
  • 2019-06-25
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 2016-03-12
  • 2017-03-10
相关资源
最近更新 更多