2

根据 Quartz 2 的文档

RequestsRecovery - 如果一个作业“请求恢复”,并且它在调度程序的“硬关闭”期间执行(即它在崩溃中运行的进程,或者机器被关闭),那么它会被重新执行当调度程序再次启动时。在这种情况下,JobExecutionContext.isRecovering() 方法将返回 true。

Spring3 支持 Quartz 1.x 和 Quartz 2.x。如果我们使用 Quartz 1.x 那么我们需要使用以下配置来创建JobDetailbean:

<bean id="ldapSynch" class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass" value="com.edfx.adb.scheduling.job.LDAPSynchronizer" />
    <property name="requestsRecovery" value="true" />       
</bean>

内部org.springframework.scheduling.quartz.JobDetailBean扩展org.quartz.JobDetail,并且在 Quartz 1.xorg.quartz.JobDetail中有一个 setter public void setRequestsRecovery(boolean shouldRecover)

但是如果我们使用 Spring3 的 Quartz 2.x 实现,则上述配置更改为:

<bean id="ldapSynch" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.edfx.adb.scheduling.job.LDAPSynchronizer" />
    <property name="requestsRecovery" value="true" />       
</bean>

而且在 Quartz 2.x 中也没有这样org.quartz.JobDetail的类,而是一个interface并且最终org.springframework.scheduling.quartz.JobDetailFactoryBean不再接受参数<property name="requestsRecovery" value="true" />

我们怎么能把这个重要的东西传递parameter给 Quartz 的调度器呢?

4

2 回答 2

5

在查看了类的org.springframework.scheduling.quartz.JobDetailFactoryBean源代码和 Quartz 2.0 的源代码后,我发现其中有一种init method是; 在此方法中,正在创建的实例。幸运的是,这个实例可以通过类的方法访问。org.springframework.scheduling.quartz.JobDetailFactoryBeanpublic void afterPropertiesSet()org.quartz.JobDetailorg.quartz.JobDetailpublic JobDetail getObject()org.springframework.scheduling.quartz.JobDetailFactoryBean

在 Quartz 2.0 中,类org.quartz.impl.JobDeialImpl实现了接口org.quartz.JobDetail;所以org.quartz.JobDetailinorg.springframework.scheduling.quartz.JobDetailFactoryBean的实例实际上是 的实例org.quartz.impl.JobDeialImpl

所以我创建了一个类com.edfx.adb.scheduling.ADBJobDetailFactoryBean,它扩展org.springframework.scheduling.quartz.JobDetailFactoryBean并覆盖了该afterPropertiesSet()方法:

package com.edfx.adb.scheduling;

import org.quartz.impl.JobDetailImpl;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;

public class ADBJobDetailFactoryBean extends JobDetailFactoryBean {

    private boolean requestsRecovery;

    public ADBJobDetailFactoryBean() {
        super();
    }

    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        JobDetailImpl jobDetail = (JobDetailImpl) getObject();
        jobDetail.setRequestsRecovery(isRequestsRecovery());
    }

    public boolean isRequestsRecovery() {
        return requestsRecovery;
    }

    public void setRequestsRecovery(boolean requestsRecovery) {
        this.requestsRecovery = requestsRecovery;
    }
}

并将spring bean配置更改为:

<bean id="ldapSynch" class="com.edfx.adb.scheduling.ADBJobDetailFactoryBean">
    <property name="jobClass" value="com.edfx.adb.scheduling.job.LDAPSynchronizer" />
    <property name="requestsRecovery" value="true" />       
</bean>

瞧。我已经通过在调度程序执行任务时停止运行服务器来测试这一点,当我重新启动服务器时,调度程序开始执行未完成的作业。

希望它会帮助某人。

于 2012-12-31T12:41:14.017 回答
1

@tapas-bose 在搜索一些石英信息时遇到了你的帖子。看起来 Spring 3.2 支持设置属性requestsRecovery。我不知道哪个版本的Spring 3。?您在回答中提到了您遇到的问题。

我直接通过 setter 注入设置 requestsRecovery 属性,它对我有用。

  <bean name="continousMonitoringProfileNotificationPushProcessing"     class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
  <property name="jobClass" value="com.mycompany.projectApp.jobs.ContinousMonitoringNotificationPushJobBean" />
    <property name="jobDataAsMap">
        <map>
            <entry key="executionSuccessful" value="true"/>
        </map>
    </property>
    <property name="durability" value="true" /> 
    <property name="requestsRecovery" value="true"/>
 </bean>

当我为 JobDetailFactoryBean 反编译代码时,它会覆盖 afterPropertiesSet 方法,该方法创建 JObDetailImpl 实例并设置 requestsRecovery,(反编译代码如下)

 public class JobDetailFactoryBean implements FactoryBean<JobDetail>, BeanNameAware, ApplicationContextAware, InitializingBean
 {
 private String name;
 private String group;
 private Class jobClass;
 private JobDataMap jobDataMap = new JobDataMap();
 private boolean durability = false;
 private boolean requestsRecovery = false;

...

.. 

..


 public void afterPropertiesSet()
{
  if (this.name == null) {
  this.name = this.beanName;
 }
  if (this.group == null) {
  this.group = "DEFAULT";
 }
if (this.applicationContextJobDataKey != null) {
 if (this.applicationContext == null) {
        throw new IllegalStateException("JobDetailBean needs to be set up in ApplicationContext to be able to handle an 'applicationContextJobDataKey'");
    }
 getJobDataMap().put(this.applicationContextJobDataKey, this.applicationContext);
 }
 Class<?> jobDetailClass;
 try
 {
      jobDetailClass = getClass().getClassLoader().loadClass("org.quartz.impl.JobDetailImpl");
  }
  catch (ClassNotFoundException ex) {
      jobDetailClass = JobDetail.class;
  }
  BeanWrapper bw = new BeanWrapperImpl(jobDetailClass);
  MutablePropertyValues pvs = new MutablePropertyValues();
  pvs.add("name", this.name);
  pvs.add("group", this.group);
  pvs.add("jobClass", this.jobClass);
  pvs.add("jobDataMap", this.jobDataMap);
  pvs.add("durability", Boolean.valueOf(this.durability));
  pvs.add("requestsRecovery", Boolean.valueOf(this.requestsRecovery));

所以我们不需要手动扩展 JobFactoryBean 类并设置 requestsRecovery 属性。

于 2014-12-11T17:35:50.547 回答