micronaut-projects / micronaut-flyway

Integration between Micronaut and Flyway
Apache License 2.0
38 stars 21 forks source link

Flyway migration fails in native #281

Closed GeitV closed 2 years ago

GeitV commented 2 years ago

Expected Behavior

When running native deployment, we expect to see that Flyway migrations are successfully runned.

Actual Behaviour

When starting app in native, flyway migration fails (runs successfully in normal mode).

The folder structure is src/main/resources/db/migration/2021 (we separate migration scripts by year, so we don't have long list of migration files to scroll through in IDE) and I feel like this structure is what messes it up. When looking in logs, the year part of folder structure seems to be gone in native deploy:

io.micronaut.context.exceptions.BeanInstantiationException: Bean definition [javax.sql.DataSource] could not be loaded: Unable to obtain inputstream for resource: db/migration/V202112101316__add_transactions_table.sql
    at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1938)
    at io.micronaut.context.DefaultApplicationContext.initializeContext(DefaultApplicationContext.java:237)
    at io.micronaut.context.DefaultBeanContext.readAllBeanDefinitionClasses(DefaultBeanContext.java:3453)
...
Caused by: org.flywaydb.core.api.FlywayException: Unable to obtain inputstream for resource: db/migration/V202112101316__add_transactions_table.sql
    at org.flywaydb.core.internal.resource.classpath.ClassPathResource.read(ClassPathResource.java:118)
    at org.flywaydb.core.internal.resolver.ChecksumCalculator.calculateChecksumForResource(ChecksumCalculator.java:64)
...

Have tried to explicitly set the folder in graalVM properties as is said in Micronaut Flyway Guide, but this really did nothing. Setting flyway and graalVM folders to classpath:db/migration/2021 and 2022 respectively gave error "public" has version 202202091124, but no migration could be resolved in the configured locations !

Only fix was to remove foldering inside db/migrations and that did the trick. But I'd still really love to use foldering, and I believe I might not be the only one.

Steps To Reproduce

Environment Information

Example Application

No response

Version

5.1.2 (micronaut 3.3.0)

shingjo commented 2 years ago

@GeitV Is this happening with Flyway + MySQL?

If yes, workaround:

Create file in your: src/main/resources/META-INF/native-image/org.flywaydb/flyway-mysql/native-image.properties

Add the following in the file: Args = -H:IncludeResources=org/flywaydb/database/version.txt

GeitV commented 2 years ago

@shingjo forgot to mention that I'm using Flyway + Postgres

If there's workaround for Postgres as well, then I'd love to use it for time being

shingjo commented 2 years ago

@GeitV My bad, miss read your issue last night.

When you say "Setting flyway and graalVM folders to classpath:db/migration/2021 and 2022 respectively".

I gather you mean that you have something like this in your application.yml:

flyway:
  datasources:
    default:
      enabled: true
      locations:
      - classpath:db/migration/2021
      - classpath:db/migration/2022

And this in your build.gradle:

graalvmNative {
    binaries {
        main {
            buildArgs.add('-Dflyway.locations=classpath:db/migration/2021,classpath:db/migration/2022')
            buildArgs.add('--verbose') //Remove after debugging if you want
        }
    }
}

Note the lack of quotes inside the flyway argument string.

With verbose you can verify that nativeCompile output has:

-Dflyway.locations=classpath:db/migration/2021,classpath:db/migration/2022 \

And not something like: '-Dflyway.locations="classpath:db/migration/2021,classpath:db/migration/2022"' or '-Dflyway.locations='"'"'classpath:db/migration/2021,classpath:db/migration/2022'"'"''

GeitV commented 2 years ago

Hey, thanks for working this out with me :)

I re-tested this configuration I only set build.gradle.kts (didn't add flyway locations in config, as it seems like flyway can handle them just fine, as long as they are inside db/migrations)

graalvmNative {
    binaries {
        getByName("main") {
            verbose.set(true)
            buildArgs.add("-Dflyway.locations=classpath:db/migration/2021,classpath:db/migration/2022")
        }
    }
}

And I can confirm, now the output is -Dflyway.locations=classpath:db/migration/2021,classpath:db/migration/2022] and this worked as intended! Thanks

However, as said, flyway can handle folders inside db/migration just fine. As in this project documentation, db/migration is already added as flyway locations. Could that folder be added so any subfolders in there could be included automatically as well? (eg. wildcards?)

I tried to add wildcard in -Dflyway.locations but this did not work. I'm just feeling that when 2023 comes, I have forgotten that after creating a new folder, I need to add it to graalVM arguments as well.

shingjo commented 2 years ago

The buildArgs.add("-flyway.locations=...") is passed directly to GraalVM and is outside of the Micronaut framework.

With Gradle, you can generate the folder locations yourself.

As in buildArgs.add(generateFlywayLocations())

GeitV commented 2 years ago

That works, didn't think about it before. I really do appreciate your help, @shingjo 👍🏻

As I think there's nothing to fix, then we can close this issue. Hopefully this thread can be helpful for anyone else experiencing the same thing.