4 Replies Latest reply on May 1, 2013 5:50 AM by Sanket Mohile

    Multiple ksession dispose issue

    Sanket Mohile Newbie

      Hi,

      I'm getting a WARN message when working with ksession1 even if I'm disposing ksession2.

      Following is the scenario -

       

      1. Create ksession1. Bind HT Handler 1.

      2. Start a process with HT and timer(Timer period 30s)

      3. DO NOT DISPOSE ksession1, neither the HT Handler 1.

      4. Timer continues as expected.

       

      5. Now, create ksession2. Bind HT Handler 2.

      6. Start a process with HT, no timers in this.

      7. Dispose the HT Handler 2 and ksession2 in transaction using CMTDisposeCommand. Gets disposed successfully.

      8. Timer still continues, but now I get following the WARN message on every timer tick(30s in my case)

       

      It is evident from the active timer that ksession1 is still active, no issues with that. It is just the WARN message that I am curious about.

       

       

      WARN Message

      17:27:26,945 INFO  [stdout] (pool-35-thread-1) Current Bill: 503.0

      17:27:26,945 INFO  [stdout] (pool-35-thread-1) Your bill was incremented. Total ammount: $504.0

       

      17:27:26,965 WARN  [com.arjuna.ats.jta] (pool-35-thread-1) ARJUNA016029: SynchronizationImple.afterCompletion - failed for org.drools.persistence.jta.JtaTransactionSynchronizationAdapter@1913209 with exception: java.lang.IllegalStateException: Illegal method call. This session was previously disposed.
      at org.drools.reteoo.DisposedReteooWorkingMemory.getProcessRuntime(DisposedReteooWorkingMemory.java:270) [drools-core-5.5.0.Final.jar:5.5.0.Final]
      at org.drools.impl.StatefulKnowledgeSessionImpl.getProcessRuntime(StatefulKnowledgeSessionImpl.java:874) [drools-core-5.5.0.Final.jar:5.5.0.Final]
      at org.drools.persistence.SingleSessionCommandService$SynchronizationImpl.afterCompletion(SingleSessionCommandService.java:455) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]
      at org.drools.persistence.jta.JtaTransactionSynchronizationAdapter.afterCompletion(JtaTransactionSynchronizationAdapter.java:22) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]
      at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(SynchronizationImple.java:96)
      at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.afterCompletion(TwoPhaseCoordinator.java:402)
      at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:103)
      at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:164)
      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1165)
      at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:117)
      at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
      at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:167)
      at org.drools.persistence.jta.JtaTransactionManager.commit(JtaTransactionManager.java:179) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]
      at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:376) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]
      at org.drools.persistence.jpa.JpaTimerJobInstance.call(JpaTimerJobInstance.java:34) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]
      at org.drools.persistence.jpa.JpaTimerJobInstance.call(JpaTimerJobInstance.java:14) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) [rt.jar:1.6.0_43]
      at java.util.concurrent.FutureTask.run(FutureTask.java:138) [rt.jar:1.6.0_43]
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98) [rt.jar:1.6.0_43]
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206) [rt.jar:1.6.0_43]
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) [rt.jar:1.6.0_43]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) [rt.jar:1.6.0_43]
      at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_43]

       

      17:27:27,007 WARN  [com.arjuna.ats.arjuna] (pool-35-thread-1) ARJUNA012127: TwoPhaseCoordinator.afterCompletion - returned failure for SynchronizationImple< 0:ffff0ae1a951:66eea469:51640136:10c, org.drools.persistence.jta.JtaTransactionSynchronizationAdapter@1913209 >

        • 2. Re: Multiple ksession dispose issue
          Shobhit Tyagi Master

          Exception says session was disposed. Can you share your code please?

          • 3. Re: Multiple ksession dispose issue
            Sanket Mohile Newbie

            Thought to dig more into this..... And finally found my culprit.... And a temporary solution to it....

            Here is all of it :-

             

            1. This "WARN" msg would come only in case of a process with a timer node.

             

            2. After some more investigation, found that on each timer tick "org.drools.persistence.jpa.JDKCallableJobCommand" gets executed by JpaTimerJobInstance and it returns me CommandService of the disposed ksession. Hence the WARN message.

             

            org.drools.persistence.jpa.JpaTimerJobInstance.java

            ...

            ...

            public Void call() throws Exception {

                    try {

                        JDKCallableJobCommand command = new JDKCallableJobCommand( this );

                         /* The following line returns me the command service object of the disposed ksession */

                        CommandService commandService = ((AcceptsTimerJobFactoryManager)scheduler).getTimerJobFactoryManager().getCommandService();

                        commandService.execute( command );

                        return null;

                    } catch( Exception e ) {

                        logger.error("Unable to execute timer job!", e);

                        throw e;

                    }

                }

              ...

               ...

             

            Reason? - Probably because we use the same SessionConfiguration to load both our session.... Ref: Read Comment by "Sebastian Calbaza" on https://issues.jboss.org/browse/JBPM-3827

            So even after I dispose my ksession, the related SingleSessionCommandService is still active somewhere with a dead ksession. And the TimerJobFactoryManager class hits me with it

            Please raise a JIRA if you guys think this is an issue.

             

            3. The Workaround: In CMTDisposeCommand Class..... In the after completion method... set the CommandService object of the disposing ksession to the CommandService object of the ksession which is alive(The one you dont dispose because it has timers running on it....)

            CMTDisposeCommand.java

            ...

            ...

             

                            @Override

                            public void afterCompletion(int status) {

             

                                  /* Set the Command Service of this ksession to one in which timer process started */

                                  /* Note: My ksession object is loaded from JPAKnowledgeService, hence a typeof CommandBasedStatefulKnowledgeSession */

                                  SingleSessionCommandService commandService = (SingleSessionCommandService)((CommandBasedStatefulKnowledgeSession)ksession1).getCommandService();

                                  InternalKnowledgeRuntime ikr = (InternalKnowledgeRuntime)commandService.getStatefulKnowledgeSession();

                                  JDKTimerService timerService = (JDKTimerService)ikr.getTimerService();

                                  JpaTimeJobFactoryManager manager = (JpaTimeJobFactoryManager)timerService.getTimerJobFactoryManager();

             

                                  SingleSessionCommandService ksession2CommandService = (SingleSessionCommandService((CommandBasedStatefulKnowledgeSession)ksession2).getCommandService();

             

                                  manager.setCommandService(ksession2CommandService);

             

                                  /* Now dispose the ksession */

                                   ksession1.dispose()

                            }

             

            ...

            ...

             

            Now this solves the issue I'd report in this thread.

            Not a good option though, ideally the TimerJobFactoryManager should not return me a SingleSessionCommandService reference with a disposed ksession.

            I'll mark this as answered. But please let me know if there are better fixes/steps or I'm missing something.

             

            Thanks,

            Sanket

            • 4. Re: Multiple ksession dispose issue
              Sanket Mohile Newbie

              Better yet approach....

              Start the two ksessions with different config objects