我正在尝试将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上的错误,还是表现得如预期?如果是这样,有人能指出我的相关文件吗?
谢谢你们,如果这是一个基本问题,请道歉。
致以最诚挚的问候,
亚历
答案 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'。