博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ObjectAlreadyExistsException:Unable to store Job : '*', because one already exists with thi s ident
阅读量:2338 次
发布时间:2019-05-10

本文共 2944 字,大约阅读时间需要 9 分钟。

#Quartz# 

现象描述 :

      项目启动要初始化程序配置的各个job, 采用的是quartz,但是发现有时候启动时报错:org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'MONITOR_RUNNER_GROUP.indexWarningRunner', because one already exists with thi

s identification, job存储失败。

        查看quartz数据库: cron_triggers,里面没有 MONITOR_RUNNER_GROUP.indexWarningRunner, job_details库里面有,triggers库里面没有。

开始做法:

存不进去是因为里面已经有了,删除job_details里面的,启动正常,但是后续还会出现这种情况。代码逻辑有问题,不是什么quartz bug。

排查:

   初始化quartz任务代码:

public void init() throws Exception {

        Map<String, BaseRunner> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType(BaseRunner.class);
        for (String name : beansOfType.keySet()) {
            BaseRunner baseRunner = beansOfType.get(name);
            JobKey jobKey = new JobKey(name, RunnerConstants.RUNNER_GROUP);
            TriggerKey triggerKey = new TriggerKey(name, RunnerConstants.RUNNER_GROUP);

            RunnerCron annotation = baseRunner.getClass().getAnnotation(RunnerCron.class);

            if (annotation == null) {
                LOG.warn("monitor schedule: {} create failed, cron is missing", jobKey.toString());
                this.tryDeleteJob(jobKey);
                continue;
            }
            String cron = this.getProperties(annotation.value());
            if (StringUtils.isNotBlank(cron)) {
                JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
                jobDetailFactoryBean.setGroup(RunnerConstants.RUNNER_GROUP);
                jobDetailFactoryBean.setName(name);
                jobDetailFactoryBean.setDurability(true);
                jobDetailFactoryBean.setJobClass(RunnerJob.class);
                jobDetailFactoryBean.getJobDataMap().put(RunnerConstants.RUNNER_NAME, name);
                jobDetailFactoryBean.afterPropertiesSet();
                JobDetail jobDetail = jobDetailFactoryBean.getObject();

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

  
                if (Objects.isNull(trigger) ) {
                    CronTrigger cronTrigger =          TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(cron)).startNow().build();
                    scheduler.scheduleJob(jobDetail, cronTrigger);
                    LOG.info("monitor schedule: {} created", triggerKey.toString());
                } else {
                    CronTrigger cronTrigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(cron)).startNow().build();
                    scheduler.rescheduleJob(triggerKey, cronTrigger);
                    LOG.info("monitor schedule: {} refreshed", triggerKey.toString());
                }
            } else {
                LOG.warn("monitor schedule: {} create failed, cron is invalid", jobKey.toString());
                this.tryDeleteJob(jobKey);
            }
        }
    }

  private void tryDeleteJob(JobKey jobKey) throws SchedulerException {

        TriggerKey triggerKey = TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup());
        scheduler.pauseTrigger(triggerKey);
        //这句话是先删除相关的trigger触发器,如果trigger关联的job没有其他触发器并且不持续,也被删除(duarble为true,只删除trigger,job还在保留)
        //否则下次启动就有可能存储job的时候报错
        //scheduler.unscheduleJob(triggerKey);

        //会删除joddetail,以及其关联的triggers

        scheduler.deleteJob(jobKey);
    }

可以看出来,如果trigger 是空,但是job 数据库还是有的。然后scheduleJob方法,存储job报错了。

最终做法是:

   虽然,一个job可以绑定多个trigger,一个trigger只能有一个job, 但是这里就做成了一对一的关系,避免混乱:判断trigger和jobDetail 有没有,都有,就更新trigger,否则deleteJob ,然后新建。或者,启动的时候一并删除,然后全部新建

 

 

 

 

转载地址:http://gcrpb.baihongyu.com/

你可能感兴趣的文章
人生的康波周期,把握住一次,足以改变命运!
查看>>
互联网公司那些价值观-阿里巴巴
查看>>
去面试快手,问了我很多消息队列的知识!
查看>>
图解LeetCode No.18之四数之和
查看>>
402. Remove K Digits
查看>>
75. Sort Colors
查看>>
获取数组中前K小的数字
查看>>
数组heapify变为堆结构
查看>>
二叉树的非递归遍历
查看>>
218. The Skyline Problem
查看>>
Java PAT (Basic Level) Practice 写出这个数
查看>>
Python PAT (Basic Level) Practice 1016 部分A+B
查看>>
Python PAT (Basic Level) Practice 1006 换个格式输出整数
查看>>
Python PAT (Basic Level) Practice 1009 说反话
查看>>
Python PAT (Basic Level) Practice 1011 A+B 和 C
查看>>
Python PAT (Basic Level) Practice 1017 A除以B
查看>>
Python PAT (Basic Level) Practice 1042 字符统计
查看>>
spring dubbo 2.7.3 zookeeper 项目构建
查看>>
spring dubbo 报错
查看>>
如何在非 bean 对象中注入 dubbo service
查看>>