[jboss-jira] [JBoss JIRA] (DROOLS-1097) Loading Session and running rules re-executes all rules

Mario Fusco (JIRA) issues at jboss.org
Wed Apr 6 06:28:00 EDT 2016


     [ https://issues.jboss.org/browse/DROOLS-1097?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Mario Fusco resolved DROOLS-1097.
---------------------------------
    Resolution: Rejected


Your reproducer was a bit convoluted and I took awhile to figure out what was going wrong there. I think I captured the essence of the problem with the following test case:

{code}
    @Test
    public void test1097() throws Exception {
        String drl =
                "import " + MyModel.class.getCanonicalName() + ";\n" +
                "rule \"expiry\" when \n" +
                "    $p : MyModel( expired );\n" +
                "then\n" +
                "    System.out.println(\"Expired \" + $p);\n" +
                "    delete($p)\n" +
                "end";

        KieServices ks = KieServices.Factory.get();
        KieBase kbase = new KieHelper().addContent( drl, ResourceType.DRL ).build();
        KieSession ksession = kbase.newKieSession();

        ksession.insert(new MyModel( 0 ));
        Assert.assertEquals( 1, ksession.getFactCount() );

        ksession.fireAllRules();

        ksession = SerializationHelper.getSerialisedStatefulKnowledgeSession(ksession, true);
        int fireAllRules = ksession.fireAllRules();
        Assert.assertEquals(0, fireAllRules);
    }

    public static class MyModel implements Serializable {

        private boolean expired = false;

        private final int id;

        public MyModel( int id ) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "MyModel[" + id + "]";
        }

        public boolean isExpired() {
            boolean result = expired;
            expired = true;
            return result;
        }
    }
{code}

Note the isExpired() method of the MyModel bean. In your implementation you used a Random generator and I rewrote it that way only because I wanted a deterministic behaviour. Anyway for what concerns Drools your implementation of that method and mine present exactly the same problem: the value returned by that method in 2 different invocations changes (or may change in your version). This corresponds under Drools point of view to a change of a fact without notifying the engine that the fact is changed. In other words this is exactly equivalent to doing in a rule consequence something like:

{code}
myModel.setExpired(true);
{code}

instead of

{code}
modify( myModel ) { setExpired( true ) };
{code}

and then complaining that Drools wasn't reacting to a change in your model.

When you serialize and deserialize the session the facts are reasserted into it thus causing the rule to fire even if you don't expect it. However the flaw is not in the serialization mechanism but it is caused by the fact that you're effectively changing the state of a fact stored in Drools working memory without notifying the engine. This can cause many other "unexpected" behaviours regardless of serialization.

> Loading Session and running rules re-executes all rules 
> --------------------------------------------------------
>
>                 Key: DROOLS-1097
>                 URL: https://issues.jboss.org/browse/DROOLS-1097
>             Project: Drools
>          Issue Type: Bug
>          Components: core engine
>    Affects Versions: 6.3.0.Final
>         Environment: Mac OS 10.10.5, Eclipse Mars Release, Java 1.8, Drools 6.3.0.Final
>            Reporter: Artur Kronenberg
>            Assignee: Mario Fusco
>         Attachments: test-standalone.zip
>
>
> This is possibly directly related to: (or rather that one relates to this one) 
> https://issues.jboss.org/browse/DROOLS-1093
> The situation: 
> * Create a session with 2 rules. 1 Rule expires facts that are in the working memory by retracting them. 
> * Add the ExpiryFact to expire some facts
> * Execute all rules -> X facts get expired 
> * dispose the existing session
> * re-load the session
> * without adding more facts to the working memory, run all rules 
> * The session re-executes more rules and retracts things from memory
> Now there seem to be 2 problems with this: 
> 1. The session does not remember what facts it expired. So it will delete more infos, that are still "somewhere". When re-loading the session from the database, we will see an NPE 
> 2. Surely since it already ran the rules against the Expiry fact, it should not run them again. 
> I will attach a unit test ExceptionTest#testRulesAreFiredTwice with this bug. 
> Let me know if this can be worked around please and/or if there are any more questions.
> Thanks,
> Artur



--
This message was sent by Atlassian JIRA
(v6.4.11#64026)


More information about the jboss-jira mailing list