spring boot + Quartz to configure dynamic timing tasks

OK, go straight to the subject

  • maven dependence
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
  • To configure
    First, rewrite the QuartJob factory to solve the injection problem

    public class QuartJobFactory extends AdaptableJobFactory {
    
        @Autowired
        private AutowireCapableBeanFactory capableBeanFactory;
    
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            // Call the method of the parent class
            Object jobInstance = super.createJobInstance(bundle);
            // Spring injection
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }
    

    Rewrite listener

    public class QuartJobSchedulingListener implements ApplicationListener<ContextRefreshedEvent> {
    
    private static final Logger log = LoggerFactory.getLogger(QuartJobSchedulingListener.class);
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            try {
                if (event.getApplicationContext().getParent() == null) {
                    log.debug("onApplicationEvent");
                    ApplicationContext applicationContext = event.getApplicationContext();
                    addDbBatchs(applicationContext);
                    //addDynamicJobs(applicationContext);
                }
    
            }
            catch (Exception e) {
                log.error("", e);
            }
        }
    
        private void addDbBatchs(ApplicationContext applicationContext) {
            SchedulerFactoryBean schedulerFactoryBean = applicationContext.getBean(SchedulerFactoryBean.class);
            BatchTaskService taskService = applicationContext.getBean(BatchTaskService.class);
            List<SysBatch> list = taskService.getAllBatch();
            for (SysBatch batch : list) {
                try {
                    QuartJobUtil.addScheduler(schedulerFactoryBean, batch);
                }
                catch (Exception e) {
                    log.error("", e);
                }
            }
    
        }
    }

    Please note: List < sysbatch > list this is the entity encapsulated by the records in the database. The table structure is as follows

    The acquired records are loaded into the timing through the methods of the QuartJobUtil utility class.

    Management timing tool class QuartJobUtil

`

public class QuartJobUtil {

private static final Log log = LogFactory.getLog(QuartJobUtil.class);

/**
 * Additional timing
 * 
 * @param schedulerFactoryBean
 * @param sysBatch
 * @throws SchedulerException
 */
public static void addScheduler(SchedulerFactoryBean schedulerFactoryBean, SysBatch sysBatch)
        throws SchedulerException {

    if (schedulerFactoryBean == null) {
        return;
    }

    Scheduler scheduler = schedulerFactoryBean.getScheduler();

    String jobName = sysBatch.getBatchId();
    String jobGroup = QuartzCron.JOB_GROUP_DYNAMIC;

    TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
    JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobName, jobGroup));

    //Get trigger
    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

    String cronExpression = sysBatch.getCron();

    DateTime runTime = new DateTime();
    runTime = runTime.plusMinutes(1);

    //No, create a
    if (null == jobDetail) {
        JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setName(jobName);
        jobDetailFactory.setGroup(jobGroup);
        jobDetailFactory.setJobClass(BatchJobCall.class);
        jobDetailFactory.setDurability(true);

        jobDetailFactory.afterPropertiesSet();

        jobDetail = jobDetailFactory.getObject();
        jobDetail.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);

        CronTriggerFactoryBean triggerFactory = new CronTriggerFactoryBean();
        triggerFactory.setJobDetail(jobDetail);
        triggerFactory.setName(jobName);
        triggerFactory.setGroup(jobGroup);
        triggerFactory.setCronExpression(cronExpression);

        try {
            triggerFactory.afterPropertiesSet();
            //Build a new trigger with a new cronExpression expression
            trigger = triggerFactory.getObject();

            log.debug("Add batch: ");
            log.debug(jobName + "-" + jobGroup);
            log.debug(sysBatch.getName());
            log.debug(cronExpression);
        }
        catch (ParseException e) {
            log.warn(sysBatch.getBatchId() + "_" + sysBatch.getCron(), e);
        }

        scheduler.scheduleJob(jobDetail, trigger);
    }
    else {
        // Existing, then update the corresponding settings
        jobDetail.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);

        CronTriggerFactoryBean triggerFactory = new CronTriggerFactoryBean();
        // Add the latest Batch to the Map
        triggerFactory.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);
        triggerFactory.setJobDetail(jobDetail);
        triggerFactory.setName(jobName);
        triggerFactory.setGroup(jobGroup);
        triggerFactory.setCronExpression(cronExpression);
        //triggerFactory.setStartTime(runTime.toDate());

        try {
            triggerFactory.afterPropertiesSet();
            //Build a new trigger with a new cronExpression expression
            trigger = triggerFactory.getObject();

            log.debug("Modify batch: ");
            log.debug(jobName + "-" + jobGroup);
            log.debug(sysBatch.getName());
            log.debug(cronExpression);
        }
        catch (ParseException e) {
            log.warn(e);
        }

        //Reset job execution by new trigger
        scheduler.rescheduleJob(triggerKey, trigger);
    }

}

    /**
     * Delete batch
     * 
     * @param schedulerFactoryBean
     * @param sysBatch
     * @throws SchedulerException
     */
    public static void deleteDocScheduler(SchedulerFactoryBean schedulerFactoryBean, SysBatch sysBatch)
            throws SchedulerException {
        if (schedulerFactoryBean == null) {
            return;
        }
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        String jobName = sysBatch.getBatchId();
        String jobGroup = QuartzCron.JOB_GROUP_DYNAMIC;

        JobKey jobKey = new JobKey(jobName, jobGroup);
        boolean result = scheduler.deleteJob(jobKey);
        log.info("Delete batch:" + jobName);
        log.info("Delete result:" + result);

    }

}

`

