[rules-users] Ruleflow not working with stateless session in drools-server 5.5.0.Final

tslonaker tslonaker+drools at gmail.com
Fri Feb 8 10:08:24 EST 2013


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.



More information about the rules-users mailing list