How to pass a String (Non managed bean) to a managed bean

放肆的年华 提交于 2019-12-13 03:57:59

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!