如何更新Quartz JobDataMap中的值?

时间:2011-04-29 17:45:12

标签: java quartz-scheduler

我正在使用quartz-scheduler 1.8.5。我创建了一个实现StatefulJob的Job。我使用SimpleTrigger和StdSchedulerFactory安排作业。

除了JobDetail的JobDataMap之外,我还必须更新Trigger的JobDataMap,以便从Job中更改JobDataMap。我试图理解为什么有必要更新两者?我注意到JobDataMap设置为脏。也许我必须明确保存它或什么?

我想我将不得不深入研究Quartz的源代码才能真正理解这里发生的事情,但我想我会先懒得先问一下。感谢您对JobDataMap内部工作的深入了解!

这是我的工作:

public class HelloJob implements StatefulJob {

    public HelloJob() {
    }

    public void execute(JobExecutionContext context)
            throws JobExecutionException {

        int count = context.getMergedJobDataMap().getInt("count");
        int count2 = context.getJobDetail().getJobDataMap().getInt("count");
        //int count3 = context.getTrigger().getJobDataMap().getInt("count");
        System.err.println("HelloJob is executing. Count: '"+count+"', "+count2+"'");

        //The count only gets updated if I updated both the Trigger and 
                // JobDetail DataMaps. If I only update the JobDetail, it doesn't persist. 
        context.getTrigger().getJobDataMap().put("count", count++);
        context.getJobDetail().getJobDataMap().put("count", count++);

        //This has no effect inside the job, but it works outside the job
        try {
            context.getScheduler().addJob(context.getJobDetail(), true);
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //These don't seem to persist between jobs
        //context.put("count", count++);
        //context.getMergedJobDataMap().put("count", count++);
    }
}

以下是我安排工作的方式:

try {
    // define the job and tie it to our HelloJob class
    JobDetail job = new JobDetail(JOB_NAME, JOB_GROUP_NAME,
            HelloJob.class);
    job.getJobDataMap().put("count", 1);
    // Trigger the job to run now, and every so often
    Trigger trigger = new SimpleTrigger("myTrigger", "group1",
            SimpleTrigger.REPEAT_INDEFINITELY, howOften);

    // Tell quartz to schedule the job using our trigger
    sched.scheduleJob(job, trigger);
    return job;
} catch (SchedulerException e) {
    throw e;
}

更新:

似乎我必须将值放入JobDetail的JobDataMap两次以使其保持不变,这样可行:

public class HelloJob implements StatefulJob {

    public HelloJob() {
    }

    public void execute(JobExecutionContext context)
            throws JobExecutionException {

        int count = (Integer) context.getMergedJobDataMap().get("count");
        System.err.println("HelloJob is executing. Count: '"+count+"', and is the job stateful? "+context.getJobDetail().isStateful());
        context.getJobDetail().getJobDataMap().put("count", count++);
        context.getJobDetail().getJobDataMap().put("count", count++);
    }
}

这似乎是一个错误,也许?或者也许我缺少一个步骤告诉JobDetail将其JobDataMap的内容刷新到JobStore?

4 个答案:

答案 0 :(得分:13)

我认为你的问题在于使用postfix ++运算符 - 当你这样做时:

context.getJobDetail().getJobDataMap().put("count", count++);  

您要将地图中的值设置为count,然后设置递增计数。

对我而言,看起来你想要:

context.getJobDetail().getJobDataMap().put("count", ++count);  

只需要做一次。

答案 1 :(得分:3)

如您所知,在Quartz中,触发器和作业是分开的,而不是与某些调度程序结合使用。他们可能允许您向数据图添加值,这些值特定于触发级别而不是作业级别等。

我认为它允许您使用不同的数据集执行相同的结束作业,但在作业级别仍然有一些常见数据。

答案 2 :(得分:2)

当scpritch76回答时,作业和触发器是分开的,因此给定作业可以有许多触发器(日程表)。

作业可以在JobDataMap中具有一些基本属性集,然后触发器可以为其JobDataMaps中的作业的特定执行提供其他属性(或覆盖基本属性)。

答案 3 :(得分:0)

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class DynamicTestJob implements Job
{

    private static final Logger log = LoggerFactory.getLogger(DynamicTestJob.class);

    @Override
    public void execute(final JobExecutionContext context)
    {
        final JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        Integer counter = (Integer) jobDataMap.get("counter");

        if (counter == null)
        {
            counter = 1;
        }
        else
        {
            counter++;
        }

        jobDataMap.put("counter", counter);

        System.out.println(counter);
    }

}