Как создать триггерный объект программно? - PullRequest
4 голосов
/ 27 января 2011

Я использую Spring Quartz Scheduler, но я не использую XML-файл.Я хочу создать всю конфигурацию программно.

Я написал следующий код.

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();
        }
    }

}

Код работает, за исключением того, что триггер не запускается, потому что я его не установил.

Здесь проблема заключается в том, что в конфигурации XML у нас есть свойство 'triggers' schedulerFactoryBean, и мы используем list для настройки наших триггеров.

Но я не могу установить это свойство программно.В SchedulerFactoryBean есть метод setTriggers, который принимает массив Trigger, но проблема заключается в том, как его создать.

Я нахожусь на нем в течение последних 4 часов, но пока нет признаков успеха.

Можеткто-нибудь поможет мне здесь?

Спасибо

Ответы [ 2 ]

8 голосов
/ 04 октября 2012

Мне удалось сделать это с помощью 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();
        }

Как вы можете заметить, все такие задачи, как получение планировщика и регистрация задания с помощью триггеров, выполняются как часть этой функции.

0 голосов
/ 27 января 2011

Основная проблема должна заключаться в том, что вам нужно запланировать задание:

scheduler.scheduleJob(jobDetail, trigger);

И я не знаю, как это для Spring Quarz Beans, но обычные Quarz Jobs и Trigger должны иметь имя игруппа!И может вам понадобится запустить планировщик: scheduler.start();

Я немного изменил ваш код, чтобы он работал без пружины, и все опускаем ненужные вещи, чтобы продемонстрировать, как он работает:

пакетный тест;

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);
    }

}
...