Search code examples
javadroolsrule-engine

drools (6.2) fact doesn't get re-evaluated in stateful session


I'm still quite new to drools (using 6.2), but am stumped at a seemingly easy problem.

Problem: I have multiple rules of which at most one should be applied. In other words, once one applies the other rules should no longer have their "when" clause be evaluated to true.

package xyz

import xyz.EvaluationResults;
import xyz.ExclusivenessTestFact;


rule "ExclusivenessTest Rule 1"
salience 10

when
    $exclusivenessFact : ExclusivenessTestFact()
    $evaluationResults : EvaluationResults(exclusiveRuleApplied == false)
then
    $evaluationResults.addResult("TR1","TR1");
    $evaluationResults.setExclusiveRuleApplied(true);
end

The idea of the rule being that after the first rule applies, it sets the exclusiveRuleApplied flag to true and hence the other rules being evaluated should no longer evaluate to true. (not sure if this is the best approach, but its the best I could come up with)

I have multiple of those rules (4 right now) and add one of each facts into the session and see through breakpoints and debugging that the EvaluationResults.getExclusiveRuleApplied() getter only gets evaluated once (while the setter is called four times, so all rules are applied).

I am using a stateful session and below is my EvaluationResults class (following the "State" example from the drools examples). I'm not sure what I am missing, I don't see any propertyChangeListener being added anywhere (also not in the examples), so not sure how this is supposed to work in the java dialect? Maybe I am missing some rule-engine settings, I use stateful sessions and stream as event processing mode (not really knowing what it is though).

package xyz
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import java.util.Map;

public class EvaluationResults 
 implements java.io.Serializable 
{
    private Boolean exclusiveRuleApplied;
    private Map<String,Object> results;

    private final PropertyChangeSupport changes = new PropertyChangeSupport(this);

    public EvaluationResults()
    {
        // default constructor
    }

    public Object addResult(final String key, final Object result)
    {
        return results.put(key, result);
    }

    public void setExclusiveRuleApplied(Boolean exclusiveRuleApplied)
    {
        Boolean oldState = this.exclusiveRuleApplied;
        this.exclusiveRuleApplied = exclusiveRuleApplied;
        // each fact change gets propagated via Java Beans PropertyChangeEvents
        this.changes.firePropertyChange( "exclusiveRuleApplied",
                                     oldState,
                                     exclusiveRuleApplied );
    }

    public Boolean getExclusiveRuleApplied()
    {
        return exclusiveRuleApplied;
    }
    public void setResults(Map<String,Object> results)
    {
        Map<String,Object> oldState = this.results;
        this.results = results;
        // each fact change gets propagated via Java Beans PropertyChangeEvents
        this.changes.firePropertyChange( "results",
                                     oldState,
                                     results );
    }

    public Map<String,Object> getResults()
    {
        return results;
    }

    @Override
    public boolean equals(Object obj)
    {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    @Override
    public int hashCode()
    {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    public void addPropertyChangeListener(final PropertyChangeListener l) {
        this.changes.addPropertyChangeListener( l );
    }

    public void removePropertyChangeListener(final PropertyChangeListener l) {
        this.changes.removePropertyChangeListener( l );
    }

}

Happy to hear any ideas. Thanks!


Solution

  • The Drools engine doesn't automatically detect when you have changed a fact. Therefore you must explicitly call update($evaluationResults) to notify it and cause it to re-evaluate the conditions of all other rules.