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
