I’m working on the chapter on Messaging and Scheduling for San Gria (Chapter 14), and I’ve finally had a chance to explore some parts of the sensational Grails Quartz plugin that have been on my to-do list for ages. I’ve had a good explore of non-re-entrant jobs, passing state between jobs, programmatically dealing with jobs, and now I’m having a look at the db-persistent jobs.

One thing that I’ve wanted to explore for the longest time is the ability to pause and resume jobs programmatically via a UI. For example, before I converted groovyblogs.org to a messaging architecture, I was really keen to add an admin UI to pause and resume polling of jobs (for instance when I was doing deploying a new version of the browser snapshot service). Now I know how :-)

First off, if you’re going to be doing programmatic stuff with your jobs, you need to put them in a group (yes you can use a default group, but it makes things easier to follow). Here’s our sample:

class ControllableJob {

    def timeout = 5000 // execute job once in 5 seconds
    def concurrent = false

    **def group = "myServices"**

    def execute() {
        println "Controllable Job running..."
    }
}

Ok, With our job named, we can do all sort of pausing and resuming operations. Let’s whip together a quick UI to post our list of operations in a “operations” field:

A Quick and Dirty Job Admin UI

To take advantage of the quartz scheduler operations, you need to do a “def quartzScheduler” to get the injection happening. After that, you have a wealth of Scheduler interface methods to work with. Here’s our controller method:

    def show = {

        def status = ""

        switch(params.operation) {
            case 'pause':
                quartzScheduler.pauseJob("ControllableJob", "myServices")
                status = "Paused Single Job"
                break
            case 'resume':
                quartzScheduler.resumeJob("ControllableJob", "myServices")
                status = "Resumed Single Job"
                break
            case 'pauseGroup':
                quartzScheduler.pauseJobGroup("myServices")
                status = "Paused Job Group"
                break
            case 'resumeGroup':
                quartzScheduler.resumeJobGroup("myServices")
                status = "Resumed Job Group"
                break
            case 'pauseAll':
                quartzScheduler.pauseAll()
                status = "Paused All Jobs"
                break
            case 'resumeAll':
                quartzScheduler.resumeAll()
                status = "Resumed All Jobs"
                break
        }

        return [ status: status ]

    }

Notice that the pause() and resume() for individual jobs take the full name of the job (“ControllableJob”) as the argument. Notice also that the Groovy switch statement is insanely useful - you can even mix string and integers in the case statement if your switch var is dynamically typed - awesome! (more info).

Anyways… must get back to exploring the database persistent options for quartz jobs so I survive a restart if need be! The end of Chapter 14 is in sight, and those people who have pre-purchased the book via the Manning MEAP program should get it towards the end of the next week/early following week. And we’ll have another 4 chapters going out in time for Christmas!

Happy programmatic scheduling! (Oh, and the sample app above is on github)