Search code examples
javaspring-bootdroolskie

getFactHandle method returns null for any fact in Drools


I have the following piece of code:

KieSession kSession = JPAKnowledgeService.loadStatefulKnowledgeSession(someId, kieBase, null, env)

for (FactHandle f : kSession.getFactHandles()) {
    Object sessionObject = kSession.getObject(f);
    logger.info(String.format("Fact:  %s", sessionObject.toString()));
}

kSession.insert(someFact);

// Let's loop again to see if our fact is indeed there
for (FactHandle f : kSession.getFactHandles()) {
    Object sessionObject = kSession.getObject(f);
    logger.info(String.format("Fact:  %s", sessionObject.toString()));
}

// Do something else with someFact, insert it into some db

// factHandle is null
FactHandle factHandle = kSession.getFactHandle(someFact);

Basically, I am loading my persistent KieSession, adding a fact to it, looping through facts to check the newly added fact is indeed there, but when I try to get it back, the factHandle object is null. I am trying to use Drools with identity based assertion mode. So my related questions are:

  1. Why is my fact handle null? The location of someFact in memory may have changed in Do something else with someFact, insert it into some db phase, would it have an effect on the issue?
  2. How does Drools compare identities? I have a private long id filed on my someFact object, annotated with @Id.
  3. I am creating my KieContainer and KieBase as follows:

```

@Bean
public KieServices kieServices() {
    return KieServices.Factory.get();
}

@Bean
public KieContainer kieContainer() throws IOException {

    final KieRepository kieRepository = kieServices().getRepository();

    kieRepository.addKieModule(new KieModule() {
        @Override
        public ReleaseId getReleaseId() {
            return kieRepository.getDefaultReleaseId();
        }
    });

    KieFileSystem kfs = kieServices().newKieFileSystem();
    PathMatchingResourcePatternResolver pmrs = new PathMatchingResourcePatternResolver();
    Resource[] files = pmrs.getResources("classpath*:com/company/**/rules/*.drl");

    for(Resource file : files) {
        String myString = IOUtils.toString(file.getInputStream(), "UTF-8");
        kfs.write("src/main/resources/"+ file.getFilename(), myString);
    }

    KieBuilder kieBuilder = kieServices().newKieBuilder(kfs);
    kieBuilder.buildAll();
    return kieServices().newKieContainer(kieRepository.getDefaultReleaseId());
}

@Bean
public KieBase kieBase() throws IOException {
    KieBaseConfiguration kieBaseConfiguration = kieServices().newKieBaseConfiguration();
    kieBaseConfiguration.setProperty("assertBehaviour", "equality");
    return KnowledgeBaseFactory.newKnowledgeBase(kieBaseConfiguration);
}

```

If I have to switch to equality based assertion, I have implemented equals and hashCode methods on my object, but couldn't find a way to define my KieBase's assertion as EQUALITY. How can I do that?


Solution

    1. Simply the location of someFact in the memory being changed in Do something else with someFact, insert it into some db, has an effect, so Drools cannot compare using identity mode.
    2. The location in the memory. Not the Javax @Id annotation.
    3. The following is how you put the engine into equality mode:

      KieBaseConfiguration kieBaseConfiguration = kieServices().newKieBaseConfiguration();
          kieBaseConfiguration.setOption(EqualityBehaviorOption.EQUALITY);
          return kieContainer().newKieBase(kieBaseConfiguration);