I am new to Spring Batch, now, I have a sample to trigger Spring batch job from Quartz scheduler. My application is started by using Spring boot to loading the spring context.
My problem is everytime my application context was finished to load, the spring batch job is executed immediately, this is unexpected. After that, the job is triggered by Quartz as time set in cron expression.
I want to have a solution for removing the first time run of the job which happens right after spring context was loaded. Could anyone give me a way to do?
Below is my configuration file, my job is named "importUserJob"
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import org.quartz.JobDataMap;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
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.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.configuration.support.MapJobRegistry;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.repository.support.SimpleJobRepository;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableBatchProcessing
public class BatchConfiguration implements BatchConfigurer{
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public DataSource dataSource;
@Autowired
@Qualifier("jpaTxnManagerBean")
public PlatformTransactionManager transactionManager;
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean(name="importUserJob")
public Job importUserJob(JobCompletionNotificationListener listener) {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1())
.end()
.build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").
chunk(10)
.reader(reader())
.processor(processor()).transactionManager(transactionManager)
.build();
}
@Bean
public TaskExecutor taskExecutor(){
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(10);
taskExecutor.setCorePoolSize(5);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
@Bean
public ItemReader<Object> reader() {
return new ItemReader<Object>() {
int i = 0;
@Override
public Object read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
if(i == 100) return null;
if(i%10 == 0) System.out.println("_________________");
i++;
System.out.println("Access to reader: "+i);
return new String("abc"); // null could not run processor
}
};
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobCompletionNotificationListener listener) throws Exception{
SchedulerFactoryBean schedulerFac = new SchedulerFactoryBean();
CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean();
cronTrigger.setCronExpression("00 31 23 ? * TUE-SAT *");
cronTrigger.setName("EveryWeekDay");
cronTrigger.setGroup("quatz-group");
JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
jobDetail.setName("importUserJob");
jobDetail.setJobClass(JobLauncherDetails.class);
jobDetail.setDurability(true);
jobDetail.setGroup("quatz-group");
Map<String, Object> map = new HashMap<>();
map.put("jobName", "importUserJob");
map.put("jobLocator", getJobRegistry());
map.put("jobLauncher", getJobLauncher());
jobDetail.setJobDataAsMap(map);
jobDetail.afterPropertiesSet();
cronTrigger.setJobDetail(jobDetail.getObject());
cronTrigger.afterPropertiesSet();
schedulerFac.setTriggers(cronTrigger.getObject());
schedulerFac.afterPropertiesSet();
return schedulerFac;
}
@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() throws Exception{
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(getJobRegistry());
postProcessor.afterPropertiesSet();
return postProcessor;
}
@Bean
public JobRegistry getJobRegistry(){
MapJobRegistry jobRegistry = new MapJobRegistry();
return jobRegistry;
}
@Override
public JobExplorer getJobExplorer() throws Exception {
JobExplorerFactoryBean jobExplorer = new JobExplorerFactoryBean();
jobExplorer.setDataSource(dataSource);
jobExplorer.afterPropertiesSet();
return jobExplorer.getObject();
}
@Override
public JobLauncher getJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.setTaskExecutor(taskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
@Override
public JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(getTransactionManager());
factory.afterPropertiesSet();
return (JobRepository) factory.getObject();
}
@Override
public PlatformTransactionManager getTransactionManager() throws Exception {
return transactionManager;
}
}