问题
I have a spring batch job. There is a step that is calling the reader method.
STEP
@Bean public Step myStep(FlatFileItemWriter<String> writer, Processor
processor, @Value("${com.tableName}") String myTableName) {
return stepBuilderFactory.get("step1")
.<MyBean, String> chunk(this.chuckSize)
.reader(reader(myTableName, this.myRowMapper))
.processor(processor)
.writer(writer)
.build();
}
READER Working
@Bean
public <T> JdbcCursorItemReader<T> reader(@Value("${com.tableName}") String tableName, RowMapper<T> rowMapper) {
JdbcCursorItemReader<T> jdbcCursorItemReader = new JdbcCursorItemReader<>();
String query = "select * from " + tableName;
jdbcCursorItemReader.setDataSource(dataSource);
jdbcCursorItemReader.setSql(query);
jdbcCursorItemReader.setRowMapper(rowMapper);
return jdbcCursorItemReader;
}
I want my reader to take dynamic tableNames. So I changed the reader to as mentioned below.
@Bean
public <T> JdbcCursorItemReader<T> reader(String tableName, RowMapper<T> rowMapper) {
JdbcCursorItemReader<T> jdbcCursorItemReader = new JdbcCursorItemReader<>();
String query = "select * from " + tableName;
jdbcCursorItemReader.setDataSource(dataSource);
jdbcCursorItemReader.setSql(query);
jdbcCursorItemReader.setRowMapper(rowMapper);
return jdbcCursorItemReader;
}
This cause the following error.
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method reader in com.walgreens.oracleextractionbatch.OracleExtractionJobConfiguration required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
I tried so many workarounds after intense googling. But I think I am missing something basic. Please help. TIA
回答1:
I changed the scope of the Reader, Writer and the Step bean to prototype. I left the scope of processor bean as is(Singleton) because the processor logic is the same for all the scenarios.
Thanks, Akash
回答2:
Making Reader dynamic in the context of Spring batch is making them lazy.
We Can make reader and writer lazy by using @StepScope
. With StepScope now We can pass parameters. The most popular way of passing Parameters are using JobParameters
or using stepExecutionContext
.
In your case , if you know table name at the start of job then use JobParameters
Sample Code for accessing JobParameters
in Step.
@Bean
@StepScope
public <T> JdbcCursorItemReader<T> reader(@Value("#{jobParameters['tableName']}") String tableName), RowMapper<T> rowMapper) {
If You are getting table name from some processing(in some previous step) then u need to set the table name in stepExecutionContext
This is how you can access table name from stepExecutionContext
@Bean
@StepScope
public <T> JdbcCursorItemReader<T> reader(@Value("#{stepExecutionContext['tableName']}") String tableName), RowMapper<T> rowMapper) {
JdbcCursorItemReader<T> jdbcCursorItemReader = new JdbcCursorItemReader<>();
String query = "select * from " + tableName;
jdbcCursorItemReader.setDataSource(dataSource);
jdbcCursorItemReader.setSql(query);
jdbcCursorItemReader.setRowMapper(rowMapper);
return jdbcCursorItemReader;
}
I hope this helps
来源:https://stackoverflow.com/questions/53909573/how-to-pass-a-string-non-managed-bean-to-a-managed-bean