org.springframework.batch.item.ReaderNotOpenException:Reader必须先打开才能读取

时间:2014-03-02 07:52:06

标签: spring spring-batch

我正在使用Spring批处理(从数据库表中读取并写入另一个表)作业

作业由Quartz安排,数据库是oracle,它是c3p0,我的读者没有打开异常

这是工作环境

<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>

主要背景是:

<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" />

例外是:

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]

1 个答案:

答案 0 :(得分:4)

这里的问题是你的读者是单身范围的。这意味着当作业第一次运行时,ItemReader会成功打开并运行作业。但是,当作业尝试第二次运行时,它使用的是第一次执行的相同实例(已经初始化)(因此例外)。我建议将readyReqPoolReader更改为步骤范围的bean,看看是否有帮助。

您可以在此处详细了解步骤范围:http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/scope/StepScope.html