We are using an AbstractRoutingDataSource implementation as described by Mark Fisher's article "Dynamic DataSource Routing" described here http://blog.springsource.com/2007/01...ource-routing/.
In this excellent article Fisher uses AbstractDependencyInjectionSpringContextTests and not AbstractTransactionalSpringContextTests for the junit testing.
Unfortunately, having transactions in the mix to roll-back or commit the data for each test causes the routing to take place at the start of the transaction -- at the top of the test. If the code changes data sources in the middle, the changes to the new data sources are ignored. We can see evidence of this below.
If I try this simple test code extending AbstractTransactionalSpringContextTests ....
Even though the first 2 DBs have tables with differing number of rows and the last DB does not exist, we get back exactly the same result for all 3 queries because the transaction begins with being set to the default datasource in my XML Spring config, which does exist. The debugged output is below.Code:public void test_dataSourceRouting() throws Exception { MyDataSourceKeyHolder.setDataSourceName("A"); System.out.println("--> name ="+MyDataSourceKeyHolder.getDataSourceName()); JdbcTemplate t = new JdbcTemplate(dataSource); int rows = t.queryForInt("select count(*) from table"); System.out.println("--> Rows ="+rows); MyDataSourceKeyHolder.setDataSourceName("B"); System.out.println("--> name ="+ MyDataSourceKeyHolder.getDataSourceName()); t = new JdbcTemplate(dataSource); rows = t.queryForInt("select count(*) from table"); System.out.println("--> Rows ="+rows); MyDataSourceKeyHolder.setDataSourceName("something that does not exist!!"); System.out.println("--> name ="+MyDataSourceKeyHolder.getDataSourceName()); t = new JdbcTemplate(dataSource); rows = t.queryForInt("select count(*) from table"); System.out.println("--> Rows ="+rows); }
The question I have is how is it that we can use all the benefits of a routing data source and all the benefits of transactions at the same time?Code:INFO Starting test SubTest#test_dataSourceRouting DEBUG Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@19ba640] DEBUG Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT ====>>>>> MyRoutingDataSource.determineCurrentLookupKey null DEBUG Acquired Connection [jdbc:db2://url, UserName=name, IBM DB2 JDBC Universal Driver Architecture] for JDBC transaction DEBUG Switching JDBC Connection [jdbc:db2://url, UserName=name, IBM DB2 JDBC Universal Driver Architecture] to manual commit DEBUG Bound value [org.springframework.jdbc.datasource.ConnectionHolder@11410e5] for key [MyRoutingDataSource@13e15f7] to thread [main] DEBUG Initializing transaction synchronization INFO Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@61373f]; default rollback = true ... ... DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] --> name =A DEBUG Executing SQL query [select count(*) from table] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] --> Rows =274 --> name =B DEBUG Executing SQL query [select count(*) from table] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] --> Rows =274 --> name =something that does not exist!! DEBUG Executing SQL query [select count(*) from table] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] DEBUG Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] bound to thread [main] --> Rows =274 DEBUG Triggering beforeCompletion synchronization DEBUG Removed value [org.springframework.jdbc.datasource.ConnectionHolder@caf0ed] for key [org.apache.commons.dbcp.BasicDataSource@159780d] from thread [main] DEBUG Returning JDBC Connection to DataSource DEBUG Initiating transaction rollback
Is there a workaround for this?
thanks.


Reply With Quote
