drools始终为true规则仅触发一次

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了drools始终为true规则仅触发一次相关的知识,希望对你有一定的参考价值。

我有这两个规则:

rule "challenge 1" salience 10
    when
        ClientTransaction(amount < 30)
    then
        challenge.setChallenge("challenge1");
end

rule "challenge 2" salience 0
    when
        eval( true )
    then
        challenge.setChallenge("challenge2");
end

和此Java代码:


public class ComputeChallengeDroolsRulesImplementation implements IComputeChallenge 
    private KieServices kieServices = KieServices.Factory.get();
    private KieSession kieSession = getKieSession();
    private static final String RULES_PATH = "rules/";

    public KieFileSystem getKieFileSystem() throws IOException 
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        String[] rules = new File(getClass().getClassLoader().getResource(RULES_PATH).getFile()).list();
        for (String rule : rules) 
            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + rule));
        
        return kieFileSystem;
    

    public KieContainer getKieContainer() throws IOException 
        getKieRepository();

        KieBuilder kb = kieServices.newKieBuilder(getKieFileSystem());
        kb.buildAll();

        KieModule kieModule = kb.getKieModule();
        KieContainer kContainer = kieServices.newKieContainer(kieModule.getReleaseId());

        return kContainer;
    

    public void getKieRepository() 
        final KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(
                new KieModule() 
                    public ReleaseId getReleaseId() 
                        return kieRepository.getDefaultReleaseId();
                    
                );
    

    @Bean
    public KieSession getKieSession() 
        try 
            return getKieContainer().newKieSession();
         catch (IOException e) 
            throw new RuntimeException(e);
        
    

    @Override
    public Challenge2 computeChallenge(ClientTransaction clientTransaction) 
        kieSession.insert(clientTransaction);
        Challenge2 challenge = new Challenge2();
        kieSession.setGlobal("challenge", challenge);
        kieSession.fireAllRules();
        return challenge;
    



这里是ClientTransation类:


public class ClientTransaction 
  private String id;
  private String merchant;
  private double amount;

  public ClientTransaction() 
  

  public ClientTransaction(String id, String merchant, double amount) 
    this.id = id;
    this.merchant = merchant;
    this.amount = amount;
  

  public String getId() 
    return id;
  

  public void setId(String id) 
    this.id = id;
  

  public String getMerchant() 
    return merchant;
  

  public void setMerchant(String merchant) 
    this.merchant = merchant;
  

  public double getAmount() 
    return amount;
  

  public void setAmount(double amount) 
    this.amount = amount;
  


这里是Challenge2类:


public class Challenge2 
  private String challenge;

  public Challenge2() 
  

  public Challenge2(String challenge) 
    this.challenge = challenge;
  

  public String getChallenge() 
    return challenge;
  

  public void setChallenge(String challenge) 
    this.challenge = challenge;
  



当我多次调用<30的ComputeChallengeDroolsRulesImplementation.computeChallenge时,它确实按预期多次返回具有“ challenge1”值的挑战对象。

但是当我多次调用ComputeChallengeDroolsRulesImplementation.computeChallenge的次数> = 30时,它第一次确实返回“ challenge2”值,但随后每次都返回具有空值的Challenge2对象?

我做错什么了吗?

谢谢

答案

我假设您仅在发生ClientTransaction事件时才触发挑战2规则。您可以通过仅在drool规则的when部分调用默认构造函数来基于事件的发生在规则上添加无条件检查。尝试如下更改您的挑战2规则:

rule "challenge 2" salience 0
    when
        ClientTransaction()
    then
        challenge.setChallenge("challenge2");
end

而且,在流口水规则中,不建议大量使用eval。有关最佳做法的更多信息,请检查here

另一答案

如以下文档所述:https://docs.jboss.org/drools/release/5.2.0.Final/drools-expert-docs/html/ch05.html

无法通知引擎有关全局变量的值更改,并且不会跟踪其更改。在约束中错误使用全局变量可能会产生令人惊讶的结果-以一种不好的方式令人惊讶。

全局变量不是为了在规则之间共享数据而设计的,切勿将它们用于此目的。规则总是会推理并对工作内存状态做出反应,因此,如果您希望将数据从一个规则传递到另一个规则,则将数据作为事实断言到工作内存中。

强烈建议您从规则内部设置或更改全局值。我们建议您始终使用工作内存接口从应用程序中设置值。

以上是关于drools始终为true规则仅触发一次的主要内容,如果未能解决你的问题,请参考以下文章

让useEffect监视条件并使其仅触发一次

WPF,`Loaded` 事件仅在第一次视图模型初始化时触发,但不会在后续视图模型初始化时触发

iOS UILocalNotification 设置为每天触发一次,每两天触发一次,并且仅在星期日触发

python将列表里的字符串一次一次显示出来

Drools - 规则层次结构和条件执行

一次一密加密解密算法