只是根据incomplete-co.de提供的建议回顾实际完成的工作.
我创建了一个类似于下面的恢复流程.恢复流程包装了我的实际批处理,仅负责为内部作业提供正确的作业参数.它可以是首次执行时的初始参数,正常执行时的新参数或上次执行失败时的旧参数.
incrementer="wrapperRunIdIncrementer"
restartable="true">
job-parameters-extractor="jobParametersExtractor" />
job-parameters-extractor="jobParametersExtractor" />
使用Spring Batch Restart机制时,解决方案的核心是RecoveryFlowDecider和JobParametersExtractor.
RecoveryFlowDecider将查询JobExplorer和JobRepository以查明我们在上次运行中是否出现故障.它将最后一次执行放在包装器的执行上下文中,以便稍后在JobParametersExtractor中使用.
请注意使用runIdIncremeter来允许重新执行包装器作业.
@Component
public class RecoveryFlowDecider implements JobExecutionDecider {
private static final String FIRST_RUN = "FIRST_RUN";
private static final String CURRENT = "CURRENT";
private static final String RECOVER = "RECOVER";
@Autowired
private JobExplorer jobExplorer;
@Autowired
private JobRepository jobRepository;
@Override
public FlowExecutionStatus decide(JobExecution jobExecution
,StepExecution stepExecution) {
// the wrapper is named as the wrapped job + WRAPPER
String wrapperJobName = jobExecution.getJobInstance().getJobName();
String jobName;
jobName = wrapperJobName.substring(0,wrapperJobName.indexOf(EtlConstants.WRAPPER));
List instances = jobExplorer.getJobInstances(jobName, 0, 1);
JobInstance internalJobInstance = instances.size() > 0 ? instances.get(0) : null;
if (null == internalJobInstance) {
return new FlowExecutionStatus(FIRST_RUN);
}
JobExecution lastExecution = jobRepository.getLastJobExecution(internalJobInstance.getJobName()
,internalJobInstance.getJobParameters());
//place the last execution on the context (wrapper context to use later)
jobExecution.getExecutionContext().put(EtlConstants.LAST_EXECUTION, lastExecution);
ExitStatus exitStatus = lastExecution.getExitStatus();
if (ExitStatus.FAILED.equals(exitStatus) || ExitStatus.UNKNOWN.equals(exitStatus)) {
return new FlowExecutionStatus(RECOVER);
}else if(ExitStatus.COMPLETED.equals(exitStatus)){
return new FlowExecutionStatus(CURRENT);
}
//We should never get here unless we have a defect
throw new RuntimeException("Unexpecded batch status: "+exitStatus+" in decider!");
}
}
然后JobParametersExtractor将再次测试上次执行的结果,如果作业失败,它将提供用于执行触发Spring Bacth重启机制的失败作业的原始参数.否则它将创建一组新的参数,并将在他的正常过程中执行.
@Component
public class JobExecutionWindowParametersExtractor implements
JobParametersExtractor {
@Override
public JobParameters getJobParameters(Job job, StepExecution stepExecution) {
// Read the last execution from the wrapping job
// in order to build Next Execution Window
JobExecution lastExecution= (JobExecution) stepExecution.getJobExecution().getExecutionContext().get(EtlConstants.LAST_EXECUTION);;
if(null!=lastExecution){
if (ExitStatus.FAILED.equals(lastExecution.getExitStatus())) {
JobInstance instance = lastExecution.getJobInstance();
JobParameters parameters = instance.getJobParameters();
return parameters;
}
}
//We do not have failed execution or have no execution at all we need to create a new execution window
return buildJobParamaters(lastExecution,stepExecution);
}
...
}