2 Replies Latest reply on Jul 8, 2009 4:21 AM by denica.gencheva

    org.hibernate.StaleObjectStateException: Row was updated or

    denica.gencheva

      I have a "decision" node directly connected to a "join" node:

      <decision name="HasSomeProperty">
       <transition to="join1" name="Yes"></transition>
      </decision>
      <join name="join1">
      </join>

      I get the following exception during the execution of the process:
      ERROR [STDERR] org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#2280181]
       at org.hibernate.persister.entity.AbstractEntityPersister.forceVersionIncrement(AbstractEntityPersister.java:1235)
       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:116)
       at org.jbpm.graph.def.Node.enter(Node.java:319)
       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_196.enter(Node_$$_javassist_196.java)
       at org.jbpm.graph.def.Transition.take(Transition.java:151)
       at org.jbpm.graph.def.Node.leave(Node.java:394)
       at org.jbpm.graph.exe.ExecutionContext.leaveNode(ExecutionContext.java:136)
       at org.jbpm.graph.node.Decision.execute(Decision.java:152)
       at org.jbpm.graph.def.Node.enter(Node.java:319)
       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_196.enter(Node_$$_javassist_196.java)
       at org.jbpm.graph.def.Transition.take(Transition.java:151)
       at org.jbpm.graph.def.Node.leave(Node.java:394)
       at org.jbpm.graph.def.Node.leave(Node.java:369)
       at org.jbpm.graph.node.Fork.execute(Fork.java:140)
       at org.jbpm.graph.def.Node.enter(Node.java:319)
       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_196.enter(Node_$$_javassist_196.java)
       at org.jbpm.graph.def.Transition.take(Transition.java:151)
       at org.jbpm.graph.def.Node.leave(Node.java:394)
       at org.jbpm.graph.node.StartState.leave(StartState.java:70)
       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_196.leave(Node_$$_javassist_196.java)
       at org.jbpm.graph.exe.Token.signal(Token.java:195)
       at org.jbpm.graph.exe.Token.signal(Token.java:140)
       at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:271)
       ...

      The process is started from an EJB instance in JBoss AS 4.2.2. I'm using jBPM 3.2.2 and have its sources. I've found the exception is caused by the session.lock(parentToken, lockMode) statement at org.jbpm.graph.node.Join.execute(Join.java:116) because the Oracle DB (which I'm using) does not support LockMode.FORCE. During debugging, if I manually change the lockMode to UPGRADE it appears to work.

      Further looking at the Join.execute() source:
      if (session!=null) {
       LockMode lockMode = LockMode.FORCE;
       if (parentLockMode!=null) {
       lockMode = LockMode.parse(parentLockMode);
       }
       log.debug("forcing version increment on parent token "+parentToken);
       session.lock(parentToken, lockMode);
       }

      I've seen the only way to change the lockMode run-time is to set the parentLockMode member field, which I've found could be done by setting a lock="pessimistic" attribute on the "join" element (org.jbpm.graph.node.Join class):
      public void read(Element element, JpdlXmlReader jpdlReader) {
       String lock = element.attributeValue("lock");
       if ( (lock!=null)
       && (lock.equalsIgnoreCase("pessimistic"))
       ) {
       parentLockMode = LockMode.UPGRADE.toString();
       }
      }

      so I've changed the "join" definition as:
      <join name="join1" lock="pessimistic">
      </join>

      So far so good, but while debugging I've found out the Join constructor is called 4 times and only two of the instances get the read method called therefore get lock mode set to UPGRADE. And then when I start the process, the instance of the Join which is used is one where parentLockMode is null and the lock mode is FORCE so I get the same exception again.

      Why do we need LockMode.FORCE? Is it possible to change the LockMode to UPGRADE without changing jBPM source?