-
-
Save jelies/5085593 to your computer and use it in GitHub Desktop.
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; | |
} | |
} |
quartz.properties example?
What should we use in case we have post construct annotation ?
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;
}
How did you autowire ExampleRepository , beacuse when autowire a service bean it throws null pointer exception.
Please create a demo app.
Nothing to say but thanks!
Thank you!
Thank you very much!
Awesome ...Great solution
How did you import SchedulerFactoryBean?
Hello, I need to create jobs dynamically, how can i implement that ?
Thans you so much! Solved inject problems
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
Any one with full working example ?
working example found - https://github.com/davidkiss/spring-boot-quartz-demo.git
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.
Are you sure @transactional works? I notice that at least Spring Aspect based logic doesn't work on such classes
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')
Thank you!