About¶
Fathom-Quartz provides Quartz Scheduler integration for your application. Quartz allows you to easily setup scheduled tasks within your application.
This is a fork of the Apache Onami Scheduler.
Installation¶
Add the Fathom-Quartz artifact.
<dependency>
    <groupId>com.gitblit.fathom</groupId>
    <artifactId>fathom-quartz</artifactId>
    <version>${fathom.version}</version>
</dependency>
Layout¶
YourApp
└── src
    └── main
        └── java
            └── conf
                ├── Jobs.java
                └── quartz.properties
Note
This module depends on the value of the application.package setting.  If you have specified an application package then your Jobs class must be ${package}/conf/Jobs.java.
Configuration¶
By default, this module will try to configure Quartz from a conf/quartz.properties resource file.
Quartz has many features and settings. Two common ones that you are likely to change are how worker threads are named and how many threads are in the Quartz threadpool.
# Prefix of Quartz worker thread
org.quartz.threadPool.threadNamePrefix = Jobs Worker
# Number of threads in the Quartz pool
org.quartz.threadPool.threadCount = 5
Usage¶
Create a conf/Jobs.java class.  Jobs can be manually scheduled in the conf/Jobs.java class or they can be annotated on each Job class.
package conf;
public class Jobs extends JobsModule {
  @Override
  protected void schedule() {
    scheduleJob(MyJob.class);
    scheduleJob(OtherJob.class).withCronExpression("0/60 * * * * ?");
  }
}
Then create some Job classes.  Job classes support injection.
@Scheduled(jobName = "My Job", cronExpression = "0/60 * * * * ?")
@DisallowConcurrentExecution
public class MyJob implements Job {
  final Logger log = LoggerFactory.getLogger(MyJob`.class);
  @Inject
  EmployeeDao employeeDao;
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    int count = employeeDao.getAll().size();
    log.debug("My job triggered, {} employees in system", count);
  }
}
Requiring Settings¶
Your job may need one or more settings to function and you may specify them as annotated requirements.
Each required setting must be present in the runtime profile configuration and must have a non-empty value otherwise the job will not be registered.
@RequireSetting("myjob.url")
@Scheduled(jobName = "My Job", cronExpression = "0/60 * * * * ?")
public class MyJob implements Job {
  final Logger log = LoggerFactory.getLogger(MyJob.class);
  @Inject
  Settings settings;
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    String url = settings.getString("myjob.url");
    log.debug("My job triggered {}", url);
  }
}
Requiring Modes¶
You might only want to load your job in a particular runtime mode. This is easily accomplished by using one or more of the mode-specific annotations: @DEV, @TEST, and @PROD.
@Scheduled(jobName = "DEV Job", cronExpression = "0/30 * * * * ?")
@DEV
public class DevJob implements Job {
  final Logger log = LoggerFactory.getLogger(DevJob.class);
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    log.debug("My DEV job triggered");
  }
}
Monitoring¶
Fathom-Quartz installs a global job listener which automatically tracks job execution statistics, buffers recent job stacktraces, and allows pause & resume control over jobs.
@Inject
JobsMonitor jobsMonitor;
public void logJobsThatThrewAnException() {
  for (JobInfo job : jobsMonitor.getJobs()) {
    if (job.getExceptionCount() > 0) {}
      log.error("{} was executed {} times and failed {} times ({}% failure rate)",
        job.getName(), job.getExecutionCount(), job.getExceptionCount(), job.getExceptionPercentage());
    }
  }
}