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

Yuri yuri0282+drools at gmail.com
Fri Feb 8 16:07:34 EST 2013


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 <rules-users at lists.jboss.org>.
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 <tslonaker+drools at gmail.com>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
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20130208/31cb1f88/attachment-0001.html 


More information about the rules-users mailing list