如何从slave步

时间:2018-03-29 12:19:13

标签: spring-boot spring-batch spring-annotations

我有一个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;
    }
 }

感谢您的帮助

1 个答案:

答案 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;
    }

}