Search code examples
javadrools

Drools- Inserting the multiple facts of the same type, with one rule


I am very new to Drools and I have completed some of the tutorials found online and read the docs. I am sure what I am about to explain has a trivial solution that I have missed but I will lay it out regardless.

I have a single rule in my drools file and an object that reads its info from a text file.

The code looks similar to this:

   public static final void main(String[] args) {
        try {
            ObjectArchive arch = ArchiveFactory.openArchive(new File("dwc.txt"));
            Iterator<Object> iter = arch.iteratorDwc();

            // load up the knowledge base
            KnowledgeBase kbase = readKnowledgeBase();
            StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
            KnowledgeRuntimeLogger logger =  KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
            while(iter.hasNext()) {
                Object dwcRecord = iter.next();
                ksession.insert(dwcRecord);
            }
            System.out.println(ksession.getFactCount());
            ksession.fireAllRules();
            logger.close();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("dwcrules.drl"), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        if (errors.size() > 0) {
            for (KnowledgeBuilderError error: errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        return kbase;
    }

I have a simple rules file that checks if a property of said object is not null and prints out the object if this is true.

Now, the problem.

If I add one object (no while loop) then the rule is fired and all is well. However, if I add multiple objects to the session and then fire the rules it tends to just grab the last one, or fire but print out a single null.

So, why is it that I am unable to add multiple facts of the same type? Or what am I missing that stops me from being able to fire the same rule on multiple facts?

Thanks in advance.

EDIT: Sorry, here is the rule:

rule "Scientific Name"
when 
    dwc : Object(dwc.getScientificName != null)
then
    System.out.println(dwc);
 end

Solution

  • I don't know exactly what is happening, as I don't have your object file to run the test, but just open your log file in the eclipse audit view and you will immediately see the objects that were inserted and which ones activate the rule.

    The rule will fire once for each object that have scientificName != null.

    Also, your rule should not be trying to match Object if you have a more specialized class/interface that define the getScientificName() method. For instance, if you have a class named "MyDwcClass", you should write the rule like this:

    rule "Scientific Name"
    when 
        dwc : MyDwcClass( scientificName != null )
    then
        System.out.println(dwc);
    end