我有一个Spring批处理作业应用程序,它解析许多包含用户详细信息的csv文件。要解析用户详细信息,我有一个从csv文件解析的LineMapper。
因此,第一个主步骤读取器从位置读取所有文件,然后使用分区程序我有从属步骤。所有从属步骤并行执行。这些从属步骤逐行解析用户详细信息的每个文件。处理完后,它将处理过的文件移动到Processed文件夹。
在测试期间,我在一个文件中保留了一些错误的值,该文件导致读取器执行FlatFileParseException。在这里,我想将此文件移动到另一个文件夹,如Failed文件夹。但我无法做到这一点。
如果任何从属步骤阅读器无法解析,我应该如何将文件写入Failed文件夹?
我正在使用Spring Boot,Spring Batch注释
错误:
FlatFileParseException:解析错误在第37行:资源
JobExecutionException:分区处理程序返回了一个不成功的步骤
代码:
BatchConfiguration.java
@Bean(name = "partitionerJob")
public Job partitionerJob()
throws UnexpectedInputException, MalformedURLException, ParseException {
return jobs.get("partitioningJob")
.start(partitionStep())
.build();
}
@Bean
public Step partitionStep()
throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("partitionStep")
.partitioner("slaveStep", partitioner())
.step(slaveStep())
.taskExecutor(taskExecutor())
.build();
}
@Bean
public CustomMultiResourcePartitioner partitioner() {
CustomMultiResourcePartitioner partitioner
= new CustomMultiResourcePartitioner();
Resource[] resources;
try {
resources = resoursePatternResolver
.getResources("file:src/main/resources/input/*.csv");
} catch (IOException e) {
throw new RuntimeException("I/O problems when resolving"
+ " the input file pattern.", e);
}
partitioner.setResources(resources);
return partitioner;
}
@StepScope
@Bean
public FlatFileItemReader<Transaction> itemReader(
@Value("#{stepExecutionContext[fileName]}") String filename)
throws UnexpectedInputException, ParseException {
return new UserDetailReader(fileName);
}
@Bean
@StepScope
public ItemWriter<Transaction> itemWriter(Marshaller
marshaller ,
@Value("#{stepExecutionContext[opFileName]}") String
filename )
throws MalformedURLException {
return new UserDetailWriter(fileName);
}
@Bean
public Step slaveStep()
throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("slaveStep").<User, User>chunk(5)
.reader(itemReader(null))
.writer(itemWriter(marshaller(), null))
.build();
}
CustomMultiResourcePartitioner.java
public class CustomMultiResourcePartitioner implements Partitioner {
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
Map<String, ExecutionContext> map = new HashMap<>(gridSize);
int i = 0, k = 1;
for (Resource resource : resources) {
ExecutionContext context = new ExecutionContext();
Assert.state(resource.exists(), "Resource does not exist: "
+ resource);
context.putString(keyName, resource.getFilename());
context.putString("opFileName",
"output"+k+++".xml");
map.put(PARTITION_KEY + i, context);
i++;
}
return map;
}
}
感谢您的帮助
答案 0 :(得分:1)
您可以使用跳过&amp;在定义步骤时使用skipLimit 属性。
以下是示例配置。 现在,您的奴隶步骤将不会失败,直到达到skipLimit。
@Bean
public Step slaveStep()
throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("slaveStep").<User, User>chunk(5)
.reader(itemReader(null))
.writer(itemWriter(marshaller(), null))
.faultTolerant()
.skip(Exception.class)
.skipLimit(500)
.build();
}
将文件移至失败文件夹
您可以为slaveStep定义 StepExecutionListener 。
在后续步骤方法中,您可以获得该步骤的所有FailureExceptions
。
使用它你可以把你的逻辑用于移动文件
示例代码
public class MyStepListener implements StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
LOGGER.info("MyStepListener beforeStep "+ stepExecution.getSummary());
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
List<Throwable> failureExceptions = stepExecution.getFailureExceptions();
// move file from one folder to another
return null;
}
}