1
votes

I am pretty new to Drools and am probably doing something really silly. The problem is that for some reason my Drools rules are not getting fired. The version of the drools that is used is 5.4

If it helps, the rules fire when I shift back to a StatelessKnowledgeSession and use the execute method to fire the rules. However, I need to use AgendaFilter to filter rules and I understand that agenda filters aren't supported on StatelessKnowledgeSession yet. As a first step, I just flipped the session to a StatefulKnowledgeSession, inserted the facts and fired all the rules.

Had to humbly say that I was breaking my head for the past couple of days on this. Too bad, the documentation isn't that friendly for drools (I refer to the official documentation and the user guide.

The Rule Validator code and the Spring factory bean with which I load the Knowledge from the rule file is quoted below. I, personally, don't see any issues with the FactoryBean. Any pointers would be of great help.

RuleValidator.java

StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();
ksession.setGlobal("validationReport", validationReport);
ksession.setGlobal("simpleCache", simpleCache);
ksession.setGlobal("ruleValidator", this);

ksession.insert(allClientDetails); //this is a list of ClientDetails objects (facts)
ksession.fireAllRules();
ksession.dispose();

return validationReport;

KnowledgeBaseFactory.java

import java.io.IOException;
import java.util.Map;

import org.apache.log4j.Logger;
import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.Resource;
import org.drools.io.ResourceFactory;
import org.springframework.beans.factory.FactoryBean;


public class KnowledgeBaseFactory implements FactoryBean<KnowledgeBase> {

    private static Logger logger=Logger.getLogger(KnowledgeBaseFactory.class);

    private KnowledgeBase knowledgeBase;

    public KnowledgeBaseFactory(Map<String,ResourceType> resourceMap) throws IOException {
        logger.debug("Resource Map : "+resourceMap);
        final KnowledgeBuilder knowledgeBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        for (Map.Entry<String, ResourceType> eachRuleResource:resourceMap.entrySet()){
            knowledgeBuilder.add(ResourceFactory.newClassPathResource(eachRuleResource.getKey()),eachRuleResource.getValue());

        }

        if (knowledgeBuilder.hasErrors()){
            logger.error(knowledgeBuilder.getErrors().toString());
            throw new RuntimeException(knowledgeBuilder.getErrors().toString());
        }
        knowledgeBase = knowledgeBuilder.newKnowledgeBase();
        knowledgeBase.addKnowledgePackages(knowledgeBuilder.getKnowledgePackages());
    }

    @Override
    public KnowledgeBase getObject() throws Exception {
        return knowledgeBase;
    }

    @Override
    public Class<?> getObjectType() {
        return knowledgeBase.getClass();
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
1
So you just changed the line "StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();" to go from StatelessKnowledgeSession to a Stateful one and it doesn't work anymore ? Right? - pgras
Yes. That is correct. And since I switched from method execute of the StatelessKnowledgeSession to fireAllRules method in StatefulKnowledgeSession, I had to insert the fact using the ksession.insert(allClientDetails);. But yeah, that is all the change that was done there. - Arun Manivannan
Difficult to say what could be wrong without know what rules are there and what the facts look like. I would go back to basics and start with seeing if you can get a simple rule to fire on inserting the facts and then build up from there.. - Nim
@Nim Agreed. I am taking a step back and starting over. Let me come back to post here when I find something useful. - Arun Manivannan

1 Answers

2
votes

Thanks for the tip @Nim

Figured out finally. I should have read the API docs properly.
Apparently, I was using the Iterable overloaded execute method in the StatelessKnowledgeSession which iterates through all my facts and applies the rules against each one of them.

However, with StatefulKnowledgeSession, I should be iterating beforehand and inserting the facts one by one. And then, I could fire the rules.

Any reason why there isn't a insert(Iterable) method in StatefulKnowledgeSession.