org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read

StackOverflow https://stackoverflow.com/questions/22125193

  •  18-10-2022
  •  | 
  •  

Question

i'm using Spring batch to run (reading from database table and writing into another table) job

the job is scheduled by Quartz and the database is oracle and it's c3p0, i'm getting reader not open exception

this is the job context

<batch:job id="readyReqPoolJob">
    <batch:step id="readyReqPoolStep">
        <batch:tasklet>
            <batch:chunk reader="readyReqPoolReader" writer="readyReqPoolWrtiter"
                commit-interval="1000" />
        </batch:tasklet>
    </batch:step>
</batch:job>


<!-- ======================================================= -->
<!-- 6) READER -->
<!-- ======================================================= -->
<bean id="readyReqPoolReader"
    class="org.springframework.batch.item.database.JdbcCursorItemReader">
    <property name="dataSource" ref="dataSource" />
    <property name="sql" value="select * from SF_ILA_Ready_Request_Pool" />
    <property name="rowMapper" ref="ReadyReqPoolRowMapper" />
</bean>
<bean id="readyReqPoolWrtiter"
    class="com.mobily.housekeepingservice.readyrequestpoolarchive.ReadyReqPoolArchiveWriter" />


<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass"
        value="org.springframework.batch.sample.quartz.JobLauncherDetails" />
    <property name="jobDataAsMap">
        <map>
            <entry key="jobName" value="readyReqPoolJob" />
            <entry key="jobLocator" value-ref="jobRegistry" />
            <entry key="jobLauncher" value-ref="jobLauncher" />
        </map>
    </property>
</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <bean id="cronTrigger"
            class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" ref="jobDetail" />
            <property name="cronExpression" value="0 0/5 * * * ?" />
        </bean>
    </property>
</bean>

the main context is:

<import resource="classpath:spring/batch/config/readyReqPoolContext.xml" />
<import resource="classpath:spring/batch/config/jdbc.commons.xml" />

<bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
        <tx:annotation-driven transaction-manager="transactionManager" />
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource" />
        </bean>

        <bean
            class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
            <property name="jobRegistry" ref="jobRegistry" />
        </bean>

        <bean id="jobRegistry"
            class="org.springframework.batch.core.configuration.support.MapJobRegistry" />


        <bean id="jobRepository"
            class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
            <property name="transactionManager" ref="transactionManager" />
        </bean>

        <!-- 4) LAUNCH JOBS FROM A REPOSITORY -->
        <bean id="jobLauncher"
            class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
            <property name="jobRepository" ref="jobRepository" />
        <property name="taskExecutor" ref="taskExecutor" />
    </bean>
    <bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />

the exception is:

