Expected Behavior:
A JobParametersIncrementer
is expected to modify the given JobParameters
to provide a modified set of JobParameters
. If the new set of JobParameters
is unique for the Job
then a new JobInstance
will be created.
Actual Behavior:
Before the JobParametersIncrementer
is executed, a JobInstance
is found in the "if" statement on line 206 in method getNextJobParameters(Job job, JobParameters jobParameters)
of JobLauncherApplicationRunner
.
private JobParameters getNextJobParameters(Job job, JobParameters jobParameters) {
if (this.jobRepository != null && this.jobRepository.isJobInstanceExists(job.getName(), jobParameters)) {
return getNextJobParametersForExisting(job, jobParameters);
}
if (job.getJobParametersIncrementer() == null) {
return jobParameters;
}
JobParameters nextParameters = new JobParametersBuilder(jobParameters, this.jobExplorer)
.getNextJobParameters(job).toJobParameters();
return merge(nextParameters, jobParameters);
}
The method getNextJobParametersForExisting(Job job, JobParameters jobParameters)
is then executed which in the case of a 'COMPLETED' JobExecution
will return the original JobParameters
object.
private JobParameters getNextJobParametersForExisting(Job job, JobParameters jobParameters) {
JobExecution lastExecution = this.jobRepository.getLastJobExecution(job.getName(), jobParameters);
if (isStoppedOrFailed(lastExecution) && job.isRestartable()) {
JobParameters previousIdentifyingParameters = getGetIdentifying(lastExecution.getJobParameters());
return merge(previousIdentifyingParameters, jobParameters);
}
return jobParameters;
}
Use Case
Restarting a 'COMPLETED' job using a JobParameterIncrementer
. Below is the JobParameterIncrementer
expected to provide a unique set of JobParameters
for each execution.
package util;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersIncrementer;
public class ForceRestart implements JobParametersIncrementer {
private static final long JOB_PARAMETER_MAXIMUM = 1000000;
@Override
public JobParameters getNext(JobParameters params) {
Long random = (long) (Math.random() * JOB_PARAMETER_MAXIMUM);
return new JobParametersBuilder(params).addLong("random", random).toJobParameters();
}
}
Version: 2.2.6.RELEASE
Comment From: wilkinsona
@benas Can we have some of your expertise here please? I believe both JobLauncherCommandLineRunner
and JobLauncherApplicationRunner
have the same behaviour at the moment.
Comment From: fmbenhassine
Expected Behavior: A JobParametersIncrementer is expected to modify the given JobParameters to provide a modified set of JobParameters
@touchrock Where did you read that expected behavior? The incrementer does not increment the given parameters, it increments the parameters of the previous instance in the sequence. This is explained in the reference documentation and in the Javadocs.
Use Case Restarting a 'COMPLETED' job using a JobParameterIncrementer
In Spring Batch, it is not possible to restart a completed job instance by design (if you attempt to do so you will get a JobInstanceAlreadyCompleteException
), you can only restart a failed or stopped instance, and this is true with or without a JobParametersIncrementer
. So trying to create an incrementer named ForceRestart
that adds a random number as a parameter will not "force a restart", it will only create a new job instance that is different from the previous one in the sequence.
The current behavior is correct: the job runner first checks the existence of a job instance with the given parameters and if a completed instance is present then it returns the same parameters which will make the job launcher throw a JobInstanceAlreadyCompleteException
as designed.
Comment From: wilkinsona
Thanks very much, @benas.