Uploaded image for project: 'jBPM'
  1. jBPM
  2. JBPM-3902

Avoid updating ProcessInstanceInfo in JPAProcessInstanceManager.getProcessInstance()

    XMLWordPrintable

Details

    • Feature Request
    • Resolution: Done
    • Major
    • jBPM 6.0.0.Beta5
    • jBPM 5.4
    • Persistence
    • None

    Description

      Currently JPAProcessInstanceManager.getProcessInstance() calls ProcessInstanceInfo.updateLastReadDate() so it may result in StaleObjectStateExcpetion even with ksession.getProcessInstance() when there are concurrent accesses to the same process instance.

      37762 04/01 12:15:40,813[pool-3-thread-9] ERROR event.def.AbstractFlushingEventListener.performExecutions  - Could not synchronize database state with session
      org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.persistence.processinstance.ProcessInstanceInfo#16]
              at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1782)
              at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2425)
              at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2325)
              at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2625)
              at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
              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:321)
              at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
              at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
              at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
              at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:504)
              at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:478)
              at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:193)
              at bitronix.tm.BitronixTransactionManager.commit(BitronixTransactionManager.java:120)
              at org.drools.persistence.jta.JtaTransactionManager.commit(JtaTransactionManager.java:179)
              at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:363)
              at org.drools.command.impl.CommandBasedStatefulKnowledgeSession.getProcessInstance(CommandBasedStatefulKnowledgeSession.java:125)
              at com.sample.ProcessMainJPA$1.run(ProcessMainJPA.java:61)
      

      Kris wrote:
      ==========
      Whenever a process instance is retrieved when using persistence, the
      process instance info is indeed updated with a new last read date. The
      most important reason for doing this is for marking the process instance
      info object as "dirty" so that when the transaction commits, the process
      instance info object (more specifically the processInstanceByteArray)
      will be updated with the latest version of the process instance (using
      the @PreUpdate update() method).

      Note that, if a process instance is only retrieved and not changed, this
      is technically not necessary, but if the process instance is updated by
      the engine after it is retrieved, this update will obviously be necessary.

      I do agree that it involves a small overhead if you're only reading
      state (assuming you don't want to use lastReadDate as that will
      obviously only work if you update every time you read) but since most
      invocations do involve changes to the process instance as well
      afterwards, and it's technically not that easy to use another way to
      determine when a process instance should be marked dirty (as persistence
      is done as a wrapper around the core engine), we decided to just keep
      track of the process instances loaded.

      One way I can see to optimize this would be to remove the last read date
      and, when the transaction commits, verify whether any changes were
      actually made, and if not reset the change, so no changes need to be
      committed.
      ==========

      Attachments

        Activity

          People

            kverlaen@redhat.com Kris Verlaenen
            rhn-support-tkobayas Toshiya Kobayashi
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: