Search code examples
javadrools

Java Drools - which Rules are applied and facts list


I'm a little bit new to drools and i want to understand more of it for a project, so i made a simple program with drools on eclipse. The workflow is quite simple, i have a model for jwelery products, and for each piece of jwelery i apply one discount based on the name.

That works great, but i want do see the list of the facts and which facts are used for each triggered rule. I have this:

Rules.drl

package com.rule

import com.javainuse.model.Product
import com.javainuse.model.Counter

rule "Offer for Diamond"
    when 
        productObject: Product(type=="diamond")
    then
        productObject.setDiscount(15);
    end

rule "Offer for Gold"
    when 
        productObject: Product(type=="gold")
    then
        productObject.setDiscount(25);
    end

model.Product.java

package com.javainuse.model;

public class Product {
    private String type;
    private int discount;

   public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public int getDiscount() {
        return discount;
    }

    public void setDiscount(int discount) {
        this.discount = discount;
    }
}

main.DroolsTest.java

package com.javainuse.main;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collection;
import java.util.Iterator;
import org.drools.compiler.compiler.DroolsParserException;
import org.drools.compiler.compiler.PackageBuilder;
import org.drools.core.FactHandle;
import org.drools.core.RuleBase;
import org.drools.core.RuleBaseFactory;
import org.drools.core.WorkingMemory;
import com.javainuse.model.Product;

public class DroolsTest {

    public static void main(String[] args) throws DroolsParserException,
            IOException {
        DroolsTest droolsTest = new DroolsTest();
        droolsTest.executeDrools();
    }

    public void executeDrools() throws DroolsParserException, IOException {

        PackageBuilder packageBuilder = new PackageBuilder();

        String ruleFile = "/com/rule/Rules.drl";
        InputStream resourceAsStream = getClass().getResourceAsStream(ruleFile);

        Reader reader = new InputStreamReader(resourceAsStream);
        packageBuilder.addPackageFromDrl(reader);
        org.drools.core.rule.Package rulesPackage = packageBuilder.getPackage();
        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
        ruleBase.addPackage(rulesPackage);

        WorkingMemory workingMemory = ruleBase.newStatefulSession();

        Product product = new Product();
        Product product2 = new Product();
        product.setType("gold");
        product2.setType("diamond");

        //List of facts!
        workingMemory.insert(product);
        workingMemory.insert(product2);
        workingMemory.fireAllRules();

System.out.println("Discount for " + product.getType() + " is " + product.getDiscount());

        System.out.println("Discount for " + product2.getType() + " is " + product2.getDiscount());

        //how many facts
        System.out.println("There are " + workingMemory.getFactCount() + " facts");
        //facts handles
        Collection<org.kie.api.runtime.rule.FactHandle> x = workingMemory.getFactHandles();
        System.out.println("Facts Handles: " + x +"\n");

        FactHandle fh;
        Iterator<org.kie.api.runtime.rule.FactHandle> it =  x.iterator();
        while(it.hasNext())
        {
            fh = (FactHandle) it.next();
            System.out.println("FactHandle to string "+fh.toExternalForm().toString());
        }
    }
}

Output:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Discount for gold is 25
Discount for diamond is 15
There are 2 facts
Facts Handles: [[fact 0:2:1889057031:1889057031:2:DEFAULT:NON_TRAIT:com.javainuse.model.Product@7098b907], [fact 0:1:93199773:93199773:1:DEFAULT:NON_TRAIT:com.javainuse.model.Product@58e1d9d]]

FactHandle to string 0:2:1889057031:1889057031:2:DEFAULT:NON_TRAIT
FactHandle to string 0:1:93199773:93199773:1:DEFAULT:NON_TRAIT

I want something like this:

Discount for gold is 25
Discount for diamond is 15
There are 2 facts: gold, diamond
gold triggered rule Offer for Gold
diamond triggered Offer for Diamond

Is it possible? I've checked the classes of WorkingMemory, Endpoint, FactHandle but nothing.


Solution

  • I found a solution just to check which facts are triggered in the facts list when a rule hits.

    • Created a function on model.Product.java that return getType();
    • Then on the main program main.Droolstest.java: calls funtions to get facts getfacts(workingMemory);

      public void getfacts( WorkingMemory workingMemory )
      {
      FactHandle fh;
      Collection<org.kie.api.runtime.rule.FactHandle> x = workingMemory.getFactHandles();
      Iterator<org.kie.api.runtime.rule.FactHandle> it =  x.iterator();
      
      System.out.println("List of facts");
      while(it.hasNext())
      {
          fh = (FactHandle) it.next();
      
          Object getobj = workingMemory.getObject(fh);
          //System.out.println("GetObject to string: " + ((Object)getobj));
      
          if (getobj instanceof RuleFact) {
              System.out.println("\nIt's a Fact: ");
              ((RuleFact) getobj).print();
          }
          //System.out.println("FactHandle to string "+ ((Object) fh.toExternalForm()).toString());
         }
      
      }
      

    output:

    Constructor RuleFact to gold
    Constructor RuleFact to diamond
    Constructor RuleFact to wood
    Inserting facts on the facts list
    List of facts
    
    It's a Fact: 
    gold
    
    It's a Fact: 
    diamond
    
    Fire all the rules
    Discount for gold is 95
    Discount for diamond is 15
    Discount for wood is 0
    There are 2 facts
    Inserting fact on the facts list
    New Rule - fire all the rules
    There are 3 facts
    Discount for gold is 95
    Discount for diamond is 15
    Discount for wood is 90
    List of facts
    
    It's a Fact: 
    wood
    
    It's a Fact: 
    gold
    
    It's a Fact: 
    diamond