The most important thing is

jobDetailFactory.setJobClass(BatchJobCall.class);
jobDetail.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);

The BatchJobCall.class class class is a response class triggered at a fixed time. Commonconstants.job "data" key is a constant to obtain the sysBatch entity in the response class.

BatchJobCall

`

public class BatchJobCall extends QuartzJobBean {

private static final Log log = LogFactory.getLog(BatchJobCall.class);

@Autowired
private AutowireCapableBeanFactory capableBeanFactory;

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    //Get entity
    SysBatch batch = (SysBatch) context.getJobDetail().getJobDataMap().get(CommonConstants.JOB_DATA_KEY);

    String beanName = batch.getBeanName();
    String beanMethod = batch.getBeanMethod();
    String argument = batch.getArgument();

    if (StringUtils.isNotEmpty(beanName) && StringUtils.isNotEmpty(beanMethod)) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");

        try {
            log.debug(batch.getBatchId() + "_" + batch.getName() + "-The specific method for starting the scheduled task is as follows:" + sdf.format(new Date()));

            Class<?> printClass = Class.forName(beanName);
            Object obj = printClass.newInstance();
            capableBeanFactory.autowireBean(obj);
            //Acquisition method
            Method printMethod = printClass.getMethod(beanMethod, String.class);
            //call
            printMethod.invoke(obj, argument);
            log.debug(batch.getBatchId() + "_" + batch.getName() + "-End of scheduled task execution:" + sdf.format(new Date()));
        }
        catch (Exception e) {
            log.warn(batch.getBatchId() + "_" + batch.getName() + "-Timed task call failed" + sdf.format(new Date()));
            throw new JobExecutionException(e);

        }

    }
}

}

`
Here, the class name and method name of sysbatch entity in the table are called through the reflection mechanism.

Finally configure QuartzConfig

`

@Configuration
public class QuartzConfig {

    @Bean
    public QuartJobSchedulingListener quartJobSchedulingListener() {
        return new QuartJobSchedulingListener();
    }

    /**
     * Get scheduled task factory
     *
     * @return Get scheduled task factory
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
        schedulerFactory.setJobFactory(jobFactory());
        return schedulerFactory;
    }

    /**
     * QuartJob Factory, solve injection problem
     *
     * @return QuartJob factory
     */
    @Bean
    public JobFactory jobFactory() {
        QuartJobFactory factory = new QuartJobFactory();
        return factory;
    }

    /**
     * Dispatch
     *
     * @return BatchJobCall
     */
    @Bean
    public BatchJobCall getJobCall() {
        return new BatchJobCall();
    }
}

`

Keywords: Java Maven Spring Database

Added by datona on Tue, 15 Oct 2019 17:06:23 +0300