Accessing Job Parameters Spring Batch

15,478

Solution 1

Another solution that works very well for ItemProcessors, ItemReaders, ItemWriters and so on is the @BeforeStep annotation. It is backed by a StepExecutionListener just like Eugene To mentioned. It is kind of a shortcut for that solution.

An implementation might look like this

@BeforeStep
public void beforeStep(StepExecution stepExecution) {
    JobParameters jobParameters = stepExecution.getJobParameters();

    Long millis = jobParameters.getLong("time");
    String path = jobParameters.getString("filePath");
}

Solution 2

You should be able to do ,

@Value("#{jobParameters['filePath']}") String filePath;

In case of any issues, you may try putting your reader in @StepScope.

Solution 3

You may add org.springframework.batch.core.listener.JobParameterExecutionContextCopyListener to your Step.

TaskletStep step = stepBuilderFactory.get("my-best-step") .<Item, Item>chunk(10) .reader(myBestReader) .writer(myBestWriter) .listener(new JobParameterExecutionContextCopyListener()) .build();

That Listener will copy JobParameters to ExecutionContext that is available in ItemReader's open and update methods

Share:
15,478

Related videos on Youtube

Deepak Puthraya
Author by

Deepak Puthraya

I am currently working as Senior Software Engineer at Playment. I enjoying coding in Java, Golang, JavaScript and Python.

Updated on September 15, 2022

Comments

  • Deepak Puthraya
    Deepak Puthraya over 1 year

    I have been struggling with accessing Job Parameters of a job using spring batch. Here is my implementation so far.

    @Configuration
    @EnableBatchProcessing
    @PropertySource("classpath:batch.properties")
    public class CSVBatchServiceImpl extends StepExecutionListenerSupport implements CSVBatchService {
        private static final Logger LOGGER = LoggerFactory.getLogger(CSVBatchServiceImpl.class);
        @Autowired
        public JobBuilderFactory jobBuilderFactory;
        @Autowired
        public StepBuilderFactory stepBuilderFactory;
    
        private QuestionReader questionReader = new QuestionReader();
    
        @Bean(name = "importQuestionsJob")
        public Job importQuestionsJob() {
            return jobBuilderFactory.get("importQuestionsJob")
                    .incrementer(new RunIdIncrementer())
                    .flow(step1())
                    .end()
                    .build();
        }
    
        @Bean
        public Step step1() {
            return stepBuilderFactory.get("step1")
                    .<Question, Question>chunk(2)
                    .reader(questionReader.reader())
                    .processor(processor())
                    .build();
        }
    
        @Bean
        public QuestionProcessor processor() {
            return new QuestionProcessor();
        }
    }
    
    class QuestionReader extends StepExecutionListenerSupport {
        private static final Logger LOGGER = LoggerFactory.getLogger(QuestionReader.class);
    
        //TODO: remove this
        private static JsonNode getJsonNode(String str) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                return mapper.readTree(str);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        @Bean
        public FlatFileItemReader<Question> reader() {
            FlatFileItemReader<Question> reader = new FlatFileItemReader<>();
            //TODO get this as a parameter
            reader.setResource(new ClassPathResource("duplicateLabels.csv"));
            reader.setLinesToSkip(1);
            reader.setLineMapper(new DefaultLineMapper<Question>() {{
                setLineTokenizer((new DelimitedLineTokenizer() {{
                    setNames(new String[]{"label", "body", "real_answer"});
                }}));
                setFieldSetMapper(new QuestionFieldSetMapper());
            }});
            return reader;
        }
    
        private static class QuestionFieldSetMapper implements FieldSetMapper<Question> {
            public Question mapFieldSet(FieldSet fieldSet) {
                Question question = new Question();
                question.setLabel(fieldSet.readString(0));
                question.setBody(getJsonNode(fieldSet.readString(1)));
                question.setRealAnswer(getJsonNode(fieldSet.readString(2)));
                return question;
            }
        }
    }
    

    I am calling the job like:

    JobParameters parameters = new JobParametersBuilder()
            .addLong("time", System.currentTimeMillis())
            .addString("filePath", "file.csv")
            .toJobParameters();
    jobLauncher.run(importQuestionsJob, parameters);
    

    How can I go about accessing the filePath parameter inside reader function?

  • M. Deinum
    M. Deinum about 7 years
    Setting a scope is mandatory using this without it will not work.
  • Deepak Puthraya
    Deepak Puthraya about 7 years
    Would really appreciate if you could tell me where I could add in code.
  • Sabir Khan
    Sabir Khan about 7 years
    I guess, you need it in reader() method so you can change reader signature like , reader(@Value("#{jobParameters['filePath']}") String filePath) but make sure that you annotate reader with @StepScope . In your step definition, you can pass null for this parameter like , questionReader.reader(null).