1

I am going to develop an application where I am trying to read CSV file using Spring FlatFileItemReader object. I like to use a Service in where a method will be called to execute reading process. But I am not directly using configuration bean object of FlatFileItemReader and others. An example of my prototype bellow.

public void executeCsvReading(){

    FlatFileItemReader<SomeModel> reader = new FlatFileItemReader<SomeModel>();

    reader.setResource(new ClassPathResource("someFile.csv"));

    reader.setLineMapper(new DefaultLineMapper<SomeModel>() {
        {

            setLineTokenizer(new DelimitedLineTokenizer() {
                {
                    setNames(new String[] { "somefield1", "somefield2" });
                }
            });

            setFieldSetMapper(new BeanWrapperFieldSetMapper<SomeModel>() {
                {
                    setTargetType(SomeModel.class);
                }
            });
        }
    });

// But how do I start this Job?
   Job job = jobBuilderFactory
            .get("readCSVFilesJob")
            .incrementer(new RunIdIncrementer())
            .start(step)
            .build();

   Step step = stepBuilderFactory.get("step1").<SomeModel, SomeModel>chunk(5)
            .reader(reader)
            .writer(new WriteItemsOn()) // Call WriteItemsOn class constructor
            .build();
}

public class WriteItemsOn implements ItemWriter<User> {

    @Override
    public void write(List<? extends SomeModel> items) throws Exception {
        // TODO Auto-generated method stub
        for (SomeModel item : items) {
            System.out.println("Item is " + item.someMethod()");
        }
    }
}

1 Answer 1

1

// But how do I start this Job?

To start the job, you need to use a JobLauncher. For example:

SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
//jobLauncher.setJobRepository(yourJobRepository);
//jobLauncher.setTaskExecutor(yourTaskExecutor);
jobLauncher.afterPropertiesSet();
jobLauncher.run(job, new JobParameters());

However, with this approach, you will need to configure infrastructure beans required by Spring Batch (JobRepository, JobLauncher, etc) yourself.

I would recommend to use a typical Spring Batch job configuration and run your job from the method executeCsvReading. Here is an example:

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class MyJob {

    private final JobBuilderFactory jobBuilderFactory;

    private final StepBuilderFactory stepBuilderFactory;

    public MyJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
        this.jobBuilderFactory = jobBuilderFactory;
        this.stepBuilderFactory = stepBuilderFactory;
    }

    @Bean
    public Step step() {
        return stepBuilderFactory.get("step")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("hello world");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Job job() {
        return jobBuilderFactory.get("job")
                .start(step())
                .build();
    }

}

With this job configuration in place, you can load the Spring application context and launch your job as follows:

public void executeCsvReading() {
   ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
   JobLauncher jobLauncher = context.getBean(JobLauncher.class);
   Job job = context.getBean(Job.class);
   jobLauncher.run(job, new JobParameters());
}

Note that loading the Spring application context can be done outside the method executeCsvReading so that it is not loaded each time this method is called. With this approach, you don't have to configure infrastructure beans required by Spring Batch yourself, they will be automatically created and added to the application context. It is of course possible to override them if needed.

Heads up: If you put the MyJob configuration class in the package of your Spring Boot app, Spring Boot will by default execute the job at startup. You can disable this behaviour by adding spring.batch.job.enabled=false to your application properties.

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.