How to start again Quartz jobs that are created dy

2019-07-25 04:27发布

问题:

I'm using spring mvc 4.2.5.RELEASE and quartz 2.2.1 quartz-jobs 2.2.1

I have a user interface when the user inputs the name and the cron expression of a quartz job, and then I create the job like this

SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

schedFact.getScheduler().getContext().put("externalInstanceEstatus", myObject);
Scheduler sched = schedFact.getScheduler();
sched.start();

JobDetail job = null;
job = newJob(MyTask.class)
.withIdentity((String) String.valueOf(myUniqueId), "group1")
.build();

Trigger triggerCron = TriggerBuilder
.newTrigger()
.withIdentity(String.valueOf(myUniqueId), "group1")
.withSchedule(
    CronScheduleBuilder.cronSchedule(myObject.getExpresionCron()))
.build();

sched.scheduleJob(job, triggerCron);

Everytime that the user goes that interface he can create a job this works fine but when I turn off the server all of my Jobs are lost. I solved this by saving the Job name and cron expression in a database and I created a method that fetch all the records from that table and I re-create the Jobs like this

public void reCreateJobs() {

        ArrayList<MyJob> listOfJobs = searchAllJobsInDB();

        SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
        Scheduler sched = schedFact.getScheduler();

        //I loop the lsit and I delete all the jobs in the scheduler just in case
        for (MyJob myJob : listOfJobs) {
            for (String group : sched.getJobGroupNames()) {
                for (JobKey jobKey : sched.getJobKeys((GroupMatcher<JobKey>) groupEquals(group))) {
                    if (jobKey.getName().equals(String.valueOf(myJob.getIdMyJob()))) {
                        sched.deleteJob(jobKey);
                    }
                }
            }
        }

        sched.start();

        //THIS IS WHERE I CREATE ALL THE JOBS AGAIN
        for (MyJob myJob : listOfJobs) {

            JobDetail job = newJob(TareaImprimir.class)
                    .withIdentity((String) String.valueOf(myJob.getIdMyJob()), "group1")
                    .build();

            JobDetail job = null;

            Trigger triggerCron = TriggerBuilder
                    .newTrigger()
                    .withIdentity(String.valueOf(myJob.getIdMyJob()), "group1")
                    .withSchedule(
                            CronScheduleBuilder.cronSchedule(myJob.getExpresionCron()))
                    .build();

            sched.scheduleJob(job, triggerCron);
        }
    }

This also works fine I can create the Jobs again and they run fine,

My problem is that I need to pass a value to the Task Class and I don't know how to pass it, I know how to pass it when I create the job for the first time like this

schedFact.getScheduler().getContext().put("externalInstance", myObject);

and then I get it in my task Class like this

 SchedulerContext schedulerContext = null;
    try {
        schedulerContext = context.getScheduler().getContext();

    } catch (SchedulerException ex) {
        ex.printStackTrace();
    }
    MyObject externalInstance
            = (MyObject) schedulerContext.get("externalInstance");

My Problem is that I don't know how to do this when I'm recreating the Jobs in my method reCreateJobs() where I get them from the DataBase

How can I set that externalInstance inside my method reCreateJobs() for every Job or How can I pass that value to the MyTask class inside that loop

this is my Task Class

public class MyTask implements Job {

@Autowired
SomeDAO someDAO;

public void execute(JobExecutionContext context)
        throws JobExecutionException {

    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

    SchedulerContext schedulerContext = null;
    try {
        schedulerContext = context.getScheduler().getContext();
    } catch (SchedulerException ex) {
        Logger.getLogger(MyTask.class.getName()).log(Level.SEVERE, null, ex);
    }
    MyObject externalInstance
            = (MyObject) schedulerContext.get("externalInstance");

    someDAO.doSomething(externalInstance.getSomething());
}

}

回答1:

Since i cant comment, adding it as an answer

Any reason why you are you not using JDBC-JobStoreTX

JDBCJobStore is used to store scheduling information (job, triggers and calendars) within a relational database. There are actually two seperate JDBCJobStore classes that you can select between, depending on the transactional behaviour you need.

JobStoreTX manages all transactions itself by calling commit() (or rollback()) on the database connection after every action (such as the addition of a job). JDBCJobStore is appropriate if you are using Quartz in a stand-alone application, or within a servlet container if the application is not using JTA transactions.

That way you can persist the data you want to JobDataMap

Holds state information for Job instances.

JobDataMap instances are stored once when the Job is added to a scheduler. They are also re-persisted after every execution of jobs annotated with @PersistJobDataAfterExecution.

JobDataMap instances can also be stored with a Trigger. This can be useful in the case where you have a Job that is stored in the scheduler for regular/repeated use by multiple Triggers, yet with each independent triggering, you want to supply the Job with different data inputs.

The JobExecutionContext passed to a Job at execution time also contains a convenience JobDataMap that is the result of merging the contents of the trigger's JobDataMap (if any) over the Job's JobDataMap (if any).