以编程方式配置块的容错,具体如下:
stepBuilders.get("step")
.<Partner,Partner>chunk(1)
.reader(reader())
.processor(processor())
.writer(writer())
.listener(logProcessListener())
.faultTolerant()
.skipLimit(10)
.skip(UnknownGenderException.class)
.listener(logSkipListener())
.build();
诀窍是,通过添加“chunk”,链转换为SimpleStepBuilder,它提供“faultTolerant”方法。
我的问题是如果你只有一个tasklet(没有读者,处理器,编写器)怎么做?
定义一个tasklet的工作方式如下:
stepBuilders.get("step")
.tasklet(tasklet())
.build();
“tasklet”的使用切换到不提供“faultTolerant”方法的TaskletStepBuilder。因此,我认为没有办法如何定义像skipLimit这样的属性。
有什么想法吗?
答案 0 :(得分:3)
Tasklet
没有要跳过的“项目”概念,因此容错只对面向块的步骤有意义。我建议你在raw中使用Spring Retry(1.1.0.RELEASE现在就出来了,你有一些流畅的构建器选项和@Retryable
注释)。
答案 1 :(得分:0)
基于@DaveSyer提供的指导并使用 org.springframework.retry:spring-retry:1.1.0.RELEASE 这就是我最终得到的结果:
Tasklet tasklet = // whatever
ProxyFactory proxyFactory = new ProxyFactory(Tasklet, new SingletonTargetSource(tasklet));
proxyFactory.addAdvice(RetryInterceptorBuilder.stateless()
.maxAttempts(3)
.build());
Step step = stepBuilderFactory.get("taskName")
.tasklet((Tasklet)proxyFactory.proxy)
.build();
我唯一还在挣扎的是,如果我想吞下导致超过maxAttempts
后重试的异常。如果我在步骤中添加ExceptionHandler
,则永远不会重试该步骤。我想这意味着异常处理程序是里面的切入点,我觉得有点令人惊讶。
答案 2 :(得分:0)
//you need to have a bean in order to define the retry policies
@Configuration
@EnableAutoConfiguration
public class MyRetryBean{
@Autowired
private RetryProperties properties;
private RetryTemplate retryTemplate;
@Bean
public RetryTemplate initializeRetryTemplate() {
Map<Class<? extends Throwable>, Boolean> retryExceptions = Collections.singletonMap(IOException.class,
Boolean.TRUE);
SimpleRetryPolicy policy = new SimpleRetryPolicy(properties.getMaxAttempt(), retryExceptions);
retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(policy);
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(properties.getBackoffPeriod());
retryTemplate.setBackOffPolicy(backOffPolicy);
return retryTemplate;
}
public RetryTemplate getRetryTemplate() {
return retryTemplate;
}
}
// in spring batch steps config
@Autowire
private MyRetryBean retryBean;
stepBuilders.get("step")
.tasklet(new MyTasklet(retryBean))
.build();
// in your tasklet
public class MyTasklet implements Tasklet{
private MyRetryBean retry;
public MyTasklet (MyRetryBean aRetry) {
this.retry= aRetry;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws IOException {
retry.getRetryTemplate().execute(new RetryCallback<RepeatStatus, IOException>() {
@Override
public RepeatStatus doWithRetry(RetryContext context) throws IOException {
throw new IOException();
}
});
return null;
}
}