Skip to content

Commit b9bb842

Browse files
committed
Restore compatibility with Flyway 5.2
Previously, the upgrade to Flyway 6 broke compatibility with Flyway 5.2 due to the use of method references that refer to two methods that do not exist in Flyway 5.2. This commit replaces the method references with lambdas that are only called if the user sets the related property. Unless a new-in-Flyway-6 property is set, the auto-configuration will work as before. When such a property is set the auto-configuration will fail with a NoSuchMethodError. This approach was chosen to make the incompatibility clear. We have also introduced support for passing any JavaMigration beans in the context into Flyway. This too relies on API that is new in Flyway 6. It is possible (although unlikely) that users had JavaMigration beans in Spring Boot 2.1 that were being ignored. This commit restores this behaviour when using Flyway 5.2. Closes gh-18193
1 parent b5589f8 commit b9bb842

File tree

2 files changed

+132
-3
lines changed

2 files changed

+132
-3
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ private void configureProperties(FluentConfiguration configuration, FlywayProper
168168
map.from(properties.getConnectRetries()).to(configuration::connectRetries);
169169
map.from(properties.getSchemas()).as(StringUtils::toStringArray).to(configuration::schemas);
170170
map.from(properties.getTable()).to(configuration::table);
171-
map.from(properties.getTablespace()).to(configuration::tablespace);
171+
// No method reference for compatibility with Flyway 5.x
172+
map.from(properties.getTablespace()).whenNonNull().to((tablespace) -> configuration.tablespace(tablespace));
172173
map.from(properties.getBaselineDescription()).to(configuration::baselineDescription);
173174
map.from(properties.getBaselineVersion()).to(configuration::baselineVersion);
174175
map.from(properties.getInstalledBy()).to(configuration::installedBy);
@@ -201,7 +202,9 @@ private void configureProperties(FluentConfiguration configuration, FlywayProper
201202
map.from(properties.getErrorOverrides()).whenNonNull().to(configuration::errorOverrides);
202203
map.from(properties.getLicenseKey()).whenNonNull().to(configuration::licenseKey);
203204
map.from(properties.getOracleSqlplus()).whenNonNull().to(configuration::oracleSqlplus);
204-
map.from(properties.getOracleSqlplusWarn()).whenNonNull().to(configuration::oracleSqlplusWarn);
205+
// No method reference for compatibility with Flyway 5.x
206+
map.from(properties.getOracleSqlplusWarn()).whenNonNull()
207+
.to((oracleSqlplusWarn) -> configuration.oracleSqlplusWarn(oracleSqlplusWarn));
205208
map.from(properties.getStream()).whenNonNull().to(configuration::stream);
206209
map.from(properties.getUndoSqlMigrationPrefix()).whenNonNull().to(configuration::undoSqlMigrationPrefix);
207210
}
@@ -220,7 +223,12 @@ private void configureFlywayCallbacks(FluentConfiguration flyway, List<Callback>
220223

221224
private void configureJavaMigrations(FluentConfiguration flyway, List<JavaMigration> migrations) {
222225
if (!migrations.isEmpty()) {
223-
flyway.javaMigrations(migrations.toArray(new JavaMigration[0]));
226+
try {
227+
flyway.javaMigrations(migrations.toArray(new JavaMigration[0]));
228+
}
229+
catch (NoSuchMethodError ex) {
230+
// Flyway 5.x
231+
}
224232
}
225233
}
226234

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.flyway;
18+
19+
import org.flywaydb.core.Flyway;
20+
import org.flywaydb.core.api.Location;
21+
import org.flywaydb.core.api.MigrationVersion;
22+
import org.flywaydb.core.api.migration.JavaMigration;
23+
import org.junit.jupiter.api.Test;
24+
25+
import org.springframework.boot.autoconfigure.AutoConfigurations;
26+
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
27+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
28+
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
29+
import org.springframework.context.annotation.Bean;
30+
import org.springframework.context.annotation.Configuration;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/**
35+
* Tests for {@link FlywayAutoConfiguration} with Flyway 5.x.
36+
*
37+
* @author Andy Wilkinson
38+
*/
39+
@ClassPathOverrides("org.flywaydb:flyway-core:5.2.4")
40+
class Flyway5xAutoConfigurationTests {
41+
42+
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
43+
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
44+
.withPropertyValues("spring.datasource.generate-unique-name=true");
45+
46+
@Test
47+
void defaultFlyway() {
48+
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class).run((context) -> {
49+
assertThat(context).hasSingleBean(Flyway.class);
50+
Flyway flyway = context.getBean(Flyway.class);
51+
assertThat(flyway.getConfiguration().getLocations())
52+
.containsExactly(new Location("classpath:db/migration"));
53+
});
54+
}
55+
56+
@Test
57+
void flywayJavaMigrationsAreIgnored() {
58+
this.contextRunner
59+
.withUserConfiguration(EmbeddedDataSourceConfiguration.class, FlywayJavaMigrationsConfiguration.class)
60+
.run((context) -> assertThat(context).hasNotFailed());
61+
}
62+
63+
@Configuration(proxyBeanMethods = false)
64+
static class FlywayJavaMigrationsConfiguration {
65+
66+
@Bean
67+
TestMigration migration1() {
68+
return new TestMigration("2", "M1");
69+
}
70+
71+
@Bean
72+
TestMigration migration2() {
73+
return new TestMigration("3", "M2");
74+
}
75+
76+
}
77+
78+
private static final class TestMigration implements JavaMigration {
79+
80+
private final MigrationVersion version;
81+
82+
private final String description;
83+
84+
private TestMigration(String version, String description) {
85+
this.version = MigrationVersion.fromVersion(version);
86+
this.description = description;
87+
}
88+
89+
@Override
90+
public MigrationVersion getVersion() {
91+
return this.version;
92+
}
93+
94+
@Override
95+
public String getDescription() {
96+
return this.description;
97+
}
98+
99+
@Override
100+
public Integer getChecksum() {
101+
return 1;
102+
}
103+
104+
@Override
105+
public boolean isUndo() {
106+
return false;
107+
}
108+
109+
@Override
110+
public boolean canExecuteInTransaction() {
111+
return true;
112+
}
113+
114+
@Override
115+
public void migrate(org.flywaydb.core.api.migration.Context context) {
116+
117+
}
118+
119+
}
120+
121+
}

0 commit comments

Comments
 (0)