Merge branch '3.1.x'

Closes gh-38268
This commit is contained in:
Andy Wilkinson 2023-11-08 17:10:19 +00:00
commit 82c9ab4cbd
2 changed files with 151 additions and 55 deletions

View File

@ -217,77 +217,114 @@ public class FlywayAutoConfiguration {
} }
} }
/**
* Configure the given {@code configuration} using the given {@code properties}.
* <p>
* To maximize forwards- and backwards-compatibility method references are not
* used.
* @param configuration the configuration
* @param properties the properties
*/
private void configureProperties(FluentConfiguration configuration, FlywayProperties properties) { private void configureProperties(FluentConfiguration configuration, FlywayProperties properties) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
String[] locations = new LocationResolver(configuration.getDataSource()) String[] locations = new LocationResolver(configuration.getDataSource())
.resolveLocations(properties.getLocations()) .resolveLocations(properties.getLocations())
.toArray(new String[0]); .toArray(new String[0]);
map.from(properties.isFailOnMissingLocations()).to(configuration::failOnMissingLocations); configuration.locations(locations);
map.from(locations).to(configuration::locations); map.from(properties.isFailOnMissingLocations())
map.from(properties.getEncoding()).to(configuration::encoding); .to((failOnMissingLocations) -> configuration.failOnMissingLocations(failOnMissingLocations));
map.from(properties.getConnectRetries()).to(configuration::connectRetries); map.from(properties.getEncoding()).to((encoding) -> configuration.encoding(encoding));
map.from(properties.getConnectRetries())
.to((connectRetries) -> configuration.connectRetries(connectRetries));
map.from(properties.getConnectRetriesInterval()) map.from(properties.getConnectRetriesInterval())
.as(Duration::getSeconds) .as(Duration::getSeconds)
.as(Long::intValue) .as(Long::intValue)
.to(configuration::connectRetriesInterval); .to((connectRetriesInterval) -> configuration.connectRetriesInterval(connectRetriesInterval));
map.from(properties.getLockRetryCount()).to(configuration::lockRetryCount); map.from(properties.getLockRetryCount())
map.from(properties.getDefaultSchema()).to(configuration::defaultSchema); .to((lockRetryCount) -> configuration.lockRetryCount(lockRetryCount));
map.from(properties.getSchemas()).as(StringUtils::toStringArray).to(configuration::schemas); map.from(properties.getDefaultSchema()).to((schema) -> configuration.defaultSchema(schema));
map.from(properties.isCreateSchemas()).to(configuration::createSchemas); map.from(properties.getSchemas())
map.from(properties.getTable()).to(configuration::table); .as(StringUtils::toStringArray)
map.from(properties.getTablespace()).to(configuration::tablespace); .to((schemas) -> configuration.schemas(schemas));
map.from(properties.getBaselineDescription()).to(configuration::baselineDescription); map.from(properties.isCreateSchemas()).to((createSchemas) -> configuration.createSchemas(createSchemas));
map.from(properties.getBaselineVersion()).to(configuration::baselineVersion); map.from(properties.getTable()).to((table) -> configuration.table(table));
map.from(properties.getInstalledBy()).to(configuration::installedBy); map.from(properties.getTablespace()).to((tablespace) -> configuration.tablespace(tablespace));
map.from(properties.getPlaceholders()).to(configuration::placeholders); map.from(properties.getBaselineDescription())
map.from(properties.getPlaceholderPrefix()).to(configuration::placeholderPrefix); .to((baselineDescription) -> configuration.baselineDescription(baselineDescription));
map.from(properties.getPlaceholderSuffix()).to(configuration::placeholderSuffix); map.from(properties.getBaselineVersion())
map.from(properties.getPlaceholderSeparator()).to(configuration::placeholderSeparator); .to((baselineVersion) -> configuration.baselineVersion(baselineVersion));
map.from(properties.isPlaceholderReplacement()).to(configuration::placeholderReplacement); map.from(properties.getInstalledBy()).to((installedBy) -> configuration.installedBy(installedBy));
map.from(properties.getSqlMigrationPrefix()).to(configuration::sqlMigrationPrefix); map.from(properties.getPlaceholders()).to((placeholders) -> configuration.placeholders(placeholders));
map.from(properties.getPlaceholderPrefix())
.to((placeholderPrefix) -> configuration.placeholderPrefix(placeholderPrefix));
map.from(properties.getPlaceholderSuffix())
.to((placeholderSuffix) -> configuration.placeholderSuffix(placeholderSuffix));
map.from(properties.getPlaceholderSeparator())
.to((placeHolderSeparator) -> configuration.placeholderSeparator(placeHolderSeparator));
map.from(properties.isPlaceholderReplacement())
.to((placeholderReplacement) -> configuration.placeholderReplacement(placeholderReplacement));
map.from(properties.getSqlMigrationPrefix())
.to((sqlMigrationPrefix) -> configuration.sqlMigrationPrefix(sqlMigrationPrefix));
map.from(properties.getSqlMigrationSuffixes()) map.from(properties.getSqlMigrationSuffixes())
.as(StringUtils::toStringArray) .as(StringUtils::toStringArray)
.to(configuration::sqlMigrationSuffixes); .to((sqlMigrationSuffixes) -> configuration.sqlMigrationSuffixes(sqlMigrationSuffixes));
map.from(properties.getSqlMigrationSeparator()).to(configuration::sqlMigrationSeparator); map.from(properties.getSqlMigrationSeparator())
map.from(properties.getRepeatableSqlMigrationPrefix()).to(configuration::repeatableSqlMigrationPrefix); .to((sqlMigrationSeparator) -> configuration.sqlMigrationSeparator(sqlMigrationSeparator));
map.from(properties.getTarget()).to(configuration::target); map.from(properties.getRepeatableSqlMigrationPrefix())
map.from(properties.isBaselineOnMigrate()).to(configuration::baselineOnMigrate); .to((repeatableSqlMigrationPrefix) -> configuration
map.from(properties.isCleanDisabled()).to(configuration::cleanDisabled); .repeatableSqlMigrationPrefix(repeatableSqlMigrationPrefix));
map.from(properties.isCleanOnValidationError()).to(configuration::cleanOnValidationError); map.from(properties.getTarget()).to((target) -> configuration.target(target));
map.from(properties.isGroup()).to(configuration::group); map.from(properties.isBaselineOnMigrate())
map.from(properties.isMixed()).to(configuration::mixed); .to((baselineOnMigrate) -> configuration.baselineOnMigrate(baselineOnMigrate));
map.from(properties.isOutOfOrder()).to(configuration::outOfOrder); map.from(properties.isCleanDisabled()).to((cleanDisabled) -> configuration.cleanDisabled(cleanDisabled));
map.from(properties.isSkipDefaultCallbacks()).to(configuration::skipDefaultCallbacks); map.from(properties.isCleanOnValidationError())
map.from(properties.isSkipDefaultResolvers()).to(configuration::skipDefaultResolvers); .to((cleanOnValidationError) -> configuration.cleanOnValidationError(cleanOnValidationError));
map.from(properties.isValidateMigrationNaming()).to(configuration::validateMigrationNaming); map.from(properties.isGroup()).to((group) -> configuration.group(group));
map.from(properties.isValidateOnMigrate()).to(configuration::validateOnMigrate); map.from(properties.isMixed()).to((mixed) -> configuration.mixed(mixed));
map.from(properties.isOutOfOrder()).to((outOfOrder) -> configuration.outOfOrder(outOfOrder));
map.from(properties.isSkipDefaultCallbacks())
.to((skipDefaultCallbacks) -> configuration.skipDefaultCallbacks(skipDefaultCallbacks));
map.from(properties.isSkipDefaultResolvers())
.to((skipDefaultResolvers) -> configuration.skipDefaultResolvers(skipDefaultResolvers));
map.from(properties.isValidateMigrationNaming())
.to((validateMigrationNaming) -> configuration.validateMigrationNaming(validateMigrationNaming));
map.from(properties.isValidateOnMigrate())
.to((validateOnMigrate) -> configuration.validateOnMigrate(validateOnMigrate));
map.from(properties.getInitSqls()) map.from(properties.getInitSqls())
.whenNot(CollectionUtils::isEmpty) .whenNot(CollectionUtils::isEmpty)
.as((initSqls) -> StringUtils.collectionToDelimitedString(initSqls, "\n")) .as((initSqls) -> StringUtils.collectionToDelimitedString(initSqls, "\n"))
.to(configuration::initSql); .to((initSql) -> configuration.initSql(initSql));
map.from(properties.getScriptPlaceholderPrefix()) map.from(properties.getScriptPlaceholderPrefix())
.to((prefix) -> configuration.scriptPlaceholderPrefix(prefix)); .to((prefix) -> configuration.scriptPlaceholderPrefix(prefix));
map.from(properties.getScriptPlaceholderSuffix()) map.from(properties.getScriptPlaceholderSuffix())
.to((suffix) -> configuration.scriptPlaceholderSuffix(suffix)); .to((suffix) -> configuration.scriptPlaceholderSuffix(suffix));
configureExecuteInTransaction(configuration, properties, map); configureExecuteInTransaction(configuration, properties, map);
map.from(properties::getLoggers).to(configuration::loggers); map.from(properties::getLoggers).to((loggers) -> configuration.loggers(loggers));
// Flyway Teams properties // Flyway Teams properties
map.from(properties.getBatch()).to(configuration::batch); map.from(properties.getBatch()).to((batch) -> configuration.batch(batch));
map.from(properties.getDryRunOutput()).to(configuration::dryRunOutput); map.from(properties.getDryRunOutput()).to((dryRunOutput) -> configuration.dryRunOutput(dryRunOutput));
map.from(properties.getErrorOverrides()).to(configuration::errorOverrides); map.from(properties.getErrorOverrides())
map.from(properties.getLicenseKey()).to(configuration::licenseKey); .to((errorOverrides) -> configuration.errorOverrides(errorOverrides));
map.from(properties.getStream()).to(configuration::stream); map.from(properties.getLicenseKey()).to((licenseKey) -> configuration.licenseKey(licenseKey));
map.from(properties.getUndoSqlMigrationPrefix()).to(configuration::undoSqlMigrationPrefix); map.from(properties.getStream()).to((stream) -> configuration.stream(stream));
map.from(properties.getCherryPick()).to(configuration::cherryPick); map.from(properties.getUndoSqlMigrationPrefix())
map.from(properties.getJdbcProperties()).whenNot(Map::isEmpty).to(configuration::jdbcProperties); .to((undoSqlMigrationPrefix) -> configuration.undoSqlMigrationPrefix(undoSqlMigrationPrefix));
map.from(properties.getKerberosConfigFile()).to(configuration::kerberosConfigFile); map.from(properties.getCherryPick()).to((cherryPick) -> configuration.cherryPick(cherryPick));
map.from(properties.getOutputQueryResults()).to(configuration::outputQueryResults); map.from(properties.getJdbcProperties())
map.from(properties.getSkipExecutingMigrations()).to(configuration::skipExecutingMigrations); .whenNot(Map::isEmpty)
.to((jdbcProperties) -> configuration.jdbcProperties(jdbcProperties));
map.from(properties.getKerberosConfigFile())
.to((configFile) -> configuration.kerberosConfigFile(configFile));
map.from(properties.getOutputQueryResults())
.to((outputQueryResults) -> configuration.outputQueryResults(outputQueryResults));
map.from(properties.getSkipExecutingMigrations())
.to((skipExecutingMigrations) -> configuration.skipExecutingMigrations(skipExecutingMigrations));
map.from(properties.getIgnoreMigrationPatterns()) map.from(properties.getIgnoreMigrationPatterns())
.whenNot(List::isEmpty) .whenNot(List::isEmpty)
.as((patterns) -> patterns.toArray(new String[0])) .to((ignoreMigrationPatterns) -> configuration
.to(configuration::ignoreMigrationPatterns); .ignoreMigrationPatterns(ignoreMigrationPatterns.toArray(new String[0])));
map.from(properties.getDetectEncoding()).to(configuration::detectEncoding); map.from(properties.getDetectEncoding())
.to((detectEncoding) -> configuration.detectEncoding(detectEncoding));
} }
private void configureExecuteInTransaction(FluentConfiguration configuration, FlywayProperties properties, private void configureExecuteInTransaction(FluentConfiguration configuration, FlywayProperties properties,
@ -476,11 +513,13 @@ public class FlywayAutoConfiguration {
OracleConfigurationExtension.class, "Oracle"); OracleConfigurationExtension.class, "Oracle");
Oracle properties = this.properties.getOracle(); Oracle properties = this.properties.getOracle();
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(properties::getSqlplus).to(extension.via(OracleConfigurationExtension::setSqlplus)); map.from(properties::getSqlplus).to(extension.via((ext, sqlplus) -> ext.setSqlplus(sqlplus)));
map.from(properties::getSqlplusWarn).to(extension.via(OracleConfigurationExtension::setSqlplusWarn)); map.from(properties::getSqlplusWarn)
map.from(properties::getWalletLocation).to(extension.via(OracleConfigurationExtension::setWalletLocation)); .to(extension.via((ext, sqlplusWarn) -> ext.setSqlplusWarn(sqlplusWarn)));
map.from(properties::getWalletLocation)
.to(extension.via((ext, walletLocation) -> ext.setWalletLocation(walletLocation)));
map.from(properties::getKerberosCacheFile) map.from(properties::getKerberosCacheFile)
.to(extension.via(OracleConfigurationExtension::setKerberosCacheFile)); .to(extension.via((ext, kerberosCacheFile) -> ext.setKerberosCacheFile(kerberosCacheFile)));
} }
} }
@ -501,7 +540,7 @@ public class FlywayAutoConfiguration {
Postgresql properties = this.properties.getPostgresql(); Postgresql properties = this.properties.getPostgresql();
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(properties::getTransactionalLock) map.from(properties::getTransactionalLock)
.to(extension.via(PostgreSQLConfigurationExtension::setTransactionalLock)); .to(extension.via((ext, transactionalLock) -> ext.setTransactionalLock(transactionalLock)));
} }
} }

View File

@ -0,0 +1,57 @@
/*
* Copyright 2012-2023 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.flyway;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.Location;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link FlywayAutoConfiguration} with Flyway 10.x.
*
* @author Andy Wilkinson
*/
@ClassPathExclusions({ "flyway-core-*.jar", "flyway-sqlserver-*.jar" })
@ClassPathOverrides({ "org.flywaydb:flyway-core:10.0.0", "com.h2database:h2:2.1.210" })
@EnabledForJreRange(min = JRE.JAVA_17)
class Flyway10xAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true");
@Test
void defaultFlyway() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getLocations())
.containsExactly(new Location("classpath:db/migration"));
});
}
}