我正在使用 SpringBoot 1.4.5 和quartz 与在Tomcat 的context.xml 中配置的DataSource 进行调度,该DataSource 通过JndiDataSource 作为bean 注入以连接到Oracle 10g DB。
下面是相关的依赖,包括Oracle驱动,我使用的是SpringBoot提供的依赖管理:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>oracle-ojdbc7</artifactId>
<version>12.1.0-2</version>
</dependency>
这是 Tomcat 在 context.xml 中配置的 DataSource(占位符属性在 catalina.properties 中定义):
<Resource name="${tomcat.dbpool.ups.quartz.resourcename}" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="${tomcat.dbpool.ups.quartz.connectionurl}"
username="${tomcat.dbpool.ups.quartz.username}"
password="${tomcat.dbpool.ups.quartz.password}"
maxTotal="${tomcat.dbpool.ups.quartz.maxTotal}"
maxIdle="${tomcat.dbpool.ups.quartz.maxIdle}"
minIdle="${tomcat.dbpool.ups.quartz.minIdle}"
maxWaitMillis="${tomcat.dbpool.ups.quartz.maxWaitMillis}"
validationQueryTimeout="${tomcat.dbpool.ups.quartz.validationQueryTimeout}"
testWhileIdle="true"
removeAbandonedOnMaintenance="true"
timeBetweenEvictionRunsMillis="${tomcat.dbpool.ups.quartz.timeBetweenEvictionRunsMillis}"
minEvictableIdleTimeMillis="${tomcat.dbpool.ups.quartz.minEvictableIdleTimeMillis}"
/>
数据源 bean 配置和石英必要的 bean:
@Bean
public JobFactory jobFactory(final ApplicationContext applicationContext) {
final AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("quartzDataSource") final DataSource quartzDS,
final JobFactory jobFactory,
@Qualifier("loansAppTrigger") final Trigger jobTrigger) throws IOException {
final SchedulerFactoryBean factory = new SchedulerFactoryBean();
// this allows to update triggers in DB when updating settings in config file:
factory.setOverwriteExistingJobs(true);
factory.setDataSource(quartzDS);
factory.setJobFactory(jobFactory);
factory.setQuartzProperties(quartzProperties());
factory.setTriggers(jobTrigger);
return factory;
}
@Bean(name = "quartzDataSource")
@Profile("!local")
public DataSource jndiDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("java:comp/env/jdbc/QUARTZ");
return dataSource;
}
@Bean
public Properties quartzProperties() throws IOException {
final PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
@Bean
public JobDetailFactoryBean checkUnconfirmedApplicationsJobDetail() {
return createJobDetail(CheckUnconfirmedApplicationsJob.class);
}
@Bean(name = "loansAppTrigger")
public SimpleTriggerFactoryBean unconfirmedLoansApplicationsTrigger(
@Qualifier("checkUnconfirmedApplicationsJobDetail") final JobDetail jobDetail,
@Value("${ups.loan.check.pending.apps.frequency}") final long frequency) {
return createTrigger(jobDetail, frequency);
}
private static JobDetailFactoryBean createJobDetail(final Class jobClass) {
final JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(jobClass);
// job has to be durable to be stored in DB:
factoryBean.setDurability(true);
return factoryBean;
}
private static SimpleTriggerFactoryBean createTrigger(final JobDetail jobDetail, final long pollFrequencyMs) {
final SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setStartDelay(0L);
factoryBean.setRepeatInterval(pollFrequencyMs);
factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
// in case of misfire, ignore all missed triggers and continue :
factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT);
return factoryBean;
}
以及quartz.properties 文件中的以下属性:
org.quartz.scheduler.instanceName=scheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
当我在 Tomcat 8 上部署它时,出现以下错误:
org.quartz.JobPersistenceException:无法存储作业:驱动程序的 Blob 表示是不支持的类型:oracle.sql.BLOB
在 Tomcat 的 lib 文件夹中,我有 oracle-ojdbc7-12.1.0-2.jar 驱动程序。