如何为持久的Quartz Jobs重命名作业类?

时间:2013-07-20 16:51:57

标签: spring quartz-scheduler

我有像这样的石英测试工作。

package com.example.spring.quartz.basic;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class ExampleJob implements Job
{
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException
    {
        JobDataMap map = context.getMergedJobDataMap();
        String timeout = (String)map.get("timeout");

        System.out.println("ExampleJob.execute() " + timeout);
    }
}

这个作业是持久的,所以它被写入数据库,似乎Quartz将完整的合格作业类名com.example.spring.quartz.basic.ExampleJob写入数据库。

因此,如果重构将ExampleJob重命名为ExampleJob2,我最终会遇到以下异常,因为quartz会查找ExampleJob并获取未找到类的异常。

问题:是否有一些技巧或模式可以用来安全地重命名我的工作类 不会导致现有的工作定义中断?

Exception in thread "main" org.springframework.context.ApplicationContextException: Failed to start bean 'quartzScheduler'; nested exception is org.springframework.scheduling.SchedulingException: Could not start Quartz Scheduler; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve trigger: com.example.spring.quartz.basic.ExampleJob [See nested exception: java.lang.ClassNotFoundException: com.example.spring.quartz.basic.ExampleJob]]
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:170)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:339)
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:143)
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:108)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:945)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.example.spring.quartz.transactional.QuartzExampleJobMain.main(QuartzExampleJobMain.java:16)
Caused by: org.springframework.scheduling.SchedulingException: Could not start Quartz Scheduler; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve trigger: com.example.spring.quartz.basic.ExampleJob [See nested exception: java.lang.ClassNotFoundException: com.example.spring.quartz.basic.ExampleJob]]
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.start(SchedulerFactoryBean.java:715)
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:167)
    ... 9 more
Caused by: org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve trigger: com.example.spring.quartz.basic.ExampleJob [See nested exception: java.lang.ClassNotFoundException: com.example.spring.quartz.basic.ExampleJob]]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.schedulerStarted(JobStoreSupport.java:683)
    at org.quartz.core.QuartzScheduler.start(QuartzScheduler.java:526)
    at org.quartz.impl.StdScheduler.start(StdScheduler.java:143)
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.startScheduler(SchedulerFactoryBean.java:649)
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.start(SchedulerFactoryBean.java:712)
    ... 10 more
Caused by: org.quartz.JobPersistenceException: Couldn't retrieve trigger: com.example.spring.quartz.basic.ExampleJob [See nested exception: java.lang.ClassNotFoundException: com.example.spring.quartz.basic.ExampleJob]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveTrigger(JobStoreSupport.java:1524)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:968)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverJobs(JobStoreSupport.java:855)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$1.execute(JobStoreSupport.java:827)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$46.execute(JobStoreSupport.java:3764)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3798)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3760)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverJobs(JobStoreSupport.java:823)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.schedulerStarted(JobStoreSupport.java:681)
    ... 14 more
Caused by: java.lang.ClassNotFoundException: com.example.spring.quartz.basic.ExampleJob
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:270)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:623)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1610)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515)
    at java.io.ObjectInputStream.readClass(ObjectInputStream.java:1481)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1331)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at java.util.HashMap.readObject(HashMap.java:1155)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at org.quartz.impl.jdbcjobstore.PostgreSQLDelegate.getObjectFromBlob(PostgreSQLDelegate.java:103)
    at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectTrigger(StdJDBCDelegate.java:1764)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveTrigger(JobStoreSupport.java:1520)
    ... 22 more

2 个答案:

答案 0 :(得分:0)

遇到一个很好的问题。

  

是否有一些技巧

是的,诀窍是用新的细节重新定义你的工作。

检查this了解方法。

希望这能解决你的问题。

答案 1 :(得分:0)

详细说明Sinchan的答案:

如果您有足够的数据来重新创建作业(即已将过期日期存档,请在许可证到期前30天通过电子邮件向员工发送提醒),请编写一个实用程序以取消计划/删除该类型的所有现有作业并重新创建它们新型。

否则:

  1. 重命名该类后,创建一个ExampleJob的空extends ExampleJob2类。这应该允许Quartz读入现有任务。
  2. 创建一个读取每个ExampleJob的实用程序,立即安排具有相同属性的相应ExampleJob2,并删除ExampleJob
  3. 此时,您应该可以删除ExampleJob类。