使用 Spring Boot 的 Spring Batch - 永远不要重试写入错误

Eri*_*ria 5 java spring spring-batch spring-boot

我使用 Spring Boot 创建了一个批处理。这是批处理的主要配置类:

@Configuration
@EntityScan({"my.domain"})
@EnableJpaRepositories({"my.domain"})
@EnableBatchProcessing
public class BatchConfiguration {

    /** Motif d'identification des fichiers d'entrée */
    @Value("${batch.input-file-pattern}")
    private String inputFilePattern;

    @Bean
    public BatchConfigurer configurer( EntityManagerFactory entityManagerFactory ){ 
        return new MapForcedBatchConfigurer( entityManagerFactory ); 
    }

    @Bean
    public Job myJob( JobBuilderFactory jobs, Step step1 ){
        return jobs.get("myJob")
                .incrementer( new RunIdIncrementer() )
                .flow( step1 )
                .end()
                .build();
    }

    @Bean
    public Step step1( StepBuilderFactory stepBuilderFactory, 
            StepExecutionListener stepExecutionListener,
            ItemReader<Input> myReader,
            ItemProcessor<Input, Dto> myProcessor, 
            ItemWriter<Dto> myWriter ){
        return stepBuilderFactory.get("myStep")
                .listener( stepExecutionListener )
                .<Input, Dto> chunk(1)
                .reader( myReader )
                .processor( myProcessor )
                .writer( myWriter )
                .faultTolerant().skipPolicy( new MySkipPolicy() ).retryLimit( 0 )
                .build();
    }

    @Bean
    public StepExecutionListener stepListener() {
        return new MyStepExecutionListener();
    }

    @Bean
    public ItemReader<Input> myReader() throws IOException {
        return new MyItemReader( inputFilePattern );
    }

    @Bean
    public ItemProcessor<Input, Dto> myProcessor(){
        return new MyItemProcessor();
    }

    @Bean
    public ItemWriter<Dto> myWriter(){
        return new MyItemWriter();
    }

}
Run Code Online (Sandbox Code Playgroud)

处理一个项目发生错误时,记录器写一条消息,然后批处理处理下一个元素。这正是我想要的。

但是当写入项目发生错误时,批处理总是重试一次操作!这样我每个写入错误都有 2 个错误日志。

无论错误发生在步骤的哪个部分,如何将批处理配置为从不重试错误?

这篇文章解释了以下内容:

【当我们在写的时候有一个skip】,框架必须找出是哪个项目导致了失败。对于读取项目的缓存列表中的每个项目,它启动一个自己的事务。项目由 ItemProcessor 处理,然后由 ItemWriter 写入。如果没有错误,则提交包含一项的 mini-chunk,下一项继续迭代。我们期望至少有一个可跳过的异常,当发生这种情况时,事务将回滚并将该项目标记为跳过的项目。一旦我们的迭代完成,我们就继续正常的块处理。

它可以是对重新执行写入操作的解释。我希望我能以某种方式绕过这种行为......

Art*_*cto 1

我认为如果没有子类化,你就没有什么可以做的 FaultTolerantChunkProcessor。调用readerIsTransactionalQueue()步骤构建器强制执行您想要的行为,但它会忽略所有异常(不会调用您的跳过策略)。

原因是 Spring Batch 尝试确定导致错误的项目,即使您的块只有一个项目,算法也不会考虑它(事实上,为什么您使用大小为 1 的块?... )

您可以做的就是自己在编写器中捕获异常。您甚至可以ItemWriter为此唯一的目的写一个包装。