com.turbospaces.quartz.QuartzFactoryBean Maven / Gradle / Ivy
package com.turbospaces.quartz;
import java.util.Objects;
import java.util.Properties;
import org.apache.commons.lang3.time.StopWatch;
import org.quartz.Job;
import org.quartz.JobKey;
import org.quartz.JobPersistenceException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.plugins.history.LoggingJobHistoryPlugin;
import org.quartz.plugins.history.LoggingTriggerHistoryPlugin;
import org.quartz.simpl.SimpleJobFactory;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.turbospaces.boot.Bootstrap;
import com.turbospaces.boot.BootstrapAware;
public class QuartzFactoryBean extends AbstractFactoryBean implements JobFactory, BootstrapAware, ApplicationContextAware {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected QuartzConfigurer configurer;
protected Bootstrap bootstrap;
protected ApplicationContext applicationContext;
public QuartzFactoryBean() {
super();
}
public QuartzFactoryBean(QuartzConfigurer configurer) {
this.configurer = Objects.requireNonNull(configurer);
}
@Override
public void setBootstrap(Bootstrap bootstrap) throws Throwable {
this.bootstrap = Objects.requireNonNull(bootstrap);
if (configurer instanceof BootstrapAware) {
((BootstrapAware) configurer).setBootstrap(bootstrap);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public Job newJob(TriggerFiredBundle bundle, Scheduler schd) throws SchedulerException {
try {
JobFactory factory = new SimpleJobFactory();
return factory.newJob(bundle, getObject());
} catch (Exception err) {
throw new SchedulerException(err);
}
}
@Override
public Class> getObjectType() {
return Scheduler.class;
}
@Override
protected Scheduler createInstance() throws Exception {
Properties props = new Properties();
props.put("org.quartz.threadPool.threadCount", bootstrap.props().QUARTZ_WORKER_POOL_COUNT.get().toString());
props.put("org.quartz.scheduler.instanceName", bootstrap.props().CLOUD_APP_ID.get());
props.put("org.quartz.scheduler.instanceId", bootstrap.props().QUARTZ_SCHEDULER_ID.get());
props.put("org.quartz.scheduler.makeSchedulerThreadDaemon", Boolean.TRUE.toString());
props.put("org.quartz.scheduler.skipUpdateCheck", Boolean.TRUE.toString());
props.put("org.quartz.plugin.triggerHistory.class", LoggingTriggerHistoryPlugin.class.getName());
props.put("org.quartz.plugin.jobHistory.class", LoggingJobHistoryPlugin.class.getName());
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
configurer.configureQuartz(props, schedulerFactory);
schedulerFactory.initialize(props);
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.setJobFactory(this);
if (bootstrap.props().QUARTZ_AUTO_REMOVE_JOBS_WITH_MISSING_CLASSES_ENABLED.get()) {
autoRemoveJobsWithMissingJobClasses(scheduler);
}
return scheduler;
}
private void autoRemoveJobsWithMissingJobClasses(Scheduler scheduler) throws SchedulerException {
log.debug("Looking for jobs with missing classes...");
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.anyGroup())) {
log.trace("Checking job key: {}", jobKey);
try {
if (scheduler.getJobDetail(jobKey) != null) {
scheduler.getJobDetail(jobKey).getJobClass();
}
} catch (JobPersistenceException e) {
if (e.getCause() instanceof ClassNotFoundException classNotFoundEx) {
log.warn("Failed to load Java class ({}) for job key '{}'. Job is about to be automatically deleted",
classNotFoundEx.getMessage(), jobKey);
scheduler.deleteJob(jobKey);
}
}
}
}
@Override
protected void destroyInstance(Scheduler instance) throws Exception {
if (instance != null) {
StopWatch stopWatch = StopWatch.createStarted();
boolean waitForCompletion = bootstrap.props().QUARTZ_SHUTDOWN_WAIT_FOR_JOBS_COMPLETION.orElse(bootstrap.isDevMode()).get();
log.info("about to shutdown quartz now ...");
instance.shutdown(waitForCompletion);
stopWatch.stop();
log.info("shut down quartz in {}", stopWatch);
}
}
}