Merge pull request #7295 from hugogiordano/master

BAEL-2798 Update to 'Scheduling in Spring with Quartz' article to add JDBC examples.
This commit is contained in:
Eric Martin 2019-07-21 20:30:19 -05:00 committed by GitHub
commit 3aa5225ab6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 14 deletions

View File

@ -32,6 +32,16 @@
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- h2 in-memory database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
@ -44,7 +54,8 @@
</build>
<properties>
<quartz.version>2.2.3</quartz.version>
<quartz.version>2.3.0</quartz.version>
<c3p0.version>0.9.5.2</c3p0.version>
</properties>
</project>

View File

@ -10,17 +10,20 @@ import javax.annotation.PostConstruct;
import org.baeldung.springquartz.config.AutoWiringSpringBeanJobFactory;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
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.boot.autoconfigure.condition.ConditionalOnExpression;
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.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import java.util.Properties;
@Configuration
@ConditionalOnExpression("'${using.spring.schedulerFactory}'=='false'")
public class QrtzScheduler {
@ -45,14 +48,9 @@ public class QrtzScheduler {
}
@Bean
public Scheduler scheduler(Trigger trigger, JobDetail job) throws SchedulerException, IOException {
StdSchedulerFactory factory = new StdSchedulerFactory();
factory.initialize(new ClassPathResource("quartz.properties").getInputStream());
public Scheduler scheduler(Trigger trigger, JobDetail job, SchedulerFactoryBean factory) throws SchedulerException {
logger.debug("Getting a handle to the Scheduler");
Scheduler scheduler = factory.getScheduler();
scheduler.setJobFactory(springBeanJobFactory());
scheduler.scheduleJob(job, trigger);
logger.debug("Starting Scheduler threads");
@ -60,6 +58,21 @@ public class QrtzScheduler {
return scheduler;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(springBeanJobFactory());
factory.setQuartzProperties(quartzProperties());
return factory;
}
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
@Bean
public JobDetail jobDetail() {

View File

@ -1,6 +1,7 @@
package org.baeldung.springquartz.basics.scheduler;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.baeldung.springquartz.config.AutoWiringSpringBeanJobFactory;
import org.quartz.JobDetail;
@ -9,7 +10,11 @@ import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -20,6 +25,7 @@ import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
@Configuration
@EnableAutoConfiguration
@ConditionalOnExpression("'${using.spring.schedulerFactory}'=='true'")
public class SpringQrtzScheduler {
@ -43,7 +49,7 @@ public class SpringQrtzScheduler {
}
@Bean
public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job) {
public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job, DataSource quartzDataSource) {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
@ -53,6 +59,9 @@ public class SpringQrtzScheduler {
schedulerFactory.setJobDetails(job);
schedulerFactory.setTriggers(trigger);
// Comment the following line to use the default Quartz job store.
schedulerFactory.setDataSource(quartzDataSource);
return schedulerFactory;
}
@ -81,4 +90,12 @@ public class SpringQrtzScheduler {
trigger.setName("Qrtz_Trigger");
return trigger;
}
@Bean
@QuartzDataSource
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource quartzDataSource() {
return DataSourceBuilder.create().build();
}
}

View File

@ -4,20 +4,31 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.concurrent.atomic.AtomicInteger;
@Service
public class SampleJobService {
public static final long EXECUTION_TIME = 5000L;
private Logger logger = LoggerFactory.getLogger(getClass());
private AtomicInteger count = new AtomicInteger();
public void executeSampleJob() {
logger.info("The sample job has begun...");
try {
Thread.sleep(5000);
Thread.sleep(EXECUTION_TIME);
} catch (InterruptedException e) {
logger.error("Error while executing sample job", e);
} finally {
count.incrementAndGet();
logger.info("Sample job has finished...");
}
}
public int getNumberOfInvocations() {
return count.get();
}
}

View File

@ -1 +1,10 @@
using.spring.schedulerFactory=true
spring.quartz.job-store-type=jdbc
# Always create the Quartz database on startup
spring.quartz.jdbc.initialize-schema=always
spring.datasource.jdbc-url=jdbc:h2:mem:spring-quartz;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

View File

@ -4,7 +4,19 @@ org.quartz.threadPool.threadCount=2
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
# job-store
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
# Enable this property for RAMJobStore
#org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
# others
org.quartz.jobStore.misfireThreshold = 60000
# Enable these properties for a JDBCJobStore using JobStoreTX
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource=quartzDataSource
# Enable this property for JobStoreCMT
#org.quartz.jobStore.nonManagedTXDataSource=quartzDataSource
# H2 database
# use an in-memory database & initialise Quartz using their standard SQL script
org.quartz.dataSource.quartzDataSource.URL=jdbc:h2:mem:spring-quartz;INIT=RUNSCRIPT FROM 'classpath:/org/quartz/impl/jdbcjobstore/tables_h2.sql'
org.quartz.dataSource.quartzDataSource.driver=org.h2.Driver
org.quartz.dataSource.quartzDataSource.user=sa
org.quartz.dataSource.quartzDataSource.password=

View File

@ -1,16 +1,30 @@
package org.baeldung;
import org.baeldung.springquartz.SpringQuartzApp;
import org.baeldung.springquartz.basics.service.SampleJobService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringQuartzApp.class)
public class SpringContextIntegrationTest {
@Autowired
private SampleJobService sampleJobService;
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
@Test
public void whenSchedulerStarts_thenJobsRun() throws InterruptedException {
assertThat(sampleJobService.getNumberOfInvocations()).isEqualTo(0);
Thread.sleep(SampleJobService.EXECUTION_TIME);
assertThat(sampleJobService.getNumberOfInvocations()).isEqualTo(1);
}
}