'Job parameters change between JobLauncherCommandLineRunner and SimpleJobLauncher

Using spring batch, I am trying to start a job with some parameters but parameters from previous instance are used.

Spring is started using ApplicationContext context = SpringApplication.run(Application.class, args);

My job bean :

@Bean
public Job closingJob(JobCompletionNotificationListener listener,
                      Step step1,
                      Step step2,
                      Step step3,
                      JobParametersValidator validator) {

    return jobBuilderFactory.get("quarterly-closing")
                            .incrementer(new RunIdIncrementer())
                            .validator(validator)
                            .listener(listener)
                            .flow(step1)
                            .next(step2)
                            .next(step3)
                            .end()
                            .build();
}

In the logs :

2020-04-15 08:51:10,259 -  INFO - [] {o.s.b.a.b.JobLauncherCommandLineRunner} --> Running default command line with: [run.id(long)=1, my.param=secondRun ]
2020-04-15 08:51:10,422 -  INFO - [] {o.s.b.c.l.s.SimpleJobLauncher} --> Job: [FlowJob: [name=my-job]] launched with the following parameters: [{run.id=2, my.param=firstRun}]

I saw a similar question but there are only one answer that doesn't help me.

Edit : I tried it with a custom JobParametersIncrementer but it doesn't work : it still uses the previous instance parameters

@Bean
public JobParametersIncrementer incrementer(){ 
   return parameters -> {
      if (parameters==null || parameters.isEmpty()) {
         return new JobParametersBuilder().addLong("run.id",1L).toJobParameters();
      }

      long id = parameters.getLong("run.id",1L) + 1;
      return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
   };
}


Solution 1:[1]

From your log statements, it does look like the RunIdIncrementer is being hit.

2020-04-15 08:51:10,259 -  INFO - [] {o.s.b.a.b.JobLauncherCommandLineRunner} --> Running default command line with: [run.id(long)=1, my.param=secondRun ]
2020-04-15 08:51:10,422 -  INFO - [] {o.s.b.c.l.s.SimpleJobLauncher} --> Job: [FlowJob: [name=my-job]] launched with the following parameters: [{run.id=2, my.param=firstRun}]

JobLauncherCommandLineRunner says:

run.id(long)=1

SimpleJobLauncher says:

run.id=2

JobLauncherCommandLineRunner

The log statement for JobLauncherCommandLineRunner happens before any modifications to the JobParameters occur.

Relevant Code Snippet (Source):

    public void run(String... args) throws JobExecutionException {
        logger.info("Running default command line with: " + Arrays.asList(args));
        launchJobFromProperties(StringUtils.splitArrayElementsIntoProperties(args, "="));
    }

Assumption

I'm assuming you're trying to execute a job more than once given a static run.id=1 parameter, and continually getting run.id=2 from your incrementer. If you're wanting to increment the JobParameters to guarantee unique JobParameters, you have to try a different approach.

Look at the below JobParameterIncrementer snippet, which take a set of JobParameters and adds a parameter random=(random long value):

    @Override
    public JobParameters getNext(JobParameters params) {
        
        Long random = (long) (Math.random() * 1000000);

        return new JobParametersBuilder(params).addLong("random", random).toJobParameters();
    }

Solution 2:[2]

Using spring batch, I am trying to start a job with some parameters but parameters from previous instance are used.

According to your job definition, you are using a JobParametersIncrementer. When you add an incrementer to your job definition, you are basically telling Spring Batch the following: Whenever I run a my job, do increment the parameters of the previous instance using my incrementer and create a new job instance.

Using a job parameters incrementer makes sense when there is a logical sequence of job instances (aka it is possible to calculate the next job instance from the previous one).

So Spring Batch will take the parameters of the previous instance, pass them to your incrementer, and use those returned by the incrementer to create the "next" job instance in the sequence.

Hopefully this makes it clear why "parameters from previous instance are used".

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mason T.
Solution 2