BAEL-2798 Update to 'Scheduling in Spring with Quartz' article to add JDBC examples.
This commit is contained in:
parent
f28bf9b13c
commit
6c6392a797
|
@ -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>
|
|
@ -1,31 +1,32 @@
|
|||
package org.baeldung.springquartz.basics.scheduler;
|
||||
|
||||
import static org.quartz.JobBuilder.newJob;
|
||||
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
|
||||
import static org.quartz.TriggerBuilder.newTrigger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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 javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.quartz.JobBuilder.newJob;
|
||||
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
|
||||
import static org.quartz.TriggerBuilder.newTrigger;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnExpression("'${using.spring.schedulerFactory}'=='false'")
|
||||
public class QrtzScheduler {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private static final Logger logger = LoggerFactory.getLogger(QrtzScheduler.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
@ -45,14 +46,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,10 +56,29 @@ 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() {
|
||||
|
||||
return newJob().ofType(SampleJob.class).storeDurably().withIdentity(JobKey.jobKey("Qrtz_Job_Detail")).withDescription("Invoke Sample Job service...").build();
|
||||
return newJob().ofType(SampleJob.class)
|
||||
.storeDurably()
|
||||
.withIdentity(JobKey.jobKey("Qrtz_Job_Detail"))
|
||||
.withDescription("Invoke Sample Job service...")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -72,6 +87,10 @@ public class QrtzScheduler {
|
|||
int frequencyInSec = 10;
|
||||
logger.info("Configuring trigger to fire every {} seconds", frequencyInSec);
|
||||
|
||||
return newTrigger().forJob(job).withIdentity(TriggerKey.triggerKey("Qrtz_Trigger")).withDescription("Sample trigger").withSchedule(simpleSchedule().withIntervalInSeconds(frequencyInSec).repeatForever()).build();
|
||||
return newTrigger().forJob(job)
|
||||
.withIdentity(TriggerKey.triggerKey("Qrtz_Trigger"))
|
||||
.withDescription("Sample trigger")
|
||||
.withSchedule(simpleSchedule().withIntervalInSeconds(frequencyInSec).repeatForever())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class SampleJob implements Job {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private static final Logger logger = LoggerFactory.getLogger(SampleJob.class);
|
||||
|
||||
@Autowired
|
||||
private SampleJobService jobService;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package org.baeldung.springquartz.basics.scheduler;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.baeldung.springquartz.config.AutoWiringSpringBeanJobFactory;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.SimpleTrigger;
|
||||
|
@ -9,7 +7,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;
|
||||
|
@ -19,11 +21,15 @@ import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
|||
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
|
||||
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ConditionalOnExpression("'${using.spring.schedulerFactory}'=='true'")
|
||||
public class SpringQrtzScheduler {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private static final Logger logger = LoggerFactory.getLogger(SpringQrtzScheduler.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
@ -43,7 +49,9 @@ 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 +61,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 +92,12 @@ public class SpringQrtzScheduler {
|
|||
trigger.setName("Qrtz_Trigger");
|
||||
return trigger;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@QuartzDataSource
|
||||
@ConfigurationProperties(prefix = "spring.datasource")
|
||||
public DataSource quartzDataSource() {
|
||||
return DataSourceBuilder.create().build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
public static final long EXECUTION_TIME = 5000L;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SampleJobService.class);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,10 @@
|
|||
using.spring.schedulerFactory=true
|
||||
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=
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue