flyway: Java Migrations are scanned, found but then ignored
Which version and edition of Flyway are you using?
Community Edition Flyway 6.0.0 (but I experienced the problem with 5.2.0 and 5.2.4 and 6.0.0-beta2)
If this is not the latest version, can you reproduce the issue with the latest one as well?
(Many bugs are fixed in newer releases and upgrading will often resolve the issue) It’s the last version when I’m writing the issue.
Which client are you using? (Command-line, Java API, Maven plugin, Gradle plugin)
Gradle Plugin. I experienced the problem with Gradle 4.9, and now with Gradle 5.4.1
Which database are you using (type & version)?
Oracle 18c
Which operating system are you using?
Centos 7
What did you do?
(Please include the content causing the issue, any relevant configuration settings, the SQL statement that failed (if relevant) and the command you ran.)
I’m running flywayInfo, or flywayMigrate, and I see that flyway knows about my SQL migrations, but ignores completely my Java migrations. It’s like they don’t exist.
When I run with debug logs, or attach a debugger to the gradle task execution, I see that the classes are scanned properly, and actually added to the classes list in the Scanner. But when the code reaches Scanner.getClasses, the statement if (!implementedInterface.isAssignableFrom(clazz)) { is returning false for all my classes. implementedInterface is org.flywaydb.core.api.migration.JavaMigration, and clazz is my class, e.g. cern.acctesting.db.migrations.base.V1_1__InsertEnum
V1_1__InsertEnum is declared the following way
import org.flywaydb.core.api.migration.BaseJavaMigration;
...
public class V1_1__InsertEnum extends BaseJavaMigration {
...
What did you expect to see?
I expect my classes to be assignable from the JavaMigration interface, and flywayInfo to take them into account and flywayMigrate to apply them.
What did you see instead?
I cannot run my migrations and my classes seem not to be assignableFrom JavaMigration.
It seems to be a problem with the ClassLoader maybe. Because a simple unit test like this is fine
@Test
public void isAssignableFrom(){
assertTrue(JavaMigration.class.isAssignableFrom(V1_1__InsertEnum.class));
}
I tried the command line tool, after producing a jar containing my migrations. It’s even more confusing because some Java migrations are recognized (e.g. V1_1__InsertEnum is ok), but others are not, while all are configured the smae.
Thank you for your help Jc ps: here is a confused and confusing post I put on stackoverflow a while ago, maybe it will give you some hints: https://stackoverflow.com/questions/57311404/most-but-not-all-java-flyway-migrations-are-skipped
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 23
I am having this issue. Starting up the spring server applies jdbc migrations, but running
gradle flywayInfosays they are in the missing or future state.If I run
gradle flywayCleanthengradle flywayInfothen I see only the SQL migrations detected and pendingIf I run
gradle flywayMigratethengradle flywayInfothen I see only the SQL migrations were applied. JDBC migrations are totally ignored.Thank you for your precious help @alextercete, I would not have made it without you! Greetings Jc
@alextercete It seems you got a good lead with the
apply from!With the project that you attached, I have no issue, until I do the
apply from.For instance here is what you can do: Here’s the content of the build.gradle:
Here’s the content of the src/flyway.gradle:
And I can reproduce the issue this way in both multi and non-multi project.
@jcgarnier Thanks for all your help so far, I think we’re getting to the bottom of it.
It looks like this StackOverflow answer explains this behaviour, particularly in this [slightly modified] bit:
My hypothesis is that there are two class loaders in play and that the one we’re getting from Gradle doesn’t have the “current” class loader as its parent, and that’s why the
isAssignableFromcheck fails. I’ll do some debugging to test this.This is what I expect:
Then the ClassPathScanner behaves as expected (the delay in time is because I attached a debugger to the gradle process):
And the classes are added to the Scanner.classes field:
But later they’re filtered out: