Announcement Announcement Module
Collapse
No announcement yet.
OptimisticLockingFailureException on JPA commit failure Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • OptimisticLockingFailureException on JPA commit failure

    Spring Batch 2.1.7
    Spring 3.0.5
    Eclipselink 1.1.1

    It appears that if the commit fails, spring batch will get an OptimisticLockingFailureException when it tries to revert the changes to the step execution. In my particular case, I have a callback through EclipseLink to update history tables before a transaction is committed. If a failure occurs during this callback, the commit fails.

    From looking through the code and the attached log file, the step execution is updated and committed before the main transaction is committed. When the commit fails, the old values for the step execution (including version) are updated to the values before the chuck started. When control returns to AbstractStep.execute(), the OptimisticLockingFailureException is thrown when the step execution is updated with the failed status because the new version had already been committed to the database.

    2011-07-06 17:40:29,494 ERROR SimpleAsyncTaskExecutor-1 [org.springframework.batch.core.step.AbstractStep] Encountered an error saving batch meta data. This job is now in an unknown state and should not be restarted.
    org.springframework.dao.OptimisticLockingFailureEx ception: Attempt to update step execution id=3225 with wrong version (35), where current version is 36
    at org.springframework.batch.core.repository.dao.Jdbc StepExecutionDao.updateStepExecution(JdbcStepExecu tionDao.java:185)
    at org.springframework.batch.core.repository.support. SimpleJobRepository.update(SimpleJobRepository.jav a:171)
    at sun.reflect.GeneratedMethodAccessor130.invoke(Unkn own Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoi npointUsingReflection(AopUtils.java:309)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.invokeJoinpoint(ReflectiveMethodInvocat ion.java:183)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :150)
    at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:110)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :172)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy77.update(Unknown Source)
    at org.springframework.batch.core.step.AbstractStep.e xecute(AbstractStep.java:244)
    at org.springframework.batch.core.job.SimpleStepHandl er.handleStep(SimpleStepHandler.java:135)
    at org.springframework.batch.core.job.flow.JobFlowExe cutor.executeStep(JobFlowExecutor.java:61)
    at org.springframework.batch.core.job.flow.support.st ate.StepState.handle(StepState.java:60)
    at org.springframework.batch.core.job.flow.support.Si mpleFlow.resume(SimpleFlow.java:144)
    at org.springframework.batch.core.job.flow.support.Si mpleFlow.start(SimpleFlow.java:124)
    at org.springframework.batch.core.job.flow.support.st ate.SplitState$1.call(SplitState.java:91)
    at org.springframework.batch.core.job.flow.support.st ate.SplitState$1.call(SplitState.java:89)
    at java.util.concurrent.FutureTask$Sync.innerRun(Futu reTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.jav a:138)
    at java.lang.Thread.run(Thread.java:662)

    https://jira.springsource.org/browse/BATCH-1767

    Attachment
    Attached Files

  • #2
    You need to flush JPA changes before Spring Batch tries to commit its own meta data. The best way to do that is in the ItemWriter. Any reason you can't do that?

    Comment


    • #3
      We are already using the JpaWriter supplied with Spring Batch which performs the flush. We have a requirement to audit all database changes and identify the changes made during a single transaction. For this reason, we implemented our auditing using an Eclipselink pre-commit hook (Hibernate can do this as well). While the transaction level auditing does not make much sense for a batch job, it is what is used by the rest of the application.

      Comment


      • #4
        I'm actually experiencing a very similar issue. Getting a OptimisticLockingFailureException when commit fails and Spring Batch tries to update the step data. I , though, use an ItemWriter as a delegate and in the write method call a DAO layer to persist the data.

        Comment


        • #5
          If you are using transaction hooks you are going to have to tread very carefully. You need to somehow ensure that the vendor hook runs before the Spring transaction synchronization, or else not use it. The easiest way would be to run your audit code in an ItemWriter or ItemWriteListener, but if you find a cleverer way and it can be exposed as a framework feature, please let us know.

          Comment


          • #6
            Having the same problem without any Transaction hooks

            Originally posted by Dave Syer View Post
            If you are using transaction hooks you are going to have to tread very carefully. You need to somehow ensure that the vendor hook runs before the Spring transaction synchronization, or else not use it. The easiest way would be to run your audit code in an ItemWriter or ItemWriteListener, but if you find a cleverer way and it can be exposed as a framework feature, please let us know.
            Hello,
            I am having the same problem using:
            - Multithreaded tasklet
            - Thread safe subclass of ItemReader, which synchronises read() method

            Anytime I get multiple simultaneous rollbacks on JPA writer, I end up with the OptimisticLockingFailureException .

            I updated :
            - https://jira.springsource.org/browse/BATCH-1767

            Reading code, I don't understand why when you restore in copy the oldVersion you also copy the version field, could you explain ?

            This issue is a blocker for us as we need multithreaded step for performance and we can have rollbacks .

            Could you suggest a workaround if any ?
            Thank you.

            Comment

            Working...
            X