14 Replies Latest reply on Jan 8, 2009 5:09 AM by Olivier Debels

    jBPM 3.3.0GA and Oracle causing StaleObjectStateException

    Petr Nejedly Newbie

      Hi guys,

      I've upgraded from 3.2.3 to 3.3.0.GA (Oracle) and getting this exception after creating a process instance :

      Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#3591]
       at org.hibernate.persister.entity.AbstractEntityPersister.forceVersionIncrement(AbstractEntityPersister.java:1239)
       at org.hibernate.event.def.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:82)
       at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:64)
       at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:584)
       at org.hibernate.impl.SessionImpl.lock(SessionImpl.java:576)
       at org.jbpm.graph.node.Join.execute(Join.java:121)
       at org.jbpm.graph.def.Node.enter(Node.java:314)
       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:585)
       at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:173)
       at org.jbpm.graph.def.Node_$$_javassist_179.enter(Node_$$_javassist_179.java)
       at org.jbpm.graph.def.Transition.take(Transition.java:151)
       at org.jbpm.graph.def.Node.leave(Node.java:389)
       at org.jbpm.graph.def.Node.leave(Node.java:353)
       at org.jbpm.graph.exe.ExecutionContext.leaveNode(ExecutionContext.java:120)
       at uk.co.ondemand.portal.workflow.actions.AbstractNodeActionHandler.execute(AbstractNodeActionHandler.java:50)
       at org.jbpm.graph.def.Action.execute(Action.java:129)
       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:585)
       at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:173)
       at org.jbpm.graph.def.Action_$$_javassist_193.execute(Action_$$_javassist_193.java)
       at org.jboss.seam.bpm.SeamUserCodeInterceptor$1.process(SeamUserCodeInterceptor.java:80)
       at org.jboss.seam.bpm.SeamUserCodeInterceptor$ContextualCall.run(SeamUserCodeInterceptor.java:33)
       at org.jboss.seam.bpm.SeamUserCodeInterceptor.executeAction(SeamUserCodeInterceptor.java:74)
       at org.jbpm.graph.def.GraphElement.executeAction(GraphElement.java:254)
       ... 171 more


      The process is here:


      <?xml version="1.0" encoding="UTF-8"?>
      
      <process-definition xmlns="" name="testProcess">
      
      
       <swimlane name="test_swimlane">
       <assignment pooled-actors="gQAUsers"></assignment>
       </swimlane>
      
      
       <start-state name="start-state1">
       <transition to="automated node"></transition>
       </start-state>
      
      
       <node name="automated node">
       <action name="write to db 1" class="uk.co.ondemand.cmm.service.workflow.handlers.MyActionHandler"></action>
       <transition to="fork1"></transition>
       </node>
      
       <task-node name="confirm node">
       <task name="task1" duedate="#{dueDate} + 5 business days" swimlane="test_swimlane">
       <description>
       This is task description
       </description>
       <controller>
       <variable access="read,write" name="myVariable" mapped-name="myTaskVariable"></variable>
       </controller>
       </task>
       <transition to="join1"></transition>
       </task-node>
      
       <node name="write">
       <action class="uk.co.ondemand.cmm.service.workflow.handlers.MyActionHandler"></action>
       <transition to="end-state1"></transition>
       </node>
      
       <fork name="fork1">
       <transition to="confirm node" name="confirm"></transition>
       <transition to="automated node 2" name="auto"></transition>
       </fork>
      
       <join name="join1">
       <transition to="write"></transition>
       </join>
      
       <node name="automated node 2">
       <action class="uk.co.ondemand.cmm.service.workflow.handlers.MyActionHandler"></action>
       <transition to="join1"></transition>
       </node>
      
      
       <end-state name="end-state1"></end-state>
      
      
      </process-definition>


      I found this issue: https://jira.jboss.org/jira/browse/JBPM-1772 which looks like a flush() has been removed which previously fixed an Oracle bug. Could this be the problem?

      Cheers,

      Petr

        • 1. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
          Ronald van Kuijk Master

          Yes, could very well be the case. jBPM 3.3 has no QA setup for Oracle (yet) so that might be why it was missed. Although Tom states in JBPM-1772 that he'll re-introduce the flush, it does not seem to be in the code. Please file a re-open https://jira.jboss.org/jira/browse/JBPM-1085 and refer top this forum post.

          If you could try from source and add a flush it would even be better.

          • 2. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
            Petr Nejedly Newbie

            I'll re-open the JIRA, thanks. I tried to put back in the flush() into thetrunk code but getting this exception:

            14:57:10,318 ERROR [GraphElement] action threw exception: collection [org.jbpm.bytes.ByteArray.byteBlocks] was not processed by flush()
            org.hibernate.AssertionFailure: collection [org.jbpm.bytes.ByteArray.byteBlocks] was not processed by flush()
             at org.hibernate.engine.CollectionEntry.postFlush(CollectionEntry.java:205)
             at org.hibernate.event.def.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:333)
             at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:28)
             at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
             at org.jbpm.graph.node.Join.execute(Join.java:121)
             at org.jbpm.graph.def.Node.enter(Node.java:314)
             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:585)
             at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:173)
             at org.jbpm.graph.def.Node_$$_javassist_179.enter(Node_$$_javassist_179.java)
             at org.jbpm.graph.def.Transition.take(Transition.java:151)
             at org.jbpm.graph.def.Node.leave(Node.java:389)
             at org.jbpm.graph.exe.Token.signal(Token.java:192)
             at org.jbpm.graph.exe.Token.signal(Token.java:140)
             at uk.co.ondemand.portal.workflow.actions.AbstractNodeActionHandler.execute(AbstractNodeActionHandler.java:50)
             at org.jbpm.graph.def.Action.execute(Action.java:129)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)........



            • 4. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
              Martin Weiler Apprentice

              Petr,

              please try to explicitly set the lock mode on the join:

              <join name="join1" lock="UPGRADE">

              and let us know how it works for you.

              • 5. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                Jose Rodriguez Newbie

                I have a similar problem, although in my case the nodes have async='true'.
                The exception I get is


                org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#48]
                 at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1769)
                 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2412)
                 at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2312)
                 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612)
                 at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:96)
                 at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
                 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
                 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
                 at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
                 at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
                 at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
                 at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
                 at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
                 at org.jbpm.persistence.db.DbPersistenceService.commit(DbPersistenceService.java:262)
                 at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:218)
                 at org.jbpm.svc.Services.close(Services.java:236)
                 at org.jbpm.JbpmContext.close(JbpmContext.java:136)
                 at org.jbpm.job.executor.JobExecutorThread.executeJob(JobExecutorThread.java:190)
                 at org.jbpm.job.executor.JobExecutorThread.run(JobExecutorThread.java:60)
                



                I have tried::
                - all the possible isolation levels (as suggested in the forum).
                - the different "lock" options in the join and in the fork.
                - tried to put back the flush that Tom removed some time ago in the Join class.
                - selected the correct hibernate dialect.

                But I still have the same issue.

                The StaleObjectStateException is making one of the nodes to be executed twice, but if you have a more complicated graph, it's making a part of the graph not to be executed at all.

                Any idea about how to proceed ? I saw that the issue JBPM-1757 was Deferred to 3.3.2 planned for May 2009. Is there any way that we could get the Join and Fork with parallel processing of nodes (async=true) before?

                Does anyone have a similar configuration running in Oracle with 3.3.0GA or is it something that simply is not working yet due to a regression error ?

                I would really appreciate any help, as I have been investigating the issue, reading the forum entries, and trying different configurations for almost a week, and I am still not able to make it work.






                • 7. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                  Jose Rodriguez Newbie

                  Hi Ronald,

                  Thanks a lot for the suggestion. With async=exclusive I don't get any exception at all. Hoever, the actions inside the nodes, are executed sequentially and not in parallel.

                  I am deploying the framework from a class, and have running the JobExecutor with several threads in a different JVM for having parallel processing of the nodes and actions..

                  Any other suggestion ?


                  • 8. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                    Ronald van Kuijk Master

                    I did not want to suggest it is a solution but can it be your actions are quick to finish after each other? Can you post what they do? Or maybe make a test that have them end with seconds in between?

                    • 9. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                      Jose Rodriguez Newbie

                      Hi Ronald,

                      I really appreciate all suggestions (it doesn't matter if they are a final solution or just a hack to make it work).

                      I have just tried to introduce a delay of 8 seconds in one of the actions of the parallel nodes, and I still get the SOE.

                      I believe the issue is related with the version column of the father node (token table). The moment a child node is created it will have a reference to the parent node, if we have two children they will have an identical copy/reference to the parent. The parent node is updated from both children when they arrive to the join, so I believe it doesn't matter the order or the delay between them, as the copy of one of the child will be out of date the moment is finished (the other node will have updated it when it finishes and arrives to the join) and therefore get the SOE.

                      I have done a small test changing manually the value of the version column of the parent token, if I decrease it by 1, after one of the child has finished and the other is waiting, I don't get the SOE.



                      • 10. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                        Ronald van Kuijk Master

                        Thanks for trying... I'm not sure the fork has the same lock options, I should look in the code.

                        • 11. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                          Jose Rodriguez Newbie

                          Ok, here it goes the way we made it work.

                          All the nodes are async='true'
                          All the forks are async='true'
                          All the joins are async='true' and lock='UPGRADE'
                          The graph has to be legal (have certain simmetry) As explained in http://www.jboss.com/index.html?module=bb&op=viewtopic&t=147553. If the graph is not legal, and the joins are async you probably will experience that some branches of the workflow are not executed.

                          In case there is anyone interested I will post the complete processdefinition.xml.

                          Some of the settings above might not be needed (I think the async='true' in the forks makes no difference)


                          • 12. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                            Petr Nejedly Newbie

                             

                            "mputz" wrote:

                            please try to explicitly set the lock mode on the join:
                            <join name="join1" lock="UPGRADE">

                            and let us know how it works for you.


                            Martin, thanks, this worked. Is this a recommended way of dealing with all joins or is it just a temporary workaround (haven't seen support for it int the designer) ?

                            Petr

                            • 13. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                              Olivier Debels Newbie

                              I stumbled into the same problem (and some others) while trying to upgrade.

                              Does this mean that when upgrading to the 3.3 version of jbpm, all process definition with joins need to be changed (lockmode upgrade needs to be added).

                              By default lockmode seems to be 'force' which gives problems with versioned items...

                              • 14. Re: jBPM 3.3.0GA and Oracle causing StaleObjectStateExceptio
                                Olivier Debels Newbie

                                Digged into it a bit further.

                                Seems to me that there are cases for which FORCE lock will never work.

                                Let me try to explain:

                                If you have a process with a fork join where the parallel branches contain a node which performs a query.

                                If you can run from start to the join in the same transaction you get into trouble with the FORCE lock.

                                What happens is:

                                - Main token gets created and persisted - version is 0
                                - Fork join is triggered, 2 child tokens are created.
                                - when query is performed in a node in one of the branches, an auto flush is done. This will increment the version of the parent lock to 1, since this one changed since the beginning of the process (some dates are filled in,...)
                                - When you arrive in the fork, the lock will try to increase the version to 1, which fails since it is already 1.

                                So my problem was not related to any bug in oracle but just due to the default locking and the fact that in my unit test I run through the complete process in one transaction.

                                In these cases you need to set lock to upgrade.

                                In other cases you can leave the default locking (force lock).