简体   繁体   中英

Spring boot batch scheduler run once

I started to learn Spring Boot Batch in version 2.1.4

I want to run my job in scheduler and this job runs only once. I mean ItemProcessor and ItemWriter run only once. ItemReader runs every time. anyone have an idea what I did wrong. In the future, I want to change scheduler to Java WatchService and pass filePath to the job but now parameter for filePath is like a string in the function parameter. This is my code:

This is my reader:

@Component
public class UserReaderImpl  {
    @StepScope
    public ItemReader<UserCsvStructure> read(String filepath) {
        FlatFileItemReader<UserCsvStructure> reader = new FlatFileItemReader();
        reader.setLinesToSkip(1);
        reader.setResource(new FileSystemResource(filepath));
        reader.setLineMapper(new DefaultLineMapper<UserCsvStructure>() {
            {
                setLineTokenizer(new DelimitedLineTokenizer() {
                    {
                        setNames(new String[]{"firstName","lastName","email"});
                    }
                });
                setFieldSetMapper(new BeanWrapperFieldSetMapper<UserCsvStructure>() {
                    {
                        setTargetType(UserCsvStructure.class);
                    }
                });
            }
        });
        return reader;
    }
}

This in my ItemProcessor

@StepScope
@Component
public class UserProcessorImpl implements ItemProcessor<UserCsvStructure, User> {
@Override
public User process(UserCsvStructure userCsvStructure) throws Exception {
    return User.builder()
            .email(userCsvStructure.getEmail())
            .firstName(userCsvStructure.getFirstName())
            .lastName(userCsvStructure.getLastName())
            .build();
}
}

This is my ItemWriter

@Component
@StepScope
public class UserWriterImpl implements ItemWriter<User>{
@Autowired
private UserRepository userRepository;

@Override
public void write(List<? extends User> list) throws Exception {
    System.out.println(list);
    userRepository.saveAll(list);
}
}

And this is my configuration

@Component
public class UserBatchCsvConfig {

@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;

@Autowired
private UserReaderImpl userReader;

@Autowired
private UserWriterImpl userWriter;

@Autowired
private UserProcessorImpl userProcessor;

public Job csvFileToDatabaseJob(UserJobCompletionNotificationListener listener, String fileName) {
    return jobBuilderFactory.get("userCsvProcess")
            .incrementer(new RunIdIncrementer())
            .listener(listener)
            .flow(csvFileToDatabaseStep(fileName))
            .end()
            .build();
}

private Step csvFileToDatabaseStep(String fileName) {
    return stepBuilderFactory.get("userCsvProcess")
            .<UserCsvStructure, User>chunk(1)
            .reader(userReader.read(fileName))
            .processor(userProcessor)
            .writer(userWriter)
            .build();
}

}

Last class is my scheduler:

@Component
public class UserCsvProcessor {

@Autowired
private JobLauncher jobLauncher;

@Autowired
private UserBatchCsvConfig job;

@Autowired
private UserJobCompletionNotificationListener userJobCompletionNotificationListener;

@Scheduled(fixedDelay = 10000)
public void runJob() throws Exception {
    jobLauncher.run(job.csvFileToDatabaseJob(userJobCompletionNotificationListener, "C:\\Users\\Anik\\Desktop\\angular\\test.csv"), new JobParameters());
}
}

I know what should I add in my code In UserCsvProcessor class I need to change my scheduled function to:

@Scheduled(fixedDelay = 10000)
public void runJob() throws Exception {
    JobParameters params = new JobParametersBuilder()
            .addString("JobID", String.valueOf(System.currentTimeMillis()))
            .toJobParameters();
    jobLauncher.run(job.csvFileToDatabaseJob(userJobCompletionNotificationListener, "C:\\Users\\Anik\\Desktop\\angular\\test.csv"), params);
}

If someone has other idea or better idea just add an answer

With the configuration you have in @Scheduled annotation you are indicating to be executed every 10 seconds. So, when your first execution is completed it will wait 10 seconds and then execute it again and so on.

@Scheduled(fixedDelay = 10000)

If you want to execute it once (I guess it is once a day) you can use cron expression in your @Scheduled annotation. Check the example below where the cron expression indicates that the method should be executed every day at 10:15 am

@Scheduled(cron = "0 15 10 * * *")

If you want to run it once a month/year you can handle the cron expression to do that. Additionally, you can read that expression from the configuration file using something like the following:

@Scheduled(cron = "${cron.expression}")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM