如何以编程方式为spring tasklet(不是块)配置容错

时间:2014-05-07 16:19:52

标签: spring batch-processing fault-tolerance tasklet

以编程方式配置块的容错,具体如下:

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这样的属性。

有什么想法吗?

3 个答案:

答案 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;
          }
        }