09:59:20,108  INFO ClassPathXmlApplicationContext:510 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@99436c6: startup date [Sun Mar 02 09:59:20 AST 2014]; root of context hierarchy
09:59:20,159  INFO XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [spring/batch/config/mainContext.xml]
09:59:20,285  INFO XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [spring/batch/config/readyReqPoolContext.xml]
09:59:20,379  INFO DefaultListableBeanFactory:663 - Overriding bean definition for bean 'readyReqPoolJob': replacing [Generic bean: class [org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean]; scope=; abstract=false; lazyInit=false
; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.batch.core.configuration.xml.JobPars
erJobFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
09:59:20,383  INFO XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [spring/batch/config/jdbc.commons.xml]
09:59:20,744  INFO ClassPathXmlApplicationContext:1374 - Bean 'jobRegistry' of type [class org.springframework.batch.core.configuration.support.MapJobRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible
 for auto-proxying)
09:59:20,759  INFO ClassPathXmlApplicationContext:1374 - Bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' of type [class org.springframework.transaction.annotation.AnnotationTransactionAttributeSource] is not e
ligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
09:59:20,761  INFO ClassPathXmlApplicationContext:1374 - Bean 'org.springframework.transaction.config.internalTransactionAdvisor' of type [class org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor] is not eligible
 for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
09:59:20,778  INFO DefaultListableBeanFactory:596 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@53ddc692: defining beans [org.springframework.batch.core.scope.internalStepScope,org.springframew
ork.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,readyReqPoolStep,readyReqPoolJob,readyReqPoolReader,readyReqPoolWrtiter,jobDetail,org.springframework.scheduling.quartz.Schedu
lerFactoryBean#0,dataSource,appJobExecutionListener,exceptionLogArchiveDAOImp,ExceptionLogRowMapper,exceptionLogWriter,itemFailureLoggerListener,log4jDebugArchiveDAOImp,log4jDebugArchiveWriter,Log4jDebugRowMapper,log4jErrorArchiveDAOImp,log4jErrorArc
hiveWriter,Log4jErrorRowMapper,log4jFatalArchiveDAOImp,log4jFatalArchiveWriter,Log4jFatalRowMapper,log4jInfoArchiveDAOImp,log4jInfoArchiveWriter,Log4jInfoRowMapper,log4jTraceArchiveDAOImp,log4jTraceArchiveWriter,Log4jTraceRowMapper,log4jWarnArchiveDA
OImp,log4jWarnArchiveWriter,Log4jWarnRowMapper,readyReqPoolArchiveDAOImp,readyReqPoolArchiveWriter,ReadyReqPoolRowMapper,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAu
towiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,jdbcTemplate,org.springframework.
batch.core.configuration.support.JobRegistryBeanPostProcessor#0,jobRegistry,jobRepository,jobLauncher,taskExecutor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
09:59:20,812  INFO MLog:80 - MLog clients using log4j logging.
09:59:20,911  INFO C3P0Registry:204 - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
09:59:21.296 [main] INFO  org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
09:59:21.312 [main] INFO  o.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
09:59:21.314 [main] INFO  org.quartz.core.QuartzScheduler - Quartz Scheduler v.1.8.6 created.
09:59:21.315 [main] INFO  org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
09:59:21.315 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v1.8.6) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

09:59:21.316 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
09:59:21.316 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 1.8.6
09:59:21.317 [main] INFO  org.quartz.core.QuartzScheduler - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@1fe0d622
09:59:21,491  INFO DefaultLifecycleProcessor:334 - Starting beans in phase 2147483647
09:59:21,491  INFO SchedulerFactoryBean:648 - Starting Quartz Scheduler now
09:59:21.491 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
09:59:21,532  INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -
> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 2rzno590zyfq8arapgjr|2022d1f4, debugUnreturnedCon
nectionStackTraces -> false, description -> null, driverClass -> oracle.jdbc.driver.OracleDriver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2rzno590zyfq8arapgjr|2022d1f4, idleConnectionTestPeriod -> 10
000, initialPoolSize -> 4, jdbcUrl -> jdbc:oracle:thin:@10.14.11.186:1522:EMADEV, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 12, maxStatements -> 0, maxStatementsPerConne
ction -> 0, minPoolSize -> 8, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> SELECT 1 FROM DUAL, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnect
ionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Exit Status : STARTING
Done
09:59:22,170  INFO SimpleJobLauncher:132 - Job: [FlowJob: [name=readyReqPoolJob]] launched with the following parameters: [{time=1393743561493}]
09:59:22,272  INFO SimpleStepHandler:135 - Executing step: [readyReqPoolStep]
09:59:22.314 [Timer-0] DEBUG org.quartz.utils.UpdateChecker - Checking for available updated version of Quartz...
10:00:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job DEFAULT.jobDetail
10:00:00,017  INFO JobLauncherDetails:69 - Quartz trigger firing with Spring Batch jobName=readyReqPoolJob
10:00:00,051  INFO SimpleJobLauncher:132 - Job: [FlowJob: [name=readyReqPoolJob]] launched with the following parameters: [{}]
10:00:00,104  INFO SimpleStepHandler:135 - Executing step: [readyReqPoolStep]
10:00:00,112 ERROR AbstractStep:222 - Encountered an error executing the step
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:142)
    at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:96)
    at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:306)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:192)
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:137)
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
    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:152)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:131)
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.IllegalStateException: Stream is already initialized.  Close before re-opening.
    at org.springframework.util.Assert.state(Assert.java:385)
    at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:399)
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:139)
    ... 12 more
10:00:00,145  INFO SimpleJobLauncher:135 - Job: [FlowJob: [name=readyReqPoolJob]] completed with the following parameters: [{}] and the following status: [FAILED]
10:00:04,963 ERROR AbstractStep:222 - Encountered an error executing the step
org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read.
    at org.springframework.batch.item.database.AbstractCursorItemReader.doRead(AbstractCursorItemReader.java:440)
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:83)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:155)
    at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:114)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:108)
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:395)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:131)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:137)
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
    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:152)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:131)
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
    at java.lang.Thread.run(Thread.java:744)
10:00:04,999  INFO SimpleJobLauncher:135 - Job: [FlowJob: [name=readyReqPoolJob]] completed with the following parameters: [{time=1393743561493}] and the following status: [FAILED]
Was it helpful?

Solution

The issue here is that your reader is singleton scoped. This means that when the job runs the first time, the ItemReader is opened successfully and the job runs. However when the job attempts to run a second time, it's using the same instance it did the first time which is already initialized (hence the exception). I'd recommend changing the readyReqPoolReader to be a step scoped bean and see if that helps.

You can read more about step scope here: http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/scope/StepScope.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top