├── .java-version ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── renovate.json ├── .gitignore ├── src ├── main │ └── java │ │ └── io │ │ └── dropwizard │ │ └── flyway │ │ ├── FlywayConfiguration.java │ │ ├── cli │ │ ├── NoOptionsFlywayCommand.java │ │ ├── DbRepairCommand.java │ │ ├── DbCleanCommand.java │ │ ├── DbInitCommand.java │ │ ├── DbInfoCommand.java │ │ ├── AbstractFlywayCommand.java │ │ ├── DbCommand.java │ │ ├── DbValidateCommand.java │ │ └── DbMigrateCommand.java │ │ ├── FlywayBundle.java │ │ └── FlywayFactory.java ├── site │ └── site.xml └── test │ └── java │ └── io │ └── dropwizard │ └── flyway │ ├── cli │ ├── DbValidateCommandTest.java │ ├── AbstractCommandTest.java │ └── DbMigrateCommandTest.java │ └── FlywayFactoryTest.java ├── .github └── workflows │ ├── release.yml │ ├── build.yml │ └── trigger-release.yml ├── pom.xml ├── mvnw.cmd ├── mvnw ├── LICENSE └── README.md /.java-version: -------------------------------------------------------------------------------- 1 | 17 -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dropwizard/dropwizard-flyway/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>dropwizard/renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | # IntelliJ IDEA 4 | *.iml 5 | *.ipr 6 | *.iws 7 | .idea/ 8 | out/ 9 | 10 | # Eclipse 11 | .settings/ 12 | .classpath 13 | .project 14 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/FlywayConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import io.dropwizard.core.Configuration; 4 | 5 | public interface FlywayConfiguration { 6 | FlywayFactory getFlywayFactory(T configuration); 7 | } 8 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release 3 | # yamllint disable-line rule:truthy 4 | on: 5 | push: 6 | tags: 7 | - dropwizard-flyway-* 8 | jobs: 9 | release: 10 | uses: dropwizard/workflows/.github/workflows/release.yml@main 11 | secrets: inherit 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build 3 | # yamllint disable-line rule:truthy 4 | on: 5 | push: 6 | branches: 7 | - release/* 8 | pull_request: 9 | jobs: 10 | yamllint: 11 | uses: dropwizard/workflows/.github/workflows/yamllint.yml@main 12 | build: 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | java-version: ['17', '21'] 17 | uses: dropwizard/workflows/.github/workflows/maven.yml@main 18 | secrets: inherit 19 | with: 20 | java-version: ${{ matrix.java-version }} 21 | -------------------------------------------------------------------------------- /.github/workflows/trigger-release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # yamllint disable rule:comments rule:line-length 3 | name: Trigger Release 4 | # yamllint disable-line rule:truthy 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | releaseVersion: 9 | description: Version of the next release 10 | required: true 11 | type: string 12 | developmentVersion: 13 | description: Version of the next development cycle (must end in "-SNAPSHOT") 14 | required: true 15 | type: string 16 | jobs: 17 | release: 18 | uses: dropwizard/workflows/.github/workflows/trigger-release.yml@main 19 | secrets: inherit 20 | with: 21 | releaseVersion: ${{ inputs.releaseVersion }} 22 | developmentVersion: ${{ inputs.developmentVersion }} 23 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | org.apache.maven.skins 6 | maven-fluido-skin 7 | 1.7 8 | 9 | 10 | 11 | 12 | dropwizard/dropwizard-flyway 13 | right 14 | red 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/NoOptionsFlywayCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.db.DatabaseConfiguration; 5 | import io.dropwizard.flyway.FlywayConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.inf.Namespace; 8 | 9 | public abstract class NoOptionsFlywayCommand extends AbstractFlywayCommand { 10 | 11 | NoOptionsFlywayCommand(String name, String description, DatabaseConfiguration databaseConfiguration, 12 | FlywayConfiguration flywayConfiguration, Class configurationClass) { 13 | super(name, description, databaseConfiguration, flywayConfiguration, configurationClass); 14 | } 15 | 16 | @Override 17 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 18 | // Empty on purpose 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbRepairCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import net.sourceforge.argparse4j.inf.Namespace; 7 | import org.flywaydb.core.Flyway; 8 | 9 | public class DbRepairCommand extends NoOptionsFlywayCommand { 10 | public DbRepairCommand(final DatabaseConfiguration databaseConfiguration, 11 | final FlywayConfiguration flywayConfiguration, 12 | final Class configurationClass) { 13 | super("repair", "Repairs the metadata table.", 14 | databaseConfiguration, flywayConfiguration, configurationClass); 15 | } 16 | 17 | @Override 18 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 19 | flyway.repair(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbCleanCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import net.sourceforge.argparse4j.inf.Namespace; 7 | import org.flywaydb.core.Flyway; 8 | 9 | public class DbCleanCommand extends NoOptionsFlywayCommand { 10 | public DbCleanCommand(final DatabaseConfiguration databaseConfiguration, 11 | final FlywayConfiguration flywayConfiguration, 12 | final Class configurationClass) { 13 | super("clean", "Drops all objects in the configured schemas.", 14 | databaseConfiguration, flywayConfiguration, configurationClass); 15 | } 16 | 17 | @Override 18 | protected void run(final Namespace namespace, final Flyway flyway) throws Exception { 19 | flyway.clean(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbInitCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import org.flywaydb.core.Flyway; 5 | import io.dropwizard.core.Configuration; 6 | import io.dropwizard.db.DatabaseConfiguration; 7 | import net.sourceforge.argparse4j.inf.Namespace; 8 | 9 | public class DbInitCommand extends NoOptionsFlywayCommand { 10 | public DbInitCommand(final DatabaseConfiguration databaseConfiguration, 11 | final FlywayConfiguration flywayConfiguration, 12 | final Class configurationClass) { 13 | super("init", "Creates and initializes the metadata table (existing database).", 14 | databaseConfiguration, flywayConfiguration, configurationClass); 15 | } 16 | 17 | @Override 18 | protected void run(final Namespace namespace, final Flyway flyway) throws Exception { 19 | flyway.baseline(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/FlywayBundle.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.core.ConfiguredBundle; 5 | import io.dropwizard.core.setup.Bootstrap; 6 | import io.dropwizard.db.DatabaseConfiguration; 7 | import io.dropwizard.flyway.cli.DbCommand; 8 | import io.dropwizard.util.Generics; 9 | 10 | public abstract class FlywayBundle 11 | implements ConfiguredBundle, DatabaseConfiguration, FlywayConfiguration { 12 | @Override 13 | public final void initialize(final Bootstrap bootstrap) { 14 | final Class klass = Generics.getTypeParameter(getClass(), Configuration.class); 15 | bootstrap.addCommand(new DbCommand(name(), this, this, klass)); 16 | } 17 | 18 | @Override 19 | public FlywayFactory getFlywayFactory(T configuration) { 20 | // Default Flyway configuration 21 | return new FlywayFactory(); 22 | } 23 | 24 | protected String name() { 25 | return "db"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbInfoCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import net.sourceforge.argparse4j.inf.Namespace; 7 | import org.flywaydb.core.Flyway; 8 | 9 | import static org.flywaydb.core.internal.info.MigrationInfoDumper.dumpToAsciiTable; 10 | 11 | public class DbInfoCommand extends NoOptionsFlywayCommand { 12 | public DbInfoCommand(final DatabaseConfiguration databaseConfiguration, 13 | final FlywayConfiguration flywayConfiguration, 14 | final Class configurationClass) { 15 | super("info", "Prints the details and status information about all the migrations.", 16 | databaseConfiguration, flywayConfiguration, configurationClass); 17 | } 18 | 19 | @Override 20 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 21 | System.out.println(dumpToAsciiTable(flyway.info().all())); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/cli/DbValidateCommandTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.mockito.ArgumentMatchers.anyBoolean; 6 | import static org.mockito.Mockito.never; 7 | import static org.mockito.Mockito.verify; 8 | 9 | public class DbValidateCommandTest extends AbstractCommandTest { 10 | 11 | @Test 12 | public void testDefaultArguments() { 13 | cli.run("db", "validate"); 14 | 15 | verify(mockFlywayFactory, never()).setOutOfOrder(anyBoolean()); 16 | verify(mockFlywayFactory, never()).setCleanOnValidationError(anyBoolean()); 17 | verify(mockFlyway).validate(); 18 | } 19 | 20 | @Test 21 | public void testOutOfOrder() { 22 | cli.run("db", "validate", "--outOfOrder"); 23 | 24 | verify(mockFlywayFactory).setOutOfOrder(true); 25 | verify(mockFlyway).validate(); 26 | } 27 | 28 | @Test 29 | public void testCleanOnValidationError() { 30 | cli.run("db", "validate", "--cleanOnValidationError"); 31 | 32 | verify(mockFlywayFactory).setCleanOnValidationError(true); 33 | verify(mockFlyway).validate(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/cli/AbstractCommandTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Application; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.core.cli.Cli; 6 | import io.dropwizard.core.setup.Bootstrap; 7 | import io.dropwizard.core.setup.Environment; 8 | import io.dropwizard.db.DatabaseConfiguration; 9 | import io.dropwizard.db.PooledDataSourceFactory; 10 | import io.dropwizard.flyway.FlywayConfiguration; 11 | import io.dropwizard.flyway.FlywayFactory; 12 | import io.dropwizard.util.JarLocation; 13 | import org.flywaydb.core.Flyway; 14 | import org.junit.jupiter.api.BeforeEach; 15 | 16 | import java.util.Optional; 17 | 18 | import static org.mockito.ArgumentMatchers.any; 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.when; 21 | 22 | public class AbstractCommandTest { 23 | protected Cli cli; 24 | 25 | protected FlywayFactory mockFlywayFactory; 26 | protected Flyway mockFlyway; 27 | 28 | private static class TestApplication extends Application { 29 | @Override 30 | public void run(TestConfiguration configuration, Environment environment) throws Exception { 31 | } 32 | } 33 | 34 | public static class TestConfiguration extends Configuration { 35 | } 36 | 37 | @BeforeEach 38 | public void setUp() throws Exception { 39 | // Setup necessary mock 40 | final JarLocation location = mock(JarLocation.class); 41 | when(location.getVersion()).thenReturn(Optional.of("1.0.0")); 42 | 43 | final DatabaseConfiguration dbConfiguration = mock(DatabaseConfiguration.class); 44 | when(dbConfiguration.getDataSourceFactory(any())).thenReturn(mock(PooledDataSourceFactory.class)); 45 | 46 | final FlywayConfiguration flywayConfiguration = mock(FlywayConfiguration.class); 47 | mockFlywayFactory = mock(FlywayFactory.class); 48 | when(flywayConfiguration.getFlywayFactory(any())).thenReturn(mockFlywayFactory); 49 | 50 | mockFlyway = mock(Flyway.class); 51 | when(mockFlywayFactory.build(any())).thenReturn(mockFlyway); 52 | 53 | // Add commands you want to test 54 | final Bootstrap bootstrap = new Bootstrap<>(new TestApplication()); 55 | bootstrap.addCommand(new DbCommand("db", dbConfiguration, flywayConfiguration, TestConfiguration.class)); 56 | 57 | // Build what'll run the command and interpret arguments 58 | cli = new Cli(location, bootstrap, System.out, System.err); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/cli/DbMigrateCommandTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import org.flywaydb.core.api.output.MigrateResult; 4 | import org.flywaydb.core.internal.license.VersionPrinter; 5 | import org.junit.jupiter.api.BeforeEach; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.mockito.ArgumentMatchers.anyBoolean; 9 | import static org.mockito.Mockito.never; 10 | import static org.mockito.Mockito.verify; 11 | import static org.mockito.Mockito.when; 12 | 13 | public class DbMigrateCommandTest extends AbstractCommandTest { 14 | private MigrateResult migrateResult; 15 | 16 | @BeforeEach 17 | void setUpFlyway() { 18 | migrateResult = new MigrateResult(VersionPrinter.getVersion(), "db", "schema", "PostgreSQL"); 19 | migrateResult.initialSchemaVersion = "initial"; 20 | migrateResult.targetSchemaVersion = "target"; 21 | migrateResult.migrationsExecuted = 23; 22 | 23 | when(mockFlyway.migrate()).thenReturn(migrateResult); 24 | } 25 | 26 | @Test 27 | public void testDefaultArguments() { 28 | cli.run("db", "migrate"); 29 | 30 | verify(mockFlywayFactory, never()).setBaselineOnMigrate(anyBoolean()); 31 | verify(mockFlywayFactory, never()).setOutOfOrder(anyBoolean()); 32 | verify(mockFlywayFactory, never()).setValidateOnMigrate(anyBoolean()); 33 | verify(mockFlywayFactory, never()).setCleanOnValidationError(anyBoolean()); 34 | verify(mockFlyway).migrate(); 35 | } 36 | 37 | @Test 38 | public void testDefaultArgumentsWithWarnings() { 39 | migrateResult.warnings.add("warning1"); 40 | migrateResult.warnings.add("warning2"); 41 | 42 | cli.run("db", "migrate"); 43 | 44 | verify(mockFlyway).migrate(); 45 | } 46 | 47 | @Test 48 | public void testInitOnMigrate() { 49 | cli.run("db", "migrate", "--initOnMigrate"); 50 | 51 | verify(mockFlywayFactory).setBaselineOnMigrate(true); 52 | verify(mockFlyway).migrate(); 53 | } 54 | 55 | @Test 56 | public void testValidateOMigrate() { 57 | cli.run("db", "migrate", "--validateOnMigrate"); 58 | 59 | verify(mockFlywayFactory).setValidateOnMigrate(true); 60 | verify(mockFlyway).migrate(); 61 | } 62 | 63 | @Test 64 | public void testOutOfOrder() { 65 | cli.run("db", "migrate", "--outOfOrder"); 66 | 67 | verify(mockFlywayFactory).setOutOfOrder(true); 68 | verify(mockFlyway).migrate(); 69 | } 70 | 71 | @Test 72 | public void testCleanOnValidationError() { 73 | cli.run("db", "migrate", "--cleanOnValidationError"); 74 | 75 | verify(mockFlywayFactory).setCleanOnValidationError(true); 76 | verify(mockFlyway).migrate(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/AbstractFlywayCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.core.cli.ConfiguredCommand; 5 | import io.dropwizard.core.setup.Bootstrap; 6 | import io.dropwizard.db.DatabaseConfiguration; 7 | import io.dropwizard.db.PooledDataSourceFactory; 8 | import io.dropwizard.flyway.FlywayConfiguration; 9 | import io.dropwizard.flyway.FlywayFactory; 10 | import net.sourceforge.argparse4j.inf.Namespace; 11 | import org.flywaydb.core.Flyway; 12 | import org.flywaydb.core.api.FlywayException; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | abstract class AbstractFlywayCommand extends ConfiguredCommand { 17 | private static final Logger LOG = LoggerFactory.getLogger(AbstractFlywayCommand.class); 18 | private final DatabaseConfiguration databaseConfiguration; 19 | private final FlywayConfiguration flywayConfiguration; 20 | private final Class configurationClass; 21 | 22 | AbstractFlywayCommand(final String name, 23 | final String description, 24 | final DatabaseConfiguration databaseConfiguration, 25 | final FlywayConfiguration flywayConfiguration, 26 | final Class configurationClass) { 27 | super(name, description); 28 | this.databaseConfiguration = databaseConfiguration; 29 | this.flywayConfiguration = flywayConfiguration; 30 | this.configurationClass = configurationClass; 31 | } 32 | 33 | @Override 34 | protected Class getConfigurationClass() { 35 | return configurationClass; 36 | } 37 | 38 | @Override 39 | protected void run(final Bootstrap bootstrap, final Namespace namespace, final T configuration) throws Exception { 40 | final PooledDataSourceFactory datasourceFactory = databaseConfiguration.getDataSourceFactory(configuration); 41 | final FlywayFactory flywayFactory = flywayConfiguration.getFlywayFactory(configuration); 42 | 43 | // Give subclasses an option to set additional config flags for flyway. 44 | setAdditionalOptions(flywayFactory, namespace); 45 | 46 | final Flyway flyway = flywayFactory.build(datasourceFactory.build(bootstrap.getMetricRegistry(), "Flyway")); 47 | 48 | try { 49 | run(namespace, flyway); 50 | } catch (FlywayException e) { 51 | LOG.error("Error while running database command", e); 52 | throw e; 53 | } 54 | } 55 | 56 | protected abstract void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace); 57 | protected abstract void run(final Namespace namespace, final Flyway flyway) throws Exception; 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.inf.Namespace; 8 | import net.sourceforge.argparse4j.inf.Subparser; 9 | import org.flywaydb.core.Flyway; 10 | 11 | import java.util.SortedMap; 12 | import java.util.TreeMap; 13 | 14 | public class DbCommand extends AbstractFlywayCommand { 15 | private static final String COMMAND_NAME_ATTR = "subCommand"; 16 | private final SortedMap> subCommands = new TreeMap<>(); 17 | 18 | public DbCommand(final String name, final DatabaseConfiguration databaseConfiguration, 19 | final FlywayConfiguration flywayConfiguration, 20 | final Class configurationClass) { 21 | super(name, "Run database migration tasks", 22 | databaseConfiguration, flywayConfiguration, configurationClass); 23 | 24 | addSubCommand(new DbMigrateCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 25 | addSubCommand(new DbCleanCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 26 | addSubCommand(new DbInitCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 27 | addSubCommand(new DbValidateCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 28 | addSubCommand(new DbInfoCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 29 | addSubCommand(new DbRepairCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 30 | } 31 | 32 | private void addSubCommand(final AbstractFlywayCommand subCommand) { 33 | subCommands.put(subCommand.getName(), subCommand); 34 | } 35 | 36 | @Override 37 | public void configure(final Subparser subparser) { 38 | for (AbstractFlywayCommand subCommand : subCommands.values()) { 39 | final Subparser cmdParser = subparser.addSubparsers() 40 | .addParser(subCommand.getName()) 41 | .setDefault(COMMAND_NAME_ATTR, subCommand.getName()) 42 | .description(subCommand.getDescription()); 43 | subCommand.configure(cmdParser); 44 | } 45 | } 46 | 47 | @Override 48 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 49 | subCommands.get(namespace.getString(COMMAND_NAME_ATTR)).setAdditionalOptions(flywayFactory, namespace); 50 | } 51 | 52 | @Override 53 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 54 | subCommands.get(namespace.getString(COMMAND_NAME_ATTR)).run(namespace, flyway); 55 | } 56 | } -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/FlywayFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import jakarta.validation.constraints.NotNull; 5 | import org.flywaydb.core.Flyway; 6 | import org.flywaydb.database.postgresql.PostgreSQLConfigurationExtension; 7 | import org.h2.jdbcx.JdbcDataSource; 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import java.nio.charset.StandardCharsets; 12 | import java.sql.SQLException; 13 | import java.util.Map; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | import static org.junit.jupiter.api.Assertions.assertNotNull; 17 | import static org.junit.jupiter.api.Assertions.assertSame; 18 | 19 | public class FlywayFactoryTest { 20 | 21 | private JdbcDataSource dataSource; 22 | 23 | @BeforeEach 24 | void setUp() throws SQLException { 25 | dataSource = new JdbcDataSource(); 26 | dataSource.setURL("jdbc:h2:mem:testdb"); 27 | dataSource.setUser("sa"); 28 | } 29 | 30 | @Test 31 | public void defaultConfigurationShouldBeValid() { 32 | final FlywayFactory factory = new FlywayFactory(); 33 | 34 | final Flyway flyway = factory.build(dataSource); 35 | 36 | assertNotNull(flyway); 37 | assertSame(dataSource, flyway.getConfiguration().getDataSource()); 38 | assertEquals(StandardCharsets.UTF_8, flyway.getConfiguration().getEncoding()); 39 | assertEquals("flyway_schema_history", flyway.getConfiguration().getTable()); 40 | assertEquals(0, flyway.getConfiguration().getSchemas().length); 41 | } 42 | 43 | @Test 44 | public void checkConfigurationWithOverridedSetting() { 45 | Flyway flyway = new FlywayFactory().build(dataSource); 46 | assertNotNull(flyway); 47 | 48 | boolean transactionalLockDefault = getPostgresTransactionLockSettings(flyway); 49 | boolean transactionalLockOverrided = !transactionalLockDefault; 50 | 51 | final FlywayFactory factory = new FlywayFactory(); 52 | Map configuration = ImmutableMap.of("flyway.postgresql.transactional.lock", String.valueOf(transactionalLockOverrided)); 53 | factory.setConfiguration(configuration); 54 | flyway = factory.build(dataSource); 55 | 56 | assertNotNull(flyway); 57 | assertEquals(StandardCharsets.UTF_8, flyway.getConfiguration().getEncoding()); // default value 58 | assertEquals(0, flyway.getConfiguration().getSchemas().length); // default value 59 | assertEquals("flyway_schema_history", flyway.getConfiguration().getTable()); // default value 60 | assertEquals(transactionalLockOverrided, getPostgresTransactionLockSettings(flyway)); // overrided value 61 | } 62 | 63 | private static boolean getPostgresTransactionLockSettings(@NotNull final Flyway flyway) { 64 | return flyway.getConfiguration().getPluginRegister().getPlugin(PostgreSQLConfigurationExtension.class).isTransactionalLock(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbValidateCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.db.DatabaseConfiguration; 5 | import io.dropwizard.flyway.FlywayConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.impl.Arguments; 8 | import net.sourceforge.argparse4j.inf.Namespace; 9 | import net.sourceforge.argparse4j.inf.Subparser; 10 | import org.flywaydb.core.Flyway; 11 | import org.flywaydb.core.api.configuration.FluentConfiguration; 12 | 13 | import static net.sourceforge.argparse4j.impl.Arguments.storeTrue; 14 | 15 | public class DbValidateCommand extends AbstractFlywayCommand { 16 | 17 | private static final String OUT_OF_ORDER = "outOfOrder"; 18 | private static final String CLEAN_ON_VALIDATION_ERROR = "cleanOnValidationError"; 19 | 20 | public DbValidateCommand(final DatabaseConfiguration databaseConfiguration, 21 | final FlywayConfiguration flywayConfiguration, 22 | final Class configurationClass) { 23 | super("validate", "Validates the applied migrations against the ones available on the classpath.", 24 | databaseConfiguration, flywayConfiguration, configurationClass); 25 | } 26 | 27 | @Override 28 | public void configure(Subparser subparser) { 29 | super.configure(subparser); 30 | 31 | subparser.addArgument("--" + OUT_OF_ORDER) 32 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 33 | .dest(OUT_OF_ORDER) 34 | .help("Allows migrations to be run \"out of order\". " + 35 | "If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored."); 36 | 37 | subparser.addArgument("--" + CLEAN_ON_VALIDATION_ERROR) 38 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 39 | .dest(CLEAN_ON_VALIDATION_ERROR) 40 | .help("Whether to automatically call clean or not when a validation error occurs. " + 41 | "This is exclusively intended as a convenience for development. " + 42 | "Even tough we strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a way of dealing with this case in a smooth manner. " + 43 | "The database will be wiped clean automatically, ensuring that the next migration will bring you back to the state checked into SCM. " + 44 | "Warning! Do not enable in production !"); 45 | } 46 | 47 | @Override 48 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 49 | final Boolean outOfOrder = namespace.getBoolean(OUT_OF_ORDER); 50 | final Boolean cleanOnValidationError = namespace.getBoolean(CLEAN_ON_VALIDATION_ERROR); 51 | 52 | if (outOfOrder != null) { 53 | flywayFactory.setOutOfOrder(outOfOrder); 54 | } 55 | 56 | if (cleanOnValidationError != null) { 57 | flywayFactory.setCleanOnValidationError(cleanOnValidationError); 58 | } 59 | 60 | } 61 | 62 | @Override 63 | protected void run(final Namespace namespace, final Flyway flyway) throws Exception { 64 | flyway.validate(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.dropwizard.modules 6 | module-parent 7 | 5.0.0 8 | 9 | dropwizard-flyway 10 | 5.0.1-1-SNAPSHOT 11 | jar 12 | 13 | Dropwizard Flyway Bundle 14 | Addon bundle for Dropwizard to support Flyway for database migrations 15 | 16 | 17 | 18 | dropwizard-flyway 19 | http://dropwizard.github.io/dropwizard-flyway/${project.version} 20 | 21 | 22 | 23 | 24 | 25 | j.schalanda 26 | Jochen Schalanda 27 | jochen@schalanda.name 28 | 29 | 30 | 31 | 32 | dropwizard_dropwizard-flyway 33 | 34 | 11.19.1 35 | 36 | 37 | 38 | 39 | 40 | io.dropwizard.flywaydb 41 | flyway-bom 42 | ${flyway.version} 43 | pom 44 | import 45 | 46 | 47 | 48 | 49 | 50 | 51 | io.dropwizard 52 | dropwizard-core 53 | 54 | 55 | io.dropwizard 56 | dropwizard-db 57 | 58 | 59 | io.dropwizard 60 | dropwizard-util 61 | 62 | 63 | org.flywaydb 64 | flyway-core 65 | 66 | 67 | net.sourceforge.argparse4j 68 | argparse4j 69 | 70 | 71 | org.slf4j 72 | slf4j-api 73 | 74 | 75 | com.fasterxml.jackson.core 76 | jackson-annotations 77 | 78 | 79 | org.junit.jupiter 80 | junit-jupiter 81 | test 82 | 83 | 84 | org.mockito 85 | mockito-core 86 | test 87 | 88 | 89 | org.mockito 90 | mockito-junit-jupiter 91 | test 92 | 93 | 94 | org.flywaydb 95 | flyway-database-postgresql 96 | test 97 | 98 | 99 | com.h2database 100 | h2 101 | 2.4.240 102 | test 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% 146 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbMigrateCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.db.DatabaseConfiguration; 5 | import io.dropwizard.flyway.FlywayConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.impl.Arguments; 8 | import net.sourceforge.argparse4j.inf.Namespace; 9 | import net.sourceforge.argparse4j.inf.Subparser; 10 | import org.flywaydb.core.Flyway; 11 | import org.flywaydb.core.api.output.MigrateResult; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | public class DbMigrateCommand extends AbstractFlywayCommand { 16 | 17 | private static final Logger LOG = LoggerFactory.getLogger(DbMigrateCommand.class); 18 | private static final String OUT_OF_ORDER = "outOfOrder"; 19 | private static final String VALIDATE_ON_MIGRATE = "validateOnMigrate"; 20 | private static final String CLEAN_ON_VALIDATION_ERROR = "cleanOnValidationError"; 21 | private static final String INIT_ON_MIGRATE = "initOnMigrate"; 22 | 23 | public DbMigrateCommand(final DatabaseConfiguration databaseConfiguration, 24 | final FlywayConfiguration flywayConfiguration, 25 | final Class configurationClass) { 26 | super("migrate", "Migrates the database.", 27 | databaseConfiguration, flywayConfiguration, configurationClass); 28 | } 29 | 30 | @Override 31 | public void configure(Subparser subparser) { 32 | super.configure(subparser); 33 | 34 | subparser.addArgument("--" + OUT_OF_ORDER) 35 | .dest(OUT_OF_ORDER) 36 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 37 | .help("Allows migrations to be run \"out of order\". " + 38 | "If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored."); 39 | 40 | subparser.addArgument("--" + VALIDATE_ON_MIGRATE) 41 | .dest(VALIDATE_ON_MIGRATE) 42 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 43 | .help("Whether to automatically call validate or not when running migrate. " + 44 | "For each sql migration a CRC32 checksum is calculated when the sql script is executed. " + 45 | "The validate mechanism checks if the sql migration in the classpath still has the same checksum as the sql migration already executed in the database."); 46 | 47 | subparser.addArgument("--" + CLEAN_ON_VALIDATION_ERROR) 48 | .dest(CLEAN_ON_VALIDATION_ERROR) 49 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 50 | .help("Whether to automatically call clean or not when a validation error occurs. " + 51 | "This is exclusively intended as a convenience for development. " + 52 | "Even tough we strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a way of dealing with this case in a smooth manner. " + 53 | "The database will be wiped clean automatically, ensuring that the next migration will bring you back to the state checked into SCM. " + 54 | "Warning! Do not enable in production !"); 55 | 56 | subparser.addArgument("--" + INIT_ON_MIGRATE) 57 | .dest(INIT_ON_MIGRATE) 58 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 59 | .help("Whether to automatically call init when migrate is executed against a non-empty schema with no metadata table. " + 60 | "This schema will then be initialized with the initVersion before executing the migrations. " + 61 | "Only migrations above initVersion will then be applied. " + 62 | "This is useful for initial Flyway production deployments on projects with an existing DB. " + 63 | "Be careful when enabling this as it removes the safety net that ensures Flyway does not migrate the wrong database in case of a configuration mistake!"); 64 | } 65 | 66 | @Override 67 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 68 | final Boolean outOfOrder = namespace.getBoolean(OUT_OF_ORDER); 69 | final Boolean validateOnMigrate = namespace.getBoolean(VALIDATE_ON_MIGRATE); 70 | final Boolean cleanOnValidationError = namespace.getBoolean(CLEAN_ON_VALIDATION_ERROR); 71 | final Boolean baselineOnMigrate = namespace.getBoolean(INIT_ON_MIGRATE); 72 | 73 | if (outOfOrder != null) { 74 | flywayFactory.setOutOfOrder(outOfOrder); 75 | } 76 | 77 | if (validateOnMigrate != null) { 78 | flywayFactory.setValidateOnMigrate(validateOnMigrate); 79 | } 80 | 81 | if (cleanOnValidationError != null) { 82 | flywayFactory.setCleanOnValidationError(cleanOnValidationError); 83 | } 84 | 85 | if (baselineOnMigrate != null) { 86 | flywayFactory.setBaselineOnMigrate(baselineOnMigrate); 87 | } 88 | } 89 | 90 | @Override 91 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 92 | final MigrateResult migrateResult = flyway.migrate(); 93 | LOG.debug("Executed {} migrations to migrate {} in database {} from schema {} -> {}", 94 | migrateResult.migrationsExecuted, migrateResult.schemaName, migrateResult.database, 95 | migrateResult.initialSchemaVersion, migrateResult.targetSchemaVersion); 96 | 97 | if (!migrateResult.warnings.isEmpty()) { 98 | LOG.warn("{} warnings when migrating {} in database {} from schema {} -> {}: {}", 99 | migrateResult.warnings.size(), migrateResult.schemaName, migrateResult.database, 100 | migrateResult.initialSchemaVersion, migrateResult.targetSchemaVersion, 101 | migrateResult.warnings 102 | ); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # 58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look 59 | # for the new JDKs provided by Oracle. 60 | # 61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then 62 | # 63 | # Apple JDKs 64 | # 65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home 66 | fi 67 | 68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then 69 | # 70 | # Apple JDKs 71 | # 72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 73 | fi 74 | 75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then 76 | # 77 | # Oracle JDKs 78 | # 79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 80 | fi 81 | 82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then 83 | # 84 | # Apple JDKs 85 | # 86 | export JAVA_HOME=`/usr/libexec/java_home` 87 | fi 88 | ;; 89 | esac 90 | 91 | if [ -z "$JAVA_HOME" ] ; then 92 | if [ -r /etc/gentoo-release ] ; then 93 | JAVA_HOME=`java-config --jre-home` 94 | fi 95 | fi 96 | 97 | if [ -z "$M2_HOME" ] ; then 98 | ## resolve links - $0 may be a link to maven's home 99 | PRG="$0" 100 | 101 | # need this for relative symlinks 102 | while [ -h "$PRG" ] ; do 103 | ls=`ls -ld "$PRG"` 104 | link=`expr "$ls" : '.*-> \(.*\)$'` 105 | if expr "$link" : '/.*' > /dev/null; then 106 | PRG="$link" 107 | else 108 | PRG="`dirname "$PRG"`/$link" 109 | fi 110 | done 111 | 112 | saveddir=`pwd` 113 | 114 | M2_HOME=`dirname "$PRG"`/.. 115 | 116 | # make it fully qualified 117 | M2_HOME=`cd "$M2_HOME" && pwd` 118 | 119 | cd "$saveddir" 120 | # echo Using m2 at $M2_HOME 121 | fi 122 | 123 | # For Cygwin, ensure paths are in UNIX format before anything is touched 124 | if $cygwin ; then 125 | [ -n "$M2_HOME" ] && 126 | M2_HOME=`cygpath --unix "$M2_HOME"` 127 | [ -n "$JAVA_HOME" ] && 128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 129 | [ -n "$CLASSPATH" ] && 130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 131 | fi 132 | 133 | # For Migwn, ensure paths are in UNIX format before anything is touched 134 | if $mingw ; then 135 | [ -n "$M2_HOME" ] && 136 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 137 | [ -n "$JAVA_HOME" ] && 138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 139 | # TODO classpath? 140 | fi 141 | 142 | if [ -z "$JAVA_HOME" ]; then 143 | javaExecutable="`which javac`" 144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 145 | # readlink(1) is not available as standard on Solaris 10. 146 | readLink=`which readlink` 147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 148 | if $darwin ; then 149 | javaHome="`dirname \"$javaExecutable\"`" 150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 151 | else 152 | javaExecutable="`readlink -f \"$javaExecutable\"`" 153 | fi 154 | javaHome="`dirname \"$javaExecutable\"`" 155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 156 | JAVA_HOME="$javaHome" 157 | export JAVA_HOME 158 | fi 159 | fi 160 | fi 161 | 162 | if [ -z "$JAVACMD" ] ; then 163 | if [ -n "$JAVA_HOME" ] ; then 164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 165 | # IBM's JDK on AIX uses strange locations for the executables 166 | JAVACMD="$JAVA_HOME/jre/sh/java" 167 | else 168 | JAVACMD="$JAVA_HOME/bin/java" 169 | fi 170 | else 171 | JAVACMD="`which java`" 172 | fi 173 | fi 174 | 175 | if [ ! -x "$JAVACMD" ] ; then 176 | echo "Error: JAVA_HOME is not defined correctly." >&2 177 | echo " We cannot execute $JAVACMD" >&2 178 | exit 1 179 | fi 180 | 181 | if [ -z "$JAVA_HOME" ] ; then 182 | echo "Warning: JAVA_HOME environment variable is not set." 183 | fi 184 | 185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 186 | 187 | # For Cygwin, switch paths to Windows format before running java 188 | if $cygwin; then 189 | [ -n "$M2_HOME" ] && 190 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 191 | [ -n "$JAVA_HOME" ] && 192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 193 | [ -n "$CLASSPATH" ] && 194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 195 | fi 196 | 197 | # traverses directory structure from process work directory to filesystem root 198 | # first directory with .mvn subdirectory is considered project base directory 199 | find_maven_basedir() { 200 | local basedir=$(pwd) 201 | local wdir=$(pwd) 202 | while [ "$wdir" != '/' ] ; do 203 | if [ -d "$wdir"/.mvn ] ; then 204 | basedir=$wdir 205 | break 206 | fi 207 | wdir=$(cd "$wdir/.."; pwd) 208 | done 209 | echo "${basedir}" 210 | } 211 | 212 | # concatenates all lines of a file 213 | concat_lines() { 214 | if [ -f "$1" ]; then 215 | echo "$(tr -s '\n' ' ' < "$1")" 216 | fi 217 | } 218 | 219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} 220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 221 | 222 | # Provide a "standardized" way to retrieve the CLI args that will 223 | # work with both Windows and non-Windows executions. 224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 225 | export MAVEN_CMD_LINE_ARGS 226 | 227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 228 | 229 | exec "$JAVACMD" \ 230 | $MAVEN_OPTS \ 231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 233 | ${WRAPPER_LAUNCHER} $MAVEN_CMD_LINE_ARGS 234 | 235 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2011 Coda Hale and Yammer, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dropwizard Flyway 2 | ================= 3 | 4 | [![Build](https://github.com/dropwizard/dropwizard-flyway/actions/workflows/build.yml/badge.svg)](https://github.com/dropwizard/dropwizard-flyway/actions/workflows/build.yml) 5 | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dropwizard_dropwizard-flyway&metric=alert_status)](https://sonarcloud.io/dashboard?id=dropwizard_dropwizard-flyway) 6 | [![Maven Central](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway.svg)](https://search.maven.org/artifact/io.dropwizard.modules/dropwizard-flyway) 7 | 8 | `dropwizard-flyway` is a set of commands using [Flyway](http://www.flywaydb.org/) for database migrations in [Dropwizard](http://dropwizard.io/) applications. 9 | 10 | 11 | Usage 12 | ----- 13 | 14 | Just add the `FlywayBundle` to your Dropwizard application inside the [`Application#initialize`](https://javadoc.io/static/io.dropwizard/dropwizard-core/4.0.0/io/dropwizard/core/Application.html#initialize(io.dropwizard.core.setup.Bootstrap) method. 15 | 16 | @Override 17 | public void initialize(Bootstrap bootstrap) { 18 | // ... 19 | bootstrap.addBundle(new FlywayBundle() { 20 | @Override 21 | public DataSourceFactory getDataSourceFactory(MyConfiguration configuration) { 22 | return configuration.getDataSourceFactory(); 23 | } 24 | 25 | @Override 26 | public FlywayFactory getFlywayFactory(MyConfiguration configuration) { 27 | return configuration.getFlywayFactory(); 28 | } 29 | }); 30 | } 31 | 32 | 33 | After that you can use one of the following Flyway commands: 34 | 35 | | Command | Description | 36 | | ------------- | ---------------------------------------------------------------------------- | 37 | | `db migrate` | Migrates the database | 38 | | `db clean` | Drops all objects in the configured schemas | 39 | | `db info` | Prints the details and status information about all the migrations | 40 | | `db validate` | Validates the applied migrations against the ones available on the classpath | 41 | | `db init` | Creates and initializes the metadata table (existing database) | 42 | | `db repair` | Repairs the metadata table | 43 | 44 | The [Flyway migrations](http://flywaydb.org/documentation/migration/) must be accessible in the classpath under `db/migration` (or any other path configured with the `locations` parameter, see [FlywayFactory](https://dropwizard.github.io/dropwizard-flyway/2.0.0-1/apidocs/io/dropwizard/flyway/FlywayFactory.html)). 45 | 46 | 47 | Configuration 48 | ------------- 49 | 50 | `dropwizard-flyway` is using the standard [DataSourceFactory](https://javadoc.io/static/io.dropwizard/dropwizard-db/4.0.0/io/dropwizard/db/DataSourceFactory.html) from [`dropwizard-db`](https://javadoc.io/doc/io.dropwizard/dropwizard-db/4.0.0/index.html) for configuring its [DataSource](http://docs.oracle.com/javase/8/docs/api/javax/sql/DataSource.html). 51 | 52 | Additionally, you can override the following configuration settings of Flyway using [FlywayFactory](https://dropwizard.github.io/dropwizard-flyway/2.0.0-1/apidocs/io/dropwizard/flyway/FlywayFactory.html): 53 | 54 | flyway: 55 | # The encoding of SQL migrations. (default: UTF-8) 56 | encoding: UTF-8 57 | 58 | # The maximum number of retries when attempting to connect to the database. (default: 0) 59 | connectRetries: 0 60 | 61 | # The maximum time between retries when attempting to connect to the database in seconds. (default: 120) 62 | connectRetriesInterval: 120 63 | 64 | # The default schema managed by Flyway. (default: the first schema listed in schemas) 65 | defaultSchema: 66 | 67 | # The schemas managed by Flyway. (default: default schema of the connection) 68 | schemas: 69 | 70 | # The fully qualified class names of the callbacks for lifecycle notifications. (default: empty list) 71 | callbacks: 72 | 73 | # The name of the schema metadata table that will be used by Flyway. (default: flyway_schema_history) 74 | metaDataTableName: flyway_schema_history 75 | 76 | # The file name prefix for sql migrations (default: V) 77 | sqlMigrationPrefix: V 78 | 79 | # The file name separator for sql migrations (default: __) 80 | sqlMigrationSeparator: __ 81 | 82 | # The file name suffixes for sql migrations (default: .sql) 83 | sqlMigrationSuffixes: 84 | - .sql 85 | 86 | # The prefix of every placeholder. (default: ${ ) 87 | placeholderPrefix: ${ 88 | 89 | # The suffix of every placeholder. (default: } ) 90 | placeholderSuffix: } 91 | 92 | # The map of to apply to sql migration scripts. (default: empty map) 93 | placeholders: 94 | 95 | # Locations to scan recursively for migrations. (default: db/migration) 96 | locations: 97 | - db/migration 98 | 99 | # The fully qualified class names of the custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. (default: empty list) 100 | resolvers: 101 | 102 | # Allows migrations to be run "out of order". If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored. (default: false) 103 | outOfOrder: false 104 | 105 | # The description to tag an existing schema with when executing baseline. (default: << Flyway Baseline >>) 106 | baselineDescription: "<< Flyway Baseline >>" 107 | 108 | # Whether to automatically call baseline when migrate is executed against a non-empty schema with no metadata table. (default: false) 109 | # Be careful when enabling this as it removes the safety net that ensures Flyway does not migrate the wrong database in case of a configuration mistake! 110 | baselineOnMigrate: false 111 | 112 | # Whether to automatically call validate or not when running migrate. (default: true) 113 | validateOnMigrate: true 114 | 115 | # The version to tag an existing schema with when executing baseline. (default: 1) 116 | baselineVersion: 1 117 | 118 | # Whether to disabled clean. (default: false) 119 | # This is especially useful for production environments where running clean can be quite a career limiting move. 120 | cleanDisabled: false 121 | 122 | # Whether to group all pending migrations together in the same transaction when applying them 123 | # (only recommended for databases with support for DDL transactions). 124 | # true if migrations should be grouped. false if they should be applied individually instead. (default: false) 125 | group: false 126 | 127 | # Ignore migrations that match this list of patterns when validating migrations. 128 | # Each pattern is of the form described type:status with * matching type or status. 129 | # Please refer to https://documentation.red-gate.com/fd/flyway-cli-and-api/configuration/parameters/flyway/ignore-migration-patterns for details. 130 | # Example: repeatable:missing,versioned:pending,*:failed (default: *:future) 131 | ignoreMigrationPatterns: 132 | - "*:future" 133 | 134 | # The username that will be recorded in the schema history table as having applied the migration. 135 | # <> for the current database user of the connection. (default: <>). 136 | installedBy: 137 | 138 | # Whether to allow mixing transactional and non-transactional statements within the same migration. 139 | # true if mixed migrations should be allowed. false if an error should be thrown instead. (default: false) 140 | mixed: false 141 | 142 | # Whether placeholders should be replaced. (default: true) 143 | placeholderReplacement: true 144 | 145 | # If set to true, default built-in callbacks (sql) are skipped and only custom callback as 146 | # defined by 'callbacks' are used. (default: false) 147 | skipDefaultCallbacks: false 148 | 149 | # If set to true, default built-in resolvers (jdbc, spring-jdbc and sql) are skipped and only custom resolvers as 150 | # defined by 'resolvers' are used. (default: false) 151 | skipDefaultResolvers: false 152 | 153 | # The map of to overwrite any existing configuration. (default: empty map) 154 | # Properties are documented here: https://documentation.red-gate.com/fd/parameters-224919673.html 155 | configuration: 156 | 157 | #### COMMERCIAL FEATURES 158 | # (Flyway Pro and Flyway Enterprise only) 159 | 160 | # Whether to batch SQL statements when executing them. (default: false) 161 | batch: false 162 | 163 | # The file where to output the SQL statements of a migration dry run. If the file specified is in a non-existent 164 | # directory, Flyway will create all directories and parent directories as needed. 165 | # <> to execute the SQL statements directly against the database. (default: <>) 166 | #dryRunOutputFile: 167 | 168 | # Comma-separated list of the fully qualified class names of handlers for errors and warnings that occur during a 169 | # migration. This can be used to customize Flyway's behavior by for example throwing another runtime exception, 170 | # outputting a warning or suppressing the error instead of throwing a FlywayException. 171 | # ErrorHandlers are invoked in order until one reports to have successfully handled the errors or warnings. 172 | # If none do, or if none are present, Flyway falls back to its default handling of errors and warnings. 173 | # <> to use the default internal handler (default: <>) 174 | #errorHandlers: 175 | 176 | # Rules for the built-in error handler that lets you override specific SQL states and errors codes from error to 177 | # warning or from warning to error. 178 | # Each error override has the following format: STATE:12345:W. It is a 5 character SQL state, a colon, the SQL 179 | # error code, a colon and finally the desired behavior that should override the initial one. The following 180 | # behaviors are accepted: W to force a warning and E to force an error. 181 | # For example, to force Oracle stored procedure compilation issues to produce errors instead of warnings, 182 | # the following errorOverride can be used: 99999:17110:E 183 | #errorOverrides: 184 | 185 | # Whether to stream SQL migrations when executing them. (default: false) 186 | stream: false 187 | 188 | # Target version up to which Flyway should consider migrations. 189 | # The special value 'current' designates the current version of the schema. (default: <>) 190 | #target: 191 | 192 | 193 | Maven Artifacts 194 | --------------- 195 | 196 | ![dropwizard-flyway 2.1.x](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway/2.1) 197 | ![dropwizard-flyway 3.0.x](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway/3.0) 198 | ![dropwizard-flyway 4.0.x](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway/4.0) 199 | 200 | This project is available on Maven Central. To add it to your project simply add the following dependencies to your `pom.xml`: 201 | 202 | 203 | io.dropwizard.modules 204 | dropwizard-flyway 205 | ${dropwizard-flyway.version} 206 | 207 | 208 | Please note that you will need to add the respective Flyway database support artifacts and configure them via the `flyway.configuration` map. 209 | 210 | Example: 211 | 212 | Add Flyway PostgreSQL dependency to your POM: 213 | 214 | 215 | org.flywaydb 216 | flyway-database-postgresql 217 | ${flyway.version} 218 | 219 | 220 | Add the configuration setting to your `flyway.configuration` block: 221 | 222 | flyway: 223 | configuration: 224 | # PostgreSQL Transactional Lock, see https://documentation.red-gate.com/fd/postgresql-transactional-lock-224919738.html 225 | flyway.postgresql.transactional.lock: false 226 | 227 | Support 228 | ------- 229 | 230 | Please file bug reports and feature requests in [GitHub issues](https://github.com/dropwizard/dropwizard-flyway/issues). 231 | 232 | 233 | License 234 | ------- 235 | 236 | Copyright (c) 2014-2024 Jochen Schalanda, Dropwizard Team 237 | 238 | This library is licensed under the Apache License, Version 2.0. 239 | 240 | See http://www.apache.org/licenses/LICENSE-2.0.html or the LICENSE file in this repository for the full license text. 241 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/FlywayFactory.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import jakarta.validation.constraints.NotBlank; 6 | import jakarta.validation.constraints.NotEmpty; 7 | import jakarta.validation.constraints.NotNull; 8 | import jakarta.validation.constraints.PositiveOrZero; 9 | import org.flywaydb.core.Flyway; 10 | import org.flywaydb.core.api.configuration.FluentConfiguration; 11 | 12 | import javax.sql.DataSource; 13 | import java.io.File; 14 | import java.nio.charset.StandardCharsets; 15 | import java.util.Collections; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | @SuppressWarnings("unused") 20 | public class FlywayFactory { 21 | @JsonProperty 22 | @NotEmpty 23 | private String encoding = StandardCharsets.UTF_8.name(); 24 | @JsonProperty 25 | @PositiveOrZero 26 | private int connectRetries = 0; 27 | @JsonProperty 28 | @PositiveOrZero 29 | private int connectRetriesInterval = 120; 30 | @JsonProperty 31 | private String defaultSchema = null; 32 | @JsonProperty 33 | @NotNull 34 | private List schemas = Collections.emptyList(); 35 | @JsonProperty 36 | @NotNull 37 | private List callbacks = Collections.emptyList(); 38 | @JsonProperty 39 | @NotEmpty 40 | private String metaDataTableName = "flyway_schema_history"; 41 | @JsonProperty 42 | @NotEmpty 43 | private String sqlMigrationPrefix = "V"; 44 | @JsonProperty 45 | @NotEmpty 46 | private String sqlMigrationSeparator = "__"; 47 | @JsonProperty 48 | @NotNull 49 | private List sqlMigrationSuffixes = Collections.singletonList(".sql"); 50 | @JsonProperty 51 | @NotEmpty 52 | private String placeholderPrefix = "${"; 53 | @JsonProperty 54 | @NotEmpty 55 | private String placeholderSuffix = "}"; 56 | @JsonProperty 57 | @NotNull 58 | private Map placeholders = Collections.emptyMap(); 59 | @JsonProperty 60 | @NotEmpty 61 | private List locations = Collections.singletonList("db/migration"); 62 | @JsonProperty 63 | @NotNull 64 | private List resolvers = Collections.emptyList(); 65 | @JsonProperty 66 | private String initSql = null; 67 | @JsonIgnore 68 | private ClassLoader classLoader = null; 69 | @JsonProperty 70 | private boolean outOfOrder = false; 71 | @JsonProperty 72 | @NotNull 73 | private String baselineDescription = "<< Flyway Baseline >>"; 74 | @JsonProperty 75 | private boolean baselineOnMigrate = false; 76 | @JsonProperty 77 | private boolean validateOnMigrate = true; 78 | @JsonProperty 79 | @NotBlank 80 | private String baseLineVersion = "1"; 81 | @JsonProperty 82 | private boolean cleanDisabled = false; 83 | @JsonProperty 84 | private boolean cleanOnValidationError = false; 85 | @JsonProperty 86 | private boolean group = false; 87 | @JsonProperty 88 | private List ignoreMigrationPatterns = Collections.singletonList("*:future"); 89 | @JsonProperty 90 | @NotNull 91 | private String installedBy = ""; 92 | @JsonProperty 93 | private boolean mixed = false; 94 | @JsonProperty 95 | private boolean placeholderReplacement = true; 96 | @JsonProperty 97 | private boolean skipDefaultCallbacks = false; 98 | @JsonProperty 99 | private boolean skipDefaultResolvers = false; 100 | 101 | // Commercial Features 102 | @JsonProperty 103 | private Boolean batch; 104 | @JsonProperty 105 | private File dryRunOutputFile; 106 | @JsonProperty 107 | private List errorOverrides; 108 | @JsonProperty 109 | private Boolean stream; 110 | @JsonProperty 111 | private String target; 112 | @JsonProperty 113 | @NotNull 114 | Map configuration = Collections.emptyMap(); 115 | 116 | /** 117 | * @see FluentConfiguration#getEncoding() 118 | */ 119 | public String getEncoding() { 120 | return encoding; 121 | } 122 | 123 | /** 124 | * @see FluentConfiguration#encoding(String) 125 | */ 126 | public void setEncoding(final String encoding) { 127 | this.encoding = encoding; 128 | } 129 | 130 | /** 131 | * @see FluentConfiguration#getConnectRetries() 132 | */ 133 | public int getConnectRetries() { 134 | return connectRetries; 135 | } 136 | 137 | /** 138 | * @see FluentConfiguration#connectRetries(int) 139 | */ 140 | public void setConnectRetries(int connectRetries) { 141 | this.connectRetries = connectRetries; 142 | } 143 | 144 | /** 145 | * @see FluentConfiguration#getConnectRetriesInterval() 146 | */ 147 | public int getConnectRetriesInterval() { 148 | return connectRetriesInterval; 149 | } 150 | 151 | /** 152 | * @see FluentConfiguration#connectRetriesInterval(int) 153 | */ 154 | public void setConnectRetriesInterval(int connectRetriesInterval) { 155 | this.connectRetriesInterval = connectRetriesInterval; 156 | } 157 | 158 | /** 159 | * @see FluentConfiguration#getDefaultSchema() 160 | */ 161 | public String getDefaultSchema() { 162 | return defaultSchema; 163 | } 164 | 165 | /** 166 | * @see FluentConfiguration#defaultSchema(String) 167 | */ 168 | public void setDefaultSchema(final String defaultSchema) { 169 | this.defaultSchema = defaultSchema; 170 | } 171 | 172 | /** 173 | * @see FluentConfiguration#getSchemas() 174 | */ 175 | public List getSchemas() { 176 | return schemas; 177 | } 178 | 179 | /** 180 | * @see FluentConfiguration#schemas(String...) 181 | */ 182 | public void setSchemas(final List schemas) { 183 | this.schemas = schemas; 184 | } 185 | 186 | /** 187 | * @see FluentConfiguration#getCallbacks() 188 | */ 189 | public List getCallbacks() { 190 | return callbacks; 191 | } 192 | 193 | /** 194 | * @see FluentConfiguration#callbacks(String...) 195 | */ 196 | public void setCallbacks(final List callbacks) { 197 | this.callbacks = callbacks; 198 | } 199 | 200 | /** 201 | * @see FluentConfiguration#getTable() 202 | */ 203 | public String getMetaDataTableName() { 204 | return metaDataTableName; 205 | } 206 | 207 | /** 208 | * @see FluentConfiguration#table(String) 209 | */ 210 | public void setMetaDataTableName(final String metaDataTableName) { 211 | this.metaDataTableName = metaDataTableName; 212 | } 213 | 214 | /** 215 | * @see FluentConfiguration#getSqlMigrationPrefix() 216 | */ 217 | public String getSqlMigrationPrefix() { 218 | return sqlMigrationPrefix; 219 | } 220 | 221 | /** 222 | * @see FluentConfiguration#sqlMigrationPrefix(String) 223 | */ 224 | public void setSqlMigrationPrefix(final String sqlMigrationPrefix) { 225 | this.sqlMigrationPrefix = sqlMigrationPrefix; 226 | } 227 | 228 | /** 229 | * @see FluentConfiguration#getSqlMigrationPrefix() 230 | */ 231 | public List getSqlMigrationSuffixes() { 232 | return sqlMigrationSuffixes; 233 | } 234 | 235 | /** 236 | * @see FluentConfiguration#sqlMigrationSuffixes(String...) 237 | */ 238 | public void setSqlMigrationSuffixes(final List sqlMigrationSuffixes) { 239 | this.sqlMigrationSuffixes = sqlMigrationSuffixes; 240 | } 241 | 242 | /** 243 | * @see FluentConfiguration#getSqlMigrationSeparator() 244 | */ 245 | public String getSqlMigrationSeparator() { 246 | return sqlMigrationSeparator; 247 | } 248 | 249 | /** 250 | * @see FluentConfiguration#sqlMigrationSeparator(String) 251 | */ 252 | public void setSqlMigrationSeparator(final String sqlMigrationSeparator) { 253 | this.sqlMigrationSeparator = sqlMigrationSeparator; 254 | } 255 | 256 | /** 257 | * @see FluentConfiguration#getPlaceholderPrefix() 258 | */ 259 | public String getPlaceholderPrefix() { 260 | return placeholderPrefix; 261 | } 262 | 263 | /** 264 | * @see FluentConfiguration#placeholderPrefix(String) 265 | */ 266 | public void setPlaceholderPrefix(final String placeholderPrefix) { 267 | this.placeholderPrefix = placeholderPrefix; 268 | } 269 | 270 | /** 271 | * @see FluentConfiguration#getPlaceholderSuffix() 272 | */ 273 | public String getPlaceholderSuffix() { 274 | return placeholderSuffix; 275 | } 276 | 277 | /** 278 | * @see FluentConfiguration#placeholderSuffix(String) 279 | */ 280 | public void setPlaceholderSuffix(final String placeholderSuffix) { 281 | this.placeholderSuffix = placeholderSuffix; 282 | } 283 | 284 | /** 285 | * @see FluentConfiguration#getPlaceholders() 286 | */ 287 | public Map getPlaceholders() { 288 | return placeholders; 289 | } 290 | 291 | /** 292 | * @see FluentConfiguration#placeholders(Map) 293 | */ 294 | public void setPlaceholders(final Map placeholders) { 295 | this.placeholders = placeholders; 296 | } 297 | 298 | /** 299 | * @see FluentConfiguration#getLocations() 300 | */ 301 | public List getLocations() { 302 | return locations; 303 | } 304 | 305 | /** 306 | * @see FluentConfiguration#locations(String...) 307 | */ 308 | public void setLocations(final List locations) { 309 | this.locations = locations; 310 | } 311 | 312 | /** 313 | * @see FluentConfiguration#getResolvers() 314 | */ 315 | public List getResolvers() { 316 | return resolvers; 317 | } 318 | 319 | /** 320 | * @see FluentConfiguration#resolvers(String...) 321 | */ 322 | public void setResolvers(final List resolvers) { 323 | this.resolvers = resolvers; 324 | } 325 | 326 | /** 327 | * @see FluentConfiguration#getInitSql() 328 | */ 329 | public String getInitSql() { 330 | return initSql; 331 | } 332 | 333 | /** 334 | * @see FluentConfiguration#initSql(String) 335 | */ 336 | public void setInitSql(String initSql) { 337 | this.initSql = initSql; 338 | } 339 | 340 | /** 341 | * @see FluentConfiguration#getClassLoader() 342 | */ 343 | public ClassLoader getClassLoader() { 344 | return classLoader; 345 | } 346 | 347 | /** 348 | * @see FluentConfiguration#FluentConfiguration(ClassLoader) 349 | */ 350 | public void setClassLoader(ClassLoader classLoader) { 351 | this.classLoader = classLoader; 352 | } 353 | 354 | /** 355 | * @see FluentConfiguration#isOutOfOrder() 356 | */ 357 | public boolean isOutOfOrder() { 358 | return outOfOrder; 359 | } 360 | 361 | /** 362 | * @see FluentConfiguration#outOfOrder(boolean) 363 | */ 364 | public void setOutOfOrder(boolean outOfOrder) { 365 | this.outOfOrder = outOfOrder; 366 | } 367 | 368 | /** 369 | * @see FluentConfiguration#getBaselineDescription() 370 | */ 371 | public String getBaselineDescription() { 372 | return baselineDescription; 373 | } 374 | 375 | /** 376 | * @see FluentConfiguration#baselineDescription(String) 377 | */ 378 | public void setBaselineDescription(String baselineDescription) { 379 | this.baselineDescription = baselineDescription; 380 | } 381 | 382 | /** 383 | * @see FluentConfiguration#isBaselineOnMigrate() 384 | */ 385 | public boolean isBaselineOnMigrate() { 386 | return baselineOnMigrate; 387 | } 388 | 389 | /** 390 | * @see FluentConfiguration#baselineOnMigrate(boolean) 391 | */ 392 | public void setBaselineOnMigrate(boolean baselineOnMigrate) { 393 | this.baselineOnMigrate = baselineOnMigrate; 394 | } 395 | 396 | /** 397 | * @see FluentConfiguration#isValidateOnMigrate() 398 | */ 399 | public boolean isValidateOnMigrate() { 400 | return validateOnMigrate; 401 | } 402 | 403 | /** 404 | * @see FluentConfiguration#validateOnMigrate(boolean) 405 | */ 406 | public void setValidateOnMigrate(boolean validateOnMigrate) { 407 | this.validateOnMigrate = validateOnMigrate; 408 | } 409 | 410 | /** 411 | * @see FluentConfiguration#getBaselineVersion() 412 | */ 413 | public String getBaseLineVersion() { 414 | return baseLineVersion; 415 | } 416 | 417 | /** 418 | * @see FluentConfiguration#baselineVersion(String) 419 | */ 420 | public void setBaseLineVersion(String baseLineVersion) { 421 | this.baseLineVersion = baseLineVersion; 422 | } 423 | 424 | /** 425 | * @see FluentConfiguration#isCleanDisabled() 426 | */ 427 | public boolean isCleanDisabled() { 428 | return cleanDisabled; 429 | } 430 | 431 | /** 432 | * @see FluentConfiguration#cleanDisabled(boolean) 433 | */ 434 | public void setCleanDisabled(boolean cleanDisabled) { 435 | this.cleanDisabled = cleanDisabled; 436 | } 437 | 438 | /** 439 | * @see FluentConfiguration#isCleanOnValidationError() 440 | */ 441 | public boolean isCleanOnValidationError() { 442 | return cleanOnValidationError; 443 | } 444 | 445 | /** 446 | * @see FluentConfiguration#cleanOnValidationError(boolean) 447 | */ 448 | public void setCleanOnValidationError(boolean cleanOnValidationError) { 449 | this.cleanOnValidationError = cleanOnValidationError; 450 | } 451 | 452 | /** 453 | * @see FluentConfiguration#isGroup() 454 | */ 455 | public boolean isGroup() { 456 | return group; 457 | } 458 | 459 | /** 460 | * @see FluentConfiguration#group(boolean) 461 | */ 462 | public void setGroup(boolean group) { 463 | this.group = group; 464 | } 465 | 466 | /** 467 | * @see FluentConfiguration#getIgnoreMigrationPatterns() 468 | */ 469 | public List getIgnoreMigrationPatterns() { 470 | return ignoreMigrationPatterns; 471 | } 472 | 473 | /** 474 | * @see FluentConfiguration#ignoreMigrationPatterns(String...) 475 | */ 476 | public void setIgnoreMigrationPatterns(final List ignoreMigrationPatterns) { 477 | this.ignoreMigrationPatterns = ignoreMigrationPatterns; 478 | } 479 | 480 | /** 481 | * @see FluentConfiguration#getInstalledBy() 482 | */ 483 | public String getInstalledBy() { 484 | return installedBy; 485 | } 486 | 487 | /** 488 | * @see FluentConfiguration#installedBy(String) 489 | */ 490 | public void setInstalledBy(String installedBy) { 491 | this.installedBy = installedBy; 492 | } 493 | 494 | /** 495 | * @see FluentConfiguration#isMixed() 496 | */ 497 | public boolean isMixed() { 498 | return mixed; 499 | } 500 | 501 | /** 502 | * @see FluentConfiguration#mixed(boolean) 503 | */ 504 | public void setMixed(boolean mixed) { 505 | this.mixed = mixed; 506 | } 507 | 508 | /** 509 | * @see FluentConfiguration#isPlaceholderReplacement() 510 | */ 511 | public boolean isPlaceholderReplacement() { 512 | return placeholderReplacement; 513 | } 514 | 515 | /** 516 | * @see FluentConfiguration#placeholderReplacement(boolean) 517 | */ 518 | public void setPlaceholderReplacement(boolean placeholderReplacement) { 519 | this.placeholderReplacement = placeholderReplacement; 520 | } 521 | 522 | /** 523 | * @see FluentConfiguration#isSkipDefaultCallbacks() 524 | */ 525 | public boolean isSkipDefaultCallbacks() { 526 | return skipDefaultCallbacks; 527 | } 528 | 529 | /** 530 | * @see FluentConfiguration#skipDefaultCallbacks(boolean) 531 | */ 532 | public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) { 533 | this.skipDefaultCallbacks = skipDefaultCallbacks; 534 | } 535 | 536 | /** 537 | * @see FluentConfiguration#isSkipDefaultResolvers() 538 | */ 539 | public boolean isSkipDefaultResolvers() { 540 | return skipDefaultResolvers; 541 | } 542 | 543 | /** 544 | * @see FluentConfiguration#skipDefaultResolvers(boolean) 545 | */ 546 | public void setSkipDefaultResolvers(boolean skipDefaultResolvers) { 547 | this.skipDefaultResolvers = skipDefaultResolvers; 548 | } 549 | 550 | // Commercial Features 551 | 552 | /** 553 | * @see FluentConfiguration#isBatch() 554 | */ 555 | public Boolean isBatch() { 556 | return batch; 557 | } 558 | 559 | /** 560 | * @see FluentConfiguration#batch(boolean) 561 | */ 562 | public void setBatch(Boolean batch) { 563 | this.batch = batch; 564 | } 565 | 566 | /** 567 | * @see FluentConfiguration#getDryRunOutput() 568 | */ 569 | public File getDryRunOutputFile() { 570 | return dryRunOutputFile; 571 | } 572 | 573 | /** 574 | * @see FluentConfiguration#dryRunOutput(File) 575 | */ 576 | public void setDryRunOutputFile(File dryRunOutputFile) { 577 | this.dryRunOutputFile = dryRunOutputFile; 578 | } 579 | 580 | /** 581 | * @see FluentConfiguration#getErrorOverrides() 582 | */ 583 | public List getErrorOverrides() { 584 | return errorOverrides; 585 | } 586 | 587 | /** 588 | * @see FluentConfiguration#errorOverrides(String...) 589 | */ 590 | public void setErrorOverrides(List errorOverrides) { 591 | this.errorOverrides = errorOverrides; 592 | } 593 | 594 | /** 595 | * @see FluentConfiguration#isStream() 596 | */ 597 | public Boolean isStream() { 598 | return stream; 599 | } 600 | 601 | /** 602 | * @see FluentConfiguration#stream(boolean) 603 | */ 604 | public void setStream(Boolean stream) { 605 | this.stream = stream; 606 | } 607 | 608 | /** 609 | * @see FluentConfiguration#getTarget() 610 | */ 611 | public String getTarget() { 612 | return target; 613 | } 614 | 615 | /** 616 | * @see FluentConfiguration#target(String) 617 | */ 618 | public void setTarget(String target) { 619 | this.target = target; 620 | } 621 | 622 | /** 623 | * @see FluentConfiguration#configuration(Map) 624 | */ 625 | public Map getConfiguration() { 626 | return configuration; 627 | } 628 | 629 | /** 630 | * Configures Flyway with these properties. 631 | * This overwrites any existing configuration. 632 | * 633 | * @see Configuration parameters 634 | */ 635 | public void setConfiguration(Map configuration) { 636 | this.configuration = configuration; 637 | } 638 | 639 | public Flyway build(final String url, final String user, final String password) { 640 | return createConfiguration().dataSource(url, user, password).load(); 641 | } 642 | 643 | public Flyway build(final DataSource dataSource) { 644 | return createConfiguration().dataSource(dataSource).load(); 645 | } 646 | 647 | private FluentConfiguration createConfiguration() { 648 | final String[] emptyStringArray = new String[0]; 649 | FluentConfiguration flyway = classLoader == null ? Flyway.configure() : Flyway.configure(classLoader); 650 | flyway = flyway 651 | .baselineOnMigrate(baselineOnMigrate) 652 | .baselineVersion(baseLineVersion) 653 | .callbacks(callbacks.toArray(emptyStringArray)) 654 | .cleanDisabled(cleanDisabled) 655 | .cleanOnValidationError(cleanOnValidationError) 656 | .configuration(configuration) 657 | .connectRetries(connectRetries) 658 | .connectRetriesInterval(connectRetriesInterval) 659 | .encoding(encoding) 660 | .group(group) 661 | .ignoreMigrationPatterns(ignoreMigrationPatterns.toArray(emptyStringArray)) 662 | .installedBy(installedBy) 663 | .locations(locations.toArray(emptyStringArray)) 664 | .mixed(mixed) 665 | .outOfOrder(outOfOrder) 666 | .placeholderPrefix(placeholderPrefix) 667 | .placeholderReplacement(placeholderReplacement) 668 | .placeholderSuffix(placeholderSuffix) 669 | .placeholders(placeholders) 670 | .resolvers(resolvers.toArray(emptyStringArray)) 671 | .initSql(initSql) 672 | .schemas(schemas.toArray(emptyStringArray)) 673 | .skipDefaultCallbacks(skipDefaultCallbacks) 674 | .skipDefaultResolvers(skipDefaultResolvers) 675 | .sqlMigrationPrefix(sqlMigrationPrefix) 676 | .sqlMigrationSeparator(sqlMigrationSeparator) 677 | .sqlMigrationSuffixes(sqlMigrationSuffixes.toArray(emptyStringArray)) 678 | .table(metaDataTableName) 679 | .validateOnMigrate(validateOnMigrate); 680 | 681 | if (defaultSchema != null) { 682 | flyway.defaultSchema(defaultSchema); 683 | } 684 | 685 | // Commercial features 686 | if (batch != null) { 687 | flyway.batch(batch); 688 | } 689 | if (dryRunOutputFile != null) { 690 | flyway.dryRunOutput(dryRunOutputFile); 691 | } 692 | if (errorOverrides != null) { 693 | flyway.errorOverrides(errorOverrides.toArray(emptyStringArray)); 694 | } 695 | if (stream != null) { 696 | flyway.stream(stream); 697 | } 698 | if (target != null) { 699 | flyway.target(target); 700 | } 701 | 702 | return flyway; 703 | } 704 | } 705 | --------------------------------------------------------------------------------