4 Replies Latest reply on Nov 26, 2013 6:22 AM by ipage

    NullPointerException reading persisted session

    jay.guidos-bidstrading.com

      Hi All,

       

      I am seeing an NPE when trying to load a persisted session.  The session has a few Drools rules and one active process.  One of the rules has a where clause that references a global variable:

       

      package com.bids.workflow

      dialect  "mvel"

      import com.bids.workflow.model.*

      global com.bids.workflow.db.DBSession dbSession

      rule "Load trading day data"

          when

              not CalendarDay()

              $calendarDay : CalendarDay() from dbSession.getCalendarDay()

          then

              insert( $calendarDay );

              System.out.println("Made a calendar day");

      end

       

      When I create a process instance this rule (and others) fires because of my FireUntilHalt command.  While the process is running I persist it and dispose() the session. I then start a second program that loads the session which loads the session and continues to wait for the process to complete.  During the load I get an exception (bottom of discussion).  The NPE is complaining that the global variable is not set, but I have not had the chance to set it yet. I don't think global variables get persisted into the session (am I right?) and the NPE happens before I get access to the session.

       

      How do I get the global defined before loading the session from persistent storage?

       

      Jay

       

      java.lang.RuntimeException: Unable to load session snapshot

        at org.drools.persistence.SessionMarshallingHelper.loadSnapshot(SessionMarshallingHelper.java:96)

        at org.drools.persistence.SingleSessionCommandService.initKsession(SingleSessionCommandService.java:253)

        at org.drools.persistence.SingleSessionCommandService.<init>(SingleSessionCommandService.java:195)

        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

        at org.drools.persistence.jpa.KnowledgeStoreServiceImpl.buildCommandService(KnowledgeStoreServiceImpl.java:100)

        at org.drools.persistence.jpa.KnowledgeStoreServiceImpl.loadStatefulKnowledgeSession(KnowledgeStoreServiceImpl.java:83)

        at org.drools.persistence.jpa.JPAKnowledgeService.loadStatefulKnowledgeSession(JPAKnowledgeService.java:131)

        at org.drools.container.spring.beans.StatefulKnowledgeSessionBeanFactory.internalAfterPropertiesSet(StatefulKnowledgeSessionBeanFactory.java:80)

        at org.drools.container.spring.beans.AbstractKnowledgeSessionBeanFactory.afterPropertiesSet(AbstractKnowledgeSessionBeanFactory.java:129)

        at com.bids.workflow.drools.BidsKnowledgeSessionFactory.loadSession(BidsKnowledgeSessionFactory.java:56)

        at com.bids.workflow.drools.BidsKnowledgeSessionFactory$loadSession.call(Unknown Source)

        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)

        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)

        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)

        at com.bids.workflow.ProcessRunner.loadSession(ProcessRunner.groovy:44)

        at com.bids.workflow.SynchronousProcessRunner.super$2$loadSession(SynchronousProcessRunner.groovy)

        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

        at java.lang.reflect.Method.invoke(Method.java:597)

        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)

        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)

        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1085)

        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:128)

        at com.bids.workflow.SynchronousProcessRunner.loadSession(SynchronousProcessRunner.groovy:32)

        at com.bids.workflow.SynchronousProcessRunner$loadSession.call(Unknown Source)

        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)

        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)

        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)

        at com.bids.workflow.ProcessTests.fromNotEmpty(ProcessTests.groovy:66)

        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

        at java.lang.reflect.Method.invoke(Method.java:597)

        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)

        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)

        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)

        at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)

        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)

        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)

        at org.jbpm.test.KnowledgeSessionCleanup$1.evaluate(KnowledgeSessionCleanup.java:28)

        at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)

        at org.junit.rules.RunRules.evaluate(RunRules.java:20)

        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)

        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)

        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)

        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)

        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)

        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)

        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)

        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)

        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)

        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)

        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)

        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)

        at org.junit.runners.Suite.runChild(Suite.java:127)

        at org.junit.runners.Suite.runChild(Suite.java:26)

        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)

        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)

        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)

        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)

        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)

        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)

        at org.junit.runner.JUnitCore.run(JUnitCore.java:160)

        at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)

        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)

        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)

      Caused by: [Error: null pointer: dbSession.getCalendarDay()]

      [Near : {... dbSession.getCalendarDay() ....}]

                   ^

      [Line: 1, Column: 1]

        at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:431)

        at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:143)

        at org.mvel2.ast.ASTNode.optimize(ASTNode.java:159)

        at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115)

        at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)

        at org.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123)

        at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119)

        at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:113)

        at org.mvel2.MVEL.executeExpression(MVEL.java:942)

        at org.drools.base.dataproviders.MVELDataProvider.getResults(MVELDataProvider.java:111)

        at org.drools.reteoo.FromNode.assertLeftTuple(FromNode.java:150)

        at org.drools.reteoo.SingleLeftTupleSinkAdapter.doPropagateAssertLeftTuple(SingleLeftTupleSinkAdapter.java:196)

        at org.drools.reteoo.SingleLeftTupleSinkAdapter.propagateAssertLeftTuple(SingleLeftTupleSinkAdapter.java:85)

        at org.drools.reteoo.NotNode.assertLeftTuple(NotNode.java:98)

        at org.drools.reteoo.CompositeLeftTupleSinkAdapter.doPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:232)

        at org.drools.reteoo.CompositeLeftTupleSinkAdapter.createAndPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:116)

        at org.drools.reteoo.LeftInputAdapterNode.assertObject(LeftInputAdapterNode.java:154)

        at org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:59)

        at org.drools.reteoo.ObjectTypeNode.assertObject(ObjectTypeNode.java:235)

        at org.drools.reteoo.EntryPointNode.assertObject(EntryPointNode.java:240)

        at org.drools.marshalling.impl.ProtobufInputMarshaller.assertHandleIntoOTN(ProtobufInputMarshaller.java:477)

        at org.drools.marshalling.impl.ProtobufInputMarshaller.readInitialFactHandle(ProtobufInputMarshaller.java:377)

        at org.drools.marshalling.impl.ProtobufInputMarshaller.readSession(ProtobufInputMarshaller.java:250)

        at org.drools.marshalling.impl.ProtobufInputMarshaller.readSession(ProtobufInputMarshaller.java:158)

        at org.drools.marshalling.impl.ProtobufMarshaller.unmarshall(ProtobufMarshaller.java:117)

        at org.drools.persistence.SessionMarshallingHelper.loadSnapshot(SessionMarshallingHelper.java:91)

        ... 71 more

      Caused by: java.lang.NullPointerException

        at org.mvel2.optimizers.impl.refl.Refle

        • 1. Re: NullPointerException reading persisted session
          swiderski.maciej

          could it be that fire until halt thread is still alive and tries to fire the rule before the ksession is actually ready to be used? Please make sure to shut it down before you dispose the ksession.

          And you're right globals are not persisted with ksession.

           

          HTH

          • 2. Re: NullPointerException reading persisted session
            jay.guidos-bidstrading.com

            Hi Maciej,

             

            The java program that tries to read the persisted session is not the same one that persisted the session.  It is run about 15 min after the first java program exits.

             

            I managed to stop the NPE by removing the where clause in the above Drools rule that referenced the global, so to me this appears to be a validation bug.  By the way, I don't see any API for killing off the FireUntilHaltCommand thread before I call dispose() on the session.  From the code, you don't even keep a reference to the thread that is calling session.fireUntilHalt().  Is there some other way to terminate this thread before calling dispose()?

             

            Jay

            • 3. Re: NullPointerException reading persisted session
              swiderski.maciej

              Jay, there is halt() method on the ksession that allows you to stop the constantly firing rules behavior after using fireUntilHalt() method. Try using it before you dispose ksession and check if that makes any difference.

              I would be very surprised if that validation bug would be present as this is quite common feature but never say never ...

               

              HTH

              • 4. Re: NullPointerException reading persisted session
                ipage

                I'm seeing the same issue.  We are persisting the session in order to recover from failures, so halting the session won't be an option.  Does anyone know if there's any way to inject the global object again before the session starts running after it's been loaded?  Or if there's a way to save the global ojects?

                 

                Thanks,

                Ian