in method SqlScriptsTestExecutionListener.executeSqlScripts(...), around line 213, the following code resides:

DataSource dataSourceFromTxMgr = getDataSourceFromTransactionManager(txMgr);
// Ensure user configured an appropriate DataSource/TransactionManager pair.
if (dataSource != null && dataSourceFromTxMgr != null && !dataSource.equals(dataSourceFromTxMgr)) {
    throw new IllegalStateException(String.format("Failed to execute SQL scripts for test context %s: " +
          "the configured DataSource [%s] (named '%s') is not the one associated with " +
          "transaction manager [%s] (named '%s').", testContext, dataSource.getClass().getName(),
           dsName, txMgr.getClass().getName(), tmName));
}

This seems to contradict the logic used in DataSourceUtils which handles such equality checks taking into account that a DataSource may be an implementation of InfrastrutureProxy.

We have a setup where the DataSource in the Spring context is directly the database DataSource (well, it is pooled), while the DataSource given to the DataSourceTransactionManager is a wrapped version. However, the wrapping class implements InfrastructureProxy, which ensures that all Spring JDBC stuff - which utilizes the DataSourceUtils class to fetch (and release) Connections - actually handles this perfectly: Even though e.g. the JdbcTemplate has gotten the "plain" DataSource, while, again, the TxMgr has the wrapped DataSource, when in a Spring managed Transaction, the JdbcTemplate ends up with Connections from the wrapped DataSource (in the DataSourceTransactionManager) due to the logic wrt. InfrastructureProxy in DataSourceUtils.

However, this is not the case in SqlScriptsTestExecutionListener, due to the much plainer .equals(..) check being performed there. Basically, had the check not been there, it would have worked. Also, had the check taken into account the InfrastructureProxy logic, it would also have worked.

(And, due to the equality being checked is dataSourceFromSpringContext.equals(dataSourceFromTxMgr) - and not the other way around - I cannot hack this to work either. The only way around that would be to also wrap the DataSource in the Spring context too (to trick the .equals(..)) - in which case I could just as well put the same DataSource in Spring context as the one given to the DataSourceTransactionManager, which of course would fix this. However, the problem is that these two are handled in different code bases, and it is not always the situation that we want to do that wrapping of the DataSource given to the DataSourceTransactionManager.).

Comment From: sbrannen

Thanks for raising the issue.

Are you on Spring Framework 5.3.x?

Also, out of curiosity...

Do you have custom code that generates the proxy implementing DataSource and InfrastructureProxy?

Or is the proxy being created by something in one of the Spring portfolio projects or a third-party library?

Comment From: sbrannen

Support for unwrapping proxied data sources has been added in 4a7a2258f9ad8771e9a8225f5a18db156372162a.

Feel free to try this out in the upcoming 5.3.4 snapshots and let us know if you run into any issues.

Comment From: stolsvik

@sbrannen It is in external library code, not in any Spring portfolio projects. I realized how this worked - and was duly impressed by the logic! - and utilized it. Then, in one of our projects, we got hit by this issue.

Thanks!