Schedule multiple jobs from json file using Spring Quartz Scheduler


Configure schedule information in json file

  1. Create a json file with schedule information like schedule time and job information details also like job id or key.
  2. This json file contains unique key for maintaining jobs.
  3. Write POJO class equivalent to json file structure.
  4. Convert JSON to List of POJO classes
  5. Pass the list to scheduler to schedule the jobs.

Json file for configuration

[
	{
		"configId": "1",
		"configName": "send_email",
		"scheduledTime": "0 * * ? * *",
		"jobData": "[email protected]"
	},
	{
		"configId": "2",
		"configName": "send_email",
		"scheduledTime": "0 * * ? * *",
		"jobData": "[email protected]"
	}
]

POJO equivalent to JOSN

  1. JobData is generic so we can write any structure in JSON file
class Config<T> {
	private String configId;
	private String configName;
	private String scheduledTime;
	private T jobData;

	public String getConfigId() {
		return this.configId;
	}

	public void setConfigId(String argConfigId) {
		this.configId = argConfigId;
	}

	public String getConfigName() {
		return this.configName;
	}

	public void setConfigName(String argConfigName) {
		this.configName = argConfigName;
	}

	public String getScheduledTime() {
		return this.scheduledTime;
	}

	public void setScheduledTime(String argScheduledTime) {
		this.scheduledTime = argScheduledTime;
	}

	public T getJobData() {
		return this.jobData;
	}

	public void setJobData(T argJobData) {
		this.jobData = argJobData;
	}

}

Job code to execute multiple types of jobs

package com.oc;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

@Component
public class MyJob implements Job {

	@SuppressWarnings("rawtypes")
	@Override
	public void execute(JobExecutionContext argContext) throws JobExecutionException {
		System.out.println("I am scheduled on " + new Date(System.currentTimeMillis()));
		System.out.println("MyJob 1" + argContext.getJobDetail().getJobDataMap().get("config"));
		Config config = (Config) argContext.getJobDetail().getJobDataMap().get("config");
		execute(config);
	}

	@SuppressWarnings("rawtypes")
	private void execute(Config argConfig) {
		switch (argConfig.getConfigName()) {
		case "send_email": {
			String email = (String) argConfig.getJobData();
			sendEmail(email);
		}
		default:
			break;
		}
	}

	private void sendEmail(String argEmail) {
		System.out.println("Send email");
		// Write send email logic
	}

}

Scheduler code

import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MyScheduler {

	public static Scheduler scheduler() throws Exception {
		StdSchedulerFactory factory = new StdSchedulerFactory();
		factory.initialize(new ClassPathResource("quartz.properties").getInputStream());

		Scheduler scheduler = factory.getScheduler();
		scheduler.setJobFactory(new SpringBeanJobFactory());

		List<Config<String>> jsonData = getJsonData();
		if (jsonData != null) {
			jsonData.forEach(config -> {
				JobDetail job = JobBuilder.newJob(MyJob.class).build();
				job.getJobDataMap().put("config", config);
				Trigger trigger = TriggerBuilder.newTrigger().forJob(job)
						.withSchedule(getScheduleBuilder(config.getScheduledTime())).build();
				try {
					scheduler.scheduleJob(job, trigger);
				} catch (SchedulerException e) {
					e.printStackTrace();
				}
			});
		}
		scheduler.start();
		return scheduler;
	}

	private static CronScheduleBuilder getScheduleBuilder(String cronExpr) {
		try {
			return CronScheduleBuilder.cronSchedule(new CronExpression(cronExpr));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return CronScheduleBuilder.cronSchedule(cronExpr);
	}

	private static List<Config<String>> getJsonData() {
		ObjectMapper objectMapper = new ObjectMapper();
		try {
			return objectMapper.readValue(new FileInputStream("/Users/tanantham/luna_dev_home/MyQuartz/config.json"),
					new TypeReference<List<Config<String>>>() {
					});
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}

Quartz properties

# thread-pool
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=2
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

# job-store
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

# others
org.quartz.jobStore.misfireThreshold = 60000