Micronaut Quartz

Integration between Micronaut and Quartz

Version:

1 Introduction

This project add integration between Micronaut and Quartz.

1.1 Release History

1.0.0

  • XXX

2 Quartz Quick Start

To add supprt for Quartz to an existing project, you should first add the Micronaut Quartz configuration to your build build configuration. For example

implementation("io.pollend.quartz:micronaut-quartz")
<dependency>
    <groupId>io.pollend.quartz</groupId>
    <artifactId>micronaut-quartz</artifactId>
</dependency>

Creating a Quartz Job with @QuartzJob

To create a Job in Quartz, a job has to implements the Job interface and annotated with @QuartzJob.

import io.pollend.quartz.annotation.QuartzJob;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;

@QuartzJob (1)
@Singleton
public class MessageJob implements Job { (2)

    List<String> messages = Collections.synchronizedList(new ArrayList<>());
    @Override
    public void execute(JobExecutionContext context)  {
        JobDataMap map = context.getJobDetail().getJobDataMap();
        messages.add(map.getString("message"));
    }
}
import io.pollend.quartz.annotation.QuartzJob
import org.quartz.Job
import org.quartz.JobDataMap
import org.quartz.JobExecutionContext
import org.quartz.JobExecutionException
import javax.inject.Singleton

@QuartzJob (1)
@Singleton
class MessageJob implements Job { (2)
    public List<String> messages = Collections.synchronizedList(new ArrayList<>())
    @Override
    void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap map = context.jobDetail.jobDataMap;
        messages.add(map.getString("message"));
    }
}
import io.pollend.quartz.annotation.QuartzJob
import org.quartz.Job
import org.quartz.JobExecutionContext
import javax.inject.Singleton

@QuartzJob (1)
@Singleton
class MessageJob : Job { (2)
    val messages: MutableList<String> = Collections.synchronizedList(ArrayList());
    override fun execute(context: JobExecutionContext?) {
        val map = context!!.jobDetail.jobDataMap
        messages.add(map.getString("message"));
    }
}
1 The @QuartzJob annotation used to designate a Quartz Job that will be used by Micronaut.
2 The Quartz Job interface.

At compile time Micronaut will produce an implementation of the Job. An instance of the bean will be retrieved when Quartz schedules the job. The Job instance can be triggered with the standard Quartz scheduler. This can be retrieved from the ApplicationContext:

Scheduler scheduler = ctx.getBean(Scheduler.class);
scheduler.scheduleJob(JobBuilder.newJob(MessageJob.class)
    .setJobData(new JobDataMap(new HashMap<String, Object>() {{
        put("message", "My Message");
    }})).build(), TriggerBuilder.newTrigger().startNow().build());
Scheduler scheduler = ctx.getBean(Scheduler.class)
scheduler.scheduleJob(JobBuilder.newJob(MessageJob.class)
    .setJobData(new JobDataMap([
        "message": "My Message"
    ])).build(), TriggerBuilder.newTrigger().startNow().build())
val scheduler = ctx.getBean(Scheduler::class.java)
scheduler.scheduleJob(JobBuilder.newJob(MessageJob::class.java).setJobData(
    JobDataMap(mutableMapOf(
        "message" to "My Message"
    ))
).build(), TriggerBuilder.newTrigger().startNow().build())

'

3 Configuring the Quartz Scheduler

The properties that can be converted from the string values in a configuration file can be configured directly.

🔗
Table 1. Configuration Properties for QuartzClientConfiguration
Property Type Description

quartz.clients.*.config-file

java.lang.String

the config file.

🔗
Table 2. Configuration Properties for QuartzConfiguration
Property Type Description

quartz.calenders

java.util.Map

calendars for scheduler.

quartz.enabled

boolean

enable quartz scheduler.

🔗
Table 3. Configuration Properties for QuartzTriggerConfiguration
Property Type Description

quartz.triggers[*].identity

java.lang.String

quartz.triggers[*].description

java.lang.String

quartz.triggers[*].priority

int

