[rules-users] RES: Behavior changes between Drools 5.0.1 and 5.1.0

Carlos Henrique Pinto da Sillva carlos.dasilva at todobpo.com.br
Mon Apr 5 08:28:48 EDT 2010


Hi all,

Last week I sent this message asking for some help identifying either an usage error from us or a possible bug in Drools Fusion 5.1.0, but so far got no answer. If any of you fellows can find any mistake in our implementation please let me know, otherwise I'll assume this is indeed a bug in 5.1.0 and proceed to register it. Thanks in advance for any help.

Carlos

>Hi all,

>We're evaluating the use of Drools Fusion as rule engine for one of our
>projects, but after updating from version 5.0.1 to 5.1.0 to fix one
>persistence issue we faced new errors and some unexpected behavior
>changes in already tested parts of our code, and we aren't unsure if
>it's our fault due to incorrect assumptions or if it's resulting from a
>new bug introduced in last release. Here follows what we are doing:

>1) we declared this in our Test_Rules.drl:

>declare UserEvent @role( event ) @expires( 30s ) end

>query "get user by login" (String login) user : UserEvent(user.login ==
>login) end

>2) this is the code we use to retrieve the Drools session (implemented
>in a singleton):

>public StatefulKnowledgeSession getKnowledgeSessionInstance() {
>if (session == null) { kbase = readKnowledgeBase();
>KnowledgeSessionConfiguration conf =
>KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); session =
>kbase.newStatefulKnowledgeSession(conf, null); }

>return session; }

>3) that's how we load the rules (some non-pertinent code was omitted):

>private KnowledgeBase readKnowledgeBase() { KnowledgeBuilder kbuilder =
>KnowledgeBuilderFactory.newKnowledgeBuilder();
>KnowledgeBaseConfiguration config =
>KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
>config.setOption(EventProcessingOption.STREAM);
>kbuilder.add(ResourceFactory.newClassPathResource("Test_Rules.drl"),
>ResourceType.DRL); KnowledgeBuilderErrors errors = kbuilder.getErrors();
>if (errors.size() > 0) { // (...) throw new
>IllegalArgumentException("Could not parse knowledge."); } KnowledgeBase
>kbase = KnowledgeBaseFactory.newKnowledgeBase(config);
>kbase.addKnowledgePackages(kbuilder.getKnowledgePackages()); return
>kbase; }

>(NOTE: Up to this point the code behaves exactly the same way in both
>versions and everything works as expected.)

>4) in this method we check our event expiration, and that's where things
>starts to behave different. In version 5.0.1, the code always worked in
>the same way, returning a null reference to userValidation if the
>expiration time is reached. Also, handleQuery is always an instance of
>EventFactHandle. Based in userValidation reference being null or not, we
>either retrieve it or update it. Again, non-related code was ommited:

>private UserTrackForValidation assertDesktopEvent(DesktopDeviceEvent
>event) { UserEvent userValidation = null; StatefulKnowledgeSession
>session =
>sessionFactory.getKnowledgeSessionInstance(createEnviroment());
>QueryResults results = session.getQueryResults("get user by login", new
>String[] {event.getLogin()});

>if (results.size() > 0) { QueryResultsRow row =
>results.iterator().next(); FactHandle handleQuery =
>row.getFactHandle("user"); userValidation = (UserTrackForValidation)
>row.get("user"); }

>if (userValidation == null) { try { userValidation =
>entityDAO.getUserTrackByLogin(event.getLogin()); } catch (Exception e) {
>e.printStackTrace(); }

>// (...) } else { // (...) session.update(handleQuery, userValidation);
>session.fireAllRules(); } }

>return userValidation; }

>However, starting with version 5.1.0, we observed some odd behaviors:
>a) after time expiration, we may or may not receive a null reference to
>userValidation, which renders the test line "if (userValidation ==
>null)" erratic; b) even when we receive a (as far as we can tell) valid
>reference to userValidation, sometimes a NullPointerException is raised,
>as can be seen in the following stacktrace:

