quartz

quartz

Cron triggers, job scheduling and async processing via Quartz.

dependency

<dependency>
  <groupId>org.jooby</groupId>
  <artifactId>jooby-quartz</artifactId>
  <version>1.5.1</version>
</dependency>

usage

import org.jooby.quartz.Quartz;
...
{
  use(new Quartz().with(MyJob.class));
}

Previous example will startup Quartz and schedule MyJob.

jobs

A job can implement the Job interface as described in the Quartz documentation

If you prefer to not implement the Job interface, all you have to do is to annotated a method with the Scheduled annotation.

By default, job name is set the class name or to the method name. Default group is set to the package name of the job class.

job methods

A job method must follow these rules:

  • It must be a public method
  • Without a return value
  • Have ZERO arguments
  • or just ONE argument of type JobExecutionContext

The next section will you show how to add a trigger to a job and some examples too.

triggers

Trigger are defined by the Scheduled annotation. The annotation defines a single and required attributes, which is basically a trigger expression or a reference to one.

Examples:

Run every 5 minutes, start immediately and repeat for ever:

@Scheduled("5m")
@Scheduled("5m; delay=0")
@Scheduled("5m; delay=0; repeat=*")

Previous, expressions are identical.

Run every 1 hour with an initial delay of 15 minutes for 10 times:

@Scheduled("1h; delay=15m; repeat=10")

Fire at 12pm (noon) every day:

0 0 12* ?

Fire at 10:15am every day:

0 15 10 ?*

It is also possible to put the name of property:

@Scheduled("job.expr")

grouping jobs together

If you have two or more jobs doing something similar, it is possible to group all them into one single class:

public class MyJobs {
  @Scheduled("5minutes")
  public void job1() {
    ...
  }

  @Scheduled("1h")
  public void job2() {
    ...
  }
}

dependency injection

Not much to add here, just let you know jobs are created by Guice.

public class MyJob {
  private A a;

  @Inject
   public MyJob(A a) {
     this.a = a;
   }

   @Scheduled("5minutes")
   public void doWork() {
     this.a.doWork();
   }
}

Injecting a Scheduler

public class MyJobManager {
  private Scheduler scheduler;

  @Inject
  public MyJobManager(Scheduler scheduler) {
    this.scheduler = scheduler;
  }
}

configuration

Example: Setting max number of threads

# default is number of available processors 
org.quartz.threadPool.threadCount = 1

Configuration follows the Quartz documentation. The only difference is that you need to put add the properties on your *.conf file, NOT in a custom quartz.properties file.

jdbc store

Jdbc Store is fully supported but it depends on the jooby-jdbc module. So, in order to use the Jdbc Store you need to follow these steps:

1st. Install the Jdbc module:

{
  use(new Jdbc());
  use(new Quartz(MyJob.class));
}

2nd. Set the quartz properties:

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = db

adding jobs programmatically

When Scheduled isn’t not enough and/or if you prefer to build jobs manually, you can try one of the available alternatives.

Example 1: build the trigger and use default job naming

{
  use(new Quartz()
    .with(MyJob.class, trigger -> {
      trigger
        .withSchedule(withIntervalInDays(3))
        .startAt(futureDate(10, MINUTES));
      })
  );
}

Example 2: build the job, the trigger and use default job naming

{
  use(new Quartz()
    .with(MyJob.class, (job, trigger) -> {
      job.withDescription("etc...");
 
      trigger
        .withSchedule(withIntervalInDays(3))
        .startAt(futureDate(10, MINUTES));
    })
  );
}

Example 3: build and set everything from scratch

{
  use(new Quartz()
   .with(
     newJob(MyJob.class).withDescription("etc...")
       .build(),
     newTrigger()
       .withSchedule(withIntervalInDays(3))
       .startAt(futureDate(10, MINUTES))
       .build()
   })
  );
}

quartz.conf

These are the default properties for quartz:

org.quartz.scheduler.instanceName = quartz

org.quartz.scheduler.instanceId = local

# thread pool 
org.quartz.threadPool.threadNamePrefix = quartz

org.quartz.threadPool.threadCount = ${runtime.processors}

org.quartz.scheduler.skipUpdateCheck = true