Created

Jul 08, 2013

Scheduling Jobs Using Sling

Posted by Ugo Cei

The Sling Commons Scheduler Service is a Sling-provided mechanism that is used to execute jobs at predefined times–either periodically or at a set time. Is is based on the Quartz scheduling library and can therefore make use of its syntax for defining the execution times of jobs, making it possible to precisely indicate times like "at 6:32pm on every Saturday and Sunday" or "at 2:30am on the first Friday of every month". At the other end of the spectrum, a simple numeric value can be used to specify the interval–in seconds–between each execution of the job.

More information about the cron-like expressions used by Quartz can be found at http://docjar.com/docs/api/org/quartz/CronExpression.html.

Inside CQ, an OSGi component that implements the java.lang.Runnable or the org.quartz.Job interface will be started if it has a configuration property called either scheduler.expression (whose value must be a cron expression) or scheduler.period (whose value must be a number of seconds).

Thanks to OSGi annotations, one can simply define a scheduled jobs using code like the following:

@Component(immediate=true)
@Service(interface="java.lang.Runnable")
@Property(name="scheduler.expression" value="0 0/10 * * * ?", type="String")
public class MyScheduledJob implements java.lang.Runnable {
  public void run() {
    // code to execute goes here
  }
}

Notice that we specified "immediate=true" in the @Component declaration. This makes sure that the component is activated immediately when the bundle is registered, a thing which is necessary for it to be properly invoked by the scheduler.

The method run() of the above component will be executed every hour at 0, 10, 20, 30, 40, and 50 minutes, zero seconds. If we had simply wanted an execution every 10 minutes, we could have used the following annotation instead:

@Property(name="scheduler.period" value="600", type="Long")

Concurrent execution of the job, which might happen if the previous execution has not yet finished when a new one is scheduled, can be prevented by setting the scheduler.concurrent property to false:

@Property(name="scheduler.concurrent", propertyPrivate=true, boolValue=false)

In a real-world scenario, we might want to be able to specify the execution time using the CQ5 Web Console. To do this, we need to modify the declaration of the property as follows:

@Component(immediate=true, metatype=true)

COMMENTS

ADD A COMMENT