0

My project executes a spring batch (version 2.1.9) based task from Quartz scheduler (version 2,2,0).
We are working in a multi-tenant environment and every tenant is maintaining is own job Repository on a tenant dedicated schema. The data source implantation is tenant sensitive and pool connections per tenant. The transaction manager used is org.springframework.jdbc.datasource.DataSourceTransactionManager

When we execute the scheduler the tasks are executed successfully. Once in a while I am getting the following exception from spring batch. Please note that other tasks share this scheduler as well. Some of them have other PlatformTransactionManagers assigned to them.

2014-08-14 17:10:00,082 INFO [tenant_id] [org.quartz.core.JobRunShell] - <Job ROOT_GROUP. dataGenerator threw a JobExecutionException: >
org.quartz.JobExecutionException: java.lang.IllegalStateException: Existing transaction detected in JobRepository.
Please fix this and try again (e.g. remove @Transactional annotations from client).
[See nested exception: java.lang.IllegalStateException: Existing transaction detected in JobRepository.
Please fix this and try again (e.g. remove @Transactional annotations from client).] 

I am familiar with this Exception when using @Transactional (see my answer post here).
But as my Job is actually running correctly from the scheduler and as a standalone app this is not a configuration issue as this happens sporadically. I guess that at some stage the transaction is delayed in a way that Spring Batch thinks is sharing the transaction. Or Maybe other tasks does not clear correctly the TransactionSynchronizationManager before returning the thread back to the Quartz Thread Pool

<bean id="jobTransactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="jobDataSource" />
</bean> 
<bean
    class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
    <property name="jobRegistry" ref="jobRegistry" />
</bean>

<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
    <property name="dataSource" ref="jobDataSource"/>
    <property name="databaseType" value="SQLSERVER"/>
    <property name="transactionManager" ref="jobTransactionManager"/>
</bean>

Any idea how to trace down this issue?
Please find the full stack trace below:

2014-08-14 11:50:00,157 INFO [tenant_id] [org.quartz.core.JobRunShell] - <Job ROOT_GROUP.dataGenerator threw a JobExecutionException: >
org.quartz.JobExecutionException: java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client). [See nested exception: java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).]
    at com.my.csd.scheduler.BatchJobWrapper.executeInternal(BatchJobWrapper.java:53)
    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:111)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:207)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:560)
Caused by: java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).
    at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:164)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy256.createJobExecution(Unknown Source)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:111)
    at org.springframework.batch.core.launch.support.SimpleJobOperator.startNextInstance(SimpleJobOperator.java:345)
    at org.springframework.batch.core.launch.support.SimpleJobOperator$$FastClassBySpringCGLIB$$44ee6049.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:640)
    at org.springframework.batch.core.launch.support.SimpleJobOperator$$EnhancerBySpringCGLIB$$540a28da.startNextInstance(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:201)
    at com.sun.proxy.$Proxy257.startNextInstance(Unknown Source)
    at com.my.csd.schedule.tasks.SpringBatchTask.process(SpringBatchTask.java:32)
    at com.my.csd.schedule.tasks.AbstractScheduledTask.process(AbstractScheduledTask.java:64)
    at com.my.csd.scheduler.BatchJobWrapper.process(BatchJobWrapper.java:60)
    at com.my.csd.scheduler.BatchJobWrapper.executeInternal(BatchJobWrapper.java:49)
    ... 3 more
Community
  • 1
  • 1
Haim Raman
  • 11,508
  • 6
  • 44
  • 70
  • Is this something related to `http://stackoverflow.com/questions/16036536/spring-batch-datasourcetransactionmanager-fails-on-oracle` – Karthik Prasad Aug 18 '14 at 06:05
  • Can we get the stack trace? Also, you're sure you aren't using `@Transactional` anywhere in your job? – Michael Minella Aug 18 '14 at 14:43
  • I added the stack trace. I am sure that I am not user @@Transactional because the job run most of the time. I suspect that this happens because of the reuse of threads from the pool provided by the scheduler – Haim Raman Aug 18 '14 at 19:19

0 Answers0