PDA

View Full Version : Multi-Thread Exception



wangxp
Nov 17th, 2007, 08:09 AM
I use HibernateJobDao and HibernateStepDao to save or update the status of Job and Step. And I use SimpleAsyncTaskExecutor to process my business logic. E.g. I generate 5 threads to process my records. I found every thread will update the status and version field in the table BATCH_Job / BATCH_Step/ BATCH_JOB_EXECUTION/ BATCH_STEP_EXECUTION. So I get a StaleObjectStateException.



21:50:30,361 INFO [STDOUT] 21:50:30,351[ERROR] def.AbstractFlushingEventListener :(301 ) - 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.springframework.batch.core.domain.StepInstance #0]
at org.hibernate.persister.entity.AbstractEntityPersi ster.check(AbstractEntityPersister.java:1765)
at org.hibernate.persister.entity.AbstractEntityPersi ster.update(AbstractEntityPersister.java:2407)
at org.hibernate.persister.entity.AbstractEntityPersi ster.updateOrInsert(AbstractEntityPersister.java:2 307)
at org.hibernate.persister.entity.AbstractEntityPersi ster.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(En tityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQue ue.java:250)
at org.hibernate.engine.ActionQueue.executeActions(Ac tionQueue.java:234)
at org.hibernate.engine.ActionQueue.executeActions(Ac tionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListe ner.performExecutions(AbstractFlushingEventListene r.java:298)
at org.hibernate.event.def.DefaultFlushEventListener. onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.j ava:1000)
at org.springframework.orm.hibernate3.SpringSessionSy nchronization.beforeCommit(SpringSessionSynchroniz ation.java:126)
at org.springframework.transaction.support.Transactio nSynchronizationUtils.triggerBeforeCommit(Transact ionSynchronizationUtils.java:48)
at org.springframework.transaction.support.AbstractPl atformTransactionManager.triggerBeforeCommit(Abstr actPlatformTransactionManager.java:835)
at org.springframework.transaction.support.AbstractPl atformTransactionManager.processCommit(AbstractPla tformTransactionManager.java:645)
at org.springframework.transaction.support.AbstractPl atformTransactionManager.commit(AbstractPlatformTr ansactionManager.java:632)
at org.springframework.transaction.support.Transactio nTemplate.execute(TransactionTemplate.java:140)
at org.springframework.batch.execution.step.simple.Si mpleStepExecutor$1.doInIteration(SimpleStepExecuto r.java:203)
at org.springframework.batch.repeat.support.TaskExecu torRepeatTemplate$ExecutingRunnable.run(TaskExecut orRepeatTemplate.java:218)
at java.lang.Thread.run(Thread.java:595)


I use JTA transaction manager and JNDI database , but it doesn't work. If I use SyncTaskExecutor to process the records one by one, everything will be fine.

wangxp
Nov 17th, 2007, 08:13 AM
Here is my code snippet:



<bean id="demoJob" class="org.springframework.batch.core.configuration.JobCo nfiguration">
<property name="restartable" value="true"/>
<property name="steps">
<bean id="step1" class="org.springframework.batch.execution.step.SimpleSte pConfiguration">
<constructor-arg>
<bean class="org.springframework.batch.execution.tasklet.ItemPr oviderProcessTasklet">
<property name="itemProvider">
<bean class="org.springframework.batch.item.provider.ListItemPr ovider">
<constructor-arg>
<list>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
<value>5</value>
</list>
</constructor-arg>
</bean>
</property>
<property name="itemProcessor">
<bean class="org.springframework.batch.execution.launch.EmptyIt emProcessor"/>
</property>
<property name="retryPolicy">
<bean class="org.springframework.batch.retry.policy.NeverRetryP olicy"/>
</property>
</bean>
</constructor-arg>
<property name="commitInterval" value="1000" />
<property name="saveRestartData" value="true"/>
</bean>
</property>
</bean>

<bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJ obLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="jobConfigurationLocator"
ref="jobConfigurationRegistry" />
<property name="jobExecutor" ref="jobExecutor" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecu tor"/>
</property>
</bean>

<aop:config>
<aop:advisor
pointcut="execution(* org.springframework.batch.execution..*Repository+. *(..))"
advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>

<bean id="jobExecutor"
class="org.springframework.batch.execution.job.DefaultJob Executor">
<property name="jobRepository" ref="jobRepository" />
<property name="stepExecutorFactory">
<bean
class="org.springframework.batch.execution.step.Prototype BeanStepExecutorFactory">
<property name="stepExecutorName" value="stepExecutor" />
</bean>
</property>
</bean>

<bean id="stepExecutor"
class="org.springframework.batch.execution.step.simple.Si mpleStepExecutor"
scope="prototype">
<property name="transactionManager" ref="transactionManager" />
<property name="repository" ref="jobRepository" />
<!-- default use RepeatTemplate -->
<property name="stepOperations">
<bean class="org.springframework.batch.repeat.support.TaskExecu torRepeatTemplate">
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecu tor"/>

</property>
<property name="interceptor">
<bean class="org.springframework.batch.repeat.interceptor.Appli cationEventPublisherRepeatInterceptor" />
</property>
</bean>
</property>
</bean>

wangxp
Nov 17th, 2007, 08:24 AM
It looks like that

http://opensource.atlassian.com/projects/spring/browse/BATCH-170