Polish "Add failure analyzer for Flyway's bootstrap failure"
Closes gh-16015
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.flyway;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@@ -63,7 +62,6 @@ import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -163,15 +161,10 @@ public class FlywayAutoConfiguration {
|
||||
private void checkLocationExists(DataSource dataSource,
|
||||
FlywayProperties properties, ResourceLoader resourceLoader) {
|
||||
if (properties.isCheckLocation()) {
|
||||
String[] locations = new LocationResolver(dataSource)
|
||||
List<String> locations = new LocationResolver(dataSource)
|
||||
.resolveLocations(properties.getLocations());
|
||||
Assert.state(locations.length != 0,
|
||||
"Migration script locations not configured");
|
||||
boolean exists = hasAtLeastOneLocation(resourceLoader, locations);
|
||||
if (!exists) {
|
||||
throw new FlywayMigrationScriptNotFoundException(
|
||||
"Cannot find migrations in the specified location",
|
||||
Arrays.asList(locations));
|
||||
if (!hasAtLeastOneLocation(resourceLoader, locations)) {
|
||||
throw new FlywayMigrationScriptMissingException(locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,7 +173,7 @@ public class FlywayAutoConfiguration {
|
||||
FlywayProperties properties) {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
String[] locations = new LocationResolver(configuration.getDataSource())
|
||||
.resolveLocations(properties.getLocations());
|
||||
.resolveLocations(properties.getLocations()).toArray(new String[0]);
|
||||
map.from(locations).to(configuration::locations);
|
||||
map.from(properties.getEncoding()).to(configuration::encoding);
|
||||
map.from(properties.getConnectRetries()).to(configuration::connectRetries);
|
||||
@@ -257,7 +250,7 @@ public class FlywayAutoConfiguration {
|
||||
}
|
||||
|
||||
private boolean hasAtLeastOneLocation(ResourceLoader resourceLoader,
|
||||
String... locations) {
|
||||
Collection<String> locations) {
|
||||
for (String location : locations) {
|
||||
if (resourceLoader.getResource(normalizePrefix(location)).exists()) {
|
||||
return true;
|
||||
@@ -387,11 +380,7 @@ public class FlywayAutoConfiguration {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public String[] resolveLocations(Collection<String> locations) {
|
||||
return resolveLocations(StringUtils.toStringArray(locations));
|
||||
}
|
||||
|
||||
public String[] resolveLocations(String[] locations) {
|
||||
public List<String> resolveLocations(List<String> locations) {
|
||||
if (usesVendorLocation(locations)) {
|
||||
DatabaseDriver databaseDriver = getDatabaseDriver();
|
||||
return replaceVendorLocations(locations, databaseDriver);
|
||||
@@ -399,15 +388,15 @@ public class FlywayAutoConfiguration {
|
||||
return locations;
|
||||
}
|
||||
|
||||
private String[] replaceVendorLocations(String[] locations,
|
||||
private List<String> replaceVendorLocations(List<String> locations,
|
||||
DatabaseDriver databaseDriver) {
|
||||
if (databaseDriver == DatabaseDriver.UNKNOWN) {
|
||||
return locations;
|
||||
}
|
||||
String vendor = databaseDriver.getId();
|
||||
return Arrays.stream(locations)
|
||||
return locations.stream()
|
||||
.map((location) -> location.replace(VENDOR_PLACEHOLDER, vendor))
|
||||
.toArray(String[]::new);
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private DatabaseDriver getDatabaseDriver() {
|
||||
@@ -421,7 +410,7 @@ public class FlywayAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
private boolean usesVendorLocation(String... locations) {
|
||||
private boolean usesVendorLocation(Collection<String> locations) {
|
||||
for (String location : locations) {
|
||||
if (location.contains(VENDOR_PLACEHOLDER)) {
|
||||
return true;
|
||||
|
||||
@@ -16,22 +16,25 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.flyway;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Exception thrown when no {@code flyway migration script} is available.
|
||||
* Exception thrown when no Flyway migration script is available.
|
||||
*
|
||||
* @author Anand Shastri
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.2.0
|
||||
*/
|
||||
|
||||
public class FlywayMigrationScriptNotFoundException extends RuntimeException {
|
||||
public class FlywayMigrationScriptMissingException extends RuntimeException {
|
||||
|
||||
private final List<String> locations;
|
||||
|
||||
public FlywayMigrationScriptNotFoundException(String message,
|
||||
List<String> locations) {
|
||||
super(message);
|
||||
this.locations = locations;
|
||||
FlywayMigrationScriptMissingException(List<String> locations) {
|
||||
super(locations.isEmpty() ? "Migration script locations not configured"
|
||||
: "Cannot find migrations location in: " + locations
|
||||
+ " (please add migrations or check your Flyway configuration)");
|
||||
this.locations = new ArrayList<>(locations);
|
||||
}
|
||||
|
||||
public List<String> getLocations() {
|
||||
@@ -21,19 +21,32 @@ import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
|
||||
/**
|
||||
* A {@code FailureAnalyzer} that performs analysis of failures caused by a
|
||||
* {@code FlywayMigrationScriptNotFoundException}.
|
||||
* {@link FlywayMigrationScriptMissingException}.
|
||||
*
|
||||
* @author Anand Shastri
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class FlywayMigrationScriptMissingFailureAnalyzer
|
||||
extends AbstractFailureAnalyzer<FlywayMigrationScriptNotFoundException> {
|
||||
class FlywayMigrationScriptMissingFailureAnalyzer
|
||||
extends AbstractFailureAnalyzer<FlywayMigrationScriptMissingException> {
|
||||
|
||||
@Override
|
||||
protected FailureAnalysis analyze(Throwable rootFailure,
|
||||
FlywayMigrationScriptNotFoundException cause) {
|
||||
return new FailureAnalysis(
|
||||
"Cannot find migrations location in " + cause.getLocations(),
|
||||
" please add migrations or check your Flyway configuration", cause);
|
||||
FlywayMigrationScriptMissingException cause) {
|
||||
StringBuilder description = new StringBuilder("Flyway failed to initialize: ");
|
||||
if (cause.getLocations().isEmpty()) {
|
||||
return new FailureAnalysis(description
|
||||
.append("no migration scripts location is configured").toString(),
|
||||
"Check your Flyway configuration", cause);
|
||||
}
|
||||
else {
|
||||
description.append(String.format(
|
||||
"none of the following migration scripts locations could be found:%n%n"));
|
||||
cause.getLocations().forEach((location) -> description
|
||||
.append(String.format("\t- %s%n", location)));
|
||||
return new FailureAnalysis(description.toString(),
|
||||
"Review the locations above or check your Flyway configuration",
|
||||
cause);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAuto
|
||||
# Failure analyzers
|
||||
org.springframework.boot.diagnostics.FailureAnalyzer=\
|
||||
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
|
||||
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
|
||||
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
|
||||
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
|
||||
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
|
||||
|
||||
@@ -209,7 +209,7 @@ public class FlywayAutoConfigurationTests {
|
||||
assertThat(context).getFailure()
|
||||
.isInstanceOf(BeanCreationException.class);
|
||||
assertThat(context).getFailure()
|
||||
.hasMessageContaining("Cannot find migrations in");
|
||||
.hasMessageContaining("Cannot find migrations location in");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.flyway;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -25,25 +25,35 @@ import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link FlywayMigrationScriptMissingFailureAnalyzer}
|
||||
* Tests for {@link FlywayMigrationScriptMissingFailureAnalyzer}.
|
||||
*
|
||||
* @author Anand Shastri
|
||||
*/
|
||||
public class FlywayMigrationScriptMissingFailureAnalyzerTests {
|
||||
|
||||
private final FlywayMigrationScriptMissingFailureAnalyzer analyzer = new FlywayMigrationScriptMissingFailureAnalyzer();
|
||||
@Test
|
||||
public void analysisForMissingScriptLocation() {
|
||||
FailureAnalysis failureAnalysis = performAnalysis();
|
||||
assertThat(failureAnalysis.getDescription())
|
||||
.contains("no migration scripts location is configured");
|
||||
assertThat(failureAnalysis.getAction())
|
||||
.contains("Check your Flyway configuration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void analysisForFlywayScriptMissingFailure() {
|
||||
FailureAnalysis failureAnalysis = this.analyzer
|
||||
.analyze(new FlywayMigrationScriptNotFoundException(
|
||||
"Migration script locations not configured",
|
||||
Collections.singletonList("classpath:db/migration")));
|
||||
public void analysisForScriptLocationsNotFound() {
|
||||
FailureAnalysis failureAnalysis = performAnalysis("classpath:db/migration");
|
||||
assertThat(failureAnalysis.getDescription()).contains(
|
||||
"none of the following migration scripts locations could be found")
|
||||
.contains("classpath:db/migration");
|
||||
assertThat(failureAnalysis.getAction()).contains(
|
||||
"Review the locations above or check your Flyway configuration");
|
||||
}
|
||||
|
||||
assertThat(failureAnalysis.getDescription())
|
||||
.endsWith("Cannot find migrations location in [classpath:db/migration]");
|
||||
assertThat(failureAnalysis.getAction())
|
||||
.endsWith(" please add migrations or check your Flyway configuration");
|
||||
private FailureAnalysis performAnalysis(String... locations) {
|
||||
FlywayMigrationScriptMissingException exception = new FlywayMigrationScriptMissingException(
|
||||
Arrays.asList(locations));
|
||||
return new FlywayMigrationScriptMissingFailureAnalyzer().analyze(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,8 +50,7 @@ org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnaly
|
||||
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
|
||||
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
|
||||
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
|
||||
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
|
||||
org.springframework.boot.diagnostics.analyzer.FlywayMigrationScriptMissingFailureAnalyzer
|
||||
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer
|
||||
|
||||
# FailureAnalysisReporters
|
||||
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
|
||||
|
||||
Reference in New Issue
Block a user