quartz.triggers[*].modified-by-calendar

java.lang.String

quartz.triggers[*].start-at

java.util.Date

quartz.triggers[*].end-at

java.util.Date

quartz.triggers[*].schedule

org.quartz.ScheduleBuilder

quartz.triggers[*].for-job

org.quartz.JobKey

quartz.triggers[*].job.new-job

java.lang.Class

quartz.triggers[*].job.identity

java.lang.String

quartz.triggers[*].job.description

java.lang.String

quartz.triggers[*].job.of-type

java.lang.Class

quartz.triggers[*].job.request-recovery

boolean

quartz.triggers[*].job.store-durably

boolean

quartz.triggers[*].client

java.lang.String

id for scheduler

quartz.triggers[*].target

java.lang.Class

job used with trigger

quartz.triggers[*].cron

java.lang.String

set a cron tab that triggers for {@link org.quartz.Job}

quartz.triggers[*].data

java.util.Map

set data for job detail

Scheduler Configuration

the config-file is the configuration for the associated scheduler. One or more clients can be configured as follows:

For Example:

quarts:
  enabled: true
  clients:
    default:
      config-file: "classpath:quartz.properties"
    two:
      config-file: "classpath:another.properties"

A configuration reference is available from the Quartz Configuration. A sample quartz.properties can be also found in the quickstart.

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

Schedules and Triggers

Schedules and triggers can be configured for daily or initial jobs with the start of the application.

For Example:

quartz:
  enabled: true
  clients:
    default:
      config-file: "classpath:quartz.properties"
  triggers:
    - start-now: true
      description: "initial trigger"
      target: "io.company.job1"
    - start-now: true
      description: "job at 2 every day"
      target: "io.company.job2"
      cron:  0 2 * * *

Calendar

TODO: setup calendar configuration

4 Job Scheduler with @QuartzSchedule

Jobs can be triggered off of an @QuartzSchdule (defined by the QuartzScheduleIntroductionAdvice).

The interface has to be marked by @QuartzSchedule and each job trigger is defined by an associated method annotated with @ScheduleOn.

import io.pollend.quartz.annotation.QuartzKey;
import io.pollend.quartz.annotation.ScheduleOn;
import org.quartz.JobKey;
import org.quartz.Trigger;

public interface SampleScheduler {
    @ScheduleOn(MessageJob1.class)
    void messageWithoutKey(@QuartzKey("message") String value);

    @ScheduleOn(MessageJob1.class)
    void messageJobWithKey(JobKey key, @QuartzKey("message") String value);

    @ScheduleOn(MessageJob1.class)
    void messageJobWithTrigger(JobKey key, Trigger trigger, @QuartzKey("message") String value);
}
import io.pollend.quartz.annotation.QuartzKey
import io.pollend.quartz.annotation.QuartzSchedule
import io.pollend.quartz.annotation.ScheduleOn
import org.quartz.JobKey
import org.quartz.Trigger

@QuartzSchedule
interface SampleScheduler {
    @ScheduleOn(MessageJob1.class)
    void messageWithoutKey(@QuartzKey("message") String value);

    @ScheduleOn(MessageJob1.class)
    void messageJobWithKey(JobKey key, @QuartzKey("message") String value)

    @ScheduleOn(MessageJob1.class)
    void messageJobWithTrigger(JobKey key, Trigger trigger, @QuartzKey("message") String value)
}
import io.pollend.quartz.annotation.QuartzKey
import io.pollend.quartz.annotation.ScheduleOn
import org.quartz.JobKey
import org.quartz.Trigger

interface SampleScheduler {

    @ScheduleOn(MessageJob1::class)
    fun messageWithoutKey(@QuartzKey("message") value: String?)

    @ScheduleOn(MessageJob1::class)
    fun messageJobWithKey(key: JobKey?, @QuartzKey("message") value: String?)

    @ScheduleOn(MessageJob1::class)
    fun messageJobWithTrigger(key: JobKey?, trigger: Trigger?, @QuartzKey("message") value: String?)
}