Description
JobParameters are managed by org.springframework.batch.core.scope.context.SynchronizationManagerSupport#executionHolder
using ThreadLocal, which prevents SpEL bindings (@Value("#{jobParameters['param']}")
) from working correctly in other threads.
However, JobParameters are typically read-only and do not change during batch execution. In a multi-threaded step (TaskExecutor), this ThreadLocal management causes access to JobParameters within JobScope or StepScope beans to fail.
I’m not sure why JobParameters need to be managed within a ThreadLocal JobContext. Could JobParameters be modified to be non-ThreadLocal instead?
I’m using a class that encapsulates JobParameters. However, access to this class's fields fails when accessed within a JobScope (or StepScope) bean in a multi-threaded step.
encapsulates JobParameters
@JobScope
@Component
public class MyJobParameters {
@Value("#{jobParameters['firstParam']}")
private String firstParam;
@Value("#{jobParameters['secondParam']}")
private String secondParam;
public String getFirstParam() {
return firstParam;
}
public String getSecondParam() {
return secondParam;
}
}
failed (multi thread step)
public Step myMultiThreadStep() {
return new StepBuilder("chunkWorkingStep", jobRepository)
.<Sample, Sample>chunk(500, new ResourcelessTransactionManager())
.reader(myReader())
.processor(myProcessor())
.writer(myWriter())
.taskExecutor(taskExecutor())
.build();
}
public ItemProcessor<Sample, Sample> myProcessor() {
String firstParam = myJobParameters.getFirstParam(); // failed
return item -> {
String secondParam = myJobParameters.getSecondParam(); // failed
return item;
};
}
ok (non multi thread step)
public Step myStep() {
return new StepBuilder("chunkWorkingStep", jobRepository)
.<Sample, Sample>chunk(500, new ResourcelessTransactionManager())
.reader(myReader())
.processor(myProcessor())
.writer(myWriter())
.build();
}
public ItemProcessor<Sample, Sample> myProcessor() {
String firstParam = myJobParameters.getFirstParam(); // ok
return item -> {
String secondParam = myJobParameters.getSecondParam(); // ok
return item;
};
}
If there’s anything I might be missing or not understanding, please let me know.