-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
In Spring Batch 6.x, SimpleJobLauncher, TaskExecutorJobOperator, and even JobOperator.run() ignore updated JobParameters on subsequent job executions when an Incrementer is present.
This behavior makes it impossible to execute the same job with different user-provided parameters (e.g. calJobYear=114, then calJobYear=115) even though the parameters are truly different.
The framework always reuses the first JobInstance signature and throws:
JobInstanceAlreadyCompleteException: A job instance already exists and is complete for identifying parameters={...}
If you want to run this job again, change the parameters.
Even though the parameters have already been changed.
This appears to be a regression / breaking behavior introduced in Spring Batch 6.0.
Environment
- Spring Batch 6.0.0
- Spring Boot (not required; can reproduce with plain Batch)
- JobRepository: tested with both MapJobRepository and JdbcJobRepository
- Java 17 / 21 / 25 (same behavior)
- Job defined with a custom
JobParametersIncrementer
Steps to Reproduce
1. Define a job with an incrementer
@Bean
public Job processCalendarJob(JobRepository jobRepository, Step step1) {
return new JobBuilder("processCalendarJob", jobRepository)
.incrementer(new RunIdIncrementer())
.start(step1)
.build();
}2. Execute job first time
JobParameters params = new JobParametersBuilder()
.addString("calJobYear", "114")
.addString("calJobUserID", "000040")
.addString("calJobUserNam", "UserA")
.addString("calJobSyncOthers", "Y")
.addLong("calJobUseOrgSeqNO", 1L)
.addLong("run.id", System.currentTimeMillis())
.toJobParameters();
jobOperator.start("processCalendarJob", params);This works correctly.
3. Change parameters and execute again
JobParameters params2 = new JobParametersBuilder()
.addString("calJobYear", "115")
.addString("calJobUserID", "000040")
.addString("calJobUserNam", "UserA")
.addString("calJobSyncOthers", "Y")
.addLong("calJobUseOrgSeqNO", 1L)
.addLong("run.id", System.currentTimeMillis())
.toJobParameters();
jobOperator.start("processCalendarJob", params2);Actual behavior
Even though calJobYear changed from 114 → 115, SimpleJobOperator internally receives the original parameters of the first execution:
parameters = {calJobYear=114, calJobUserID=000040, ...}
And Spring Batch throws:
JobInstanceAlreadyExistsException
JobInstanceAlreadyCompleteException
Expected behavior
Spring Batch should treat the second execution as a new JobInstance, because the identifying parameters are different (calJobYear=115).
This is the behavior in Spring Batch 4.x and 5.x.
Debug Evidence
Debugger shows:
✔ The caller sends correct updated parameters to JobOperator
✘ Inside Spring Batch core (SimpleJobOperator), the parameters become the first run's parameters
✘ Incrementer only receives {} empty parameters (ignoring user-provided ones)
Thus, the JobInstance identity is incorrectly frozen to the first execution.
This prevents all subsequent executions unless the job name is changed.
Why This is a Serious Issue
- Many real-world batch jobs must run repeatedly with different user-provided parameters
(yearly jobs, monthly jobs, financial closing jobs, report generation jobs, etc.) - SB6 silently ignores updated parameters, making such jobs impossible to execute
- @JobScope and @StepScope also fail to receive updated parameters because the upstream parameters are incorrect
- The behavior contradicts documentation which states identifying parameters determine JobInstance identity
This is effectively a breaking change from Spring Batch 5 → 6.
Root Cause Analysis (Observed)
Spring Batch 6 seems to:
- Freeze JobInstance identity based on the first parameter schema
- Ignore subsequent user-provided JobParameters when an incrementer is present
- Only pass
{}toJobParametersIncrementer.getNext()
Thus any attempt to execute the job again with different parameters is blocked.
Request
Please confirm whether:
- This is a regression in Spring Batch 6
- Or a design change that should be documented more clearly
- Or a bug in how JobParameters are propagated to JobOperator/JobLauncher
If it is unintended, please consider restoring the previous behavior:
✔ Allow different identifying JobParameters to create new JobInstances
✔ Do not freeze Parameter schema at first execution
✔ Ensure Incrementer receives full original parameters
Workarounds Tested (and failed)
- Using
TaskExecutorJobOperatorinstead ofSimpleJobOperator - Using
JobLauncher.run()directly - Removing identifying flags
- Removing
run.id - Adding custom incrementer
- Using pure JDBC JobRepository
- Using in-memory MapJobRepository
- Using @JobScope, @StepScope beans
- Using completely new JobParametersBuilder
None of these resolved the issue.
Conclusion
This issue effectively blocks migration to Spring Batch 6 for any applications that must:
- Run the same job multiple times
- With different parameters
- Without changing the job name
Please help clarify whether this is a bug or an intentional behavior change.
Thank you!