>java.lang.NullPointerException at
>org.drools.common.AbstractWorkingMemory.update(AbstractWorkingMemory.jav
>a:1329) at
>org.drools.common.AbstractWorkingMemory.update(AbstractWorkingMemory.jav
>a:1288) at
>org.drools.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSes
>sionImpl.java:248) at
>br.com.todobpo.lam.ejb.session.ContactCenterRuleServiceImpl.assertSimple
>Event(ContactCenterRuleServiceImpl.java:191) at
>br.com.todobpo.lam.ejb.session.ContactCenterRuleServiceImpl.insertEvent(
>ContactCenterRuleServiceImpl.java:89) at
>sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>at
>sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
>a:39) at
>sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
>Impl.java:25) at java.lang.reflect.Method.invoke(Method.java:597)
>at
>org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.j
>ava:122) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:111) at
>org.jboss.ejb3.EJBContainerInvocationWrapper.invokeNext(EJBContainerInvo
>cationWrapper.java:69) at
>org.jboss.ejb3.interceptors.aop.InterceptorSequencer.invoke(InterceptorS
>equencer.java:73) at
>org.jboss.ejb3.interceptors.aop.InterceptorSequencer.aroundInvoke(Interc
>eptorSequencer.java:59) at
>sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>at
>sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
>a:39) at
>sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
>Impl.java:25) at java.lang.reflect.Method.invoke(Method.java:597)
>at
>org.jboss.aop.advice.PerJoinpointAdvice.invoke(PerJoinpointAdvice.java:1
>74) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.fillMethod(
>InvocationContextInterceptor.java:72) at
>org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextIn
>terceptor_z_fillMethod_1000702.invoke(InvocationContextInterceptor_z_fil
>lMethod_1000702.java) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.setup(Invoc
>ationContextInterceptor.java:88) at
>org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextIn
>terceptor_z_setup_1000702.invoke(InvocationContextInterceptor_z_setup_10
>00702.java) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.connectionmanager.CachedConnectionInterceptor.invoke(Cach
>edConnectionInterceptor.java:62) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(T
>ransactionScopedEntityManagerInterceptor.java:56) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInte
>rceptor.java:47) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.tx.StatelessBMTInterceptor.handleInvocation(StatelessBMTI
>nterceptor.java:106) at
>org.jboss.ejb3.tx.BMTInterceptor.invoke(BMTInterceptor.java:55)
>at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessIn
>stanceInterceptor.java:68) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
>at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterc
>eptor.java:76) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
>at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3Authe
>nticationInterceptorv2.java:186) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationIntercepto
>r.java:41) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerSh
>utdownInterceptor.java:67) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(
>CurrentInvocationInterceptor.java:67) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessConta
>iner.java:421) at
>org.jboss.ejb3.session.InvokableContextClassProxyHack._dynamicInvoke(Inv
>okableContextClassProxyHack.java:53) at
>org.jboss.aop.Dispatcher.invoke(Dispatcher.java:91) at
>org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemoti
>ngInvocationHandler.java:82) at
>org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:891)
>at
>org.jboss.remoting.transport.socket.ServerThread.completeInvocation(Serv
>erThread.java:744) at
>org.jboss.remoting.transport.socket.ServerThread.processInvocation(Serve
>rThread.java:697) at
>org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java
>:524) at
>org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:2
>32) at
>org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvo
>ker.java:211) at org.jboss.remoting.Client.invoke(Client.java:1724)
>at org.jboss.remoting.Client.invoke(Client.java:629) at
>org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteIn
>terceptor.java:60) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropa
>gationInterceptor.java:61) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.security.client.SecurityClientInterceptor.invoke(Security
>ClientInterceptor.java:65) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.jav
>a:74) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at org.jboss.aspects.remoting.PojiProxy.invoke(PojiProxy.java:62)
>at $Proxy7.invoke(Unknown Source) at
>org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerB
>ase.invoke(SessionProxyInvocationHandlerBase.java:207)
>at
>org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerB
>ase.invoke(SessionProxyInvocationHandlerBase.java:164)
>at $Proxy6.insertEvent(Unknown Source) at
>br.com.todobpo.lam.ejb.test.Authenticate.authenticationOk(Authenticate.j
>ava:70) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>at
>sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
>a:39) at
>sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
>Impl.java:25) at java.lang.reflect.Method.invoke(Method.java:597)
>at
>org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMet
>hod.java:44) at
>org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallab
>le.java:15) at
>org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMetho
>d.java:41) at
>org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod
>.java:20) at
>org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner
>.java:76) at
>org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner
>.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>at
>org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4Tes
>tReference.java:46) at
>org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.ja
>va:38) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
>stRunner.java:467) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
>stRunner.java:683) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRun
>ner.java:390) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRu
>nner.java:197) at
>org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteIn
>terceptor.java:72) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropa
>gationInterceptor.java:61) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.security.client.SecurityClientInterceptor.invoke(Security
>ClientInterceptor.java:65) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at
>org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.jav
>a:74) at
>org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.jav
>a:102) at org.jboss.aspects.remoting.PojiProxy.invoke(PojiProxy.java:62)
>at $Proxy7.invoke(Unknown Source) at
>org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerB
>ase.invoke(SessionProxyInvocationHandlerBase.java:207)
>at
>org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerB
>ase.invoke(SessionProxyInvocationHandlerBase.java:164)
>at $Proxy6.insertEvent(Unknown Source) at
>br.com.todobpo.lam.ejb.test.Authenticate.authenticationOk(Authenticate.j
>ava:70) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>at
>sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
>a:39) at
>sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
>Impl.java:25) at java.lang.reflect.Method.invoke(Method.java:597)
>at
>org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMet
>hod.java:44) at
>org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallab
>le.java:15) at
>org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMetho
>d.java:41) at
>org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod
>.java:20) at
>org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner
>.java:76) at
>org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner
>.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>at
>org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4Tes
>tReference.java:46) at
>org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.ja
>va:38) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
>stRunner.java:467) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
>stRunner.java:683) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRun
>ner.java:390) at
>org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRu
>nner.java:197)

