Search code examples
grailsquartz-schedulergrails-plugin

How to configure Quartz triggers in Grails to allow different schedules for testing and production


I am trying to adopt the Quartz plugin (:quartz:1.0.1) in Grails 2.2.4 and am trying to figure out how to allow development and testing to use a different schedule than what is desired in production without having to change the code deployed to each.

Here is my experience.

I am using a JDBC JobStore and the Quartz Monitor plugin (:quartz-monitor:1.0) too. So I have a job defined like this:

class TestJob {
    static triggers = {
        cron name: 'testTrigger', startDelay: 1000, cronExpression: '0 0/1 * * * ?'
    }
    ...
}

When I run the Grails application the trigger is set up for the job, stored in the database, and starts executing. If I go in and make an intentional change to the cron expression through the Quartz Monitor it is reflected in the database and the execution schedule.

If I now restart the application the trigger is changed back to what is defined in the job. So using this approach I am pretty much stuck with whatever is in the triggers block for the job. If I remove the triggers block from the code altogether then the database definitions go unaltered and control the schedule which seems like an improvement.

So I think it makes sense to not define any triggers in the Job, but that leaves me trying to figure out how to load the triggers up in the first place and in a way that does not overwrite intentional changes. It seems like adding a block to the config (probably in an external config file) for defining triggers would make sense. As far as I can tell I would need to write something to parse this at start-up (in BootStrap?) and apply it through the Quartz API.

Does something like this already exist that am missing in all of my documentation reading and googling? Or maybe I am wrongheaded in a more fundamental way.

Update with some implementation details

Hans gave me some ideas about what should work for my situation.

I ended up turning off the JDBC job store because I decided the config should be the authority for triggering. I put the job/trigger information into an external config file that looks like this.

quartzJobs: [
    'TestJob': [
        cronTriggers: [
            cronExpression: '0 0 7 ? * 2-6'
        ]
    ]
]

Then I have some code called in BootStrap that looks like this.

def jobs = grailsApplication.config.quartzJobs
if (jobs) {
    jobs.each { job, details ->
        List triggers = (details?.cronTriggers instanceof Map) ? [details.cronTriggers]: details.cronTriggers
        if (triggers) {
            def j = grailsApplication.mainContext.getBean(job)
            triggers.each { trigger ->
                String cronExpression = trigger.cronExpression ?: '1 1 1 1 1 ? 2099'
                j.schedule(cronExpression)
            }
        }
    }
}

Solution

  • You can put the configuration in your Config.groovy or in a properties file that gets read from grails.config.locations.

    And then in you BootStrap.groovy you can do:

    TestJob.schedule(grailsApplication.config.cronExpression)
    

    In this cronExpression is the name of the property you chose in the properties file.

    See http://grails-plugins.github.io/grails-quartz/guide/triggers.html for the different Job.schedule() methods that are available.