尝试将我的项目从 Spring Boot 1.5.8 更新到 2.0.1,但 Quartz 出现问题。我使用 Spring BOM 并且有 Quartz 2.3.0 版本。
这是我的 QuartzConfigurer,它为 Spring 设置 Bean:
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.scheduling.quartz.SpringBeanJobFactory;
import javax.annotation.PostConstruct;
@Slf4j
@Configuration
public class QuartzConfigurer {
@Value("${quartz.cron.contract-status}")
private String contractCron;
@Value("${quartz.config-filename}")
private String quartzConfigFileName;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void init() {
log.debug("Initialization of quartz configurer");
}
@Bean
public SpringBeanJobFactory springBeanJobFactory() {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job) {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource(quartzConfigFileName));
schedulerFactory.setJobFactory(springBeanJobFactory());
schedulerFactory.setJobDetails(job);
schedulerFactory.setTriggers(trigger);
return schedulerFactory;
}
@Bean
public JobDetailFactoryBean jobDetail() {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(ContractStatusJob.class);
jobDetailFactory.setName("Qrtz_Contract_Job_Detail");
jobDetailFactory.setDescription("Invoke contract job detail");
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
@Bean
public CronTriggerFactoryBean trigger(JobDetail job) {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(job);
log.debug("Configuring trigger to fire based on cron {}", contractCron);
trigger.setCronExpression(contractCron);
trigger.setName("Qrtz_Contract_Trigger");
return trigger;
}
}
这是上面文件中使用的 AutowiringSpringBeanJobFactory:
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
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;
}
}
这是与 Spring Boot 1.5.8 一起使用的quartz.properties,它工作正常。这是 QuartzConfigurer 中使用的属性文件:
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = default
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.default.driver = org.postgresql.Driver
org.quartz.dataSource.default.URL = jdbc:postgresql://localhost:5432/example
org.quartz.dataSource.default.user = postgres
org.quartz.dataSource.default.password = postgres
org.quartz.dataSource.default.maxConnections = 5
org.quartz.dataSource.default.validationQuery = select 0 from dual
这是启动应用程序时抛出的异常:
2018-05-08 15:26:52.855 INFO 21200 --- [ restartedMain] o.s.s.quartz.SchedulerFactoryBean : Loading Quartz config from [class path resource [quartz.properties]]
2018-05-08 15:26:52.873 INFO 21200 --- [ restartedMain] org.quartz.impl.StdSchedulerFactory : Using ConnectionProvider class 'org.quartz.utils.C3p0PoolingConnectionProvider' for data source 'default'
2018-05-08 15:26:52.874 WARN 21200 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scheduler' defined in class path resource [com/onwelo/vendormanagement/core/configuration/quartz/QuartzConfigurer.class]: Invocation of init method failed; nested exception is org.quartz.SchedulerException: Could not initialize DataSource: default [See nested exception: org.quartz.SchedulerException: ConnectionProvider class 'org.quartz.utils.C3p0PoolingConnectionProvider' could not be instantiated. [See nested exception: java.lang.reflect.InvocationTargetException]]
我的数据库配置根本没有改变,并且在 Spring Boot 1.5.8 上运行良好。
您必须添加 C3P0 依赖项:
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
配置 Quartz 使用 HikariCP(默认为 c3p0)
# quartz.properties
org.quartz.dataSource.quartzDataSource.provider=hikaricp
了解更多:https://github.com/quartz-scheduler/quartz/wiki/How-to-Use-DB-Connection-Pool
我以前也遇到过同样的问题。这显然是由于缺少“c3p0”依赖性。
https://mvnrepository.com/artifact/c3p0/c3p0
编译组:'c3p0',名称:'c3p0',版本:'0.9.1.2'
我已将以下依赖项添加到我的 build.gradle 文件中,然后刷新依赖项。然后这个错误就消失了。
Quartz 2.3.0 和其他 RC 版本发布时带有错误的 c3p0 groupId。问题应该在后续版本中修复,但按照 https://stackoverflow.com/a/50860439/2144470 中所述添加依赖项,这也是一个解决方案。
所以它应该可以将依赖关系更改为:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>