The property spring.flyway.locations sets the location of resources for Flyway migrations.

This is ignored for Fixed Java Migrations, when they come via FlywayAutoConfiguration.

FlywayAutoConfiguration sets all Spring Beans from the current Application Context into the Flyway Configuration regardless of the given Locations settings.

Release: 2.3.1.RELEASE

Example

There are two Java packages with Flyway Java Migration classes: - db.migration1 - db.migration2

The former contains a Spring Component, the latter not.

Setting the property spring.flyway.locations to classpath:db/migration1 will result to execution of only Migrations from the package db.migration1 - that's correct.

On the other hand, setting the property spring.flyway.locations to classpath:db/migration1 will result to execution of only Migrations from both packages db.migration1 and db.migration2 as well - that's incorrect.

Demo Code

https://github.com/ttulka/spring-boot-samples/tree/master/flyway-fixed-java-migrations-bug

Comment From: wilkinsona

Thanks for the report and sample.

As noted in the documentation, " Flyway will be auto-configured with any beans that implement JavaMigration". You have component-scanned both db/migration1 and db/migration2. The db.migration1 package contains V1_0__test_spring_bean which is a @Component so it becomes a bean in the application context and it is registered with Flyway. spring.flyway.location configures Flyway's own migration discovery and has no effect on component scanning and the registration of components as beans in the context. In short, this is working as intended and as described in the documentation.

You haven't described your use case, but if you would like finer control over the migrations that Flyway uses, you should do that by controlling whether or not V1_0__test_spring_bean is registered in the context. One way to achieve that is by using profiles and @Profile to include or exclude V1_0__test_spring_bean from the context's beans as required.

Comment From: ttulka

Many thanks for the reply!

this is working as intended and as described in the documentation

Is there any intention to improve it?

My use-case: I have multiple schemas to be migrated in a particular order, one by one. To achieve that I'm using my own implementation of FlywayMigrationStrategy. This will create new FlywayConfig and Flyway instances per schema and call the method migrate() upon them. Every instance has a single different schema and location per schema, eg. classpath:db/migration/schema1 for schema1, classpath:db/migration/schema2 for schema2 etc. Everything works fine except the migrations which are registered as Beans in Spring Context (because they need access to another beans). Those migrations are executed multiple times, exactly once per every migrate() call regardless the configuration (location setting).

To control if the bean is registered or not doesn't seem to be applicable. Is there any other way in the current Spring Boot?

Comment From: ttulka

One way would be to filter the Java Migration in the config, similar as follows:

flywayConfig.javaMigrations(Arrays.stream(flywayConfig.getJavaMigrations())
    .filter(jm -> jm.getClass().getPackageName().endsWith(schema))
    .toArray(JavaMigration[]::new));

It's unfortunatelly pretty hacky :)

Comment From: wilkinsona

To achieve that I'm using my own implementation of FlywayMigrationStrategy. This will create new FlywayConfig and Flyway instances per schema and call the method migrate() upon them.

The FlywayMigrationStrategy is intended to control how the auto-configured Flyway instance is migrated. It's not really being used as intended if you are creating new Flyway instances when it is called.

As you are creating your own Flyway instances already, I suspect that the auto-configuration isn't providing much value. It is aimed at the typical situation where there's a single DataSource that needs to be migrated with that migration being handled by a single Flyway instance. If you need to work with multiple Flyway instances to satisfy your ordering requirements, I would exclude FlywayAutoConfiguration or define your own Flyway bean (that will cause the auto-configuration to back off) and do everything yourself.

Comment From: ttulka

Thanks, I'm happy with this :-)