<div dir="ltr">Hi Tim,<div>I know that you posted these through nabble, and it's not necessarily propagating your message to the community. I have gotten a good response by registering for the mailing list and sending messages directly to <span style="font-family:arial,sans-serif;font-size:13px;white-space:nowrap">Rules Users List <<a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>>. </span></div>
<div style><span style="font-family:arial,sans-serif;font-size:13px;white-space:nowrap">I am replying to your message through the rules-users mailing list - this way everyone on the list will definitely see your post.</span></div>
<div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Feb 8, 2013 at 9:08 AM, tslonaker <span dir="ltr"><<a href="mailto:tslonaker+drools@gmail.com" target="_blank">tslonaker+drools@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I am new to Drools and I am struggling with this ruleflow issue. Please let<br>
me know if I have been posting this info to the wrong message board.<br>
<br>
My situation is that I am working on converting our application from using<br>
an expensive commercial rule engine to Drools. Our rule engine<br>
implementation uses a stateless server and it heavily depends on ruleflows.<br>
We could develop the rules using salience but that isn't ideal.<br>
<br>
It seems to me that there is still a bug in drools-server when using<br>
ruleflows in a stateless session. It seems that the fix for issue 2718<br>
<<a href="https://issues.jboss.org/browse/JBRULES-2718" target="_blank">https://issues.jboss.org/browse/JBRULES-2718</a>> partially fixed the<br>
problem. There is an easy workaround if you are coding your solution in<br>
Java. You just create a new instance of the Stateless session every time.<br>
But in drools-server I don’t have any control over that.<br>
<br>
<br>
tslonaker wrote<br>
<div><div class="h5">> I found a much easier way to recreate the problem described in my previous<br>
> post. I believe I have also found the root cause of the problem. Below<br>
> are the steps to recreate the issue:<br>
><br>
> - Create a simple ruleflow and rules and compile them into a rule package.<br>
> - In code create a stateless session<br>
> - In a loop<br>
> o Create a fact<br>
> o Create a new execution batch with the following commands<br>
> - Insert the fact from above<br>
> - Start Process<br>
> - Fire All Rules<br>
> - Get Objects<br>
> o Execute the batch<br>
> o Check the results (number of rules that ran)<br>
><br>
> I posted before that the problem didn’t happen while executing locally<br>
> (not in drools server). I didn’t realize this before, but adding a loop<br>
> that executes the rules multiple times with the same session recreates the<br>
> problem.<br>
><br>
> Below is code that will recreate the issue. Notice that the code below<br>
> creates one instance of ksession and reuses it in the loop.<br>
><br>
> //Setup<br>
> KnowledgeBuilder kbuilder =<br>
> KnowledgeBuilderFactory.newKnowledgeBuilder();<br>
><br>
> //The package includes the ruleflow<br>
> kbuilder.add( ResourceFactory.newFileResource(<br>
> ("YourRulePackage_WithRuleflow.pkg") ), ResourceType.PKG );<br>
> KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();<br>
> kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );<br>
*<br>
> //Create the stateless knowledge session outside the for loop<br>
> StatelessKnowledgeSession ksession =<br>
> kbase.newStatelessKnowledgeSession();<br>
*<br>
><br>
> //Loop through executing the rules with the same data 3 times<br>
> for (int x = 0; x < 3; x++)<br>
> {<br>
> //Create a new instance of the input fact<br>
> FactType inputDataType = kbase.getFactType("SimpleRuleflowTest",<br>
> "Input");<br>
> Object inputData = inputDataType.newInstance();<br>
> inputDataType.set(inputData, "Name", "Test data");<br>
><br>
> //Create a new instance of the command list<br>
> List cmds = new ArrayList();<br>
> cmds.add( CommandFactory.newInsert( inputData ));<br>
> cmds.add( CommandFactory.newStartProcess( "TestRuleflow"));<br>
> cmds.add( CommandFactory.newFireAllRules("rules"));<br>
> cmds.add( CommandFactory.newGetObjects("output"));<br>
><br>
> //Execute the rules<br>
> ExecutionResults results = ksession.execute(<br>
> CommandFactory.newBatchExecution( cmds ) );<br>
><br>
> //Get the number of rules that ran<br>
> Object rules = results.getValue("rules");<br>
> System.out.println("Rules that ran: " + rules.toString());<br>
> }<br>
><br>
><br>
><br>
> Each iteration through the loop should fire 3 rules. Running the code<br>
> above you should get the following output:<br>
><br>
> Rules that ran: 3<br>
> Rules that ran: 1<br>
> Rules that ran: 1<br>
><br>
><br>
> I spent several hours researching the drools source code and I believe I<br>
> have found the problem. What I have found is related to<br>
> Issue 2718 <<a href="https://issues.jboss.org/browse/JBRULES-2718" target="_blank">https://issues.jboss.org/browse/JBRULES-2718</a>><br>
> .<br>
> Check out the change made for this issue:<br>
> 2718 fix<br>
> <<a href="https://source.jboss.org/viewrep/Drools/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java?r1=63021da325036ec6fbdf4019e8c8293db21555ec&r2=fad9b951f44ac813e5faf50f097335c2a97007ae" target="_blank">https://source.jboss.org/viewrep/Drools/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java?r1=63021da325036ec6fbdf4019e8c8293db21555ec&r2=fad9b951f44ac813e5faf50f097335c2a97007ae</a>><br>
> .<br>
><br>
> Below is a snippet from the code that was modified for issue 2718. The<br>
> “if (!initialized)” block was added. The code loops through event<br>
> listeners on the wm object and adds them to the stateless session’s<br>
> listeners. This works fine for the first rule execution. But the next<br>
> rule execution creates a new instance for wm. Therefore it also creates<br>
> new instances of listeners for wm. So we have a new instance of wm and<br>
> the stateless session is pointing to the old listeners from the first<br>
> instance of wm. I believe that is why it only runs correctly one time. It<br>
> seems that that the “if (!initialized)” block of code needs to execute<br>
> every time newWorkingMemory() is called.<br>
><br>
> public StatefulKnowledgeSession newWorkingMemory() {<br>
> :<br>
> :<br>
> ReteooWorkingMemory wm = new ReteooWorkingMemory(<br>
> this.ruleBase.nextWorkingMemoryCounter(),<br>
> this.ruleBase,<br>
> (SessionConfiguration) this.conf,<br>
> this.environment );<br>
> :<br>
> :<br>
><br>
*<br>
> if (!initialized) {<br>
*<br>
> // copy over the default generated listeners that are used for internal<br>
> stuff once<br>
> for (org.drools.event.AgendaEventListener listener:<br>
> wm.getAgendaEventSupport().getEventListeners()) {<br>
> this.agendaEventSupport.addEventListener(listener);<br>
> }<br>
> for (org.drools.event.WorkingMemoryEventListener listener:<br>
> wm.getWorkingMemoryEventSupport().getEventListeners()) {<br>
> this.workingMemoryEventSupport.addEventListener(listener);<br>
> }<br>
> InternalProcessRuntime processRuntime = wm.getProcessRuntime();<br>
> if (processRuntime != null) {<br>
> for (ProcessEventListener listener:<br>
> processRuntime.getProcessEventListeners()) {<br>
> this.processEventSupport.addEventListener(listener);<br>
> }<br>
> }<br>
> initialized = true;<br>
> }<br>
> :<br>
> :<br>
> }<br>
><br>
><br>
> So, I tested this theory in my test function. I used reflection to flip<br>
> the “initialized” flag at the bottom of my loop. I did this to force the<br>
> listeners of the stateless session to be refreshed for every execute call.<br>
> It worked! The other nodes in the ruleflow now get executed after the<br>
> first rule execution. Below is a snippet of my modified test code:<br>
><br>
><br>
> //Same As Above<br>
> :<br>
> :<br>
> //Create the stateless knowledge session outside the for loop<br>
> StatelessKnowledgeSession ksession =<br>
> kbase.newStatelessKnowledgeSession();<br>
><br>
> //Loop through executing the rules with the same data 3 times<br>
> for (int x = 0; x < 3; x++)<br>
> {<br>
> :<br>
> :<br>
> //Flip the initialized flag to false through reflection<br>
*<br>
> Field field =<br>
> StatelessKnowledgeSessionImpl.class.getDeclaredField("initialized");<br>
> field.setAccessible(true);<br>
> field.setBoolean(ksession, false);<br>
*<br>
> }<br>
><br>
><br>
> Running the code above you should get the following output:<br>
><br>
> Rules that ran: 3<br>
> Rules that ran: 3<br>
> Rules that ran: 3<br>
><br>
> My original problem deals with drools-server. It isn’t possible for me to<br>
> flip the initialized flag to false in that scenario. So, is there any<br>
> sort of workaround that would get me past this issue when using<br>
> drools-server?<br>
<br>
<br>
<br>
<br>
<br>
--<br>
</div></div>View this message in context: <a href="http://drools.46999.n3.nabble.com/Ruleflow-not-working-with-stateless-session-in-drools-server-5-5-0-Final-tp4021624p4022161.html" target="_blank">http://drools.46999.n3.nabble.com/Ruleflow-not-working-with-stateless-session-in-drools-server-5-5-0-Final-tp4021624p4022161.html</a><br>
<div class="HOEnZb"><div class="h5">Sent from the Drools: User forum mailing list archive at Nabble.com.<br>
<br>
_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a></div></div></blockquote></div><br></div></div>