Job doesn't reschedule immediately when triggers update in quartz - spring

I'm trying to develop an spring application using Quartz which reads trigger time for Job from database and run it. I have managed to implement this scenario successfully.However, during job execution when i update the trigger time in database, it doesn't run the trigger the job according to the new time but it always run old time.
Code:
#Configuration
#ComponentScan
public class QuartzConfiguration {
#Bean
public MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
MethodInvokingJobDetailFactoryBean obj = new MethodInvokingJobDetailFactoryBean();
obj.setTargetBeanName("jobone");
obj.setTargetMethod("myTask");
return obj;
}
#Autowired
public TestModelRepository testModelRepository;
#Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(MyJobTwo.class);
TestModel result = testModelRepository.findOne((long) 1);
factory.setGroup("mygroup");
factory.setName("myjob");
return factory;
}
public TestModelRepository getTestModelRepository() {
return testModelRepository;
}
public void setTestModelRepository(TestModelRepository testModelRepository) {
this.testModelRepository = testModelRepository;
}
#Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(){
CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
stFactory.setJobDetail(jobDetailFactoryBean().getObject());
//stFactory.setStartDelay(3000;
stFactory.setName("mytrigger");
stFactory.setGroup("mygroup");
TestModel result = testModelRepository.findOne((long) 1);
stFactory.setCronExpression(result.getCronTime());
return stFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setTriggers(cronTriggerFactoryBean().getObject());
return scheduler;
}
}
Job:
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
public class MyJobTwo extends QuartzJobBean {
public static final String COUNT = "count";
private static URI jiraServerUri = URI.create("");
JiraRestClient restClient = null;
private String name;
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
final AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
restClient = factory.createWithBasicHttpAuthentication(jiraServerUri,"", "");
}
public void setName(String name) {
this.name = name;
}
Any idea?

Just in case if someone needs solution.
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setOverwriteExistingJobs(true);

Related

JobParameters cannot be found in spring batch

