Spring Batch_Configuring a Step for Restart
spring官方文档:http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html#stepRestart
当一个普通的 job 处于complete 的状态的时候,是不能被restart的。
下面来演示如何使一个job 能够被 restart。
restartable="true"
<job id="footballJob" restartable="false">
...
</job>
首先job应该要配置成 restartable="true"。然后看step如何配置:
allow-start-if-complete="true"
这是设置当该step完成时,也可以重启。这个默认值是false。
start-limit="3"
这是设置可以重启的次数,默认值是Integer.MAX_VALUE.
这是spring 官方文档给的demo:
<job id="footballJob" restartable="true">
<step id="playerload" next="gameLoad">
<tasklet>
<chunk reader="playerFileItemReader" writer="playerWriter"
commit-interval="10" />
</tasklet>
</step>
<step id="gameLoad" next="playerSummarization">
<tasklet allow-start-if-complete="true">
<chunk reader="gameFileItemReader" writer="gameWriter"
commit-interval="10" />
</tasklet>
</step>
<step id="playerSummarization">
<tasklet start-limit="3">
<chunk reader="playerSummarizationSource" writer="summaryWriter"
commit-interval="10" />
</tasklet>
</step>
</job>
下面是我的关于restart的配置:
spring-batch-restart.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 包的扫描 -->
<context:component-scan base-package="com.lyx.batch" />
<bean id="exceptionHandler" class="com.lyx.batch.ExceptionListener" />
<batch:step id="abstractStep" abstract="true">
<batch:listeners>
<batch:listener ref="exceptionHandler" />
</batch:listeners>
</batch:step>
<bean id="abstractCursorReader" abstract="true"
class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- add people desc job begin -->
<batch:job id="addPeopleDescJob" restartable="true">
<batch:step id="addDescStep" parent="abstractStep">
<batch:tasklet allow-start-if-complete="true"
start-limit="2">
<batch:chunk reader="peopleAddDescReader" processor="addDescProcessor"
writer="addDescPeopleWriter" commit-interval="2" />
</batch:tasklet>
</batch:step>
</batch:job>
<!-- add people desc job end -->
<bean id="peopleAddDescReader" parent="abstractCursorReader"
scope="step">
<property name="sql">
<value><![CDATA[select first_name ,last_name from people where
first_name like ? or last_name like ?]]></value>
</property>
<property name="rowMapper" ref="peopleRowMapper" />
<property name="preparedStatementSetter" ref="preparedStatementSetter" />
<property name="fetchSize" value="20" />
</bean>
<bean id="peopleRowMapper" class="com.lyx.batch.PeopleRowMapper" />
<bean id="preparedStatementSetter" class="com.lyx.batch.PeoplePreparedStatementSetter" />
<bean id="addDescProcessor" class="com.lyx.batch.AddPeopleDescProcessor" />
<bean id="addDescPeopleWriter" class="com.lyx.batch.AddDescPeopleWriter" />
<!--tomcat jdbc pool数据源配置 -->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
destroy-method="close">
<property name="poolProperties">
<bean class="org.apache.tomcat.jdbc.pool.PoolProperties">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="034039" />
</bean>
</property>
</bean>
<!-- spring batch 配置jobRepository -->
<batch:job-repository id="jobRepository"
data-source="dataSource" transaction-manager="transactionManager"
isolation-level-for-create="REPEATABLE_READ" table-prefix="BATCH_"
max-varchar-length="1000" />
<!-- spring的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- batch luncher -->
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
AppMain8.java
package com.lyx.batch;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试restart
*
* @author Lenovo
*
*/
public class AppMain8 {
public static void main(String[] args)
throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
long startTime = System.currentTimeMillis(); // 获取开始时间
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:spring-batch-restart.xml" });
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
Job job = (Job) context.getBean("addPeopleDescJob");
JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");
JobExecution result = launcher.run(job,
jobParametersBuilder.toJobParameters());
ExitStatus es = result.getExitStatus();
if (es.getExitCode().equals(ExitStatus.COMPLETED.getExitCode())) {
System.out.println("任务正常完成");
} else {
System.out.println("任务失败,exitCode=" + es.getExitCode());
}
long endTime = System.currentTimeMillis(); // 获取结束时间
System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
}
}
当第一运行成功时:
select * from batch_job_instance;
JOB_INSTANCE_ID VERSION JOB_NAME JOB_KEY
--------------- ------- ---------------- --------------------------------
1 0 addPeopleDescJob d41d8cd98f00b204e9800998ecf8427e
当第二次运行成功时,查询一下相关的表:
select * from batch_job_execution;会发现有两个job_execution,都是属于一个job instance。
JOB_INSTANCE_ID VERSION JOB_NAME JOB_KEY
--------------- ------- ---------------- --------------------------------
1 0 addPeopleDescJob d41d8cd98f00b204e9800998ecf8427e
JOB_EXECUTION_ID JOB_INSTANCE_ID CREATE_TIME
---------------- --------------- -------------------
1 1 2014-11-14 12:33:12
2 1 2014-11-14 12:33:48
查看step运行信息:
select STEP_EXECUTION_ID , STEP_NAME , JOB_EXECUTION_ID from batch_step_execution;
STEP_EXECUTION_ID STEP_NAME JOB_EXECUTION_ID
----------------- ----------- ----------------
1 addDescStep 1
2 addDescStep 2
相应的数据库也会多出一倍的数据。
当第三次运行job时,报如下异常信息:
Caused by: org.springframework.batch.core.StartLimitExceededException: Maximum start limit exceeded for step: addDescStepStartMax: 2
很明显,就是重启的次数以用尽。
=================END=================