Search code examples
javaspringspring-batchjobs

Spring Batch delay step initializing


I have a Spring Batch job with two steps. The first one downloads a file and the second on processes the file. The problem is the second step does not know what the name of the file is until the first step has been run.

The job automatically already instantaties the steps so it can be run when needed. I can't think of any way to make sure the step initializes after the first step has been run.

This is the code:

    @Bean
public Job insertIntoDbFromCsvb(){
    return jobs.get("Insert Entity Records Job")
            .incrementer(new RunIdIncrementer())
             .listener(new InsertRecordListener())
            .start(downloadFileStep())
            .next(insertIntoDBStep())
            .build();
}

@Bean
ItemProcessor<Entity, Entity> csvEntityProcessor() {
    return new EntityItemProcessor();
}

@Bean
public Step insertIntoDBStep(){
    return steps.get("Insert Entity Records Step")
            .<Entity, Entity>chunk(500)
            .reader(csvFileReader())
            .processor(csvEntityProcessor())
            .writer(itemWriter())
            .build();
}

@Bean
public Step downloadFileStep(){
    return steps.get("Download File Step")
            .tasklet(new DownloadFileTasklet("https://leidata-preview.gleif.org/storage/golden-copy-files/2018/06/14/49694/20180614-0000-gleif-goldencopy-lei2-golden-copy.csv.zip",
                    fileDao,
                    FileAction.INIT_ENTITY,
                    this))
            .allowStartIfComplete(true)
            .build();
}

@Bean
public FlatFileItemReader<Entity> csvFileReader(){
    System.out.println("file name: " + fileName);
    FlatFileItemReader<Entity> reader = new FlatFileItemReader<>();
    reader.setResource(new ClassPathResource("data/"+this.fileName));
    reader.setStrict(false);
    reader.setLinesToSkip(1);
    reader.setLineMapper(lineMapper());

    return reader;
}

You can see that reader.setResource(new ClassPathResource("data/"+this.fileName)); takes the local variable fileName that I set in the Tasklet of the first step.


Solution

  • Late binding is handled by Spring Batch, you have to set the scope of the bean to step.

    Using XML :

    <bean id="myReader" scope="step"...>
    

    Using Java (annotation to set on your bean declaration) :

    @StepScope
    

    Documentation : https://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html#step-scope