Search code examples
javadrools

drools always true rule fires only once


I have these 2 rules :

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

and this java code :


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

}

here is the ClientTransation class :


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

And here is the Challenge2 class :


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


when i call ComputeChallengeDroolsRulesImplementation.computeChallenge with an amount < 30 multiple times, it does return a challence object with a "challenge1" value multiple times as expected.

But when i call ComputeChallengeDroolsRulesImplementation.computeChallenge with an amount >= 30 multiple times, the first time it does return a "challenge2" value, but every subsequent time it return a Challenge2 object with a null value ?

Am i doing something wrong ?

Thank you


Solution

  • I am assuming you want to fire challenge 2 rule only when ClientTransaction event occurs. You can add a no condition check on a rule based on the occurrence of an event by just calling default constructor in the when part of a drool rule. Try changing you challenge 2 rule as below:

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

    Also, it is not recommended to use eval so much in the drools rule. To more about best practices, check here