I'm trying to configure where/how to find the flyway callbacks using the FlywayConfigurationCustomizer with something like the following.

configuration.callbacks("db");

On debugging why this was not working I saw that FlywayAutoConfiguration seems to be overwriting any changes to the list of callbacks that may have been made by a FlywayConfigurationCustomizer.

Starting with the code here FlywayAutoConfiguration.java#L120 it seems that:

  1. FlywayAutoConfiguration: auto discovered spring components that implement Callback are used to configure flyway.
  2. My customizer: configures the flyway callbacks.
  3. FlywayAutoConfiguration: replaces list of callbacks with the same list from 1.

Incidentally, it seems to do this by calling two differently named methods that have exactly the same content configureCallbacks and configureFlywayCallbacks.

Spring Boot: 2.7.0

Comment From: wilkinsona

Thanks for the report, @oliverhenlich.

Incidentally, it seems to do this by calling two differently named methods that have exactly the same content configureCallbacks and configureFlywayCallbacks.

This looks like a hangover from when Flyway had both Callback and FlywayCallback interfaces and when FlywayCallback was removed we didn't clean things up properly.

Out of interest, why are you mixing Callback beans and configuring the callbacks using a FlywayConfigurationCustomizer? When both are involved, one is always going to overwrite the other.

Comment From: oliverhenlich

Thanks @wilkinsona,

What I was trying to do was make instances of our JavaMigrations implement Callback. Since they are not spring components I wanted to let flyway scan for them (which works when you do something like configuration.callbacks("db");) but also preserve a generic spring component that also implemented Callabck.

It's not blocking me right now, I've worked around it but would be good if it didn't silently overwrite callbacks :)

Comment From: wilkinsona

preserve a generic spring component that also implemented Callback

Unfortunately, this isn't possible due to the way that FluentConfiguration is implemented. The methods in question are:

  • org.flywaydb.core.api.configuration.FluentConfiguration.callbacks(Callback...)
  • org.flywaydb.core.api.configuration.FluentConfiguration.callbacks(String...)

The Callback... variant calls ClassicConfiguration.setCallbacks(Callback...) and the String... variant calls setCallbacksAsClassNames(String...). Both of these methods call this.callbacks.clear() and then set the callbacks. As far as I can tell, this means that you can't have both your Spring component that implements Callback and callbacks found by scanning your db package configured at the same time.

… I've worked around it but would be good if it didn't silently overwrite callbacks

Ideally, any FlywayConfigurationCustomizer beans would be called after the auto-configuration has made all its changes to FluentConfiguration. I don't think we can change that in a maintenance release as there's a chance that someone's relying on the current behavior. We may be able to log a warning now and then tidy thing up in 3.0. The unfortunate hangover from Callback and FlywayCallback will complicate that a bit though.

I'll flag this for a team meeting so that we can discuss it and figure out what to do.