-
Jul 8th, 2011, 09:53 AM
#1
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
log-1.zip
-
Jul 11th, 2011, 02:26 AM
#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?
-
Jul 11th, 2011, 11:15 AM
#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.
-
Jul 11th, 2011, 03:04 PM
#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.
-
Jul 12th, 2011, 03:37 AM
#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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules