@ -17,12 +17,9 @@
@@ -17,12 +17,9 @@
package org.springframework.boot.autoconfigure.quartz ;
import java.util.concurrent.Executor ;
import java.util.concurrent.Executors ;
import javax.sql.DataSource ;
import com.zaxxer.hikari.HikariDataSource ;
import org.junit.After ;
import org.junit.Rule ;
import org.junit.Test ;
import org.quartz.Calendar ;
@ -31,7 +28,6 @@ import org.quartz.JobDetail;
@@ -31,7 +28,6 @@ import org.quartz.JobDetail;
import org.quartz.JobExecutionContext ;
import org.quartz.JobKey ;
import org.quartz.Scheduler ;
import org.quartz.SchedulerException ;
import org.quartz.SimpleScheduleBuilder ;
import org.quartz.Trigger ;
import org.quartz.TriggerBuilder ;
@ -39,16 +35,16 @@ import org.quartz.TriggerKey;
@@ -39,16 +35,16 @@ import org.quartz.TriggerKey;
import org.quartz.impl.calendar.MonthlyCalendar ;
import org.quartz.impl.calendar.WeeklyCalendar ;
import org.quartz.simpl.RAMJobStore ;
import org.quartz.simpl.SimpleThreadPool ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.boot.autoconfigure.AutoConfigurations ;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration ;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties ;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration ;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration ;
import org.springframework.boot.jdbc.DataSourceBuilder ;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext ;
import org.springframework.boot.test.context.runner.ApplicationContextRunner ;
import org.springframework.boot.test.context.runner.ContextConsumer ;
import org.springframework.boot.test.rule.OutputCapture ;
import org.springframework.boot.test.util.TestPropertyValues ;
import org.springframework.context.ConfigurableApplicationContext ;
import org.springframework.context.annotation.AnnotationConfigApplicationContext ;
import org.springframework.context.annotation.Bean ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.context.annotation.Import ;
@ -56,13 +52,13 @@ import org.springframework.context.annotation.Primary;
@@ -56,13 +52,13 @@ import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment ;
import org.springframework.jdbc.core.JdbcTemplate ;
import org.springframework.scheduling.quartz.LocalDataSourceJobStore ;
import org.springframework.scheduling.quartz.LocalTaskExecutorThreadPool ;
import org.springframework.scheduling.quartz.QuartzJobBean ;
import org.springframework.util.Assert ;
import org.springframework.util.ObjectUtils ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.hamcrest.CoreMatchers.containsString ;
import static org.mockito.Mockito.mock ;
import static org.mockito.Mockito.verifyZeroInteractions ;
/ * *
* Tests for { @link QuartzAutoConfiguration } .
@ -75,163 +71,140 @@ public class QuartzAutoConfigurationTests {
@@ -75,163 +71,140 @@ public class QuartzAutoConfigurationTests {
@Rule
public OutputCapture output = new OutputCapture ( ) ;
private ConfigurableApplicationContext context ;
@After
public void closeContext ( ) {
if ( this . context ! = null ) {
this . context . close ( ) ;
}
}
@Test
public void withNoDataSource ( ) throws Exception {
load ( ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getJobStoreClass ( ) )
. isAssignableFrom ( RAMJobStore . class ) ;
}
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner ( )
. withPropertyValues ( "spring.datasource.generate-unique-name=true" )
. withConfiguration ( AutoConfigurations . of ( QuartzAutoConfiguration . class ) ) ;
@Test
public void withDataSourceUseMemoryByDefault ( ) throws Exception {
load ( new Class < ? > [ ] { EmbeddedDataSourceConfiguration . class ,
DataSourceTransactionManagerAutoConfiguration . class } ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getJobStoreClass ( ) )
. isAssignableFrom ( RAMJobStore . class ) ;
public void withNoDataSource ( ) {
this . contextRunner . run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getJobStoreClass ( ) )
. isAssignableFrom ( RAMJobStore . class ) ;
} ) ;
}
@Test
public void withDataSource ( ) throws Exception {
load ( new Class < ? > [ ] { QuartzJobsConfiguration . class ,
EmbeddedDataSourceConfiguration . class ,
DataSourceTransactionManagerAutoConfiguration . class } ,
"spring.quartz.job-store-type=jdbc" ) ;
testWithDataSource ( ) ;
public void withDataSourceUseMemoryByDefault ( ) {
this . contextRunner . withConfiguration ( AutoConfigurations . of (
DataSourceAutoConfiguration . class ,
DataSourceTransactionManagerAutoConfiguration . class ) ) . run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getJobStoreClass ( ) )
. isAssignableFrom ( RAMJobStore . class ) ;
} ) ;
}
@Test
public void withDataSourceNoTransactionManager ( ) throws Exception {
load ( new Class < ? > [ ] { QuartzJobsConfiguration . class ,
EmbeddedDataSourceConfiguration . class } ,
"spring.quartz.job-store-type=jdbc" ) ;
testWithDataSource ( ) ;
}
private void testWithDataSource ( ) throws SchedulerException {
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getJobStoreClass ( ) )
. isAssignableFrom ( LocalDataSourceJobStore . class ) ;
JdbcTemplate jdbcTemplate = new JdbcTemplate (
this . context . getBean ( DataSource . class ) ) ;
assertThat ( jdbcTemplate . queryForObject ( "SELECT COUNT(*) FROM QRTZ_JOB_DETAILS" ,
Integer . class ) ) . isEqualTo ( 2 ) ;
assertThat ( jdbcTemplate . queryForObject (
"SELECT COUNT(*) FROM QRTZ_SIMPLE_TRIGGERS" , Integer . class ) ) . isEqualTo ( 0 ) ;
}
@Test
public void withTaskExecutor ( ) throws Exception {
load ( QuartzExecutorConfiguration . class ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getThreadPoolClass ( ) )
. isEqualTo ( LocalTaskExecutorThreadPool . class ) ;
public void withDataSource ( ) {
this . contextRunner . withUserConfiguration ( QuartzJobsConfiguration . class )
. withConfiguration ( AutoConfigurations . of ( DataSourceAutoConfiguration . class ,
DataSourceTransactionManagerAutoConfiguration . class ) )
. withPropertyValues ( "spring.quartz.job-store-type=jdbc" )
. run ( assertDataSourceJobStore ( "dataSource" ) ) ;
}
@Test
public void withMultipleTaskExecutors ( ) throws Exception {
load ( QuartzMultipleExecutorsConfiguration . class ) ;
assertThat ( this . context . getBeansOfType ( Executor . class ) ) . hasSize ( 2 ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getThreadPoolClass ( ) )
. isEqualTo ( SimpleThreadPool . class ) ;
public void withDataSourceNoTransactionManager ( ) {
this . contextRunner . withUserConfiguration ( QuartzJobsConfiguration . class )
. withConfiguration ( AutoConfigurations . of (
DataSourceAutoConfiguration . class ) )
. withPropertyValues ( "spring.quartz.job-store-type=jdbc" )
. run ( assertDataSourceJobStore ( "dataSource" ) ) ;
}
@Test
public void withMultipleTaskExecutorsWithPrimary ( ) throws Exception {
load ( QuartzMultipleExecutorsWithPrimaryConfiguration . class ) ;
assertThat ( this . context . getBeansOfType ( Executor . class ) ) . hasSize ( 2 ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getThreadPoolClass ( ) )
. isEqualTo ( LocalTaskExecutorThreadPool . class ) ;
public void dataSourceWithQuartzDataSourceQualifierUsedWhenMultiplePresent ( ) {
this . contextRunner
. withUserConfiguration ( QuartzJobsConfiguration . class ,
MultipleDataSourceConfiguration . class )
. withPropertyValues ( "spring.quartz.job-store-type=jdbc" )
. run ( assertDataSourceJobStore ( "quartzDataSource" ) ) ;
}
@Test
public void withMultipleTaskExecutorsWithCustomizer ( ) throws Exception {
load ( QuartzMultipleExecutorsWithCustomizerConfiguration . class ) ;
assertThat ( this . context . getBeansOfType ( Executor . class ) ) . hasSize ( 3 ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getThreadPoolClass ( ) )
. isEqualTo ( LocalTaskExecutorThreadPool . class ) ;
private ContextConsumer < AssertableApplicationContext > assertDataSourceJobStore (
String datasourceName ) {
return ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getJobStoreClass ( ) )
. isAssignableFrom ( LocalDataSourceJobStore . class ) ;
JdbcTemplate jdbcTemplate = new JdbcTemplate ( context . getBean (
datasourceName , DataSource . class ) ) ;
assertThat ( jdbcTemplate . queryForObject (
"SELECT COUNT(*) FROM QRTZ_JOB_DETAILS" , Integer . class ) ) . isEqualTo ( 2 ) ;
assertThat ( jdbcTemplate . queryForObject (
"SELECT COUNT(*) FROM QRTZ_SIMPLE_TRIGGERS" , Integer . class ) )
. isEqualTo ( 0 ) ;
} ;
}
@Test
public void withConfiguredJobAndTrigger ( ) throws Exception {
load ( QuartzFullConfiguration . class , "test-name=withConfiguredJobAndTrigger" ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getJobDetail ( JobKey . jobKey ( "fooJob" ) ) ) . isNotNull ( ) ;
assertThat ( scheduler . getTrigger ( TriggerKey . triggerKey ( "fooTrigger" ) ) ) . isNotNull ( ) ;
Thread . sleep ( 1000L ) ;
this . output . expect ( containsString ( "withConfiguredJobAndTrigger" ) ) ;
this . output . expect ( containsString ( "jobDataValue" ) ) ;
public void withTaskExecutor ( ) {
this . contextRunner . withUserConfiguration ( MockExecutorConfiguration . class )
. withPropertyValues (
"spring.quartz.properties.org.quartz.threadPool.threadCount=50" )
. run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getMetaData ( ) . getThreadPoolSize ( ) ) . isEqualTo ( 50 ) ;
Executor executor = context . getBean ( Executor . class ) ;
verifyZeroInteractions ( executor ) ;
} ) ;
}
@Test
public void withConfiguredCalendars ( ) throws Exception {
load ( QuartzCalendarsConfiguration . class ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getCalendar ( "weekly" ) ) . isNotNull ( ) ;
assertThat ( scheduler . getCalendar ( "monthly" ) ) . isNotNull ( ) ;
public void withConfiguredJobAndTrigger ( ) {
this . contextRunner . withUserConfiguration ( QuartzFullConfiguration . class )
. withPropertyValues ( "test-name=withConfiguredJobAndTrigger" )
. run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getJobDetail ( JobKey . jobKey ( "fooJob" ) ) )
. isNotNull ( ) ;
assertThat ( scheduler . getTrigger ( TriggerKey . triggerKey ( "fooTrigger" ) ) )
. isNotNull ( ) ;
Thread . sleep ( 1000L ) ;
this . output . expect ( containsString ( "withConfiguredJobAndTrigger" ) ) ;
this . output . expect ( containsString ( "jobDataValue" ) ) ;
} ) ;
}
@Test
public void withQuartzProperties ( ) throws Exception {
load ( "spring.quartz.properties.org.quartz.scheduler.instanceId=FOO" ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getSchedulerInstanceId ( ) ) . isEqualTo ( "FOO" ) ;
public void withConfiguredCalendars ( ) {
this . contextRunner . withUserConfiguration ( QuartzCalendarsConfiguration . class )
. run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getCalendar ( "weekly" ) ) . isNotNull ( ) ;
assertThat ( scheduler . getCalendar ( "monthly" ) ) . isNotNull ( ) ;
} ) ;
}
@Test
public void withCustomizer ( ) throws Exception {
load ( QuartzCustomConfiguration . class ) ;
assertThat ( this . context . getBeansOfType ( Scheduler . class ) ) . hasSize ( 1 ) ;
Scheduler scheduler = this . context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getSchedulerName ( ) ) . isEqualTo ( "fooScheduler" ) ;
public void withQuartzProperties ( ) {
this . contextRunner . withPropertyValues (
"spring.quartz.properties.org.quartz.scheduler.instanceId=FOO" )
. run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getSchedulerInstanceId ( ) ) . isEqualTo ( "FOO" ) ;
} ) ;
}
@Test
public void dataSourceWithQuartzDataSourceQualifierUsedWhenMultiplePresent ( ) {
load ( MultipleDataSourceConfiguration . class , "spring.quartz.job-store-type=jdbc" ) ;
}
private void load ( String . . . environment ) {
load ( new Class < ? > [ 0 ] , environment ) ;
public void withCustomizer ( ) {
this . contextRunner . withUserConfiguration ( QuartzCustomConfiguration . class )
. run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( Scheduler . class ) ;
Scheduler scheduler = context . getBean ( Scheduler . class ) ;
assertThat ( scheduler . getSchedulerName ( ) ) . isEqualTo ( "fooScheduler" ) ;
} ) ;
}
private void load ( Class < ? > config , String . . . environment ) {
load ( new Class < ? > [ ] { config } , environment ) ;
}
private void load ( Class < ? > [ ] configs , String . . . environment ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ( ) ;
TestPropertyValues . of ( environment ) . applyTo ( ctx ) ;
if ( ! ObjectUtils . isEmpty ( configs ) ) {
ctx . register ( configs ) ;
}
ctx . register ( QuartzAutoConfiguration . class ) ;
ctx . refresh ( ) ;
this . context = ctx ;
}
@Import ( ComponentThatUsesScheduler . class )
@Configuration
@ -292,51 +265,11 @@ public class QuartzAutoConfigurationTests {
@@ -292,51 +265,11 @@ public class QuartzAutoConfigurationTests {
}
@Configuration
protected static class Quartz ExecutorConfiguration extends BaseQuartzConfiguration {
protected static class Mock ExecutorConfiguration extends BaseQuartzConfiguration {
@Bean
public Executor executor ( ) {
return Executors . newSingleThreadExecutor ( ) ;
}
}
@Configuration
protected static class QuartzMultipleExecutorsConfiguration
extends QuartzExecutorConfiguration {
@Bean
public Executor anotherExecutor ( ) {
return Executors . newSingleThreadExecutor ( ) ;
}
}
@Configuration
protected static class QuartzMultipleExecutorsWithPrimaryConfiguration
extends QuartzExecutorConfiguration {
@Bean
@Primary
public Executor primaryExecutor ( ) {
return Executors . newSingleThreadExecutor ( ) ;
}
}
@Configuration
protected static class QuartzMultipleExecutorsWithCustomizerConfiguration
extends QuartzMultipleExecutorsConfiguration {
@Bean
public Executor yetAnotherExecutor ( ) {
return Executors . newSingleThreadExecutor ( ) ;
}
@Bean
public SchedulerFactoryBeanCustomizer customizer ( ) {
return ( schedulerFactoryBean ) - > schedulerFactoryBean
. setTaskExecutor ( yetAnotherExecutor ( ) ) ;
return mock ( Executor . class ) ;
}
}
@ -358,15 +291,21 @@ public class QuartzAutoConfigurationTests {
@@ -358,15 +291,21 @@ public class QuartzAutoConfigurationTests {
@Bean
@Primary
public DataSource applicationDataSource ( ) {
return new Hikari DataSource( ) ;
public DataSource applicationDataSource ( ) throws Exception {
return createTest DataSource( ) ;
}
@QuartzDataSource
@Bean
public DataSource quartzDataSource ( ) {
return DataSourceBuilder . create ( ) . url ( "jdbc:hsqldb:mem:quartztest" )
. username ( "sa" ) . build ( ) ;
public DataSource quartzDataSource ( ) throws Exception {
return createTestDataSource ( ) ;
}
private DataSource createTestDataSource ( ) throws Exception {
DataSourceProperties properties = new DataSourceProperties ( ) ;
properties . setGenerateUniqueName ( true ) ;
properties . afterPropertiesSet ( ) ;
return properties . initializeDataSourceBuilder ( ) . build ( ) ;
}
}