I've first seen this when trying to build a native SB image 3.2.1 with flyway-core:10.4.1. Flyway Autoconfigure NativeImageResourceProviderCustomizer (code link) creates a custom org.flywaydb.core.api.ResourceProvider using a org.flywaydb.core.internal.scanner.Scanner.

The constructor for Scanner has changed between version 9 and 10, whereby the former accepted more arguments.

The code:

Scanner<JavaMigration> scanner = new Scanner<>(JavaMigration.class,
                    Arrays.asList(configuration.getLocations()), configuration.getClassLoader(),
                    configuration.getEncoding(), configuration.isDetectEncoding(), false, new ResourceNameCache(),
                    new LocationScannerCache(), configuration.isFailOnMissingLocations());

should be replaced with

Scanner<JavaMigration> scanner = new Scanner<>(
     JavaMigration.class,                   // Class<I> implementedInterface
     false,                                            // boolean stream
     new ResourceNameCache(),    // ResourceNameCache resourceNameCache
     new LocationScannerCache(), // LocationScannerCache locationScannerCache
     configuration                              // Configuration configuration [FluentConfiguration provided will do]                   
);

I can make the change for this in SB, however, how should Flyway 9 be handled?

Comment From: goverdhan07

@UbiquitousBear - I was wondering if we could introduce a condition wherein if the flyway version is >= 10 use the newer constructor and if version == 9 use the older constructor that accepts more arguments. let me know what you think?

Comment From: MazizEsa

Is it open for contribution? I am interested to work on this.

Comment From: wilkinsona

Thanks, @MazizEsa. It's all yours.

Comment From: MazizEsa

@wilkinsona thanks. Which branch I should merge fix to?

Comment From: scottfrederick

@MazizEsa If you want to submit the changes to the 3.1.x branch, we can merge it there and then merge forward to other branches. It's also fine if you submit the change to main, and we can rebase it to 3.1.x ourselves.

Comment From: MazizEsa

Got it @scottfrederick . Thanks!

Comment From: wilkinsona

How's it going, @MazizEsa?

Comment From: MazizEsa

Hi @wilkinsona . Was busy this past weeks. Ill be able to get to it this week. My apologies.

Comment From: MazizEsa

@scottfrederick @wilkinsona I just noticed there's a push to fix this already? by @wilkinsona . On 19 March, a65e1018f08b76d2c9769d2d266567f3a9f4d589, origin/main

SpringBoot Flyway auto-configuration does not work with Flyway 10 when using GraalVM

Is this sufficient for this ticket, or a mechanism to handle both cases (9 and 10) is needed?

Comment From: wilkinsona

mechanism to handle both cases (9 and 10) is needed?

Yes, it's needed on 3.2.x.

https://github.com/spring-projects/spring-boot/commit/a65e1018f08b76d2c9769d2d266567f3a9f4d589 is only on main where we required Flyway 10. For 3.2.x, we use Flyway 9.x by default but we also try to support Flyway 10 when a user manually upgrades the dependency.

Comment From: MazizEsa

@wilkinsona want to run by you here before I begin implementation. Im working from main branch.

  1. I will put condition for the 2 dependencies added for 10 (postgres and hsqldb) (condition to check the flyway version)
  2. The postgres package core vs without core we'll it up to the user.
  3. org.springframework.boot.autoconfigure.flyway.NativeImageResourceProviderCustomizer we'll it up to the user as well.

What do you think?

Comment From: wilkinsona

I will put condition for the 2 dependencies added for 10 (postgres and hsqldb) (condition to check the flyway version)

To detect Flyway 10, a class from flyway-core that was added in 10.0 should be used. We can't rely on classes in other modules as they may not be in use. org.flywaydb.core.extensibility.Tier is one possibility.

Once we've detected Flyway 10, we then need to use reflection to create the Scanner instance to tolerate the change in its constructor arguments. For Flyway 9, the code would remain as it currently is. For Flyway 10, we'd use reflection.

You can test your changes with a new test class that looks something like this:

package org.springframework.boot.autoconfigure.flyway;

import java.util.Collection;

import org.flywaydb.core.api.ResourceProvider;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.flywaydb.core.api.resource.LoadableResource;
import org.junit.jupiter.api.Test;

import org.springframework.boot.testsupport.classpath.ClassPathOverrides;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Tests for {@link NativeImageResourceProviderCustomizer} with Flyway 10.
 *
 * @author Moritz Halbritter
 * @author Andy Wilkinson
 */
@ClassPathOverrides("org.flywaydb:flyway-core:10.12.0")
class Flyway10NativeImageResourceProviderCustomizerTests {

    private final NativeImageResourceProviderCustomizer customizer = new NativeImageResourceProviderCustomizer();

    @Test
    void nativeImageResourceProviderShouldFindMigrations() {
        FluentConfiguration configuration = new FluentConfiguration();
        this.customizer.customize(configuration);
        ResourceProvider resourceProvider = configuration.getResourceProvider();
        Collection<LoadableResource> migrations = resourceProvider.getResources("V", new String[] { ".sql" });
        LoadableResource migration = resourceProvider.getResource("V1__init.sql");
        assertThat(migrations).containsExactly(migration);
    }

}

If this test passes (it fails at the moment with a NoSuchMethodError) and NativeImageResourceProviderCustomizerTests continues to pass with the default Flyway 9.x then that'll be a strong indication that the changes are good.

Comment From: wilkinsona

Closing in favor of #40821.