I have the following configuration
Job Definition
Code:<job id="thumbnailJob" incrementer="dateIncrementer"> <step id="step1ThumbnailReaderWriter"> <tasklet> <listeners> <listener ref="thumbnailBatchListener"/> </listeners> <chunk reader="thubmnailItemReader" writer="batchWritierProvider" commit-interval="1" skip-limit="10000000"> <skippable-exception-classes> java.lang.Exception </skippable-exception-classes> </chunk> </tasklet> </step> </job> <!-- Listener class which logs the progess of the ItemWriter + errors --> <beans:bean id="thumbnailBatchListener" class="com.siemens.c4bs.batch.ThumbnailBatchListener"> <beans:property name="batchLogDAO" ref="batchLogDAO"></beans:property> </beans:bean> <!-- ThumbnailItem reader reads files from a directors and passes them to the writer. --> <beans:bean id="thubmnailItemReader" class="com.siemens.c4bs.batch.DirectoryFileItemReader"> <beans:property name="directory" value="${thumbnail.incomingDir}"/> </beans:bean> <beans:bean id="thumbnailJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean"> <beans:property name="jobClass" value="com.siemens.c4bs.batch.RetryJobLauncherDetails" /> <beans:property name="group" value="quartz-batch" /> <beans:property name="jobDataAsMap"> <beans:map> <beans:entry key="jobName" value="thumbnailJob" /> <beans:entry key="jobLocator" value-ref="jobRegistry" /> <beans:entry key="jobLauncher" value-ref="jobLauncher" /> <beans:entry key="jobOperator" value-ref="jobOperator" /> </beans:map> </beans:property> </beans:bean>
My writer calls a service which is also used generally by the application which is transactional and I get the following exception.
Code:org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@21470daa] for key [org.apache.commons.dbcp.BasicDataSource@33bdfcdb] bound to thread [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1] at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:599) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:374) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:263) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635) at com.siemens.c4bs.service.ThumbnailServiceImpl$$EnhancerByCGLIB$$1ae324ae.createThumbnail(<generated>) at com.siemens.c4bs.batch.ThumbnailItemWriter.write(ThumbnailItemWriter.java:27) at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:156) at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:137) at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$3.doWithRetry(FaultTolerantChunkProcessor.java:284) at org.springframework.batch.retry.support.RetryTemplate.doExecute(RetryTemplate.java:231) at org.springframework.batch.retry.support.RetryTemplate.execute(RetryTemplate.java:180) at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:213) at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.write(FaultTolerantChunkProcessor.java:371) at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:178) at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74) at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:268) at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76) at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367) at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143) at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:242) at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198) at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:348) at org.springframework.batch.core.job.flow.FlowJob.access$0(FlowJob.java:1) at org.springframework.batch.core.job.flow.FlowJob$JobFlowExecutor.executeStep(FlowJob.java:135) at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60) at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144) at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124) at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:103) at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:250) at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:110) at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49) at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:105) at com.siemens.c4bs.batch.RetryJobLauncherDetails.executeInternal(RetryJobLauncherDetails.java:74) at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:86) at org.quartz.core.JobRunShell.run(JobRunShell.java:202) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525) Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@21470daa] for key [org.apache.commons.dbcp.BasicDataSource@33bdfcdb] bound to thread [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1] at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:182) at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:574) ... 40 more
My writer code
On removing the transactional attribute. Everything works fine. But I would prefer not to do this as this method is also used generally used in the applicationCode:public class ThumbnailItemWriter<T> implements ItemWriter<T> { private IThumbnailService thumbnailService; @Override public void write(List<? extends T> fileList) throws Exception { for (Object file : fileList) { thumbnailService.createThumbnail((File) file); } } public IThumbnailService getThumbnailService() { return thumbnailService; } public void setThumbnailService(IThumbnailService thumbnailService) { this.thumbnailService = thumbnailService; } }


Reply With Quote