I need your help plizz!!
i have a spring batch app and i need to pass job parameters to my quartz job.
Here is my JobLauncher in which i want to pass each line of list as job parameters :
#Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
JdbcTemplate Jd = new JdbcTemplate(ds);
List<QuartzParameters> list=null;
list=Jd.query("select * from FLUX_INFO",new QuartzParametersMapper());
for (QuartzParameters i : list) {
Job job = jobLocator.getJob(jobName);
JobParametersBuilder JP = new JobParametersBuilder();
JP.addString("PAYS", i.getPAYS());
JP.addString("CRON", i.getCRON());
JP.addString("CLASSAPP",i.getCLASSAPP());
JobParameters paramJobParameters=JP.toJobParameters();
JobExecution jobExecution = jobLauncher.run(job, paramJobParameters);
log.info("{}_{} was completed successfully", job.getName(), jobExecution.getId());
} } catch (Exception e) {
log.error("Encountered job execution exception!");
}}}
And here is my batch config class :
#Value("#{jobParameters[CLASSAPP]}")
private String ClassApp;
#Scope("step")
#Bean
public JdbcCursorItemReader<FichierEclate> readerDB(){
JdbcCursorItemReader<FichierEclate> reader = new JdbcCursorItemReader<FichierEclate>();
reader.setDataSource(ds);
reader.setSql(query(ClassApp));
reader.setRowMapper(new FichierEclateRowMapper());
return reader;
}
i am also using another parameter in Quartz config :
#Value("#{jobParameters[CRON]}")
private String CRON_EXPRESSION;
#StepScope
#Bean
public JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(QuartzJobLauncher.class);
Map map = new HashMap();
map.put("jobName", "JobFinal");
map.put("jobLauncher", jobLauncher);
map.put("jobLocator", jobLocator);
map.put("CRON_EXPRESSION", CRON_EXPRESSION );
factory.setJobDataAsMap(map);
factory.setGroup("etl_group");
factory.setName("etl_job");
return factory;}
I am also using the job parameter in the processor class :
#Value("#{jobParameters[CLASSAPP]}")
private String ClassApp;
#Scope("step")
#Override
public TdfFile process(FichierEclate item) throws Exception {
//some code and use the **CLASSAPP** variable }
i tried to use #StepScope But same problem !! i get this :
Error creating bean with name 'batchConfig': Unsatisfied dependency expressed through field 'ClassApp'; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Here is QuartzConfiguration class :
#Configuration
public class QuartzConfiguration {
#Value("#{jobParameters[CRON]}")
private String CRON_EXPRESSION;
#Autowired
private JobLauncher jobLauncher;
#Autowired
private JobLocator jobLocator;
public QuartzConfiguration() {
super();
}
#Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry);
return jobRegistryBeanPostProcessor;
}
#Bean
#Scope(value="step", proxyMode=ScopedProxyMode.TARGET_CLASS)
public JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(QuartzJobLauncher.class);
Map map = new HashMap();
map.put("jobName", "JobFinal");
map.put("jobLauncher", jobLauncher);
map.put("jobLocator", jobLocator);
map.put("CRON_EXPRESSION", CRON_EXPRESSION );
factory.setJobDataAsMap(map);
factory.setGroup("etl_group");
factory.setName("etl_job");
return factory;
}
// Job is scheduled after every 3 minutes
#Bean
public CronTriggerFactoryBean cronTriggerFactoryBean() {
CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
stFactory.setJobDetail(jobDetailFactoryBean().getObject());
stFactory.setStartDelay(3000);
stFactory.setName("cron_trigger");
stFactory.setGroup("cron_group");
stFactory.setCronExpression(CRON_EXPRESSION);
// stFactory.getJobDataMap().get(app);
return stFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setTriggers(cronTriggerFactoryBean().getObject());
return scheduler;
}}
And here is the jobLauncher class :
public class QuartzJobLauncher extends QuartzJobBean {
private static final Logger log = LoggerFactory.getLogger(QuartzJobLauncher.class);
#Autowired
private DataSource ds;
private String jobName;
private JobLauncher jobLauncher;
private JobLocator jobLocator;
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public JobLauncher getJobLauncher() {
return jobLauncher;
}
public void setJobLauncher(JobLauncher jobLauncher) {
this.jobLauncher = jobLauncher;
}
public JobLocator getJobLocator() {
return jobLocator;
}
public void setJobLocator(JobLocator jobLocator) {
this.jobLocator = jobLocator;
}
#Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
JdbcTemplate Jd = new JdbcTemplate(ds);
List<QuartzParameters> list=null;
list=Jd.query("select * from FLUX_INFO",new QuartzParametersMapper());
for (QuartzParameters i : list) {
Job job = jobLocator.getJob(jobName);
JobParametersBuilder JP = new JobParametersBuilder();
JP.addString("PAYS", i.getPAYS());
JP.addString("CRON", i.getCRON());
JP.addString("CLASSAPP",i.getCLASSAPP());
JobParameters paramJobParameters=JP.toJobParameters();
final JobExecution jobExecution = jobLauncher.run(job, paramJobParameters);
log.info("{}_{} was completed successfully", job.getName(), jobExecution.getId());
}} catch (Exception e) {
log.error("Encountered job execution exception!");
}}}
I tried to add #Scope(value="step", proxyMode=ScopedProxyMode.TARGET_CLASS) on classes directly or on Beans !! Both ways did not work !
Did anyone try a solution to solve this pliz ?!
Since you are injecting the job parameter in a field of your class, then #Scope("step") should be placed on the class itself, something like:
#Component
#Scope("step")
public class MyProcessor implements ItemProcessor<FichierEclate, TdfFile> {
#Value("#{jobParameters[CLASSAPP]}")
private String ClassApp;
#Override
public TdfFile process(FichierEclate item) throws Exception {
//some code and use the **CLASSAPP** variable
}
}
The same thing should be done for other classes where you want to inject jobParameters[CRON] and jobParameters[CLASSAPP].

Records are not written in files when invoked from BillerOrderWriter which implements ItemWriter in Spring Batch

