为什么Quartz任务没有执行(尽管QUARTZ表已更新为正确的任务详细信息)

3

我正在使用Spring 3和Quartz 1.8.6。我已经按以下方式在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);

现在问题是一切工作正常,没有任何异常,并且作业详细信息已更新到预定义的quartz数据库详细信息中。但是该作业未被执行。您能帮我解决这个问题吗?

你能解释一下你想要实现什么吗?从我的角度来看,这似乎只是一个简单的“为什么它不起作用”的问题。 - bhdrkn
实际上我正在尝试从UI中在运行时添加任务。它可以正常工作,没有任何异常被抛出,但是任务从未被执行 :( - Abhinab Kanrar
是的...我正在使用在Spring应用程序上下文XML中定义的调度程序实例。经过检查,它显示为true,即它正在运行。 - Abhinab Kanrar
也许它没有被正确地安排计划。您可以使用此处的代码片段查看作业何时设置为执行下一个(getNextFireTime()):http://www.mkyong.com/java/how-to-list-all-jobs-in-the-quartz-scheduler/ - headlikearock
我遇到了类似的问题,你也遇到了吗? - Jerry
显示剩余4条评论
2个回答

0

1
如果手动创建了调度程序,那么您是完全正确的。SchedulerFactoryBean会自行设置这两个属性。您可以查看SchedulerFactoryBean的源代码。 - bhdrkn

0

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

更新

既然你已经有了默认构造函数,我建议进行一些重构。我使用的是带有Spring的2.2.1版本的quartz,因此某些类名可能不同。

首先让我们将实体分解为两个部分。

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实现)几乎代理了所有内容并保存了大量状态。这将干扰quartz的执行。

更新2

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


它有一个默认构造函数,但我忘记添加了 :( 然而它并没有起作用。 - Abhinab Kanrar
这个想法基于以下回答:期望的输出/结果是否取决于您提供给非默认构造函数的参数? - flo
@flo 不,它不依赖于您提供给默认构造函数的参数。但是由于JobDetail需要将jobClass作为参数,如果您的类没有默认构造函数,则无法初始化对象实例。 - bhdrkn
@bhdrkn 我知道这一点;我想也许原帖发布者依赖于他添加作业时使用的参数。 - flo
我执行了调试并发现任务调度程序处于运行状态,任务成功添加到调度程序中。但是,在接下来的代码中,当我试图查找与调度程序相关联的所有任务名称时,它会抛出nullpointer异常,即实际上没有任务在调度程序中。你能帮我解决这个问题吗? - Abhinab Kanrar
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接