Skip to content

Commit

Permalink
Ensure that SchedulerFactoryBean and Scheduler beans depend on the
Browse files Browse the repository at this point in the history
Flyway and Liquibase.

see gh-17528
  • Loading branch information
nosan committed Jul 17, 2019
1 parent 3a49996 commit e84b840
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,27 @@

import javax.sql.DataSource;

import liquibase.integration.spring.SpringLiquibase;
import org.flywaydb.core.Flyway;
import org.quartz.Calendar;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
Expand All @@ -56,7 +63,8 @@
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class, PlatformTransactionManager.class })
@EnableConfigurationProperties(QuartzProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class })
public class QuartzAutoConfiguration {

@Bean
Expand Down Expand Up @@ -125,16 +133,68 @@ public QuartzDataSourceInitializer quartzDataSourceInitializer(DataSource dataSo
return new QuartzDataSourceInitializer(dataSourceToUse, resourceLoader, properties);
}

@Bean
public static DataSourceInitializerSchedulerDependencyPostProcessor dataSourceInitializerSchedulerDependencyPostProcessor() {
return new DataSourceInitializerSchedulerDependencyPostProcessor();
/**
* Additional configuration to ensure that {@link SchedulerFactoryBean} and
* {@link Scheduler} beans depend on the {@link QuartzDataSourceInitializer}
* bean(s).
*/
@Configuration(proxyBeanMethods = false)
protected static class SchedulerQuartzDataSourceInitializerDependencyConfiguration
extends AbstractSchedulerDependsOnBeanFactoryPostProcessor {

SchedulerQuartzDataSourceInitializerDependencyConfiguration() {
super(QuartzDataSourceInitializer.class);
}

}

/**
* Additional configuration to ensure that {@link SchedulerFactoryBean} and
* {@link Scheduler} beans depend on the {@link SpringLiquibase} bean(s).
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SpringLiquibase.class)
@ConditionalOnBean(SpringLiquibase.class)
protected static class SchedulerSpringLiquibaseDependencyConfiguration
extends AbstractSchedulerDependsOnBeanFactoryPostProcessor {

SchedulerSpringLiquibaseDependencyConfiguration() {
super(SpringLiquibase.class);
}

}

/**
* Additional configuration to ensure that {@link SchedulerFactoryBean} and
* {@link Scheduler} beans depend on the {@link FlywayMigrationInitializer}
* bean(s).
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Flyway.class)
@ConditionalOnBean(FlywayMigrationInitializer.class)
protected static class SchedulerFlywayMigrationInitializerDependencyConfiguration
extends AbstractSchedulerDependsOnBeanFactoryPostProcessor {

SchedulerFlywayMigrationInitializerDependencyConfiguration() {
super(FlywayMigrationInitializer.class);
}

}

private static class DataSourceInitializerSchedulerDependencyPostProcessor
/**
* {@link BeanFactoryPostProcessor} that can be used to declare that all
* {@link Scheduler} and {@link SchedulerFactoryBean} beans should "depend on" one
* or more specific beans.
*/
protected abstract static class AbstractSchedulerDependsOnBeanFactoryPostProcessor
extends AbstractDependsOnBeanFactoryPostProcessor {

DataSourceInitializerSchedulerDependencyPostProcessor() {
super(Scheduler.class, SchedulerFactoryBean.class, "quartzDataSourceInitializer");
/**
* Create an instance with dependency types.
* @param dependencyTypes dependency types
*/
protected AbstractSchedulerDependsOnBeanFactoryPostProcessor(Class<?>... dependencyTypes) {
super(Scheduler.class, SchedulerFactoryBean.class, dependencyTypes);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package org.springframework.boot.autoconfigure.quartz;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.Executor;

import javax.sql.DataSource;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.quartz.Calendar;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
Expand All @@ -39,9 +43,11 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
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.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
Expand All @@ -52,6 +58,7 @@
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.quartz.LocalDataSourceJobStore;
import org.springframework.scheduling.quartz.QuartzJobBean;
Expand Down Expand Up @@ -115,6 +122,30 @@ void withDataSourceAndInMemoryStoreDoesNotInitializeDataSource() {
});
}

@Test
void withLiquibase() {
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, LiquibaseAutoConfiguration.class))
.withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never",
"spring.liquibase.change-log=classpath:org/quartz/impl/jdbcjobstore/liquibase.quartz.init.xml")
.run(assertDataSourceJobStore("dataSource"));
}

@Test
void withFlyway(@TempDir Path flywayDir) throws Exception {
try (InputStream stream = new ClassPathResource("org/quartz/impl/jdbcjobstore/tables_h2.sql")
.getInputStream()) {
Files.copy(stream, flywayDir.resolve("V2__quartz.sql"));
}
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, FlywayAutoConfiguration.class))
.withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never",
"spring.flyway.locations=filesystem:" + flywayDir, "spring.flyway.baseline-on-migrate=true")
.run(assertDataSourceJobStore("dataSource"));
}

@Test
void withDataSourceNoTransactionManager() {
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
Expand Down

0 comments on commit e84b840

Please sign in to comment.