Мне удалось сделать это с помощью Spring Scheduling Framework.
Я понимаю, что это очень старый пост, но, поскольку содержание по этой теме довольно скудное, лучше разместить его здесь.
Основная проблема в коде для первого сообщения заключается в том, что afterPropertiesSet()
не был вызван как для объекта JobDetail
, так и для объекта CronTrigger
. Функция afterProperties
выполняет некоторую обработку введенных значений до того, как cron будет готов к запуску.
Кроме того, я использовал MethodInvokingJobDetailFactoryBean
вместо обычного jobDetail
объекта, поскольку это дает мне больше гибкости при вызове функции cron в данном классе.
Вот мой код:
package test.spring;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.text.ParseException;
public class ProgrammaticCron {
public static void callWorkFlow() {
System.out.println("Abhishek Jain");
}
public static void main (String[] args) {
try {
GenericApplicationContext applicationContext = new GenericApplicationContext();
MethodInvokingJobDetailFactoryBean jdfb = new MethodInvokingJobDetailFactoryBean();
jdfb.setTargetClass(ProgrammaticCron.class);
jdfb.setTargetMethod("callWorkFlow");
jdfb.setName("Trial program");
jdfb.afterPropertiesSet();
JobDetail jd = (JobDetail)jdfb.getObject();
CronTriggerBean ctb = new CronTriggerBean();
ctb.setJobDetail(jd);
ctb.setName("Daily cron");
ctb.setJobName(jd.getName());
try {
ctb.setCronExpression("59 * * * * ? *");
} catch (ParseException e) {
e.printStackTrace();
}
ctb.afterPropertiesSet();
SchedulerFactoryBean sfb = new SchedulerFactoryBean();
sfb.setJobDetails(new JobDetail[]{(JobDetail)jdfb.getObject()});
sfb.setTriggers(new Trigger[]{ctb});
sfb.afterPropertiesSet();
try {
sfb.start();
} catch (SchedulingException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
afterProperties()
важен, и это можно понять из afterProperties
реализации SchedulerFactoryBean
, которая выглядит следующим образом:
//---------------------------------------------------------------------
// Implementation of InitializingBean interface
//---------------------------------------------------------------------
public void afterPropertiesSet() throws Exception {
if (this.dataSource == null && this.nonTransactionalDataSource != null) {
this.dataSource = this.nonTransactionalDataSource;
}
if (this.applicationContext != null && this.resourceLoader == null) {
this.resourceLoader = this.applicationContext;
}
// Create SchedulerFactory instance.
SchedulerFactory schedulerFactory = (SchedulerFactory)
BeanUtils.instantiateClass(this.schedulerFactoryClass);
initSchedulerFactory(schedulerFactory);
if (this.resourceLoader != null) {
// Make given ResourceLoader available for SchedulerFactory configuration.
configTimeResourceLoaderHolder.set(this.resourceLoader);
}
if (this.taskExecutor != null) {
// Make given TaskExecutor available for SchedulerFactory configuration.
configTimeTaskExecutorHolder.set(this.taskExecutor);
}
if (this.dataSource != null) {
// Make given DataSource available for SchedulerFactory configuration.
configTimeDataSourceHolder.set(this.dataSource);
}
if (this.nonTransactionalDataSource != null) {
// Make given non-transactional DataSource available for SchedulerFactory configuration.
configTimeNonTransactionalDataSourceHolder.set(this.nonTransactionalDataSource);
}
// Get Scheduler instance from SchedulerFactory.
try {
this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
populateSchedulerContext();
if (!this.jobFactorySet && !(this.scheduler instanceof RemoteScheduler)) {
// Use AdaptableJobFactory as default for a local Scheduler, unless when
// explicitly given a null value through the "jobFactory" bean property.
this.jobFactory = new AdaptableJobFactory();
}
if (this.jobFactory != null) {
if (this.jobFactory instanceof SchedulerContextAware) {
((SchedulerContextAware) this.jobFactory).setSchedulerContext(this.scheduler.getContext());
}
this.scheduler.setJobFactory(this.jobFactory);
}
}
finally {
if (this.resourceLoader != null) {
configTimeResourceLoaderHolder.remove();
}
if (this.taskExecutor != null) {
configTimeTaskExecutorHolder.remove();
}
if (this.dataSource != null) {
configTimeDataSourceHolder.remove();
}
if (this.nonTransactionalDataSource != null) {
configTimeNonTransactionalDataSourceHolder.remove();
}
}
registerListeners();
registerJobsAndTriggers();
}
Как вы можете заметить, все такие задачи, как получение планировщика и регистрация задания с помощью триггеров, выполняются как часть этой функции.