Description
Bug description
JobScopeTestExecutionListener
registers a JobExecution
with id 123 (created via MetaDataInstanceFactory#createJobExecution()
) for every test using JobSynchronizationManager.register()
.
If the Job
under test relies on Job-scoped parameters obtained from the execution stored in the JobSynchronizationManager
, the 123rd job execution will fail, because when the Job starts and attempts to register its own JobExecution
with id 123, the JobSynchronizationManager
will not store it (since an execution with that id already exists).
In my specific case, this leads to expressions like #{jobParameters['myParam']}
evaluating to null
, because JobScope.getContext()
will return the execution registered by the JobScopeTestExecutionListener
.
I spent quite some time debugging this issue, because this only affects code that accesses the JobExecution
via the synchronization manager and only after exactly 123 times.
Environment
Spring Batch 4.3.2, Spring Boot 2.4.4.
Steps to reproduce
- Create
Job
with a@JobScope
dStep
that queries the job parameters. - Run the Job 123 (or more) times.
Expected behavior
The default id of a JobExecution
(defined in MetaDataInstanceFactory#DEFAULT_JOB_EXECUTION_ID
) should be a value that is not reached naturally by repeatedly calling a job. The same probably applies for instance ids and step execution ids.
Minimal Complete Reproducible example
I attached a demo project
demo.zip
Unzip it and run ./mvnw test
.
The project contains a job scoped tasklet step that throws an exception if the job parameter is null
.
A test runs this job, supplying the parameter, and repeats itself 125 times. When running the test, the repetition with execution id 123 fails.
Workaround
Place
public JobExecution getJobExecution() {
return null;
}
somewhere in the test class. This causes JobScopeTestExecutionListener
to not register its own JobExecution
.