[rules-users] Inconsistent results in fusion

Edson Tirelli ed.tirelli at gmail.com
Thu Dec 17 15:27:35 EST 2009


   Richard,

   There are some misconceptions in your example. I will try to clarify some
things:

1. The Ruleflow: every time you call "ksession.startProcess("myflow");", you
start a new flow instance (or process instance if you prefer). For each
instance, it will activate in turn your groups one, two and three, moving to
the next group when no more activations exist. Although, you didn't tie you
facts/rules to any particular instance, meaning you have a "pool of facts"
and a "pool of flow instances" that are all matching themselves in no
specific way. In other words, you are inserting messages and starting flows
50 times in your example. Imagine that when the flow instance #20 reaches
node "three", you are at the same time inserting message #30... message
number #30 will activate the rule "NotThree" and it will fire as part of the
flow instance #20... you will have your "strange" behaviors.

2. On top of the situation above, you are firing rules with fireUntilHalt(),
meaning the engine is running in asynchronous, reactive mode, and you will
have no control at all over the results you are getting back.

3. Since you mentioned fusion on the subject of this message, I guess you
are probably setting the message role as "event", and in stream mode, the
engine will try to determine when a fact is no longer needed and can be
automatically expired. Although, at the same time, you are trying to retract
the event in rules of group "three". Since the fact might have been already
expired by that time, you are getting the consequence exception saying the
fact is no longer in the working memory.

   I guess what I am saying is: all these features in Drools are there for a
reason, and it is possible to mistakenly try to use them for things they are
not intended to. The only way to prevent that is by educating users. If the
documentation is not clear, please help us make it better.

   Back to your example, first things first: simplify it...

* do you really need the engine to run it in reactive mode? try batching
facts and fire rules in a more controlled manner. Single thread is, as you
know, a lot easier to deal with than multi-threads.

* do you need to have all your events in the same session? If you can have
one session per "request", your flow+rules+events will work as you expect.
If you need to have all events and flow and rules in the same session, then
you need to tie rules to flow instances using process variables, possibly
also using goal facts to drive your progress, etc.

* do you really need events and stream mode? cloud mode (default) is much
easier to understand and deal with, since there is no automatic garbage
collection, session clock requirements, etc.

   Hope it helps,
       Edson

2009/12/17 RichardA <Richard.Ambridge at sun.com>

>
> Hi all again,
> I am having a problem where the results of the rules is not consistent.
> I am using rules flow and fireUntilHalt..
>
> Here is most of my code: (expanding the default drools example)
>
> private static KnowledgeBase readKnowledgeBase() throws Exception {
>                KnowledgeBuilder kbuilder =
> KnowledgeBuilderFactory.newKnowledgeBuilder();
>
>  kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"),
> ResourceType.DRL);
>
>  kbuilder.add(ResourceFactory.newClassPathResource("Flow.rf"),
> ResourceType.DRF);
>                KnowledgeBuilderErrors errors = kbuilder.getErrors();
>                if (errors.size() > 0) {
>                        for (KnowledgeBuilderError error: errors) {
>                                System.err.println(error);
>                        }
>                        throw new IllegalArgumentException("Could not parse
> knowledge.");
>                }
>                KnowledgeBaseConfiguration conf =
> KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
>                conf.setOption(EventProcessingOption.STREAM);
>                KnowledgeBase kbase =
> KnowledgeBaseFactory.newKnowledgeBase(conf);
>                kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
>                return kbase;
>        }
>
> public static final void main(String[] args) {
>                try {
>                        // load up the knowledge base
>                        KnowledgeBase kbase = readKnowledgeBase();
>                        final StatefulKnowledgeSession ksession =
> kbase.newStatefulKnowledgeSession();
>                        new Thread(new Runnable() {
>              public void run() {
>                          ksession.fireUntilHalt();
>                      }
>                    }, "FireAllRules").start();
>                        // go !
>                        for(int i=0;i<50;i++){
>                          Message message = new Message();
>                          message.setMessage("one");
>                          ksession.insert(message);
>                          ksession.startProcess("myflow");
>                        }
>                        System.out.println("Sleeping");
>                        Thread.sleep(20000);
>                        System.out.println("Halt");
>                        ksession.halt();
>                } catch (Throwable t) {
>                        t.printStackTrace();
>                }
>        }
>
> So, notice fireUntilHalt is started in a thread.
> And its in STREAM mode
> and I use flow group and sample rules set.
> Then inject 50 messages, and after each inject start the 'myflow'
>
> The rule flow is like this;
> Start->  One -> Two -> Three -> End
>
> and the rules are:
> rule "One"
>    ruleflow-group "One"
>        when
>                m : Message( message=="one" )
>        then
>
>                m.setMessage( "two" );
>                update( m );
> end
>
> rule "Two"
>    ruleflow-group "Two"
>        when
>                m : Message( message=="two" )
>        then
>                m.setMessage( "three" );
>                update( m );
> end
>
> rule "NotThree"
>    ruleflow-group "Three"
>        when
>                m : Message( message!="three" )
>        then
>                System.out.println( "Message is not three????????????" );
>                retract(m);
> end
> rule "Three"
>    ruleflow-group "Three"
>        when
>                m : Message( message=="three" )
>        then
>                retract(m);
> end
>
>
> So, from that you should see that as an object is injected it has
> message=="one"
> so flow group One should match, the message updates to 'two'
> then flow group two should match, message updates to 'three'
> and then the group three rule Three should match and the object retracted.
>
> Sometimes I run this I get results as expected.
> Other times I get 1 message hit the 'NotThree' rule.
> Other times I get lots of them hit the 'NotThree' rule.
> Sometimes I get;
> Exception in thread "FireAllRules"
> org.drools.runtime.rule.ConsequenceException: org.drools.FactException:
> Retract error: handle not found for object: null. Is it in the working
> memory?
>        at
>
> org.drools.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:23)
>
>
> Its driving me mad as my project is failing due to inconsistent results.
> Please help..
>
> --
> View this message in context:
> http://n3.nabble.com/Inconsistent-results-in-fusion-tp93259p93259.html
> Sent from the Drools - User mailing list archive at Nabble.com.
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>



-- 
 Edson Tirelli
 JBoss Drools Core Development
 JBoss by Red Hat @ www.jboss.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20091217/27ca19ad/attachment.html 


More information about the rules-users mailing list