Search code examples
spring-bootflyway

Run Flyway migrate with spring boot explicitly


I have a spring boot based application that I want to run Flyway migrations on. The app needs to run the flyway migrate only under certain circumstances. For instance if the "migrate" argument is passed to Main().

There also are 2 different Datasources that need to be migrated.

@SpringBootApplication
public class ExampleMain implements CommandLineRunner {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ExampleMain.class)
                                    .web(WebApplicationType.NONE)
                                    .run(args);
    }

    @Override
    public void run(String... args) throws Exception {
        if (args[0].equals("migrate"))
            migrate();
        else
            System.out.println("The world is round");
    }
    
    private void migrate() {
        createFlywayForDb1().migrate();
        createFlywayForDb2().migrate();
    }
    
    private Flyway createFlywayForDb1() {
        return createFlyway("XXX", "XXX", "XXX", new String[] { "classpath:com/example/migrations/db1" } );
    }
    private Flyway createFlywayForDb2() {
        return createFlyway("ZZZ", "ZZZ", "ZZZ", new String[] { "classpath:com/example/migrations/db2" } );
    }
    
    private Flyway createFlyway(String url, String userName, String userPassword, String[] locations) {
        return Flyway.configure()
                .dataSource(url, userName, userPassword)
                .locations(locations)
                .ignoreMissingMigrations(true)
                .ignoreIgnoredMigrations(true)
                .load();
    }
}

The Flyway.migrate() won't work in this case because the Java migration classes need their spring boot beans injected. Is there some way to Autoload a Flyway instance?

I've read this but can't find a way to do the above. Any help would be greatly appreciated!


Solution

  • First, you need to stop Spring Boot from executing Flyway migrations on startup. If you define a bean implementing FlywayMigrationStrategy, then Spring Boot will invoke that bean instead of directly invoking Flyway to execute the migrations. The implementation will not actually execute the migrations.

    @Bean
    public FlywayMigrationStrategy noopFlywayMigrationStrategy() {
      return flyway -> System.out.println("I'm not migrating right now.");
    }
    

    Spring Boot auto-configures a Flyway bean which you can inject into you application. Invoke the migrate method on that bean to execute the migrations.

    @SpringBootApplication
    public class ExampleMain implements CommandLineRunner {
    
      @Autowired
      private Flyway flyway;
        
      @Override
      public void run(String... args) throws Exception {
        if (args[0].equals("migrate")) {
          flyway.migrate();
        }
      }
    
      public static void main(String[] args) {
        new SpringApplicationBuilder(ExampleMain.class)
            .web(WebApplicationType.NONE)
            .run(args);
      }
    }