ItemWriter的Spring Batch跳过异常

时间:2014-03-20 03:07:44

标签: spring-batch

我正在尝试将Spring Batch 2.2.5与Java配置一起使用。这是我的配置:

@Configuration
@EnableBatchProcessing
public class JobConfiguration {
    @Autowired
    private JobBuilderFactory jobBuilder;

    @Autowired
    private StepBuilderFactory stepBuilder;

    @Bean
    @Autowired
    public Job processDocumentsJob() {
        return jobBuilder.get("processDocumentsJob")
                .start(procesingStep())
                .build();
    }

    @Bean
    @Autowired
    public Step procesingStep() {
           CompositeItemProcessor<File, DocumentPackageFileMetadata> compositeProcessor = new CompositeItemProcessor<File, DocumentPackageFileMetadata>();
           compositeProcessor.setDelegates(Lists.newArrayList(
                   documentPackageFileValidationProcessor(),     
                   documentMetadataFileTransformer()
           ));
        return stepBuilder.get("procesingStep")
                .<File, DocumentPackageFileMetadata>chunk(1)
                .reader(documentPackageFileReader())
                .processor(compositeProcessor)
                .writer(documentMetadataFileMigrator())
                .faultTolerant()
                .skip(DocumentImportException.class)
                .skipLimit(10)
                .listener(stepExecutionListener())
                .build();
    }
....


}

使用上面的配置,如果itemwriter(documentMetadataFileMigrator指向的bean)抛出'DocumentImportException',则不会跳过该异常。 Spring Batch实际上会再次重试相同的输入。即它将对'documentPackageFileValidationProcessor'使用相同的输入。

但是,如果我将项目编写器中的逻辑移动到迭代处理器中:

 @Bean
        @Autowired
        public Step procesingStep() {
               CompositeItemProcessor<File, DocumentPackageFileMetadata> compositeProcessor = new CompositeItemProcessor<File, DocumentPackageFileMetadata>();
               compositeProcessor.setDelegates(Lists.newArrayList(
                       documentPackageFileValidationProcessor(),     
                       documentMetadataFileTransformer(),
                       documentMetadataFileMigratorAsProcessor() // same as itemwriter, but implemented as itemprocessor
               ));
            return stepBuilder.get("procesingStep")
                    .<File, DocumentPackageFileMetadata>chunk(1)
                    .reader(documentPackageFileReader())
                    .processor(compositeProcessor)                    
                    .faultTolerant()
                    .skip(DocumentImportException.class)
                    .skipLimit(10)
                    .listener(stepExecutionListener())
                    .build();
        }

然后将正确跳过该异常。即Spring Batch不会针对'documentPackageFileValidationProcessor'重试相同的项目。它将转到下一个要处理的项目(从'documentPackageFileReader'返回的项目)。

这是Spring Batch上的错误,还是表现得如预期?如果是这样,有人能指出我的相关文件吗?

谢谢你们,如果这是一个基本问题,请道歉。

致以最诚挚的问候,

亚历

2 个答案:

答案 0 :(得分:12)

这种行为是正确的。 ItemWriter接收要写入的项目列表。如果抛出可跳过的异常,Spring Batch会尝试确定哪个项实际导致异常,因此只跳过该项。这样做的方法是回滚事务,将提交间隔更改为1,然后重新处理每个项目并再次尝试写入。这样只允许跳过带错误的项目而不需要跳过整个块。

此处讨论了同样的问题(仅使用XML配置):How is the skipping implemented in Spring Batch?

答案 1 :(得分:1)

最后,这对我有用 - 如果我想使用itemwriter,而不重新处理相同的项目:

 @Bean
    @Autowired
    public Step procesingStep() {
           CompositeItemProcessor<DocumentPackageFileMetadata, DocumentPackageFileMetadata> compositeProcessor = new CompositeItemProcessor<DocumentPackageFileMetadata, DocumentPackageFileMetadata>();
           compositeProcessor.setDelegates(Lists.newArrayList(
                   documentPackageFileValidationProcessor(),
                   documentPackageFileExtractionProcessor(),
                   documentMetadataFileTransformer()
           ));
        return stepBuilder.get("procesingStep")
                .<DocumentPackageFileMetadata, DocumentPackageFileMetadata>chunk(1)
                .reader(documentPackageFileReader())
                .processor(compositeProcessor)
                .writer(documentMetadataFileMigrator())
                .faultTolerant()
                .skip(DocumentImportException.class)
                .noRetry(DocumentImportException.class)
                .noRollback(DocumentImportException.class)
                .skipLimit(10)
                .listener(skipListener())
                .listener(documentPackageReadyForProcessingListener())
                .listener(stepExecutionListener())
                .build();
    }

请注意,我已指定'noRetry'和'noRollback'。