>c) handleQuery can either receive an EventFactHandle or a
>DisconnectedFactHandle, without no apparent pattern. For the later case
>(DisconnectedFactHandle), the returned class lacks a useful isValid()
>method (the current implementation only throws an exception), thus we
>are unable to check the returned object before using it;

>d) finally, we noticed that all mentioned errors happens only when we
>set the real time clock in the KnowledgeSessionConfiguration object.
>Using the pseudo clock, there are no runtime errors and the object
>expiration behavior appears to be correct, like in 5.0.1.

>So, after all this information, we have a couple questions:

>1) Is really correct to assume that after an event expiration the object
>reference will always be null (as observed up to version 5.0.1) ? If
>not, how can we determine the event associated object sanity ? 2) Why
>starting from version 5.1.0 we started to observe the occurrence of
>DisconnectedFactHandle ? Can this detail be safely ignored, or is this a
>sign that something went wrong when trying to retrieve the event ?
>3) Is there something flawed in our presented approach ? Or did we bump
>into a new bug ?

>Any help is apreciated.

>Carlos


Esta mensagem pode conter informa??o confidencial e/ou privilegiada, sendo seu sigilo protegido por lei. Se voc? n?o for o destinat?rio ou a pessoa autorizada a receber esta mensagem, n?o pode usar, copiar ou divulgar as informa??es nela contidas ou tomar qualquer a??o baseada nessas informa??es. Se voc? recebeu esta mensagem por engano, por favor avise imediatamente ao remetente, respondendo o e-mail e em seguida apague-o. Agradecemos sua coopera??o.

This message may contain confidential and/or privileged information, being the sigil protected by law. If you are not the addressee or authorized to receive this for the addressee, you must not use, copy, disclose or take any action based on this message or any information herein. If you have received this message in error, please advise the sender immediately by reply e-mail and delete this message. Thank you for your cooperation.




More information about the rules-users mailing list