重试功能在Spring批处理中不起作用

重试功能在Spring批处理中不起作用,spring,spring-batch,retrytemplate,Spring,Spring Batch,Retrytemplate,我有一个批处理作业,其中我使用的是ScriptBatch.3.0.x版本 我的用例是在中间出现任何中间故障时重试作业 我正在使用基于块的处理和StepBuilderFactory进行作业。通过在其中添加重试,我看不出有什么不同 return stepBuilderFactory.get("ValidationStepName") .<Long, Info> chunk(10) .reader(.....)

我有一个批处理作业,其中我使用的是ScriptBatch.3.0.x版本

我的用例是在中间出现任何中间故障时重试作业

我正在使用基于块的处理和StepBuilderFactory进行作业。通过在其中添加重试,我看不出有什么不同

    return stepBuilderFactory.get("ValidationStepName")
            .<Long, Info> chunk(10)
            .reader(.....)
            .processor(.....)
    //        .faultTolerant()
    //        .retryLimit(5)
    //        .retryLimit(5).retry(Exception.class)
            .writer(......)
            .faultTolerant()
            .retryLimit(5)
            //.retryLimit(5).retry(Exception.class)
            .transactionManager(jpaTransactionManager())
            .listener(new ChunkNotificationListener())
            .build();
返回stepBuilderFactory.get(“ValidationStepName”)
. 区块(10)
.读者(……)
.处理器(…)
//.容错()
//.再犯限制(5)
//.retryLimit(5).重试(Exception.class)
.作者(……)
.容错()
.再犯限制(5)
//.retryLimit(5).重试(Exception.class)
.transactionManager(jpaTransactionManager())
.listener(新的ChunkNotificationListener())
.build();
我不确定我在这里遗漏了什么,我希望在这里添加retryLimit()会在获得任何异常时重试相同的块n次

我希望在这里添加retryLimit()会在获得任何异常时重试相同的块n次

如果指定重试限制,则需要指定要重试的异常。否则,您将有一个带有消息的
非法状态异常
:如果提供了重试限制,则还必须指定可重试的异常

编辑:

第1点:版本3.0.9通过了以下测试:

import java.util.Arrays;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.tasklet.TaskletStep;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.item.support.ListItemWriter;
import org.springframework.transaction.PlatformTransactionManager;

@RunWith(MockitoJUnitRunner.class)
public class TestRetryConfig {

    @Rule
    public ExpectedException expectedException = ExpectedException.none();
    @Mock
    private JobRepository jobRepository;
    @Mock
    PlatformTransactionManager transactionManager;

    @Test
    public void testRetryLimitWithoutException() {
        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("If a retry limit is provided then retryable exceptions must also be specified");

        StepBuilderFactory stepBuilderFactory = new StepBuilderFactory(jobRepository, transactionManager);

        TaskletStep step = stepBuilderFactory.get("step")
                .<Integer, Integer>chunk(2)
                .reader(new ListItemReader<>(Arrays.asList(1, 2, 3)))
                .writer(new ListItemWriter<>())
                .faultTolerant()
                .retryLimit(3)
                .build();
    }
}
第7项重试3次,然后该步骤按预期失败


我希望这能有所帮助。

两个人认为,1。在没有提供异常的情况下,我没有得到任何异常,异常发生1次,作业完成2次。即使我将异常作为.retryLimit(5).retry(exception.class)提供,它也没有帮助Mahmoud,感谢示例代码片段,它帮助了我。我有一个后续问题,上面的实现是无状态实现还是有状态实现对不起,我不确定我是否理解这个问题,无状态或有状态是什么意思?重试时,我是否会保持中间状态?示例代码仅使用ItemReader和ItemWriter。假设我们有ItemReader、ItemProcessor和ItemWriter。如果itemWriter中存在任何中间故障,步骤将执行ItemProcessor和itemWriter(如果我的理解是正确的),在这种情况下,上述代码段将保持获得异常或未获得异常的状态。请参阅以了解更多细节。是的,如果存在错误,ItemProcessor和itemWriter都将重新执行。您可以向示例中添加一个简单的处理器(将项目打印到标准输出),并查看它的行为。
import java.util.Arrays;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class MyJob {

    @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(5)
                .reader(itemReader())
                .writer(itemWriter())
                .faultTolerant()
                .retryLimit(3)
                .retry(Exception.class)
                .build();
    }

    @Bean
    public Job job() {
        return jobs.get("job")
                .start(step())
                .build();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}
item = 1
item = 2
item = 3
item = 4
item = 5
item = 6
item = 7
item = 6
item = 7
item = 6
item = 7