Appfuse and Quartz: a very quick tutorial

Quartz is an enterprise-class job scheduler for use in stand-alone and full-blown J2EE applications. It's very easy to implement, scalable and light-weight. I have used Quartz in a number of projects and it works a wonder, no matter if deployed in a complex Weblogic application or a light pojo-based one.
Integrating Quartz with AppFuse (and Spring) is a simple task. For basic scheduling it does not even require you to write a single line of code, everything is done inside the Spring configuration file.
In this tutorial, Quartz is used to invoke a dummy method on the service layer. Things shouldn't be much different in a real life implementation, except that your business logic will be probably using a "dao" implementation to access the persistence store.
During this tutorial I will use %APPFUSE% to reference the "HOME" folder of your Appfuse based application.

Configuration

Code

Quartz persistence

Quartz uses JobStores to persist information about triggers, jobs and calendars. The default Job Store is the "RAMJobStore". As indicated by the name, it keeps all the information in RAM, hence triggers and job information don't survive JVM restarts. Actually, this can be the desired behavior for an application. On some occasions, it may be necessary to persist the scheduling information on some less volatile storage. That's when the "JDBCJobStore" comes in handy. This JobStore persists all the scheduling information in a database. It comes in two flavours:
The default JobStore used by Spring is the JobStoreCMT, through a LocalDataSourceJobStore that delegates to a Spring-managed DataSource instead of using a Quartz-managed connection pool. Due to the lack of serialization capability of the MethodInvokingJobDetailFactoryBean, it is not possible to activate the JDBCJobStore and invoke a method on the service layer using the previous example.
A QuartzJobBean must be used instead. A QuartzJobBean is a simple wrapper around a Quartz Job class.
public class DummyJob extends QuartzJobBean {

  private ApplicationContext ctx;
  <!-- Always expose this --/>
  public void setApplicationContext(ApplicationContext applicationContext) {
    this.ctx = applicationContext;
  }

  protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    SomeManager sm = (SomeManager)ctx.getBean("someManager");
    sm.doScheduledOperation();
  }
}
As you can see from the code above, it's not possible to inject a bean reference into the QuartzJobBean without incurring serialization issues. Therefore the service bean has to be retrieved explicitly from the ApplicationContext. Few additional changes have to be implemented to activate a JDBCJobStore and use a QuartzJobBean: