How to configure fault tolerance programmatically for a spring tasklet (not a chunk)

一曲冷凌霜 提交于 2019-12-06 02:21:54

问题


Programmatically configuring fault tolerance for a chunk works kind of as follows:

stepBuilders.get("step")
  .<Partner,Partner>chunk(1)
  .reader(reader())
  .processor(processor())
  .writer(writer())
  .listener(logProcessListener())
  .faultTolerant()
  .skipLimit(10)
  .skip(UnknownGenderException.class)
  .listener(logSkipListener())
  .build();

The trick is, that with adding "chunk", the chain switches to a SimpleStepBuilder which offers the "faultTolerant" method.

My question is how to do that if you just have a tasklet (no reader, processor, writer)?

Defining a tasklet works as follows:

stepBuilders.get("step")
  .tasklet(tasklet())
  .build();

The usage of "tasklet" switches to a TaskletStepBuilder which does not offer a "faultTolerant" method. Therefore I see no way how to define properties like skipLimit and that like.

Any ideas?


回答1:


A Tasklet has no notion of "items" to skip, so fault tolerance only makes sense for a chunk-oriented step. I suggest you use Spring Retry in the raw (1.1.0.RELEASE is out now, just, and you have some fluent builder options and a @Retryable annotation there).




回答2:


Based on the guidance given by @DaveSyer and using org.springframework.retry:spring-retry:1.1.0.RELEASE this is what I have ended up with:

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();

The only thing I'm struggling with still is if I want to swallow the exception that causes the retry after maxAttempts is exceeded. If I add an ExceptionHandler to the step then the step is never retried. I guess that means the exception handler is inside the pointcut which I find a little surprising.




回答3:


//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;
          }
        }


来源:https://stackoverflow.com/questions/23523130/how-to-configure-fault-tolerance-programmatically-for-a-spring-tasklet-not-a-ch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!