Spring batch partitioner: How to extend the reader class as a bean and refer it inside configuration class

41 Views Asked by At

Here is my configuration class,

@Bean
  @StepScope
    public JdbcPagingItemReader<DailyTransactionByUserId> pagingItemReader(
            @Value("#{stepExecutionContext['fromRow']}") Integer fromRow,
            @Value("#{stepExecutionContext['toRow']}") Integer toRow) throws Exception
    {  
      //Logic using fromRow and toRow
    }

    @Bean
        public DialyTransactionByUserIdPartitioner partitioner() 
        {
          DialyTransactionByUserIdPartitioner columnRangePartitioner = new DialyTransactionByUserIdPartitioner();
            return columnRangePartitioner;
        }
      @Bean
        public ItemWriter<DailyTransactionByUserId> dialyTransactionByUserIdItemWriter()
        {
            ItemWriter<DailyTransactionByUserId> itemWriter = appContext.getBean(DailyTransactionByUserWriter.class);
            return itemWriter;
        }
        @Bean
        public ItemProcessor<DailyTransactionByUserId, DailyTransactionByUserId> dialyTransactionByUserIdProcessor() {
            ItemProcessor<DailyTransactionByUserId, DailyTransactionByUserId> itemProcessor = appContext.getBean(DailyTransactionByUserProcessor.class);
            return itemProcessor;
        }
      //Master
        @Bean
        public Step dialyTransactionstep1() 
        {
            return new StepBuilder("FERA_DAILY_TRANSACTION_BY_USERID_API_CALL_STEP", jobRepository)
                    .partitioner(slaveStep().getName(), partitioner())
                    .step(slaveStep())
                    .gridSize(feraDailyTransactionByUserIdBatchProperties.getDailyTransactionByUserIdBatchStep1PartitionGridSize())
                    .taskExecutor(dailyTransactionByUserTaskExecutor())
                    .build();
        }
        
        // slave step
        @Bean
        public Step slaveStep() 
        {
            
            try {
                return new StepBuilder("slaveStep", jobRepository)
                        .<DailyTransactionByUserId, DailyTransactionByUserId>chunk(feraDailyTransactionByUserIdBatchProperties.getDailyTransactionByUserIdBatchStep1ReaderPageSize(),transactionManager)
                        .taskExecutor(dailyTransactionByUserTaskExecutor())
                        .reader(pagingItemReader(null,null))
                        .processor(dialyTransactionByUserIdProcessor())
                        .writer(dialyTransactionByUserIdItemWriter())
                        .build();
            } catch (Exception ex) {
                throw new RuntimeException("Error creating slave step: " + ex.getMessage());
            }
        }

Here the writter and processer is read as bean and injected to step. Now how to make reader also in same way? What should be in place of ".reader(pagingItemReader(null,null))" if reader is also injected as bean?

1

There are 1 best solutions below

0
M. Deinum On

You can just inject the beans into the method as arguments which is actually the recommended way to do this.

Something like this:

@Bean
@StepScope
public JdbcPagingItemReader<DailyTransactionByUserId> pagingItemReader(
    @Value("#{stepExecutionContext['fromRow']}") Integer fromRow,
    @Value("#{stepExecutionContext['toRow']}") Integer toRow) throws Exception
{  
  //Logic using fromRow and toRow
}

@Bean
public DialyTransactionByUserIdPartitioner partitioner() 
{
    return new DialyTransactionByUserIdPartitioner();
}

//Master
@Bean
public Step dialyTransactionstep1(
    Step slaveStep, 
    DialyTransactionByUserIdPartitioner partitioner,
    TaskExecutor dailyTransactionByUserTaskExecutor) 
{
    return new StepBuilder("FERA_DAILY_TRANSACTION_BY_USERID_API_CALL_STEP", jobRepository)
                    .partitioner(slaveStep.getName(), partitioner)
                    .step(slaveStep)
                    .gridSize(feraDailyTransactionByUserIdBatchProperties.getDailyTransactionByUserIdBatchStep1PartitionGridSize())
                    .taskExecutor(dailyTransactionByUserTaskExecutor)
                    .build();
}
        
// slave step
@Bean
public Step slaveStep(
    JdbcPagingItemReader<DailyTransactionByUserId> reader
    DailyTransactionByUserProcessor processor, 
    DailyTransactionByUserWriter writer,
    TaskExecutor dailyTransactionByUserTaskExecutor) 
{
    return new StepBuilder("slaveStep", jobRepository)
                .<DailyTransactionByUserId, DailyTransactionByUserId>chunk(feraDailyTransactionByUserIdBatchProperties.getDailyTransactionByUserIdBatchStep1ReaderPageSize(),transactionManager)
                .taskExecutor(dailyTransactionByUserTaskExecutor)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .build();
}

You can now also remove the @Bean methods for the processor/writer as those are already beans. When you start doing things like ApplicationContext.getBean from @Bean methods you want to rethink your solution.