`

Quartz scheduler plugins – hidden treasure

阅读更多

Although briefly described in the official documentation, I believe Quartz plugins aren’t known enough, looking at how useful they are.

Essentially plugins in Quartz are convenient classes wrapping registration of underlying listeners. You are free to write your own plugins but we will focus on existing ones shipped with Quartz.

LoggingTriggerHistoryPlugin

First some background. Two main abstractions in Quartz are jobs and triggers. Job is a piece of code that we would like to schedule. Trigger instructs the scheduler when this code should run. CRON (e.g. run every Friday between 9 AM and 5 PM until November) and simple (run 100 times every 2 hours) triggers are most commonly used. You associate any number of triggers to a single job.

Believe it or not, Quartz by default provides no logging or monitoring whatsoever of executed jobs and triggers. There is an API, but no built-in logging is implemented. It won’t show you that it now executes this particular job due to this trigger firing. So the first thing you should do is adding the following lines to your quartz.properties:

org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin
	 
org.quartz.plugin.triggerHistory.triggerFiredMessage=Trigger [{1}.{0}] fired job [{6}.{5}] scheduled at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}, next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}
	 
org.quartz.plugin.triggerHistory.triggerCompleteMessage=Trigger [{1}.{0}] completed firing job [{6}.{5}] with resulting trigger instruction code: {9}. Next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}
	 
org.quartz.plugin.triggerHistory.triggerMisfiredMessage=Trigger [{1}.{0}] misfired job [{6}.{5}]. Should have fired at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}


The first line (and the only required) loads the plugin class LoggingTriggerHistoryPlugin. The remaining lines are configuring the plugin, customizing the logging messages. I found the built-in defaults not very well thought, e.g. they display current time which is already part of the logging framework message. You are free to construct any logging message, see the API for details. Adding these extra few lines makes debugging and monitoring much easier:

LoggingTriggerHistoryPlugin | Trigger [Demo.Every-few-seconds] fired job [Demo.Print-message] scheduled at:  04-04-2012 23:23:47.036, next scheduled at:  04-04-2012 23:23:51.036
//...job output
LoggingTriggerHistoryPlugin | Trigger [Demo.Every-few-seconds] completed firing job [Demo.Print-message] with resulting trigger instruction code: DO NOTHING. Next scheduled at:  04-04-2012 23:23:51.036


You see now why naming your triggers (Demo.Every-few-seconds) and jobs (Demo.Print-message) is so important.

LoggingJobHistoryPlugin

There is another handy plugin related to logging:

org.quartz.plugin.jobHistory.class=org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobHistory.jobToBeFiredMessage=Job [{1}.{0}] to be fired by trigger [{4}.{3}], re-fire: {7}
org.quartz.plugin.jobHistory.jobSuccessMessage=Job [{1}.{0}] execution complete and reports: {8}
org.quartz.plugin.jobHistory.jobFailedMessage=Job [{1}.{0}] execution failed with exception: {8}
org.quartz.plugin.jobHistory.jobWasVetoedMessage=Job [{1}.{0}] was vetoed. It was to be fired by trigger [{4}.{3}] at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}


The rule is the same – plugin + extra configuration. See JavaDoc of LoggingJobHistoryPlugin for details and possible placeholders. Quick look at logs reveals very descriptive output:

Trigger [Demo.Every-few-seconds] fired job [Demo.Print-message] scheduled at:  04-04-2012 23:34:53.739, next scheduled at:  04-04-2012 23:34:57.739
Job [Demo.Print-message] to be fired by trigger [Demo.Every-few-seconds], re-fire: 0
//...job output
Job [Demo.Print-message] execution complete and reports: null
Trigger [Demo.Every-few-seconds] completed firing job [Demo.Print-message] with resulting trigger instruction code: DO NOTHING. Next scheduled at:  04-04-2012 23:34:57.739


I have no idea why these plugins aren’t enabled by default. After all, if you don’t want such a verbose output, you can turn it off in your logging framework. Never mind, I think it is a good idea to have them in place when troubleshooting Quartz execution.

XMLSchedulingDataProcessorPlugin

This is a pretty comprehensive plugin. It reads XML file (by default named quartz_data.xml) containing jobs and triggers definitions and adds them to the scheduler. This is especially useful when you have a global job that you need to add once. Plugin can either update the existing jobs/triggers or ignore the XML file if they already exist – very useful when JDBCJobStore is used.
org.quartz.plugin.xmlScheduling.class=org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin

In the aforementioned article we have been manually adding job to the scheduler:

val trigger = newTrigger().
        withIdentity("Every-few-seconds", "Demo").
        withSchedule(
            simpleSchedule().
                    withIntervalInSeconds(4).
                    repeatForever()
        ).
        build()
  
val job = newJob(classOf[PrintMessageJob]).
        withIdentity("Print-message", "Demo").
        usingJobData("msg", "Hello, world!").
        build()
  
scheduler.scheduleJob(job, trigger)


The same can be achieved with XML configuration, just place the following quartz_data.xml in your CLASSPATH:

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation=" http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd ">
 
    <processing-directives>
        <overwrite-existing-data>false</overwrite-existing-data>
        <ignore-duplicates>true</ignore-duplicates>
    </processing-directives>
 
    <schedule>
        <trigger>
            <simple>
                <name>Every-few-seconds</name>
                <group>Demo</group>
                <job-name>Print-message</job-name>
                <job-group>Demo</job-group>
                <repeat-count>-1</repeat-count>
                <repeat-interval>4000</repeat-interval>
            </simple>
        </trigger>
 
        <job>
            <name>Print-message</name>
            <group>Demo</group>
            <job-class>com.blogspot.nurkiewicz.quartz.demo.PrintMessageJob</job-class>
            <job-data-map>
                <entry>
                    <key>msg</key>
                    <value>Hello, World!</value>
                </entry>
            </job-data-map>
        </job>
 
    </schedule>
 
 
</job-scheduling-data>


The same can be achieved with XML configuration, just place the following quartz_data.xml in your CLASSPATH:
org.quartz.plugin.xmlScheduling.fileNames=/etc/quartz/system-jobs.xml,/home/johnny/my-jobs.xml
org.quartz.plugin.xmlScheduling.scanInterval=60


ShutdownHookPlugin

Last but not least, ShutdownHookPlugin. Small but probably useful plugin that register shutdown hook in the JVM in order to gently stop the scheduler. However I recommend turning cleanShutdown off – if the system already tries to abruptly stop the application (typically scheduler shutdown is called by Spring via SchedulerFactoryBean) or the user hit Ctrl+C – waiting for currently running jobs seems like a bad idea. After all, maybe we are killing the application because some jobs are running for too long/hunging?

org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=false


As you can see Qurtz ships with few quite interesting plugins. For some reason they aren’t described in detail in the official documentation, but they work pretty well and are a valuable addition to scheduler.

The source code with applied plugins is available on GitHub.
分享到:
评论

相关推荐

    quartz scheduler 入门教程

    quartz scheduler 入门教程 Quartz Scheduler 是一种功能丰富、开源的任务调度程序库,可以在任何 Java 程序中使用。它可以用来创建简单或者复杂的执行次数可以达成千上万的任务。任务可以是任何 Java 可以做的事情...

    Getting_Started_with_Quartz_Scheduler.pdf Version 2.2.1

    ### 关于Quartz Scheduler #### 什么是Quartz Scheduler? Quartz Scheduler是一款功能强大的开源作业调度框架,被广泛应用于Java应用程序中。它能够触发在指定时间运行的作业,并且支持复杂的工作流模式。Quartz ...

    Quartz_Scheduler_Configuration_Guide.pdf Version2.2.1

    ### Quartz Scheduler 配置指南知识点概述 #### 一、配置概览 《Quartz Scheduler Configuration Guide》版本2.2.1是一份详细介绍了如何配置Quartz Scheduler的重要文档。该文档适用于Quartz Scheduler 2.2.1及...

    quartz-scheduler分享.docx

    Quartz-Scheduler是一款开源的Java定时任务框架,它允许开发者精细地控制任务的执行时间,以及灵活地组织和管理大量的任务。Quartz的核心特性包括可持久化的作业存储、集群支持以及丰富的API,使得它成为企业级应用...

    Quartz Scheduler Framework 2.0.chm

    Quartz is a full-featured, open source job scheduling service that can be integrated with, or ... The Quartz Scheduler includes many enterprise-class features, such as JTA transactions and clustering.

    Quartz Scheduler入门

    Quartz Scheduler是一款强大的开源任务调度库,广泛应用于Java应用程序中,用于执行定时任务。它提供了丰富的API和灵活性,使得开发者可以方便地定义、安排和控制任务执行。在本文中,我们将深入探讨Quartz ...

    最新 Spring 4.2.2 集成 Quartz Scheduler 2.2.2 任务调度示例

    本资源是一个最新 Spring 4.2.2 集成 Quartz Scheduler 2.2.2 的一个简单的 demo,也是博客《最新 Spring 4.2.2 集成 Quartz Scheduler 2.2.2 任务调度示例》的配套示例项目,该博客地址是:...

    基于QuartzScheduler的简单状态机Winder.zip

    Winder 是一个基于 Quartz Scheduler 的简单状态机。它有助于在 Quartz Scheduler 上编写多个步骤任务。Winder 源于一种在 eBay Cloud 中广泛使用的状态机。eBay 平台即服务(PaaS)使用它来将软件部署到数十万个...

    shiro+SpringMVC+Spring+mybatis+maven+mybatis 自动刷新+ Quartz scheduler 定时器

    "shiro+SpringMVC+Spring+mybatis+maven+mybatis 自动刷新+Quartz scheduler 定时器"是一个常见的技术栈组合,每个组件都有其特定的功能和作用。 1. **Shiro**:Apache Shiro 是一个强大且易用的Java安全框架,提供...

    Quartz Scheduler详解

    9. **监听器和插件(Listeners & Plugins):** Quartz提供了灵活的事件监听器以及插件机制,开发者可以通过监听器获得作业执行的反馈,通过插件扩展Quartz的功能。 **Quartz Scheduler 2.1.x的特性变化:** - API...

    spring timer、quartz俩种任务调度

    Spring框架提供了对定时任务的强大支持,包括内置的`Spring Timer`和集成第三方的`Quartz Scheduler`。这两种方式都允许开发者灵活地安排和执行周期性任务。下面我们将深入探讨这两种任务调度器及其在Spring中的使用...

    对于Quartz.net 3.0.7.0(目前最高版本)的使用:能过配置文件实现工作调整

    3. **Scheduler(调度器)**: Scheduler是Quartz的核心,负责管理所有的Job和Trigger,并根据Trigger的时间规则执行Job。 **使用quartz_jobs.xml配置文件** 在Quartz.NET 3.x中,虽然XML配置文件并不是默认的首选...

    Quartz中文入门教程

    Quartz中文入门教程 前言 Quartz让任务调度简单 ...用调度器(Scheduler)调用你的作业 编程调度同声明性调度 有状态和无状态作业 Quartz框架的其他特征 Quartz下一步计划 了解更多Quartz特征

    Quartz_Scheduler_Example_Programs_and_Sample_Code.pdf Version 2.2.1

    ### Quartz Scheduler 示例程序与样例代码分析 #### 概述 Quartz Scheduler 是一款功能强大的开源作业调度框架,被广泛应用于 Java 应用程序中。它提供了丰富的 API 和灵活的配置选项来帮助开发者轻松实现定时任务...

    Quartz调度、终止执行的任务

    关于终止执行的任务,Quartz提供了`scheduler.pauseJob()`和`scheduler.resumeJob()`方法来暂停和恢复Job。如果你想要终止某个任务,你可以调用`scheduler.deleteJob()`来移除Job实例,使其不再执行。例如: ```...

Global site tag (gtag.js) - Google Analytics