1

I am using Spring Batch to read some data from CSV files and put it in a database. My Batch job must be compound of 2 steps :

  1. Check files (names, extension, content ..)
  2. Read lines from CSV and save them in DB (ItemReader, ItemProcessor, ItemWriter..)

Step 2 must not be executed if Step 1 generated an error (files are not conform, files doesn't exist ...)

FYI, I am using Spring Batch without XML configuration ! Only annotations : Here's what my job config class looks like :

@Configuration
@EnableBatchProcessing
public class ProductionOutConfig {

    @Autowired
    private StepBuilderFactory steps;

    @Autowired
    private JobBuilderFactory jobBuilderFactory;


    @Autowired
    private ProductionOutTasklet productionOutTasklet;

    @Autowired
    private CheckFilesForProdTasklet checkFilesForProdTasklet;

    @Bean
    public Job productionOutJob(@Qualifier("productionOut")Step productionOutStep,
                                @Qualifier("checkFilesForProd") Step checkFilesForProd){
        return jobBuilderFactory.get("productionOutJob").start(checkFilesForProd).next(productionOutStep).build();
    }

    @Bean(name="productionOut")
    public Step productionOutStep(){
        return steps.get("productionOut").
                tasklet(productionOutTasklet)
                .build();}

    @Bean(name = "checkFilesForProd")
    public Step checkFilesForProd(){
        return steps.get("checkFilesForProd")
                .tasklet(checkFilesForProdTasklet)
                .build();
    }
}
Loic Mouchard
  • 1,121
  • 7
  • 22
Ghassen
  • 591
  • 1
  • 15
  • 33

2 Answers2

3

What you are looking for is already the default behavior of Spring Batch i.e. next step wouldn't be executed if previous step has failed. To mark current step as failed step, you need to throw a run time exception which is not caught.

If exception is not handled, spring batch will mark that step as failed and next step wouldn't be executed. So all you need to do is to throw an exception on your failed scenarios.

For complicated job flows , you might like to use - JobExecutionDecider , Programmatic Flow Decisions

Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
1

As the documentation specifies you can use the method "on" which starts a transition to a new state if the exit status from the previous state matches the given pattern.

Your code could be similar to something like this :

    return jobBuilderFactory.get("productionOutJob")
           .start(checkFilesForProd)
           .on(ExitStatus.FAILED.getExitCode()).end()
           .from(checkFilesForProd)
           .on("*")
           .to(productionOutStep)
           .build();
mabad
  • 51
  • 4
  • I changed like this : `return jobBuilderFactory.get("productionOutJob") .start(checkFilesForProd) .on(ExitStatus.FAILED.getExitCode()).end() .from(productionOutStep) .end() .build();` I think logically it's correct but now I couldn't find how to switch between returning `ExitStatus.FAILED` and `ExitStatus.COMPLETED` in my `checkFilesForProdTasklet` – Ghassen Aug 29 '17 at 12:54
  • Sorry i reversed the order of your tasks in my first answer. What about this one ? return jobBuilderFactory.get("productionOutJob") .start(checkFilesForProd) .on(ExitStatus.FAILED.getExitCode()).end() .from(checkFilesForProd) .on(ALL_PATTERN) .to(productionOutStep) .build(); Is it the result you are expecting ? – mabad Aug 29 '17 at 13:05
  • 1 - ALL_PATTERN is not known, does it mean whatever the result is ? 2 - My 2nd question is how to return ExitStatus.FAILED and ExitStatus.COMPLETED in my tasklet depending on the business logic ? – Ghassen Aug 29 '17 at 13:31
  • To match all pattern you have to put "*" as parameter and yes it means that the result doesn't matter. For your second question, if you want to generate an ExitStatus.FAILED, your tasklet has to throw an exception. The framework will catch this exception and mark the BatchStatus and ExistStatus as FAILED. – mabad Aug 29 '17 at 15:50