Announcement Announcement Module
Collapse
No announcement yet.
Multi-Thread Exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multi-Thread Exception

    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.

    Code:
    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.AbstractEntityPersister.check(AbstractEntityPersister.java:1765)
    	at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2407)
    	at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
    	at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
    	at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
    	at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
    	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
    	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
    	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
    	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    	at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:126)
    	at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:48)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:835)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:645)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632)
    	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    	at org.springframework.batch.execution.step.simple.SimpleStepExecutor$1.doInIteration(SimpleStepExecutor.java:203)
    	at org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.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.

  • #2
    Here is my code snippet:

    Code:
    	<bean id="demoJob" class="org.springframework.batch.core.configuration.JobConfiguration">
    		<property name="restartable" value="true"/>
    		<property name="steps">
    			<bean id="step1" class="org.springframework.batch.execution.step.SimpleStepConfiguration">
    				<constructor-arg>
    					<bean class="org.springframework.batch.execution.tasklet.ItemProviderProcessTasklet">
    						<property name="itemProvider">
    							<bean class="org.springframework.batch.item.provider.ListItemProvider">
    								<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.EmptyItemProcessor"/>
    						</property>
    						<property name="retryPolicy">
    							<bean class="org.springframework.batch.retry.policy.NeverRetryPolicy"/>
    						</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.SimpleJobLauncher">
    		<property name="jobRepository" ref="jobRepository" />
    		<property name="jobConfigurationLocator"
    			ref="jobConfigurationRegistry" />
    		<property name="jobExecutor" ref="jobExecutor" />
    		<property name="taskExecutor">
    			<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
    		</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.DefaultJobExecutor">
    		<property name="jobRepository" ref="jobRepository" />
    		<property name="stepExecutorFactory">
    			<bean
    				class="org.springframework.batch.execution.step.PrototypeBeanStepExecutorFactory">
    				<property name="stepExecutorName" value="stepExecutor" />
    			</bean>
    		</property>
    	</bean>
    
    	<bean id="stepExecutor"
    		class="org.springframework.batch.execution.step.simple.SimpleStepExecutor"
    		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.TaskExecutorRepeatTemplate">
    				<property name="taskExecutor">
    					<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
    					 
    				</property>
    				<property name="interceptor">
    					<bean class="org.springframework.batch.repeat.interceptor.ApplicationEventPublisherRepeatInterceptor" />
    				</property>
       			</bean>
    		</property>
    	</bean>

    Comment


    • #3
      It looks like that

      http://opensource.atlassian.com/proj...owse/BATCH-170

      Comment

      Working...
      X