데이터베이스의 일부 엔티티를 검색하고 만료 시간 ("isexpired") 플래그를 업데이트해야합니다. 이 후 나는 동일한 엔티티의 속성으로 지정된 URL에 json으로 전체 엔티티를 게시합니다.스프링 배치 JdbcPagingItemReader가 제대로 닫히지 않았기 때문에 제대로 초기화되지 않음
이 코드는 배치 작업을 실행하고 데이터베이스를 업데이트하지만 아래의 오류를 보여주는 유지하고 스프링 소스 STS에서 디버깅 할 때, 데이터베이스 업데이트하기 전에 프로그램이 여러 번 연속 반복 계속 나타납니다 :
INFO: Overriding bean definition for bean 'expireAndPostApiEntityJob': 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.JobParserJobFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
Jan 19, 2015 4:46:56 PM org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from class path resource [application.properties]
Jan 19, 2015 4:46:56 PM org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
INFO: Overriding bean definition for bean 'itemReader': replacing [Generic bean: class [org.springframework.batch.item.database.JdbcCursorItemReader]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/batch/jobs/job-extract-users.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [spring/batch/jobs/job-extract-users.xml]]
Jan 19, 2015 4:46:56 PM org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
INFO: Overriding bean definition for bean 'pagingItemReader': replacing [Generic bean: class [org.springframework.batch.item.database.JdbcPagingItemReader]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/batch/jobs/job-extract-users.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [spring/batch/jobs/job-extract-users.xml]]
Jan 19, 2015 4:46:56 PM org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
INFO: Overriding bean definition for bean 'apiItemProcessor': replacing [Generic bean: class [com.x.apimanagerbatchjob.ApiItemProcessor]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/batch/jobs/job-extract-users.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [spring/batch/jobs/job-extract-users.xml]]
Jan 19, 2015 4:46:56 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.s[email protected]7faf889f: defining beans [jobRepository,transactionManager,jobLauncher,databaseProperties,dataSource,itemReader,pagingItemReader,apiItemProcessor,oracleItemWriter,org.springframework.batch.core.scope.internalStepScope,org.springframework.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,expireAndPostApiEntityStep,expireAndPostApiEntityJob,runScheduler,org.springframework.scheduling.support.ScheduledMethodRunnable#0,org.springframework.scheduling.config.IntervalTask#0,org.springframework.scheduling.config.ScheduledTaskRegistrar#0,apiDAO,scopedTarget.itemReader,scopedTarget.pagingItemReader,scopedTarget.apiItemProcessor]; root of factory hierarchy
Jan 19, 2015 4:46:56 PM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jan 19, 2015 4:46:56 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: oracle.jdbc.driver.OracleDriver
Jan 19, 2015 4:46:56 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=expireAndPostApiEntityJob]] launched with the following parameters: [{isexpired=0}]
Jan 19, 2015 4:46:56 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [expireAndPostApiEntityStep]
Jan 19, 2015 4:46:56 PM org.springframework.batch.core.step.AbstractStep execute
SEVERE: 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.database.JdbcPagingItemReader.open(JdbcPagingItemReader.java:249)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy4.open(Unknown Source)
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 org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:127)
at com.x.apimanagerbatchjob.scheduler.RunScheduler.run(RunScheduler.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalStateException: Cannot open an already opened ItemReader, call close first
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.batch.item.database.AbstractPagingItemReader.doOpen(AbstractPagingItemReader.java:133)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:139)
... 40 more
을
컨텍스트 구성의 일부와 스프링 코드를 여기에 인라인 할 것입니다. App.java - 응용 프로그램의 진입 점입니다.
public class App {
public static void main(String[] args) {
String[] springConfig = { "spring/batch/jobs/job-extract-users.xml" };
@SuppressWarnings({ "resource", "unused" })
ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
}
}
RunScheduler.java - 작업
Component
public class RunScheduler {
public void run() {
String[] springConfig = { "spring/batch/jobs/job-extract-users.xml" };
@SuppressWarnings({ "resource" })
ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("expireAndPostApiEntityJob");
try {
JobParameters param = new JobParametersBuilder().addString("isexpired", "0").toJobParameters();
JobExecution execution = jobLauncher.run(job, param);
System.out.println("Exit Status : " + execution.getStatus());
System.out.println("Exit Status : " + execution.getAllFailureExceptions());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Done");
}
}
<import resource="classpath:spring/**/context.xml" />
<import resource="classpath:spring/**/database.xml" />
<bean id="itemReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="select id, apikey, apitoken, url, isexpired, createddate, modifieddate, posterror from apis where isexpired = #{jobParameters['isexpired']}" />
<property name="rowMapper">
<bean class="com.x.apimanagerbatchjob.ApiRowMapper" />
</property>
</bean>
<bean id="pagingItemReader"
class="org.springframework.batch.item.database.JdbcPagingItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="queryProvider">
<bean
class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="selectClause" value="select id, apikey, apitoken, url, isexpired, createddate, modifieddate, posterror" />
<property name="fromClause" value="from apis" />
<property name="whereClause" value="where isexpired=:isexpired" />
<property name="sortKey" value="id" />
</bean>
</property>
<property name="parameterValues">
<map>
<entry key="isexpired" value="#{jobParameters['isexpired']}" />
</map>
</property>
<!-- use property place holder configure -->
<property name="pageSize" value="${pagingItemReader.pageSize}" />
<property name="rowMapper">
<bean class="com.x.apimanagerbatchjob.ApiRowMapper" />
</property>
</bean>
<bean id="apiItemProcessor" class="com.x.apimanagerbatchjob.ApiItemProcessor" scope="step"/>
<bean id="oracleItemWriter"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>
<![CDATA[
update apis
set isexpired = 1,
modifieddate = CURRENT_DATE
where id = :id
]]>
</value>
</property>
<!-- It will take care matching between object property and sql name parameter -->
<property name="itemSqlParameterSourceProvider">
<bean
class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" />
</property>
</bean>
<job id="expireAndPostApiEntityJob" xmlns="http://www.springframework.org/schema/batch">
<step id="expireAndPostApiEntityStep">
<tasklet>
<chunk reader="pagingItemReader" processor="apiItemProcessor" writer="oracleItemWriter"
commit-interval="1" />
</tasklet>
</step>
</job>
<bean id="runScheduler" class="com.x.apimanagerbatchjob.scheduler.RunScheduler" />
<!-- Run every 900 seconds (15 mins) -->
<task:scheduled-tasks>
<task:scheduled ref="runScheduler" method="run" fixed-delay="${scheduler.interval}" />
<!--
<task:scheduled ref="runScheduler" method="run" cron="*/900 * * * * *" />
-->
</task:scheduled-tasks>
<bean id="apiDAO" class="com.x.apimanagerbatchjob.ApiDAOJDBCTemplateImpl">
<property name="dataSource" ref="dataSource" />
</bean>
내가 도움을 주셔서 감사합니다 JdbcPagingItemReader의 콩을 구성 컨텍스트 XML을 시작 클래스 이걸로. 고맙습니다.
고마워요 마이클. 이 문제의 원인인지 확실하지 않지만 귀하의 제안을 시도 할 것입니다. 왜 내가 이렇게 말한 이유는 스케줄러를 추가하고 두 번째로 컨텍스트를 참조하기 전에 이미이 예외가 발생했기 때문입니다. 동일한 문맥을 두 번 언급하는 것이 문제가 될 수 있지만 봄과 봄의 배치에 익숙하지 않다는 것을 알았지 만, 당시와 같이 분리하는 방법을 알지 못했지만 지금 생각합니다. RunScheduler 클래스를 소개하기 전에이 예외를 얻었 음을 고려할 때,이 문제의 원인이 될 수있는 다른 사항은 무엇입니까? – sage
Hello Michael, 코드 예제를 게시 할 수 있습니까? 별도의 패키지에있는 다른 클래스의 컨텍스트에 액세스해야하는 시나리오를 고려한 간단한 예제를 찾을 수 없습니다. App과 Runscheduler 클래스를 병합하고 선언 컨텍스트를 정적으로 만드는 것으로 접근하여 매우 잘못되었다고 생각합니다. 그것은 과도한 루핑을 중지했지만 Java.nullpointer 예외로 인해 실속합니다. – sage