Wrapped data sources, such as OpenTelemetryDataSource are not detected correctly for flyway, because they are not unwrapped.
As a workaround, you can do this following. It seems to work, but it would be better to generalize the idea of unwrapping. Maybe try to unwrap all data sources? The workaround is based on this unwrap call.
public class MyOpenTelemetryDataSource extends OpenTelemetryDataSource
implements EmbeddedDatabase {
public ObservabilitySdkDataSource(DataSource delegate) {
super(delegate);
}
@Override
public void shutdown() {
// this is not an embedded database, this is just a workaround be able to unwrap the database for flyway
}
}
Without this workaround you get the following exception:
at org.springframework.boot.jdbc.UnsupportedDataSourcePropertyException.throwIf(UnsupportedDataSourcePropertyException.java:36) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.jdbc.DataSourceBuilder$ReflectionDataSourceProperties.getMethod(DataSourceBuilder.java:560) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.jdbc.DataSourceBuilder$ReflectionDataSourceProperties.get(DataSourceBuilder.java:550) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.jdbc.DataSourceBuilder.build(DataSourceBuilder.java:178) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration.getMigrationDataSource(FlywayAutoConfiguration.java:150) ~[spring-boot-autoconfigure-2.7.0.jar:2.7.0]
at org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration.configureDataSource(FlywayAutoConfiguration.java:131) ~[spring-boot-autoconfigure-2.7.0.jar:2.7.0]
at org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration.flyway(FlywayAutoConfiguration.java:118) ~[spring-boot-autoconfigure-2.7.0.jar:2.7.0]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.20.jar:5.3.20]
... 114 common frames omitted
The exception is thrown when flyway tries to retrieve the url from the original datasource - which is wrapped by OpenTelemetryDataSource like in this setup:
spring:
datasource:
driverClassName: org.hsqldb.jdbc.JDBCDriver
url: jdbc:hsqldb:mem:obsdemo
username: sa
password: sa
flyway:
baselineOnMigrate: true
user: sa
password: sa
Comment From: wilkinsona
Thanks for the suggestion.
In your configuration example above, the username and password for Flyway and the data source are the same. If this applies in your real application, can avoid the problem by removing spring.flyway.user and spring.flyway.password. The main datasource will then be used to migrate the database.
Another option is to define your own DataSource bean and annotate its @Bean method with @FlywayDataSource. This will allow you to provide a Flyway-specific data source which removes the need for us to try and derive one from the main data source.
We can consider broadening the cases in which derivation will unwrap the DataSource. I vaguely recall some problems in the past with unwrapping and certain JDBC drivers (Oracle perhaps) so we may not be able to do so.
Comment From: wilkinsona
I think https://github.com/spring-projects/spring-boot/issues/24154 is the Oracle UCP problem that I was remembering. I don't think it will prevent us from unwrapping more generally.