I have modified my application to allow adding/removing/updating rules during
runtime.  However, when I add a new rule to the rulebase, I don't get the
behavior I expect.

First, as soon as I call RuleBase.addPackage(), the new rules fire (the RHS code
runs).  Shouldn't that happen only when I call fireAllRules()?

Second, newly added collect() rules don't collect already asserted objects. New
non-collect rules can see the objects just fine.

Attached is a testcase, and below is the output it produces.  Am I doing
something wrong, or is this a bug?  I'm running Drools 4.0.3 on JDK 1.5.0.13.

Start
RuleBase created
Adding rules about 'tom':
package rules;
import java.util.ArrayList;
import test.Tester.Record;
import test.Tester;
rule "Collect tom"
when
 $list : ArrayList(size > 0) from collect( Record(field1 == "tom") )
then
 Tester.show($list, "Collect tom");
end

rule "Non collect tom"
when
 $rec : Record( field1 == "tom" )
then
 System.out.println("Find 'tom' " + $rec.dump());
end

inserting record 1:"tom",
inserting record 2:"fred",
inserting record 3:"harry",
inserting record 4:"fred",
inserting record 5:"ed",
inserting record 6:"tom",
inserting record 7:"sreeni",
inserting record 8:"jill",
inserting record 9:"ralph",
inserting record 10:"tom",

fireAllRules()
Find 'tom' 10:"tom",
'Collect tom' collected 3 records => 1:"tom", 6:"tom", 10:"tom",
Find 'tom' 6:"tom",
Find 'tom' 1:"tom",

adding rules about 'fred':
package morerules;
import java.util.ArrayList;
import test.Tester.Record;
import test.Tester;
rule "Collect fred"
when
 $list : ArrayList(size > 0) from collect( Record(field1 == "fred") )
then
 Tester.show($list, "Collect fred");
end

rule "Non collect fred"
when
 $rec : Record( field1 == "fred" )
then
 System.out.println("Find 'fred' " + $rec.dump());
end

 ==> Why do the new rules fire when added?
Find 'fred' 4:"fred",
Find 'fred' 2:"fred",
'Collect fred' collected 0 records =>
 ==> Why doesn't the collect rule collect? The non-collect rule works.
fireAllRules()

Changing record 3 to 'fred'
fireAllRules()
Find 'fred' 3:"fred",
'Collect fred' collected 1 records => 3:"fred",
 ==> Why does the collect rule not see the other two 'fred' records?

--
Dirk Bergstrom               [EMAIL PROTECTED]
_____________________________________________
Juniper Networks Inc.,          Computer Geek
Tel: 408.745.3182           Fax: 408.745.8905
package test;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.drools.FactHandle;
import org.drools.RuleBase;
import org.drools.RuleBaseConfiguration;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.compiler.DroolsParserException;
import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.rule.builder.dialect.java.JavaDialectConfiguration;

public class Tester {

    private static String RULES_TOM =
        "package rules;\n" +
        "import java.util.ArrayList;\n" +
        "import test.Tester.Record;\n" +
        "import test.Tester;\n" +
        "rule \"Collect tom\"\n" +
        "when\n" +
        " $list : ArrayList(size > 0) from collect( Record(field1 == \"tom\") )\n" +
        "then\n" +
        " Tester.show($list, \"Collect tom\");\n" +
        "end\n\n" +
        "rule \"Non collect tom\"\n" +
        "when\n" +
        " $rec : Record( field1 == \"tom\" )\n" +
        "then\n" +
        " System.out.println(\"Find 'tom' \" + $rec.dump());\n" +
        "end";

    private static String RULES_FRED =
        "package morerules;\n" +
        "import java.util.ArrayList;\n" +
        "import test.Tester.Record;\n" +
        "import test.Tester;\n" +
        "rule \"Collect fred\"\n" +
        "when\n" +
        " $list : ArrayList(size > 0) from collect( Record(field1 == \"fred\") )\n" +
        "then\n" +
        " Tester.show($list, \"Collect fred\");\n" +
        "end\n\n" +
        "rule \"Non collect fred\"\n" +
        "when\n" +
        " $rec : Record( field1 == \"fred\" )\n" +
        "then\n" +
        " System.out.println(\"Find 'fred' \" + $rec.dump());\n" +
        "end";

