Spring Batch пропускает исключение для ItemWriter

Я пытаюсь использовать 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) выдает "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, или она ведет себя как ожидалось? Если да, может ли кто-нибудь указать мне соответствующую документацию?

Спасибо, ребята, и извинения, если это фундаментальный вопрос.

С наилучшими пожеланиями,

Alex

2 ответа

Решение

Это поведение правильно. ItemWriter получает список элементов для записи. Если выдается пропускаемое исключение, Spring Batch пытается определить, какой элемент фактически вызвал исключение, поэтому пропускается только этот элемент. То, как это делается, - откат транзакции, интервал фиксации меняется на 1, затем каждый элемент обрабатывается повторно, и запись выполняется снова. Это позволяет пропустить только элемент с ошибкой, а не пропустить весь фрагмент.

Здесь обсуждается та же проблема (только с использованием XML-конфигурации): как реализован пропуск в Spring Batch?

В конце концов, это то, что работает для меня - если я хочу использовать 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'.

Другие вопросы по тегам