I am trying to write successful records using one writer and failed records in another writer.
I have written BillerOrderWriter class which implements ItemWriter. I put some log statements and I can see it writes success billerOrderId or failed billerOrderId . But, it seems like it does not invoke DatabaseToCsvFileJobConfig or SuccessfulOrdersToCsvFileJobConfig .
public class BillerOrderWriter implements ItemWriter<BillerOrder>{
private static Logger log = LoggerFactory.getLogger("BillerOrderWriter.class");
#Autowired
SuccessfulOrdersToCsvFileJobConfig successfulOrdersToCsvFileJobConfig;
#Autowired
DatabaseToCsvFileJobConfig databaseToCsvFileJobConfig;
#Override
public void write(List<? extends BillerOrder> items) throws Exception {
for (BillerOrder item : items) {
log.info("item = " + item.toString());
if (item.getResult().equals("SUCCESS")) {
log.info(" Success billerOrderId = " + item.getBillerOrderId());
successfulOrdersToCsvFileJobConfig.successfulDatabaseCsvItemWriter();
} else {
log.info("Failed billerOrderId = " + item.getBillerOrderId());
databaseToCsvFileJobConfig.databaseCsvItemWriter();
}
}
}
}
Here is BatchConfig class.
#Bean
public BillerOrderWriter billerOrderWriter() {
return new BillerOrderWriter();
}
#Bean
public Job importJobOrder(JobCompletionNotificationListner listener, Step step1) {
return jobBuilderFactory.get("importJobOrder")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
.end()
.build();
}
#Bean(name="step1")
public Step step1(BillerOrderWriter billerOrderWriter) {
return stepBuilderFactory.get("step1")
.<BillerOrder, BillerOrder> chunk(10)
.reader((ItemReader<? extends BillerOrder>) reader())
.processor(processor())
.writer(billerOrderWriter)
.build();
}
Here is my successwriter and failedwriter class .
#Configuration
public class SuccessfulOrdersToCsvFileJobConfig {
private static Logger log = LoggerFactory.getLogger("SuccessfulOrdersToCsvFileJobConfig.class");
#Bean
public ItemWriter<BillerOrder> successfulDatabaseCsvItemWriter() {
log.info("Entering SuccessfulOrdersToCsvFileJobConfig...");
FlatFileItemWriter<BillerOrder> csvFileWriter = new FlatFileItemWriter<>();
String exportFileHeader = "BillerOrderId;SuccessMessage";
OrderWriter headerWriter = new OrderWriter(exportFileHeader);
csvFileWriter.setHeaderCallback(headerWriter);
String exportFilePath = "/tmp/SuccessBillerOrderIdForRetry.csv";
csvFileWriter.setResource(new FileSystemResource(exportFilePath));
LineAggregator<BillerOrder> lineAggregator = createOrderLineAggregator();
csvFileWriter.setLineAggregator(lineAggregator);
return csvFileWriter;
}
private LineAggregator<BillerOrder> createOrderLineAggregator() {
log.info("Entering createOrderLineAggregator...");
DelimitedLineAggregator<BillerOrder> lineAggregator = new DelimitedLineAggregator<>();
lineAggregator.setDelimiter(";");
FieldExtractor<BillerOrder> fieldExtractor = createOrderFieldExtractor();
lineAggregator.setFieldExtractor(fieldExtractor);
return lineAggregator;
}
private FieldExtractor<BillerOrder> createOrderFieldExtractor() {
log.info("Entering createOrderFieldExtractor...");
BeanWrapperFieldExtractor<BillerOrder> extractor = new BeanWrapperFieldExtractor<>();
extractor.setNames(new String[] {"billerOrderId","successMessage"});
return extractor;
}
}
#Configuration
public class DatabaseToCsvFileJobConfig {
private static Logger log = LoggerFactory.getLogger("DatabaseToCsvFileJobConfig.class");
#Bean
public ItemWriter<BillerOrder> databaseCsvItemWriter() {
log.info("Entering databaseCsvItemWriter...");
FlatFileItemWriter<BillerOrder> csvFileWriter = new FlatFileItemWriter<>();
String exportFileHeader = "BillerOrderId;ErrorMessage";
OrderWriter headerWriter = new OrderWriter(exportFileHeader);
csvFileWriter.setHeaderCallback(headerWriter);
String exportFilePath = "/tmp/FailedBillerOrderIdForRetry.csv";
csvFileWriter.setResource(new FileSystemResource(exportFilePath));
LineAggregator<BillerOrder> lineAggregator = createOrderLineAggregator();
csvFileWriter.setLineAggregator(lineAggregator);
return csvFileWriter;
}
private LineAggregator<BillerOrder> createOrderLineAggregator() {
log.info("Entering createOrderLineAggregator...");
DelimitedLineAggregator<BillerOrder> lineAggregator = new DelimitedLineAggregator<>();
lineAggregator.setDelimiter(";");
FieldExtractor<BillerOrder> fieldExtractor = createOrderFieldExtractor();
lineAggregator.setFieldExtractor(fieldExtractor);
return lineAggregator;
}
private FieldExtractor<BillerOrder> createOrderFieldExtractor() {
log.info("Entering createOrderFieldExtractor...");
BeanWrapperFieldExtractor<BillerOrder> extractor = new BeanWrapperFieldExtractor<>();
extractor.setNames(new String[] {"billerOrderId","errorMessage"});
return extractor;
}
}
Here is my job completion listener class.
#Component
public class JobCompletionNotificationListner extends JobExecutionListenerSupport {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(JobCompletionNotificationListner.class);
#Override
public void afterJob(JobExecution jobExecution) {
log.info("In afterJob ...");
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
DatabaseToCsvFileJobConfig databaseToCsvFileJobConfig = new DatabaseToCsvFileJobConfig();
SuccessfulOrdersToCsvFileJobConfig successfulOrdersToCsvFileJobConfig = new SuccessfulOrdersToCsvFileJobConfig();
}
}
}
In your BillerOrderWriter#write method, it is supposed to write code that does the actual write operation of items to a data sink. But in your case, you are calling successfulOrdersToCsvFileJobConfig.successfulDatabaseCsvItemWriter(); and databaseToCsvFileJobConfig.databaseCsvItemWriter(); which create item writer beans. You should inject those delegate writers and call their write method when needed, something like:
public class BillerOrderWriter implements ItemWriter<BillerOrder>{
private ItemWriter<BillerOrder> successfulDatabaseCsvItemWriter;
private ItemWriter<BillerOrder> databaseCsvItemWriter;
// constructor with successfulDatabaseCsvItemWriter + databaseCsvItemWriter
#Override
public void write(List<? extends BillerOrder> items) throws Exception {
for (BillerOrder item : items) {
if (item.getResult().equals("SUCCESS")) {
successfulDatabaseCsvItemWriter.write(Collections.singletonList(item));
} else {
databaseCsvItemWriter.write(Collections.singletonList(item));
}
}
}
}
Instead Of BillerOrderWriter, I wroter BillerOrderClassifier class.
public class BillerOrderClassifier implements Classifier<BillerOrder, ItemWriter<? super BillerOrder>> {
private static final long serialVersionUID = 1L;
private ItemWriter<BillerOrder> successItemWriter;
private ItemWriter<BillerOrder> failedItemWriter;
public BillerOrderClassifier(ItemWriter<BillerOrder> successItemWriter, ItemWriter<BillerOrder> failedItemWriter) {
this.successItemWriter = successItemWriter;
this.failedItemWriter = failedItemWriter;
}
#Override
public ItemWriter<? super BillerOrder> classify(BillerOrder billerOrder) {
return billerOrder.getResult().equals("SUCCESS") ? successItemWriter : failedItemWriter;
}
}
In BatchConfiguration, I wrote classifierBillerOrderCompositeItemWriter method.
#Bean
public ClassifierCompositeItemWriter<BillerOrder> classifierBillerOrderCompositeItemWriter() throws Exception {
ClassifierCompositeItemWriter<BillerOrder> compositeItemWriter = new ClassifierCompositeItemWriter<>();
compositeItemWriter.setClassifier(new BillerOrderClassifier(successfulOrdersToCsvFileJobConfig.successfulDatabaseCsvItemWriter(), databaseToCsvFileJobConfig.databaseCsvItemWriter()));
return compositeItemWriter;
}
#Bean(name="step1")
public Step step1() throws Exception{
return stepBuilderFactory.get("step1")
.<BillerOrder, BillerOrder> chunk(10)
.reader((ItemReader<? extends BillerOrder>) reader())
.processor(processor())
.writer(classifierBillerOrderCompositeItemWriter())
.stream(successfulOrdersToCsvFileJobConfig.successfulDatabaseCsvItemWriter())
.stream(databaseToCsvFileJobConfig.databaseCsvItemWriter())
.build();
}

