2
votes

In my spring batch code, I am reading a csv file, processing it into a bean and trying to get the bean with values in writer. But I am unable to get the bean in writer. UserVO is the bean which has the values from csv file, which I am trying to get in writer. I initialized the bean as a common variable also, hoping that will be processed by reader ,processor and writer. Even used @Bean and @Autowired annotations before UserVO user = new UserVO();. Kindly help me solving this issue. Following is my code,

@EnableBatchProcessing
@Configuration
public class CsvFileToDatabaseConfig {

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Autowired
    public DataSource dataSource;

    UserVO user = new UserVO();

    @Bean
    public FlatFileItemReader<UserVO> csvReader() {
         FlatFileItemReader<UserVO> reader = new FlatFileItemReader<UserVO>();
        try{

        reader.setResource(new ClassPathResource("user.csv"));
        reader.setLineMapper(new DefaultLineMapper<UserVO>() {{
            setLineTokenizer(new DelimitedLineTokenizer() {{
                setNames(new String[] { "memberId", "mailId", "fullName", "appCode", "active"});
            }});
            setFieldSetMapper(new BeanWrapperFieldSetMapper<UserVO>() {{
                setTargetType(UserVO.class);
            }});
        }});

        }
        catch(Exception e){
            System.out.println(" Exception in reading " + e.getMessage());
        }
         return reader;
    }


    @Bean
    ItemProcessor<UserVO, UserVO> csvProcessor() {          
        return new Processor();
    }

    @Bean
    public JdbcBatchItemWriter<UserVO> csvWriter(UserVO user) {
         JdbcBatchItemWriter<UserVO> csvWriter = new JdbcBatchItemWriter<UserVO>();
         System.out.println("MEMBER ID --->" + user.memberId);
        return csvWriter;
    }

    @Bean
    public Step csvFileToDatabaseStep() throws Exception {
        LDSService ldsService = new LDSService();

        return stepBuilderFactory.get("csvFileToDatabaseStep")
                .<UserVO, UserVO>chunk(1)
                .reader(csvReader())
                .processor(csvProcessor())
                .writer(csvWriter(user))            
                .build();
    }

    @Bean
    Job csvFileToDatabaseJob(JobCompletionNotificationListener listener) throws Exception {
        return jobBuilderFactory.get("csvFileToDatabaseJob")
                .incrementer(new RunIdIncrementer())
                .listener(listener)
                .flow(csvFileToDatabaseStep())
                .end()
                .build();
    }

}
2
Your reader creates UserVo instances, which are passed to the processor and finally to the writer. So why on earth would you need to share it like you do now? Apparently you are working around Spring Batch. - M. Deinum

2 Answers

0
votes
public class SkipFooterLineItemProcessor implements ItemProcessor<UserVO, UserVO> {


    @Override
    public UserVO process(UserVO item) throws Exception {

       return item;

    }
}
0
votes

It looks like there are some confusions in your understanding of how things work that I would like to make clear before answering your question.

When you define Spring beans for Spring Batch components (reader, writer, etc), there is no actual reading or writing happening at that time. You are only defining those beans to be used by the step in your job. When you write this:

@Bean
public FlatFileItemReader<UserVO> csvReader() {
     FlatFileItemReader<UserVO> reader = new FlatFileItemReader<UserVO>();
    try{

    reader.setResource(new ClassPathResource("user.csv"));
    reader.setLineMapper(new DefaultLineMapper<UserVO>() {{
        setLineTokenizer(new DelimitedLineTokenizer() {{
            setNames(new String[] { "memberId", "mailId", "fullName", "appCode", "active"});
        }});
        setFieldSetMapper(new BeanWrapperFieldSetMapper<UserVO>() {{
            setTargetType(UserVO.class);
        }});
    }});

    }
    catch(Exception e){
        System.out.println(" Exception in reading " + e.getMessage());
    }
     return reader;
}

catching the exception and printing Exception in reading means you think that reading is happening at this method while it is not. This method only defines the item reader that will be used by the step. The actual reading will be done in the org.springframework.batch.item.ItemReader#read method called automatically by the chunk oriented step. Same thing for the writer (in regards to System.out.println("MEMBER ID --->" + user.memberId);).

Now that said, you don't need to create an instance of UserVO, you just need to specify which domain type each line of the CSV file should be mapped to and the reader will create instances of this type (as mentioned by M. Deinum in comments). So you need to remove this line: UserVO user = new UserVO(); and your job definition should be fine.

You can find a similar use case in the getting started guide here: https://spring.io/guides/gs/batch-processing/. You will see there is no need to manually create an instance of the domain type Person.

Hope this helps and clarifies a few things.