在此示例中,我尝试了Spring Batch重试。 Retry feature is not working in Spring Batch,它可以正常工作。 我正在尝试使用retrytemplate实现相同的功能,但是在抛出异常时看不到重试不起作用。
@Configuration
@EnableBatchProcessing
//@EnableRetry
public class RetryBatchJob {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public ItemReader<Integer> itemReader() {
return new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
@Bean
public ItemWriter<Integer> itemWriter() {
return items -> {
for (Integer item : items) {
System.out.println("item = " + item);
if (item.equals(7)) {
throw new Exception("Sevens are sometime nasty, let's retry them");
}
}
};
}
@Bean
public Step step() {
return steps.get("step")
.<Integer, Integer>chunk(2)
.reader(itemReader())
.writer(itemWriter())
/*.faultTolerant()
.retryLimit(5)
.retry(Exception.class)*/
.build();
}
@Bean
public Job job() {
Job job = null;
try {
job = retryTemplate().execute(new RetryCallback<Job, Throwable>() {
@Override
public Job doWithRetry(RetryContext context) throws Throwable {
return jobs.get("job")
.start(step())
.build();
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return job;
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(RetryBatchJob.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(5, singletonMap(Exception.class, true));
retryPolicy.setMaxAttempts(5);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
使用RetryTemplate时是否缺少某些东西?我也尝试过在步骤和作业方法上进行声明式配置,但是没有运气。
@Retryable(value = {Exception.class},
maxAttemptsExpression = "5"
)
注意:使用spring-retry 1.2.2 RELEASE。
答案 0 :(得分:0)
方法@Bean public Job job() { ... }
用于定义类型Job
的Spring Bean。根据您的代码,您正在此方法内调用retryTemplate().execute
,并期望重试该作业。这是不正确的。
您可以尝试的是先定义您的工作,例如:
@Bean
public Job job() {
return jobs.get("job")
.start(step())
.build();
}
然后在main
方法中调用从应用程序上下文获得的作业bean上的重试模板,类似:
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(RetryBatchJob.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
RetryTemplate retryTemplate = context.getBean(RetryTemplate.class);
retryTemplate.execute(new RetryCallback<JobExecution, Exception>() {
@Override
public JobExecution doWithRetry(RetryContext context) throws Exception {
return jobLauncher.run(job, new JobParameters());
};
});
}
如果我理解正确,您正在尝试使用重试模板自动重试失败的作业,类似于此PR中的建议:https://github.com/spring-projects/spring-batch/pull/440。
无论如何,我希望该示例对您有所帮助。
答案 1 :(得分:0)
作业执行过程中引发的异常不会停止执行,作业将继续执行,直到返回执行结果为FAILED或COMPLETED ...,这使其成为RetryTemplate.execute()的肯定结果。 您可以利用返回的执行状态在发生故障的情况下引发runtimeException。
RetryTemplate template = new RetryTemplate();
ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
exponentialBackOffPolicy.setInitialInterval(5000);
exponentialBackOffPolicy.setMultiplier(ExponentialBackOffPolicy.DEFAULT_MULTIPLIER);
exponentialBackOffPolicy.setMaxInterval(ExponentialBackOffPolicy.DEFAULT_MAX_INTERVAL);
Map<Class<? extends Throwable>, Boolean> exceptions = new HashMap<>();
exceptions.put(Exception.class, true);
SimpleRetryPolicy policy = new SimpleRetryPolicy(3, exceptions);
template.setRetryPolicy(policy);
template.setBackOffPolicy(exponentialBackOffPolicy);
template.execute(new RetryCallback<JobExecution, Exception>() {
@Override
public JobExecution doWithRetry(RetryContext context) throws Exception {
return runJob(job, paramMap);
}
});
函数:runJob()
public JobExecution runJob(Job job, Map<String, JobParameter> paramMap) throws Exception {
JobExecution exe = jobLauncher.run(job, new JobParameters(paramMap));
if(exe.getStatus().equals(BatchStatus.FAILED))
throw new RuntimeException(exe.toString());
return exe;
}