Spring Quartz: Disable Quartz scheduler

We have an service with a quartz scheduler.
This service can be scaled accordingly some needs.
Our Quartz scheduler is not in a cluster mode.
So, we need to able or disable scheduler according to an environment variable.
Service can't be splitted in order to have two independent services.
This is our related Quartz configuration class:
#Configuration
public class QuartzSchedulerConfiguration {
private static final String HOURLY_CRON_EXPRESSION = "0 0 * * * ?";
private static final String MIDNIGHT_CRON_EXPRESSION = "0 0 0 * * ?";
#Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, Trigger[] fitxersJobTrigger)
throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setOverwriteExistingJobs(true);
factory.setAutoStartup(true);
factory.setJobFactory(jobFactory);
factory.setQuartzProperties(quartzProperties());
factory.setTriggers(fitxersJobTrigger);
return factory;
}
#Bean
public JobDetailFactoryBean loadPendingDocumentsJobDetail() {
return createJobDetailFactoryBean(LoadPendingDocumentsJob.class);
}
#Bean
public SimpleTriggerFactoryBean loadPendingDocumentsJobTrigger(
#Qualifier("loadPendingDocumentsJobDetail") JobDetail jobDetail) {
long interval = jobsConfiguration.get().getParameters().stream()
.filter(param -> "loadPendingDocumentsJobInterval".equals(param.getName()))
.findAny()
.map(param -> (Integer)param.getValue())
.orElse(600000); // every 10 minutes
LOG.debug("loadPendingDocumentsJobInterval = " + interval);
return createIntervalTriggerFactoryBean(jobDetail, interval);
}
private CronTriggerFactoryBean createCronTriggerFactoryBean(JobDetail jobDetail, String expression) {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setCronExpression(expression);
factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
return factoryBean;
}
private JobDetailFactoryBean createJobDetailFactoryBean(Class<? extends Job> jobClass) {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(jobClass);
factoryBean.setDurability(true);
return factoryBean;
}
private SimpleTriggerFactoryBean createIntervalTriggerFactoryBean(JobDetail jobDetail, long interval) {
SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setStartDelay(0L);
factoryBean.setRepeatInterval(interval);
factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
return factoryBean;
}
}
Any ideas?
You can try using the #ConditionalOnProperty Annotation on your configuration class.

