I'm setting up a job server using Spring Batch. My JdbcCursorItemReader needs to be configured with sql that changes on a per-job run basis. Because the sql changes, I want the reader to have @StepScope so I don't need to worry about sql statefulness.
So I've setup a class like this:
public class ParameterSettingJdbcCursorItemReader extends JdbcCursorItemReader implements StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
JobParameters jobParameters = stepExecution.getJobParameters();
if (jobParameters != null) {
List<Object> args = new ArrayList<Object>();
for (JobParameter jobParameter : jobParameters.getParameters().values()) {
args.add(jobParameter.getValue());
}
Object[] arrayArgs = args.toArray(new Object[args.size()]);
String sql = String.format(getSql(), arrayArgs);
setSql(sql);
}
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
}
The idea is that I pass sql parameters to the object via JobParameters and use String.format to fill in the dynamically-changing sql.
I am using Java-based configuration throughout my server. My bean for one instance of my ItemReader looks like:
@Bean
@StepScope
public ItemReader<MyInputObject> myInputObjectItemReader() {
ParameterSettingJdbcCursorItemReader itemReader = new ParameterSettingJdbcCursorItemReader();
itemReader.setDataSource(myDataSource());
itemReader.setSql("SELECT * FROM my_table WHERE date = '%1$s'");
itemReader.setRowMapper(myInputObjectMapper);
return itemReader;
}
When I start up my server and run the Spring Batch job, I get this error: java.lang.IllegalStateException: No Scope registered for scope 'step'
I've read elsewhere that in order to be able to use StepScope, one needs to first add it to the xml app configuration like this :
<bean class="org.springframework.batch.core.scope.StepScope" />
But since I'm using Java-based configuration, that's not an option.
So how do I register the StepScope via a Java-based config? I've tried this:
@Bean
public org.springframework.batch.core.scope.StepScope stepScope() {
return new org.springframework.batch.core.scope.StepScope();
}
... but when I do I get all sorts of NPEs during app startup on beans that have no relation to StepScope.
Thanks in advance.
You have to register the scope with the ApplicationContext
. Normally that would be done for you when you use @EnableBatchProcessing
. Did you do that (add that annotation to one of your @Configurations
)?
+1 to Dave's point about using @EanbleBatchProcesssing. That will add a StepScope
to your context. However, your code still won't work once you've done that because you're returning an ItemReader for "myInputObjectItemReader" instead of ParameterSettingJdbcCursorItemReader
. See the issue here for details on why that matters: Spring-batch @BeforeStep does not work with @StepScope
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With