Scheduling jobs with quartz-jruby
There would be times when you would want to run repetitive tasks once in every few minutes. Like for example, downloading twitter feeds or importing data from one system to another system and so on. Most operating systems have an utility called Cron to do that. Sometimes you may have so many of these small processes that it may not be feasible to fork off a new process every time. It might be easier to have it running as a server. Java has an excellent library called Quartz.
Quartz is a full-featured, open source job scheduling service that can be integrated with, or used along side virtually any Java EE or Java SE application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may executed virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as JTA transactions and clustering.
The Java Way
To have a simple cron job, you need to write something like this. First you write the job. For example, here we have a cron job that gets fired every 20 seconds.
//SimpleJob.java
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SimpleJob implements Job {
private static Logger _log = LoggerFactory.getLogger(SimpleJob.class);
public SimpleJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException {
// do something complicated
_log.info("hello job");
}
}
And then you have to schedule it.
//CronScheduler.java
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
public class CronScheduler{
public void run() throws Exception {
Logger log = LoggerFactory.getLogger(CronScheduler.class);
// First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
// jobs can be scheduled before sched.start() has been called
JobDetail job = new JobDetail("job1", "group1", SimpleJob.class);
CronTrigger trigger = new CronTrigger("trigger1", "group1", "job1",
"group1", "0/20 * * * * ?");
sched.addJob(job, true);
Date ft = sched.scheduleJob(trigger);
//start the scheduler
sched.start();
}
public static void main(String[] args) throws Exception {
CronScheduler example = new CronScheduler();
example.run();
}
}
The Ruby Way
Although the above code works, this seems very .... umm... verbose. I have written a wrapper around Quartz that makes it a lot more palatable. Now presenting quartz-jruby. You can install it like below.
$ jruby -S gem install quartz-jruby
Now for some ruby code. This sets up the logger, manages jobs and schedules them with a friendly syntax.
# cron_scheduler.java
require 'java'
require 'rubygems'
gem 'quartz-jruby'
require 'quartz'
# configure log4j the way you want. I am lazy. :-)
org.apache.log4j.BasicConfigurator.configure
class CronScheduler
# this adds all the scheduler stuff to your class
include Quartz::Scheduler
schedule(:hello_job, :every=>20.seconds) do
# any ruby code
info "I fire every 20 seconds"
end
end
# run the scheduler
CronScheduler.instance.run
Feedback
If you would like to check the source, you can visit quartz-jruby on github. Your comments are welcome.
