diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java index ceef7372c7e..b7bf6649ed8 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java @@ -210,10 +210,7 @@ public class FlywayAutoConfiguration { map.from(properties.isCleanDisabled()).to(configuration::cleanDisabled); map.from(properties.isCleanOnValidationError()).to(configuration::cleanOnValidationError); map.from(properties.isGroup()).to(configuration::group); - map.from(properties.isIgnoreMissingMigrations()).to(configuration::ignoreMissingMigrations); - map.from(properties.isIgnoreIgnoredMigrations()).to(configuration::ignoreIgnoredMigrations); - map.from(properties.isIgnorePendingMigrations()).to(configuration::ignorePendingMigrations); - map.from(properties.isIgnoreFutureMigrations()).to(configuration::ignoreFutureMigrations); + configureIgnoredMigrations(configuration, properties, map); map.from(properties.isMixed()).to(configuration::mixed); map.from(properties.isOutOfOrder()).to(configuration::outOfOrder); map.from(properties.isSkipDefaultCallbacks()).to(configuration::skipDefaultCallbacks); @@ -262,6 +259,18 @@ public class FlywayAutoConfiguration { // No method reference for compatibility with Flyway version < 7.9 map.from(properties.getDetectEncoding()) .to((detectEncoding) -> configuration.detectEncoding(detectEncoding)); + // No method reference for compatibility with Flyway version < 8.0 + map.from(properties.getBaselineMigrationPrefix()) + .to((baselineMigrationPrefix) -> configuration.baselineMigrationPrefix(baselineMigrationPrefix)); + } + + @SuppressWarnings("deprecation") + private void configureIgnoredMigrations(FluentConfiguration configuration, FlywayProperties properties, + PropertyMapper map) { + map.from(properties.isIgnoreMissingMigrations()).to(configuration::ignoreMissingMigrations); + map.from(properties.isIgnoreIgnoredMigrations()).to(configuration::ignoreIgnoredMigrations); + map.from(properties.isIgnorePendingMigrations()).to(configuration::ignorePendingMigrations); + map.from(properties.isIgnoreFutureMigrations()).to(configuration::ignoreFutureMigrations); } private void configureFailOnMissingLocations(FluentConfiguration configuration, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java index f34d4c0447f..f4b8aa3c9cf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java @@ -227,21 +227,25 @@ public class FlywayProperties { /** * Whether to ignore missing migrations when reading the schema history table. */ + @Deprecated private boolean ignoreMissingMigrations; /** * Whether to ignore ignored migrations when reading the schema history table. */ + @Deprecated private boolean ignoreIgnoredMigrations; /** * Whether to ignore pending migrations when reading the schema history table. */ + @Deprecated private boolean ignorePendingMigrations; /** * Whether to ignore future migrations when reading the schema history table. */ + @Deprecated private boolean ignoreFutureMigrations = true; /** @@ -371,9 +375,9 @@ public class FlywayProperties { private Boolean detectEncoding; /** - * Filename prefix of state scripts. Requires Flyway Teams. + * Filename prefix for baseline migrations. Requires Flyway Teams. */ - private String stateScriptPrefix; + private String baselineMigrationPrefix; /** * Prefix of placeholders in migration scripts. @@ -672,34 +676,46 @@ public class FlywayProperties { this.group = group; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "spring.flyway.ignore-migration-patterns") public boolean isIgnoreMissingMigrations() { return this.ignoreMissingMigrations; } + @Deprecated public void setIgnoreMissingMigrations(boolean ignoreMissingMigrations) { this.ignoreMissingMigrations = ignoreMissingMigrations; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "spring.flyway.ignore-migration-patterns") public boolean isIgnoreIgnoredMigrations() { return this.ignoreIgnoredMigrations; } + @Deprecated public void setIgnoreIgnoredMigrations(boolean ignoreIgnoredMigrations) { this.ignoreIgnoredMigrations = ignoreIgnoredMigrations; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "spring.flyway.ignore-migration-patterns") public boolean isIgnorePendingMigrations() { return this.ignorePendingMigrations; } + @Deprecated public void setIgnorePendingMigrations(boolean ignorePendingMigrations) { this.ignorePendingMigrations = ignorePendingMigrations; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "spring.flyway.ignore-migration-patterns") public boolean isIgnoreFutureMigrations() { return this.ignoreFutureMigrations; } + @Deprecated public void setIgnoreFutureMigrations(boolean ignoreFutureMigrations) { this.ignoreFutureMigrations = ignoreFutureMigrations; } @@ -888,12 +904,12 @@ public class FlywayProperties { this.detectEncoding = detectEncoding; } - public String getStateScriptPrefix() { - return this.stateScriptPrefix; + public String getBaselineMigrationPrefix() { + return this.baselineMigrationPrefix; } - public void setStateScriptPrefix(String stateScriptPrefix) { - this.stateScriptPrefix = stateScriptPrefix; + public void setBaselineMigrationPrefix(String baselineMigrationPrefix) { + this.baselineMigrationPrefix = baselineMigrationPrefix; } public String getScriptPlaceholderPrefix() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 74b5eb5cbbe..038045c1a9f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -872,6 +872,10 @@ "http://localhost:9200" ] }, + { + "name": "spring.flyway.baseline-migration-prefix", + "defaultValue": "B" + }, { "name": "spring.flyway.connect-retries-interval", "defaultValue": 120 diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway5xAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway5xAutoConfigurationTests.java index 9c6a5548cc1..4dbff8c68c1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway5xAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway5xAutoConfigurationTests.java @@ -117,7 +117,7 @@ class Flyway5xAutoConfigurationTests { } @Override - public boolean isStateScript() { + public boolean isBaselineMigration() { return false; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway7xAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway7xAutoConfigurationTests.java new file mode 100644 index 00000000000..15523d1dc71 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/Flyway7xAutoConfigurationTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012-2020 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.flywaydb.core.api.callback.Callback; +import org.flywaydb.core.api.callback.Context; +import org.flywaydb.core.api.callback.Event; +import org.junit.jupiter.api.Test; + +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.ClassPathOverrides; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link FlywayAutoConfiguration} with Flyway 7.x. + * + * @author Andy Wilkinson + */ +@ClassPathOverrides("org.flywaydb:flyway-core:7.15.0") +class Flyway7xAutoConfigurationTests { + + 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")); + }); + } + + @Test + void callbacksAreConfigured() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, CallbackConfiguration.class) + .run((context) -> { + assertThat(context).hasSingleBean(Flyway.class); + Flyway flyway = context.getBean(Flyway.class); + Callback callbackOne = context.getBean("callbackOne", Callback.class); + Callback callbackTwo = context.getBean("callbackTwo", Callback.class); + assertThat(flyway.getConfiguration().getCallbacks()).hasSize(2); + assertThat(flyway.getConfiguration().getCallbacks()).containsExactlyInAnyOrder(callbackTwo, + callbackOne); + verify(callbackOne, atLeastOnce()).handle(any(Event.class), any(Context.class)); + verify(callbackTwo, atLeastOnce()).handle(any(Event.class), any(Context.class)); + }); + } + + @Configuration(proxyBeanMethods = false) + static class CallbackConfiguration { + + @Bean + Callback callbackOne() { + return mockCallback(); + } + + @Bean + Callback callbackTwo() { + return mockCallback(); + } + + private Callback mockCallback() { + Callback callback = mock(Callback.class); + given(callback.supports(any(Event.class), any(Context.class))).willReturn(true); + given(callback.getCallbackName()).willReturn("callback"); + return callback; + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java index c500128dd45..514852b703e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java @@ -499,8 +499,9 @@ class FlywayAutoConfigurationTests { assertThat(context).hasSingleBean(Flyway.class); Flyway flyway = context.getBean(Flyway.class); assertThat(flyway.getConfiguration().getConnectRetries()).isEqualTo(5); - assertThat(flyway.getConfiguration().isIgnoreMissingMigrations()).isTrue(); - assertThat(flyway.getConfiguration().isIgnorePendingMigrations()).isTrue(); + assertThat(flyway.getConfiguration().getBaselineDescription()).isEqualTo("<< Custom baseline >>"); + assertThat(flyway.getConfiguration().getBaselineVersion()) + .isEqualTo(MigrationVersion.fromVersion("1")); }); } @@ -657,6 +658,13 @@ class FlywayAutoConfigurationTests { }); } + @Test + void baselineMigrationPrefixIsCorrectlyMapped() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) + .withPropertyValues("spring.flyway.baseline-migration-prefix=BL") + .run(validateFlywayTeamsPropertyOnly("baselineMigrationPrefix")); + } + private ContextConsumer validateFlywayTeamsPropertyOnly(String propertyName) { return (context) -> { assertThat(context).hasFailed(); @@ -892,13 +900,13 @@ class FlywayAutoConfigurationTests { @Bean @Order(1) FlywayConfigurationCustomizer customizerOne() { - return (configuration) -> configuration.connectRetries(5).ignorePendingMigrations(true); + return (configuration) -> configuration.connectRetries(5).baselineVersion("1"); } @Bean @Order(0) FlywayConfigurationCustomizer customizerTwo() { - return (configuration) -> configuration.connectRetries(10).ignoreMissingMigrations(true); + return (configuration) -> configuration.connectRetries(10).baselineDescription("<< Custom baseline >>"); } } @@ -1008,7 +1016,7 @@ class FlywayAutoConfigurationTests { } @Override - public boolean isStateScript() { + public boolean isBaselineMigration() { return false; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java index ba1cf88ef82..c6eb39a7555 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java @@ -44,11 +44,12 @@ import static org.assertj.core.api.Assertions.assertThat; */ class FlywayPropertiesTests { + @SuppressWarnings("deprecation") @Test void defaultValuesAreConsistent() { FlywayProperties properties = new FlywayProperties(); Configuration configuration = new FluentConfiguration(); - assertThat(configuration.getFailOnMissingLocations()).isEqualTo(properties.isFailOnMissingLocations()); + assertThat(configuration.isFailOnMissingLocations()).isEqualTo(properties.isFailOnMissingLocations()); assertThat(properties.getLocations().stream().map(Location::new).toArray(Location[]::new)) .isEqualTo(configuration.getLocations()); assertThat(properties.getEncoding()).isEqualTo(configuration.getEncoding()); @@ -61,7 +62,7 @@ class FlywayPropertiesTests { assertThat(configuration.getLockRetryCount()).isEqualTo(50); assertThat(properties.getDefaultSchema()).isEqualTo(configuration.getDefaultSchema()); assertThat(properties.getSchemas()).isEqualTo(Arrays.asList(configuration.getSchemas())); - assertThat(properties.isCreateSchemas()).isEqualTo(configuration.getCreateSchemas()); + assertThat(properties.isCreateSchemas()).isEqualTo(configuration.isCreateSchemas()); assertThat(properties.getTable()).isEqualTo(configuration.getTable()); assertThat(properties.getBaselineDescription()).isEqualTo(configuration.getBaselineDescription()); assertThat(MigrationVersion.fromVersion(properties.getBaselineVersion())) @@ -113,7 +114,8 @@ class FlywayPropertiesTests { ignoreProperties(configuration, "callbacks", "classLoader", "dataSource", "javaMigrations", "javaMigrationClassProvider", "resourceProvider", "resolvers"); // Properties we don't want to expose - ignoreProperties(configuration, "resolversAsClassNames", "callbacksAsClassNames", "apiExtensions", "loggers"); + ignoreProperties(configuration, "resolversAsClassNames", "callbacksAsClassNames", "apiExtensions", "loggers", + "driver"); // Handled by the conversion service ignoreProperties(configuration, "baselineVersionAsString", "encodingAsString", "locationsAsStrings", "targetAsString"); diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f1913125035..b08fe204b6e 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -309,7 +309,7 @@ bom { ] } } - library("Flyway", "7.15.0") { + library("Flyway", "8.0.0") { group("org.flywaydb") { modules = [ "flyway-core"