    static String[][] MYDATA = {
        { "1", "tom", },
        { "2", "fred", },
        { "3", "harry", },
        { "4", "fred", },
        { "5", "ed", },
        { "6", "tom", },
        { "7", "sreeni", },
        { "8", "jill", },
        { "9", "ralph", },
        { "10", "tom", },
    };

    public static void show(ArrayList rs, String msg) {
        System.out.print("'" + msg + "' collected " + rs.size() +
            " records => ");
        for (Object r : rs) {
            System.out.print(((Record) r).dump());
        }
        System.out.println("");
    }

    static Record setup(WorkingMemory workingMemory) {
        Record testrec = null;
        for (String[] data: MYDATA) {
            Record rec = new Record(data);
            System.out.println("inserting record " + rec.dump());
            rec.setFactHandle(workingMemory.insert(rec));
            if (rec.id.equals("3")) testrec = rec;
        }
        return testrec;
    }

    public static void doit() throws Exception {
        System.out.println("Start");
        PackageBuilderConfiguration pkgBuilderCfg = new PackageBuilderConfiguration();
        JavaDialectConfiguration javaConf = (JavaDialectConfiguration)
            pkgBuilderCfg.getDialectConfiguration("java");
        javaConf.setCompiler(JavaDialectConfiguration.JANINO);
        javaConf.setJavaLanguageLevel("1.5");

        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
        System.out.println("RuleBase created");
        System.out.println("Adding rules about 'tom':\n" + RULES_TOM + "\n");
        addRule(pkgBuilderCfg, ruleBase, RULES_TOM);
        WorkingMemory workingMemory = ruleBase.newStatefulSession();
        Record testrec = setup(workingMemory);

        System.out.println("\nfireAllRules()");
        workingMemory.fireAllRules();

        System.out.println("\nadding rules about 'fred':\n" + RULES_FRED + "\n");
        System.out.println(" ==> Why do the new rules fire when added?");
        addRule(pkgBuilderCfg, ruleBase, RULES_FRED);
        System.out.println(" ==> Why doesn't the collect rule collect?" +
        		" The non-collect rule works.");
        System.out.println("fireAllRules()");
        workingMemory.fireAllRules();

        testrec.field1 = "fred";
        System.out.println("\nChanging record 3 to 'fred'");
        workingMemory.update(testrec.factHandle, testrec);
        System.out.println("fireAllRules()");
        workingMemory.fireAllRules();
        System.out.println(" ==> Why does the collect rule not see the other " +
            "two 'fred' records?");
    }

    private static void addRule(PackageBuilderConfiguration pkgBuilderCfg,
        RuleBase ruleBase, String rules) throws DroolsParserException,
        IOException, Exception {
        PackageBuilder rulePackageBuilder = new PackageBuilder(pkgBuilderCfg);
        rulePackageBuilder.addPackageFromDrl(new StringReader(rules));
        if (rulePackageBuilder.hasErrors()) {
            throw new Exception("Errors parsing rule : " +
                rulePackageBuilder.getErrors().toString());
        }
        ruleBase.addPackage(rulePackageBuilder.getPackage());
    }

    public static class Record {
        public String id;
        public String field1;
        public FactHandle factHandle;
        public Record(String[] values) {
            this.id = values[0];
            field1 = values[1];
        }
        public void setFactHandle(FactHandle factHandle) {
            this.factHandle = factHandle;
        }
        public String getfield1() {
            return field1;
        }
        public String dump() {
            return this.id + ":\"" + this.field1 + "\", ";
        }
    }

    public static final void main(String[] args) {
        try {
            doit();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}
_______________________________________________
rules-users mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/rules-users

Reply via email to