Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drools- how to find out which all rules were matched?

I've one .DRL file which has say 10 rules. Once I insert a fact, some rules may be matched- how do I find out which rules were matched programmatically?

like image 669
gauravphoenix Avatar asked Nov 13 '13 10:11

gauravphoenix


People also ask

How do you know which rule was fired in Drools?

drl. Both the utility functions are called and it shows whether the particular rule was called or not. In the above example, all the rules are being called, but in an enterprise application, this utility function can be really useful to debug and find out whether a particular rule was fired or not.

How rules are executed in Drools?

Let's quickly summarize how Drools works. Rules are written on . drl files, facts or POJOs are inserted in the Knowledge Base, then rules are applied on each fact. If a "When" part of a rule satisfies a fact, the "Then" part will execute.

How do you call one rule from another rule in Drools?

Well, the answer is we can't call a Rule from another Rule. Drools matches the Rules with incoming data/facts, and if the data satisfies the Rule condition, it stores the data in an Agenda. It might be possible for the same data or facts to be matched by different rules, so it stores matching facts in an Agenda.

What are the rules in Drools?

Drools keywords are rule, when, then, and end. In the above example, the rule names are “Hello World” and “GoodBye”. The when part is the condition in both the rules and the then part is the consequence.


1 Answers

Note that this answer is valid for versions of Drools up to 5.x. If you have moved on to 6 or above, then take a look at the modified answer from @melchoir55. I haven't tested it myself, but I'll trust that it works.

To keep track of rule activations, you can use an AgendaEventListener. Below is an example, as found here:

https://github.com/gratiartis/sctrcd-payment-validation-web/blob/master/src/main/java/com/sctrcd/drools/util/TrackingAgendaEventListener.java

You just need to create such a listener and attach it to the session like so:

ksession = kbase.newStatefulKnowledgeSession();
AgendaEventListener agendaEventListener = new TrackingAgendaEventListener();
ksession.addEventListener(agendaEventListener);
//...
ksession.fireAllRules();
//...
List<Activation> activations = agendaEventListener.getActivationList();

Note that there is also WorkingMemoryEventListener which enables you to do the same with tracking insertions, updates and retractions of facts.

Code for a tracking & logging AgendaEventListener:

package com.sctrcd.drools.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.drools.definition.rule.Rule;
import org.drools.event.rule.DefaultAgendaEventListener;
import org.drools.event.rule.AfterActivationFiredEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A listener that will track all rule firings in a session.
 * 
 * @author Stephen Masters
 */
public class TrackingAgendaEventListener extends DefaultAgendaEventListener {

    private static Logger log = LoggerFactory.getLogger(TrackingAgendaEventListener.class);

    private List<Activation> activationList = new ArrayList<Activation>();

    @Override
    public void afterActivationFired(AfterActivationFiredEvent event) {
        Rule rule = event.getActivation().getRule();

        String ruleName = rule.getName();
        Map<String, Object> ruleMetaDataMap = rule.getMetaData();

        activationList.add(new Activation(ruleName));
        StringBuilder sb = new StringBuilder("Rule fired: " + ruleName);

        if (ruleMetaDataMap.size() > 0) {
            sb.append("\n  With [" + ruleMetaDataMap.size() + "] meta-data:");
            for (String key : ruleMetaDataMap.keySet()) {
                sb.append("\n    key=" + key + ", value="
                        + ruleMetaDataMap.get(key));
            }
        }

        log.debug(sb.toString());
    }

    public boolean isRuleFired(String ruleName) {
        for (Activation a : activationList) {
            if (a.getRuleName().equals(ruleName)) {
                return true;
            }
        }
        return false;
    }

    public void reset() {
        activationList.clear();
    }

    public final List<Activation> getActivationList() {
        return activationList;
    }

    public String activationsToString() {
        if (activationList.size() == 0) {
            return "No activations occurred.";
        } else {
            StringBuilder sb = new StringBuilder("Activations: ");
            for (Activation activation : activationList) {
                sb.append("\n  rule: ").append(activation.getRuleName());
            }
            return sb.toString();
        }
    }

}
like image 171
Steve Avatar answered Oct 02 '22 10:10

Steve