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