Stop a scheduling job from rest endpoint

I am doing a Spring Boot Project
This is the main class
#SpringBootApplication
#ComponentScan(basePackages="blabla.quartz")
#EnableScheduling
public class App
{
public static void main( String[] args )
{
ConfigurableApplicationContext context =SpringApplication.run(App.class, args);
}
}
This is the controller
#RestController
public class Controller {
#Autowired
private SampleTask m_sampletask;
#Autowired TaskScheduler taskScheduler;
ScheduledFuture scheduledFuture;
int jobid=0;
#RequestMapping(value = "start/{job}", method = RequestMethod.GET)
public void start(#PathVariable String job) throws Exception {
m_sampletask.addJob(job);
Trigger trigger = new Trigger(){
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
org.quartz.CronExpression cronExp=null;
CronSequenceGenerator generator = new CronSequenceGenerator("0 * * ? * *");
Date nextExecutionDate = generator.next(new Date());
System.out.println(nextExecutionDate);
return nextExecutionDate;
}
};
scheduledFuture = taskScheduler.schedule(m_sampletask, trigger);
}
}
This is the ScheduleConfigurer implementation
#Service
public class MyTask implements SchedulingConfigurer{
#Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("somegroup-");
scheduler.setPoolSize(10);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
scheduler.setAwaitTerminationSeconds(20);
return scheduler;
}
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
}
}
This is the class which I am calling from controller as scheduled job
#Component
public class SampleTask implements Runnable{
private List<String> jobs=new ArrayList<String>();
private String jobName;
public void addJob(String job){
jobName=job;
}
#Override
public void run() {
System.out.println("Currently running "+jobName);
}
}
How to stop the schedule job by a rest endpoint(Suppose "/stop/{jobname}").. When I have started the job using the "/start/{jobname}" rest endpoint?
You will probably need to use the quartz scheduler (if not already), and add a service with the required methods, then inject that service into your controller.
There's a decent example here: https://github.com/javabypatel/spring-boot-quartz-demo
If you want an in-memory job store (that isn't a database), checkout the RAMJobStore: http://www.quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigRAMJobStore.html
Stop Example
This is an excerpt from the demo project. Credit goes to Jayesh Patel: https://github.com/javabypatel
/**
* Stop a job
*/
#Override
public boolean stopJob(String jobName) {
System.out.println("JobServiceImpl.stopJob()");
try{
String jobKey = jobName;
String groupKey = "SampleGroup";
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jkey = new JobKey(jobKey, groupKey);
return scheduler.interrupt(jkey);
} catch (SchedulerException e) {
System.out.println("SchedulerException while stopping job. error message :"+e.getMessage());
e.printStackTrace();
}
return false;
}

Failed to run job based on schedule

I'm tying to run the batch based on schedule.I have used scheduled annotation & cron expression. Batch is running only once. No error is getting displayed. I have added maven dependency for quartz.I have not added any XML file.
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,SwaggerConfig.class,
WebMvcAutoConfiguration.class,RepositoryRestMvcAutoConfiguration.class })
#EnableScheduling
#ComponentScan
public class BatchApplication {
public static void main(String[] args) throws Exception {
SpringApplication app = new SpringApplication(BatchApplication.class);
app.setWebEnvironment(false);
ConfigurableApplicationContext ctx = app.run(args);
System.out.println(ctx.getBean(DataSource.class));
JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);
Job addLeaveAllocationJob = ctx.getBean("addLeaveAllocationJob", Job.class);
JobParameters jobParameters = new JobParametersBuilder().addDate("date", new Date())
.toJobParameters();
JobExecution jobExecution = jobLauncher.run(addLeaveAllocationJob, jobParameters);
BatchStatus batchStatus = jobExecution.getStatus();
while(batchStatus.isRunning()){
System.out.println("*** Still Running ************");
Thread.sleep(2000);
}
}
}
I have job class which is scheduled with #scheduled annotation with cron expression.
#Configuration
#EnableBatchProcessing
#Component
public class LeaveAllocationJobConfiguration {
#Autowired
private JobBuilderFactory jobs;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
private EntityManagerFactory entityManagerFactory;
#Bean
public ItemReader<Employee> reader() {
JpaPagingItemReader<Employee> employeeReader = new JpaPagingItemReader<Employee>();
employeeReader.setEntityManagerFactory(entityManagerFactory);
employeeReader.setQueryString("from Employee");
return employeeReader;
}
#Bean
#Scheduled(cron="0 0/1 * 1/1 * ? *")
public Job addLeaveAllocationJob() {
System.out.println("Hello");
return jobs.get("addLeaveAllocationJob").listener(protocolListener()).start(step()).build();
}
#Bean
public Step step() {
// important to be one in this case to commit after every line read
return stepBuilderFactory.get("step").<Employee, EmployeeDTO> chunk(1).reader(reader()).processor(processor())
.writer(writer()).build();
}
/**
* #return
*/
#Bean
public ItemWriter<? super EmployeeDTO> writer() {
return new ItemWriter<EmployeeDTO>() {
#Override
public void write(List<? extends EmployeeDTO> items) throws Exception {
System.out.println("Processing " + items);
}
};
}
#Bean
public ItemProcessor<Employee, EmployeeDTO> processor() {
return new ItemProcessor<Employee, EmployeeDTO>() {
#Override
public EmployeeDTO process(Employee employee) throws Exception {
return new EmployeeDTO(employee);
}
};
}
#Bean
public ProtocolListener protocolListener() {
return new ProtocolListener();
}
}
Please help me to solve the issue
Chek this link.enter link description here

Resources