Programatically Scheduling Jobs in Grails with Quartz
Posted by Rob James | Posted in General News, Innovation, Software | Posted on 01-12-2009-05-2008
6
In a recent project I was working on I had a requirement to be able to set up Quartz jobs programatically as the application is running. So in other words, when the app is started, there are no jobs scheduled or running, but through a user interface, create jobs and schedule them. I could not find any info on how to do this effectively in Grails, but found it to be easy. Real Easy!!!
Start by installing Quartz;
grails install-plugin quartz
Typically when creating Quartz Jobs in Grails, you would now go ahead and do “grails create-job”, but doing so will automatically trigger the job to run every minute (even if you leave the trigger off) as a default.
Instead, we are going to create a Service to run as a Job. That’s right you can use regular grails services as a Job Class with some minor modifications. And all the Grails Service goodness comes along with it
grails create-service JobScheduler
To make the service to act as a Job, you need to do a few things. The service needs to implement the Job Interface and has to include an execute method (I also needed to use the execute method that took the JobExecutionContext) so your JobScheduler class looks like this;
import org.quartz.Job
import org.quartz.JobExecutionContext;
class JobScheduler implements Job{
boolean transactional = false
public void execute (JobExecutionContext jobExecutionContext) {
println “I have been triggered to run ” + new Date()
}
}
In this example, my job is just printing a statement so I know that the job has run. So now we need to schedule the actual job. Triggering a job can be done through a controller, service or wherever you like. And make sure you check out the JavaDocs for SimpleTrigger and TriggerUtils, they are your friends!!! The only thing to remember is to include the quartzScheduler Bean from the app context
Here are some examples of how you can do it.
Firstly, schedule a one-off job so you just schedule your JobService to be called at some time in the future, this is quite easily done with the SimpleTrigger. Add the following to your controller
def quartzScheduler
And then add the following action
def scheduleOneOff() {
def jobDetail = new JobDetail(“myJob”, null, JobScheduler.class);
def trigger = new SimpleTrigger(“myTrigger”, null, new Date() + 1)
quartzScheduler.scheduleJob(jobDetail, trigger);
}
How easy was that?!?! Its pretty self explanatory, but as you can see we create a JobDetail, which passes the job name, “myJob”, group name (null in this instance) and you pass the Job Class. This is where you tell it about your service you previously created.
We then create a trigger for our Job which in this instance is a simple trigger with the name “myTrigger”, and again a null group and start date in 1 day (you can obviously set it to whatever you want by passing a valid date object).
Finally using the quartzScheduler bean, you schedule the job by passing the jobDetail and trigger to the scheduleJob method.
What about scheduling a recurring job that starts at 2am on the 1st of every month? Easy, use the makeMonthlyTrigger method from the TriggerUtils anonymous class;
def scheduleMonthly() {
def jobDetail = new JobDetail(“myJob”, null, JobScheduler.class);
def trigger = TriggerUtils.makeMonthlyTrigger(1, 2, 0);
trigger.setStartTime(new Date() + 1)
trigger.setName(“myTrigger”);
quartzScheduler.scheduleJob(jobDetail, trigger);
}
Things are very similar except that we have used the makeMonthlyTrigger and passed the start date, hour and minute. We have also told it to start in one day from today (as before) and have given our trigger a name.
There are helper methods to set triggers to happen on the minute, hour, week, month etc and of course you can schedule using your handy Cron expressions too.
By passing JobDetail parameters to your JobService, you could theoretically just use that JobService as a scheduler wrapper service and it can then be a generic scheduler for any job you may want to trigger.
