8 Replies Latest reply on Mar 14, 2008 10:36 PM by tak2

    StaleObjectStateException in a Fork with states

    jfbenck

      Hi,

      I'm working a jBPM implementation with the following characteristics:

      1) All calls go to external systems, so we use states for modeling the different steps.
      2) We might be using forks in our processes, which thus contain states.
      3) The external systems store their reply in a variable attached to a token.


      Without the usage of forks, jBPM works fine. I've been creating some tests to simulate the behaviour of our backend systems by using various threads. Whenever two or more threads within a fork try to signal their respective token at the same time, the second thread throws a hibernate StateObjectStateException when calling JbpmContext.close().

      To signal jBPM to continue processing of a state from the external system (simulated by the thread) we use the following code:

      JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
      try {
      ProcessInstance processInstance = jbpmContext.getProcessInstance(callInfo.getProcessid());
      Token token = jbpmContext.getTokenForUpdate(callInfo.getTokenid());
      token.setProcessInstance(processInstance);
      processInstance.getContextInstance().addVariables(contextData,token);
      
      token.signal();
      } finally {
      jbpmContext.close();
      }
      


      I have to do token.setProcessInstance(), as the process instance == null when calling getTokenForUpdate(), which results in a NPE on token.signal().

      I've been looking through mailing lists, documentation and Google to find any info about this problem. Unfortunately to no avail. I've got the following questions:

      1) Is my process instance/token retrieval code correct? The jBPM examples which some with the source only contain a quick-and-dirty solution?
      2) Should I take care of synchronization myself or is jBPM supposed to handle this (as I expect) and have I run into a bug?


      Thanks for your time.

      Jeroen

        • 1. Re: StaleObjectStateException in a Fork with states

          You might find the discussions in the "Token.signal() ---> 2 tokens?" thread useful...

          • 2. Re: StaleObjectStateException in a Fork with states
            jfbenck

            pojomonkey, thanks for the reply. However, I don't think it helped me. My current code signal()s the tokens within the fork, and should thus be correct. In fact, perhaps to clarify, when the signal()s are executed in sequence, no exceptions occur.

            Oh, and I'm using jBPM 3.1.4 btw

            • 3. Re: StaleObjectStateException in a Fork with states
              kukeltje

              look in the jira... there is info there about SOE....

              • 4. Re: StaleObjectStateException in a Fork with states
                jeffj55374

                We too use forks, joins and sub proceses extensively with async nodes. StaleObjectExecption have been in issue for us with JBPM 3.2.2.

                Our problem isn't in the fork, but the join that follows.

                In November a fix was made to Join.java where they added a flush. I pulled a copy of this file into our code base. There is a Jira issue for this. Tom Baeyens checked in the code in November. But I can't find the issue number. If you look at the CVS history for Join.java you should see the change.

                This significantly helped elimate the most of our StaleObjectExceptions. We would get a StaleObjectException frequently when two or more async sub-processes finished and both their next transitions were into the same Join node.

                We just discovered another issue with Join and StaleObjectExcption. If two or more of the transitions coming into the join are executed at the same time so the Join.execute method is called by multiple threads simultaneously. Each thread tries to updated the parent token and a StaleObjectException results. We are trying to create a unit test that reliable produces the problem. At the moment it is a race condition so it doesn't happen everytime.

                Hope this helps.

                • 5. Re: StaleObjectStateException in a Fork with states

                  Are you using at least READ_COMMITTED isolation in the DB?

                  If not, I think that before you finish, you'll find that you need to.

                  See http://jira.jboss.org/jira/browse/JBPM-983

                  • 6. Re: StaleObjectStateException in a Fork with states
                    jfbenck

                    estaub> Already using READ_COMMITTED, unfortunately no effect
                    jeffj55374> Thanks for the info, upgrading jBPM may not be an option, so we'll have to resort to writing some custom locking code I guess...

                    • 7. Re: StaleObjectStateException in a Fork with states
                      kukeltje

                       

                      upgrading jBPM may not be an option, so we'll have to resort to writing some custom locking code I guess...


                      hmmm.... upgrading to a stable, released new version of jBPM is no option, patching an older version with custom, not tested, temporary code is? what are you running? 3.0? since upgrading from 3.1 is fairly easy.

                      • 8. Re: StaleObjectStateException in a Fork with states
                        tak2

                        Was this issue for the join with multi-threads fixed?
                        I am facing same issue, too.

                        My application server is Oracle, IBM, and Fujitsu with Oracle 10g DB.
                        I have two parallel asynchronous nodes between fork and join, and these node are executed by different thread via MDB.

                        Here is what I understood from code so far.
                        In execute method in Join node, when it call session.lock(parentToken, LockMode.FORCE), hibernate seems like incrementing version (why for locking???), and same operation to the same object in another thread throw StaleObjectStateException.
                        This is basic feature we need for concurrent operation, and very easy to implement with SQL based programming with "select for update".

                        I tried to LockMode.UPGRADE, but it's same.

                        So, I tried to called "select for update" against parent Token record instead of using session.lock(), and this operation worked as I expected, but when committing transaction on JbpmContext.close(), later thread still throw StaleObjectStateException.

                        OK, then I load object after getting lock (after select for update) by session.load(parentToken.getId(), Token.class, LockMode.UPGRADE), but surprisingly the parentToken object returned still had old version, even DB record was committed and version was incremented.

                        Does someone solve this issue?
                        or am I doing something wrong?