Skip to content

Commit

Permalink
Merge branch '2.6.x' into 2.7.x
Browse files Browse the repository at this point in the history
Closes gh-29086
  • Loading branch information
snicoll committed Dec 16, 2021
2 parents b85b6b0 + 55859ea commit 63427b7
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
Expand Down Expand Up @@ -103,6 +105,7 @@ public SimpleJobOperator jobOperator(ObjectProvider<JobParametersConverter> jobP
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(DataSource.class)
@ConditionalOnClass(DatabasePopulator.class)
@Conditional(OnBatchDatasourceInitializationCondition.class)
static class DataSourceInitializerConfiguration {

@Bean
Expand All @@ -116,4 +119,12 @@ BatchDataSourceScriptDatabaseInitializer batchDataSourceInitializer(DataSource d

}

static class OnBatchDatasourceInitializationCondition extends OnDatabaseInitializationCondition {

OnBatchDatasourceInitializationCondition() {
super("Batch", "spring.batch.jdbc.initialize-schema", "spring.batch.initialize-schema");
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration;
import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
Expand Down Expand Up @@ -233,6 +234,7 @@ protected static class IntegrationComponentScanConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(JdbcMessageStore.class)
@ConditionalOnSingleCandidate(DataSource.class)
@Conditional(OnIntegrationDatasourceInitializationCondition.class)
protected static class IntegrationJdbcConfiguration {

@Bean
Expand Down Expand Up @@ -342,4 +344,12 @@ static class TcpAddressConfigured {

}

static class OnIntegrationDatasourceInitializationCondition extends OnDatabaseInitializationCondition {

OnIntegrationDatasourceInitializationCondition() {
super("Integration", "spring.integration.jdbc.initialize-schema");
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@
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.autoconfigure.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
Expand Down Expand Up @@ -134,13 +136,22 @@ private PlatformTransactionManager getTransactionManager(
@SuppressWarnings("deprecation")
@ConditionalOnMissingBean({ QuartzDataSourceScriptDatabaseInitializer.class,
QuartzDataSourceInitializer.class })
@Conditional(OnQuartzDatasourceInitializationCondition.class)
public QuartzDataSourceScriptDatabaseInitializer quartzDataSourceScriptDatabaseInitializer(
DataSource dataSource, @QuartzDataSource ObjectProvider<DataSource> quartzDataSource,
QuartzProperties properties) {
DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
return new QuartzDataSourceScriptDatabaseInitializer(dataSourceToUse, properties);
}

static class OnQuartzDatasourceInitializationCondition extends OnDatabaseInitializationCondition {

OnQuartzDatasourceInitializationCondition() {
super("Quartz", "spring.quartz.jdbc.initialize-schema");
}

}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
Expand Down Expand Up @@ -58,6 +59,7 @@ class JdbcSessionConfiguration {
@SuppressWarnings("deprecation")
@ConditionalOnMissingBean({ JdbcSessionDataSourceScriptDatabaseInitializer.class,
JdbcSessionDataSourceInitializer.class })
@Conditional(OnJdbcSessionDatasourceInitializationCondition.class)
JdbcSessionDataSourceScriptDatabaseInitializer jdbcSessionDataSourceScriptDatabaseInitializer(
@SpringSessionDataSource ObjectProvider<DataSource> sessionDataSource,
ObjectProvider<DataSource> dataSource, JdbcSessionProperties properties) {
Expand All @@ -84,4 +86,12 @@ void customize(SessionProperties sessionProperties, JdbcSessionProperties jdbcSe

}

static class OnJdbcSessionDatasourceInitializationCondition extends OnDatabaseInitializationCondition {

OnJdbcSessionDatasourceInitializationCondition() {
super("Jdbc Session", "spring.session.jdbc.initialize-schema");
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.autoconfigure.sql.init;

import java.util.Locale;

import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;

/**
* Condition that checks if the database initialization of a particular component should
* be considered.
*
* @author Stephane Nicoll
* @since 2.6.2
* @see DatabaseInitializationMode
*/
public class OnDatabaseInitializationCondition extends SpringBootCondition {

private final String name;

private final String[] propertyNames;

/**
* Create a new instance with the name of the component and the property names to
* check, in order. If a property is set, its value is used to determine the outcome
* and remaining properties are not tested.
* @param name the name of the component
* @param propertyNames the properties to check (in order)
*/
public OnDatabaseInitializationCondition(String name, String... propertyNames) {
this.name = name;
this.propertyNames = propertyNames;
}

@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String propertyName = getConfiguredProperty(environment);
DatabaseInitializationMode mode = getDatabaseInitializationMode(environment, propertyName);
boolean match = match(mode);
String messagePrefix = (propertyName != null) ? propertyName : "default value";
return new ConditionOutcome(match, ConditionMessage.forCondition(this.name + "Database Initialization")
.because(messagePrefix + " is " + mode));
}

private boolean match(DatabaseInitializationMode mode) {
return !mode.equals(DatabaseInitializationMode.NEVER);
}

private DatabaseInitializationMode getDatabaseInitializationMode(Environment environment, String propertyName) {
if (StringUtils.hasText(propertyName)) {
String candidate = environment.getProperty(propertyName, "embedded").toUpperCase(Locale.ENGLISH);
if (StringUtils.hasText(candidate)) {
return DatabaseInitializationMode.valueOf(candidate);
}
}
return DatabaseInitializationMode.EMBEDDED;
}

private String getConfiguredProperty(Environment environment) {
for (String propertyName : this.propertyNames) {
if (environment.containsProperty(propertyName)) {
return propertyName;
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ private ContextConsumer<AssertableApplicationContext> assertDatasourceIsNotIniti
assertThat(context).hasSingleBean(JobLauncher.class);
assertThat(context.getBean(BatchProperties.class).getJdbc().getInitializeSchema())
.isEqualTo(DatabaseInitializationMode.NEVER);
assertThat(context).doesNotHaveBean(BatchDataSourceScriptDatabaseInitializer.class);
assertThatExceptionOfType(BadSqlGrammarException.class)
.isThrownBy(() -> new JdbcTemplate(context.getBean(DataSource.class))
.queryForList("select * from BATCH_JOB_EXECUTION"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ void integrationJdbcDataSourceInitializerDisabled() {
.withPropertyValues("spring.datasource.generate-unique-name=true",
"spring.integration.jdbc.initialize-schema=never")
.run((context) -> {
assertThat(context).doesNotHaveBean(IntegrationDataSourceScriptDatabaseInitializer.class);
IntegrationProperties properties = context.getBean(IntegrationProperties.class);
assertThat(properties.getJdbc().getInitializeSchema()).isEqualTo(DatabaseInitializationMode.NEVER);
JdbcOperations jdbc = context.getBean(JdbcOperations.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ void withDataSource() {
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class))
.withPropertyValues("spring.quartz.job-store-type=jdbc").run(assertDataSourceJobStore("dataSource"));
.withPropertyValues("spring.quartz.job-store-type=jdbc")
.run(assertDataSourceInitializedByDataSourceDatabaseScriptInitializer("dataSource"));
}

@Test
Expand All @@ -134,14 +135,15 @@ void withDataSourceAndInMemoryStoreDoesNotInitializeDataSource() {
void withDataSourceNoTransactionManager() {
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.quartz.job-store-type=jdbc").run(assertDataSourceJobStore("dataSource"));
.withPropertyValues("spring.quartz.job-store-type=jdbc")
.run(assertDataSourceInitializedByDataSourceDatabaseScriptInitializer("dataSource"));
}

@Test
void dataSourceWithQuartzDataSourceQualifierUsedWhenMultiplePresent() {
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class, MultipleDataSourceConfiguration.class)
.withPropertyValues("spring.quartz.job-store-type=jdbc")
.run(assertDataSourceJobStore("quartzDataSource"));
.run(assertDataSourceInitializedByDataSourceDatabaseScriptInitializer("quartzDataSource"));
}

@Test
Expand All @@ -155,23 +157,6 @@ void transactionManagerWithQuartzTransactionManagerUsedWhenMultiplePresent() {
});
}

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);
assertThat(context).hasSingleBean(QuartzDataSourceScriptDatabaseInitializer.class);
QuartzDataSourceScriptDatabaseInitializer initializer = context
.getBean(QuartzDataSourceScriptDatabaseInitializer.class);
assertThat(initializer).hasFieldOrPropertyWithValue("dataSource", context.getBean(dataSourceName));
};
}

@Test
void withTaskExecutor() {
this.contextRunner.withUserConfiguration(MockExecutorConfiguration.class)
Expand Down Expand Up @@ -277,7 +262,8 @@ void withLiquibase() {
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"));
.run(assertDataSourceInitialized("dataSource").andThen((context) -> assertThat(context)
.doesNotHaveBean(QuartzDataSourceScriptDatabaseInitializer.class)));
}

@Test
Expand All @@ -292,7 +278,8 @@ void withFlyway(@TempDir Path flywayLocation) throws Exception {
.withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never",
"spring.flyway.locations=filesystem:" + flywayLocation,
"spring.flyway.baseline-on-migrate=true")
.run(assertDataSourceJobStore("dataSource"));
.run(assertDataSourceInitialized("dataSource").andThen((context) -> assertThat(context)
.doesNotHaveBean(QuartzDataSourceScriptDatabaseInitializer.class)));
}

@Test
Expand Down Expand Up @@ -352,6 +339,29 @@ void whenTheUserDefinesTheirOwnDatabaseInitializerThenTheAutoConfiguredQuartzIni
.hasSingleBean(QuartzDataSourceScriptDatabaseInitializer.class).hasBean("customInitializer"));
}

private ContextConsumer<AssertableApplicationContext> assertDataSourceInitialized(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);
};
}

private ContextConsumer<AssertableApplicationContext> assertDataSourceInitializedByDataSourceDatabaseScriptInitializer(
String dataSourceName) {
return assertDataSourceInitialized(dataSourceName).andThen((context) -> {
assertThat(context).hasSingleBean(QuartzDataSourceScriptDatabaseInitializer.class);
QuartzDataSourceScriptDatabaseInitializer initializer = context
.getBean(QuartzDataSourceScriptDatabaseInitializer.class);
assertThat(initializer).hasFieldOrPropertyWithValue("dataSource", context.getBean(dataSourceName));
});
}

private ContextConsumer<AssertableApplicationContext> assertSchedulerName(String schedulerName) {
return (context) -> {
assertThat(context).hasSingleBean(SchedulerFactoryBean.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ void disableDataSourceInitializer() {
this.contextRunner
.withPropertyValues("spring.session.store-type=jdbc", "spring.session.jdbc.initialize-schema=never")
.run((context) -> {
assertThat(context).doesNotHaveBean(JdbcSessionDataSourceScriptDatabaseInitializer.class);
JdbcIndexedSessionRepository repository = validateSessionRepository(context,
JdbcIndexedSessionRepository.class);
assertThat(repository).hasFieldOrPropertyWithValue("tableName", "SPRING_SESSION");
Expand Down

0 comments on commit 63427b7

Please sign in to comment.