为什么Quartz作业没有被执行(尽管QUARTZ表正在使用适当的作业详细信息进行更新)

时间:2015-08-18 10:49:34

标签: java spring hibernate quartz-scheduler

我正在使用Quartz 1.8.6的Spring 3。我已经通过以下方式在applicationcontext文件中定义了SchedulerFactoryBean:

<bean id="quartzscheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
    <property name="autoStartup">
        <value>true</value>
    </property>
    <property name="quartzProperties">
        <props>
            <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
            <prop key="org.quartz.scheduler.instanceName">MyClusteredScheduler</prop>
            <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
            <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
            <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
            <prop key="org.quartz.jobStore.isClustered">true</prop>
            <prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
            <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
        </props>
    </property>
    <property name="dataSource">
        <ref bean="quartzdataSource" />
    </property>
</bean>

<bean id="quartzdataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3305/quartz" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>

这是我的工作类,它实际上是一个实体bean类,按以下方式定义:

@Entity
@Table(name = "DATABASEMONITOR")
public class DatabaseMonitor implements Serializable, Job {

    @Id
    @GeneratedValue
    @Column(name = "ID", unique = true, nullable = false)
    private Integer id;

    @Column(name = "NAME", nullable = false)
    private String name;

    public DatabaseMonitor(String name, String sqlQuery){
        this.name = name;
        this.sqlQuery = sqlQuery;
    }

    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        System.out.println("inside job");
    }
}

这是我的调度程序控制器类:

public class SchedulerController {

    public static void addJob(DatabaseMonitor databaseMonitor){

        JobDetail job = new JobDetail();
        job.setName(databaseMonitor.getName());
        job.setJobClass(DatabaseMonitor.class);

        CronTrigger trigger = new CronTrigger();
        trigger.setName(databaseMonitor.getName());
        try {
            trigger.setCronExpression("0/2 * * * * ?");
            Scheduler scheduler = (Scheduler) BeansManager.getInstance().getBean("quartzscheduler");
            scheduler.scheduleJob(job, trigger);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

    }

}

从主类我调用这个调度函数来在运行时添加作业:

DatabaseMonitor databaseMonitor = new DatabaseMonitor(new Date().toString(), "query string");
        SchedulerController.addJob(databaseMonitor);

现在问题是一切正常,没有任何异常,工作细节在预定义的石英数据库详细信息中得到更新。但这项工作没有得到执行。你能帮帮我吗?

2 个答案:

答案 0 :(得分:0)

您的DatabaseMonitor应该有默认构造函数。 Quartz将尝试执行JobDetailJobDetail将从头开始创建DatabaseMonitor并执行其execute方法。由于DatabaseMonitor没有默认构造函数,因此无法执行。

更新

由于您已经有一个默认构造函数,我建议稍微重构一下。我使用带有弹簧的2.2.1版本的石英,因此一些类名可能会有所不同。

首先让你的实体分成两部分。

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

public class DatabaseMonitor {
    @Id
    @GeneratedValue
    @Column(name = "ID", unique = true, nullable = false)
    private Integer id;

    @Column(name = "NAME", nullable = false)
    private String name;

    @Column(name = "SQL_QUERY", nullable = false)
    private String sqlQuery;

    // Getters && Setters && Def. Const etc.
}

我稍后会解释工作部分。然后让你的控制器重构为一个spring bean。

import org.quartz.JobDataMap;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.ParseException;

@Component
public class SchedulerController {

    @Autowired
    Scheduler scheduler;

    public void addJob(DatabaseMonitor databaseMonitor) {

        final JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("sqlQuery", databaseMonitor.getSqlQuery());
        final JobDetailImpl jobDetail = new JobDetailImpl();
        jobDetail.setName(databaseMonitor.getName());
        jobDetail.setDurability(true);
        jobDetail.setJobDataMap(jobDataMap);
        jobDetail.setJobClass(DatabaseJob.class);

        try {
            final CronTriggerImpl trigger = new CronTriggerImpl();
            trigger.setCronExpression("0/2 * * * * ?");
            trigger.setName(databaseMonitor.getName());
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (ParseException | SchedulerException e) {
            e.printStackTrace();
        }
    }
}

如您所见,我正在使用JobDataMap将参数传递给我的作业。这个参数可能是sqlQuery。让我们检查一下我们的工作。

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

import java.io.Serializable;

public class DatabaseJob implements Job, Serializable {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        final JobDataMap jobDataMap = context.getMergedJobDataMap();
        final String sqlQuery = jobDataMap.getString("sqlQuery");
        System.out.println("SqlQuery: " + sqlQuery);
    }
}

我正在从上下文中读取我的查询。我的工作不包含任何州。在您的实施中,您的工作也是一个实体。 Hibernate(或其他JPA实现)代理几乎所有东西,并拥有很多状态。这会因石英执行而中断。

更新2

我创建了一个示例应用程序并将其放到github

答案 1 :(得分:0)

您的配置缺少必填项 CONTAINS(*, 'NOT Tokyo')org.quartz.threadPool.class属性。

请参阅: http://quartz-scheduler.org/documentation/quartz-1.x/configuration/ConfigThreadPool