Skip to content

Instantly share code, notes, and snippets.

@jelies
Last active October 24, 2024 16:38
Show Gist options
  • Save jelies/5085593 to your computer and use it in GitHub Desktop.
Save jelies/5085593 to your computer and use it in GitHub Desktop.
Quartz (2.1.6) java config with spring (3.2.1). Using a SpringBeanJobFactory to automatically autowire quartz classes.
package com.jelies.spring3tomcat7.config.quartz;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
/**
* This JobFactory autowires automatically the created quartz bean with spring @Autowired dependencies.
*
* @author jelies (thanks to Brian Matthews: http://webcache.googleusercontent.com/search?q=cache:FH-N1i--sDgJ:blog.btmatthews.com/2011/09/24/inject-application-context-dependencies-in-quartz-job-beans/+&cd=7&hl=en&ct=clnk&gl=es)
*
*/
public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
package com.jelies.spring3tomcat7.service.proceso;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.jelies.spring3tomcat.model.entity.Example;
import com.jelies.spring3tomcat.repository.ExampleRepository;
import com.jelies.spring3tomcat.service.ExampleService;
@Service
@Transactional
public class ExampleService implements Job {
@Autowired
private ExampleRepository exampleRepository;
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
Example example = new Example();
example.setFoo("test");
exampleRepository.save(example);
}
}
package com.jelies.spring3tomcat7.config;
import java.io.IOException;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import com.jelies.spring3tomcat7.config.quartz.AutowiringSpringBeanJobFactory;
@Configuration
public class QuartzConfig {
private final Logger log = LoggerFactory.getLogger(this.getClass().getSimpleName());
@Autowired
private DataSource dataSource;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void init() {
log.debug("QuartzConfig initialized.");
}
@Bean
public SchedulerFactoryBean quartzScheduler() {
SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean();
quartzScheduler.setDataSource(dataSource);
quartzScheduler.setTransactionManager(transactionManager);
quartzScheduler.setOverwriteExistingJobs(true);
quartzScheduler.setSchedulerName("jelies-quartz-scheduler");
// custom job factory of spring with DI support for @Autowired!
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
quartzScheduler.setJobFactory(jobFactory);
quartzScheduler.setQuartzProperties(quartzProperties());
Trigger[] triggers = { procesoMQTrigger().getObject() };
quartzScheduler.setTriggers(triggers);
return quartzScheduler;
}
@Bean
public JobDetailFactoryBean procesoMQJob() {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(ExampleService.class);
jobDetailFactory.setGroup("spring3-quartz");
return jobDetailFactory;
}
@Bean
public CronTriggerFactoryBean procesoMQTrigger() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(procesoMQJob().getObject());
cronTriggerFactoryBean.setCronExpression(0 * * * * ?);
cronTriggerFactoryBean.setGroup("spring3-quartz");
return cronTriggerFactoryBean;
}
@Bean
public Properties quartzProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
Properties properties = null;
try {
propertiesFactoryBean.afterPropertiesSet();
properties = propertiesFactoryBean.getObject();
} catch (IOException e) {
log.warn("Cannot load quartz.properties.");
}
return properties;
}
}
@wbwiles
Copy link

wbwiles commented Apr 16, 2015

Thank you!

@ajkret
Copy link

ajkret commented Jul 1, 2015

quartz.properties example?

@efi-mk
Copy link

efi-mk commented Aug 23, 2015

What should we use in case we have post construct annotation ?

@panneerselvampst
Copy link

panneerselvampst commented May 4, 2016

Thank you.. I am trying to create jobs and triggers dynamically like below . How i can inject new @bean(name = "testDynamciSJob") to schedulerfactorybean dynamically?

@bean(name = "testDynamciSJob")
public CronTriggerFactoryBean testDynamciSJob() throws ClassNotFoundException, ParseException {
System.out.println(
"TestDynamciJob constructor called]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]");
return createCronTrigger("com.jnj.scheduler.job.TestDynamciJob", "TestDynamciJob", "TestDynamciJob");
}

public JobDetailFactoryBean cronJobDetail(String classname,String jobName,String groupName) throws ClassNotFoundException {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(Class.forName(classname));
jobDetailFactory.setGroup(groupName);
jobDetailFactory.setName(jobName);
jobDetailFactory.afterPropertiesSet();
jobDetailFactory.setDurability(true);
jobDetailFactory.afterPropertiesSet();
return jobDetailFactory;
}

public CronTriggerFactoryBean createCronTrigger(String classname,String name,String groupName) throws ClassNotFoundException, ParseException {
    CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
    cronTriggerFactoryBean.setJobDetail(cronJobDetail(classname,name,groupName).getObject());
    cronTriggerFactoryBean.setCronExpression(cronExpression);
    cronTriggerFactoryBean.setGroup(groupName);
    cronTriggerFactoryBean.setName(name);
    cronTriggerFactoryBean.afterPropertiesSet();
    // in case of misfire, ignore all missed triggers and continue :
    cronTriggerFactoryBean.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW);
    return cronTriggerFactoryBean;
}

@jijeshvu07
Copy link

How did you autowire ExampleRepository , beacuse when autowire a service bean it throws null pointer exception.

@lvillarino
Copy link

Please create a demo app.

@theflofly
Copy link

Nothing to say but thanks!

@adbourne
Copy link

Thank you!

@corberan
Copy link

Thank you very much!

@derrick-null
Copy link

Awesome ...Great solution

@shaowin16
Copy link

How did you import SchedulerFactoryBean?

@levkovych67
Copy link

Hello, I need to create jobs dynamically, how can i implement that ?

@bugmakesprogress
Copy link

Thans you so much! Solved inject problems

@Greetzkenny
Copy link

I came across a problem when trying your solution and I noticed that your ExampleService, who implements Job, has no public no-argument constructor. This is mandatory according to: http://www.quartz-scheduler.org/documentation/quartz-2.x/cookbook/DefineJobWithData.html

@thedevd
Copy link

thedevd commented Nov 22, 2018

Any one with full working example ?

@bkahlerventer
Copy link

@edin-m
Copy link

edin-m commented Dec 17, 2019

Does anybody have something like this for Spring Boot 2.x and Spring 5.2?

It doesn't work for me because for some reason, in Spring internally, two (of the same) types don't match so Spring can't autowire.

@apolischuk
Copy link

Are you sure @transactional works? I notice that at least Spring Aspect based logic doesn't work on such classes

@zipajeet
Copy link

Hello team I am getting bellow error when updating Java 17 -

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.regex.Pattern]: Factory method 'skipPattern' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'quartzEndpoint' defined in class path resource [org/springframework/boot/actuate/autoconfigure/quartz/QuartzEndpointAutoConfiguration.class]: Unsatisfied dependency expressed through method 'quartzEndpoint' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scheduler' defined in class path resource [com/blackberry/mtd/compliance/output/scheduling/impl/SchedulingConfiguration.class]: Unsatisfied dependency expressed through method 'scheduler' parameter 4; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applicationTaskExecutor' defined in class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.LinkageError-->loader 'app' attempted duplicate class definition for org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$fb3f90ed. (org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$fb3f90ed is in unnamed module of loader 'app')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment