1
votes

I asked this question in drools forum,t no one answered. so I'm asking here.

Our rule is creates dynamic from database. We use Drools 6.0.1. When removed the rule use the API knowledgeBase.removeKnowledgePackage(), exception was throw.

The rule content is like :

package test 

import java.util.Map 

rule "test" 

    salience 0 
    date-effective "2014-05-19" 
    date-expires "2014-12-30" 
    no-loop true   

   when 

       Map( this['_type'] == 'SaleItemInfo' && ( 
        this['filmTypeKey'] in ("1") 
        && 
        this['sumPrice'] > 4B 
       )) 

       Map( this['_type'] == 'Member' && ( 
            this['dynamicPeriod'] == "CurrentDay" 
              && 
                this['consumeWayCode'] == "01324T" 
                  && 
                this['dynamicConsumeCount'] > 10 
       )) 

       Map( this['_type'] == 'SaleItemInfo' && ( 
        this['filmTypeKey'] in ("1") 
       ))

   then 
       System.out.println("=============="); 

end 

When I removed the rule, an exception throw:

java.lang.IllegalArgumentException: Cannot remove a sink, when the list of sinks is null at org.drools.core.reteoo.ObjectSource.removeObjectSink(ObjectSource.java:203) at org.drools.core.reteoo.ObjectSource.doRemove(ObjectSource.java:242) at org.drools.core.common.BaseNode.remove(BaseNode.java:120) at org.drools.core.reteoo.ReteooBuilder.removeNode(ReteooBuilder.java:240) at org.drools.core.reteoo.ReteooBuilder.removeTerminalNode(ReteooBuilder.java:183) at org.drools.core.reteoo.ReteooBuilder.removeRule(ReteooBuilder.java:157) at org.drools.core.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:1409) at org.drools.core.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:1400) at org.drools.core.reteoo.ReteooRuleBase.removePackage(ReteooRuleBase.java:1318) at org.drools.core.impl.KnowledgeBaseImpl.removeKnowledgePackage(KnowledgeBaseImpl.java:205) at com.oristartech.rule.drools.DroolsTest.removePackage(DroolsTest.java:128) at com.oristartech.rule.drools.DroolsTest.testDrools(DroolsTest.java:67) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597). .....

I found https://issues.jboss.org/browse/JBRULES-2465 said this problem was fixed.

When I changed drools version to 5.6, no exception was thrown.

So, is it a problem, or did I make a mistake in our rule file? Thanks.

UPDATE :

According to laune's suggestion, I add the demo code here:

public class DemoTest {
  public static void main(String[] args) {
    System.setProperty( "drools.dateformat", "yyyy-MM-dd" );

    KnowledgeBuilderConfiguration builderConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
    KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder(builderConf);
    builder.add(ResourceFactory.newClassPathResource("demo.drl"), ResourceType.DRL);

    if (builder.hasErrors()) {
        throw new RuntimeException(builder.getErrors().toString());
    }
    KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
    Collection<KnowledgePackage> packs = builder.getKnowledgePackages();
    kBase.addKnowledgePackages(packs);
    StatelessKnowledgeSession session = kBase.newStatelessKnowledgeSession();

    List<Object> facts = new ArrayList<Object>();
    Map<String, Object> f1 = new HashMap<String, Object>();
    f1.put("_type", "SaleItemInfo");
    f1.put("sumPrice", 100);
    f1.put("filmTypeKey", "1");
    facts.add(f1);

    Map<String, Object> f2 = new HashMap<String, Object>();
    f2.put("_type", "SaleItemInfo");
    f2.put("sumPrice", 300);
    f2.put("filmTypeKey", "1");
    facts.add(f2);

    Map<String, Object> f3 = new HashMap<String, Object>();
    f3.put("_type", "Member");
    f3.put("dynamicPeriod", "CurrentDay");
    f3.put("consumeWayCode", "01324T");
    f3.put("dynamicConsumeCount", 20);
    facts.add(f3);

    session.execute(facts);
    for(KnowledgePackage pk : packs) {
        kBase.removeKnowledgePackage(pk.getName());
    }
  }

}

For test easily, I copy the rule content to demo.drl . In our system, we have no drl file, all rules were loaded and composed from database, but the logic is same.

1
Which forum? It was not on [email protected].laune
The third conditional element is redundant and may even be harmful: it matches any Map that matches the first CE, and, possibly several others, so that the rule could fire repeatedly with pairs of different Map facts.laune
These issues always require a small but complete (!) sample of code demonstrating the problem. I suggest that you add this here, or try the list with that.laune
laune, I think my post was not accepted by the mail list.michael
@laune, We provide a web page to our customer, they define the rule freely ,so some times the rule content will appear like in the question. I realize this will lead full Cartesian product, i think we must add some constraint in the web page.michael

1 Answers

0
votes

To summarize all:

1) The rule is not well written, since the third CE binds the same Map object as the first CE (and, depending on WM contents) any other Map with the given constraints. => AP for @michael to improve the rule builder.

2) The presented demo code contains

session.execute(facts);
for(KnowledgePackage pk : packs) {
    kBase.removeKnowledgePackage(pk.getName());
}

Removing the knowledge packages from the (stateless) session is pointless. The session has been disposed by execute anyway, and the knowledge base can be "thrown away" without emptying it.

3) As for removing the regression from Drools 6.x, I strongly urge @michael to try again on this list: [email protected]. AFAIK, this list accepts all emails. (If there is another failure, pls comment here and I'll see to it.)

I hope this has helped to clarify and improve the issue.