问题
I am using Spring quartz Scheduler but I am not using an XML file. I want to create the entire configuration programmatically.
I have written the following code.
package com.eaportal.service.impl;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.quartz.JobDetail;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.JobDetailBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import com.eaportal.service.intfc.AuctionWinnerService;
public class NormalAuctionWinnerServiceImpl1 implements AuctionWinnerService {
@SuppressWarnings("deprecation")
public void declareWinner(int auctionId, Map<String, Object> parameterMap) {
System.out.println("INSIDE DECLARE WINNER METHOD.");
/** STEP 1 : INSTANTIATE TASK CLASS **/
NormalAuctionWinnerTask1 runMeTask = new NormalAuctionWinnerTask1();
System.out.println("FINISHED STEP 1");
/** STEP 2 : INSTANTIATE JOB DETAIL CLASS AND SET ITS PROPERTIES **/
Map<String,Object> jobDataAsMap = new HashMap<String,Object>();
jobDataAsMap.put("runMeTask",runMeTask);
JobDetailBean jdb = new JobDetailBean();
jdb.setJobClass(NormalAuctionWinnerTask1.class);
jdb.setJobDataAsMap(jobDataAsMap);
System.out.println("FINISHED STEP 2");
/** STEP 3 : INSTANTIATE CRON TRIGGER AND SET ITS PROPERTIES **/
CronTriggerBean ctb = new CronTriggerBean();
Date d1 = new Date();
Date d2 = new Date();
d2.setMinutes(d1.getMinutes()+10);
ctb.setStartTime(d1);
ctb.setEndTime(d2);
ctb.setJobDetail(jdb);
try {
ctb.setCronExpression("59 * * * * ? *");
} catch (ParseException e) {
e.printStackTrace();
}
/** STEP 4 : INSTANTIATE SCHEDULER FACTORY BEAN AND SET ITS PROPERTIES **/
SchedulerFactoryBean sfb = new SchedulerFactoryBean();
sfb.setJobDetails(new JobDetail[]{jdb});
try {
sfb.start();
} catch (SchedulingException e) {
e.printStackTrace();
}
}
}
The code is working except the trigger doesn't fire coz I haven't set it.
Here the problem is in XML configuration we have 'triggers' property of schedulerFactoryBean and we use list to configure our triggers.
But I am not able to set the same property programmatically. There is a setTriggers method in SchedulerFactoryBean that accepts an array of Trigger but how to create it is the problem.
I am on it for the last 4 hrs still no sign of success.
Can someone help me here?
Thanks
回答1:
I was able to do this with Spring Scheduling Framework successfully.
I understand this is a very old post but as the content on this topic is pretty scarce, it should be a better idea to put it here.
The major problem in the code for the first post is that the afterPropertiesSet()
hasn't been invoked on both the JobDetail
object as well as the CronTrigger
object. The afterProperties
function does some processing on the entered values before the cron is ready to be run.
Also, I have used the MethodInvokingJobDetailFactoryBean
instead of the regular jobDetail
object as it gives me more flexibility on the function to be called by the cron in the given class.
Here is my code:
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()
is important and it can be understood from the afterProperties
implementation of SchedulerFactoryBean
which is as follows:
//---------------------------------------------------------------------
// 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();
}
As you may notice, all such tasks as getting the scheduler and registering the job with the triggers is done as a part of this function.
回答2:
The main problem should be, that you need to schedule the job:
scheduler.scheduleJob(jobDetail, trigger);
And I do not know how it is for Spring Quarz Beans, but normal Quarz Jobs and Trigger must have a name and a group! And may you need to start the scheduler: scheduler.start();
I have modified your code a bit that it works without spring, and all leave out the stuff that is not needed, to demonstrate how it works:
package test;
import java.text.ParseException;
import java.util.Date;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
public class Demo {
public static class TestJob implements Job{
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("execute");
}
}
public static void declareWinner() throws SchedulerException, ParseException {
JobDetail jobDetail = new JobDetail("job","group",Demo.TestJob.class);
CronTrigger trigger = new CronTrigger("trigger","group");
trigger.setStartTime(new Date());
trigger.setEndTime(new Date(new Date().getTime() + 10 * 60 * 1000));
trigger.setCronExpression("* * * * * ? *");
/** STEP 4 : INSTANTIATE SCHEDULER FACTORY BEAN AND SET ITS PROPERTIES **/
SchedulerFactory sfb = new StdSchedulerFactory();
Scheduler scheduler = sfb.getScheduler();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
public static void main (String[] args) throws SchedulerException, Exception {
declareWinner();
Thread.sleep(10000);
}
}
来源:https://stackoverflow.com/questions/4816568/how-to-create-trigger-object-programmatically