Atomikos Forum |
|
Hello everyone,
I have been evaluating Atomikos for a couple of weeks and think I have encountered a bug, but since I exercise a very simple scenario, it very well may be due to misconfiguration or some limitation of Atomikos that I'm not aware of. Can anyone clarify? The scenario is as follows: Within global transaction I create two connections to DB. I use them so that both are registered in transaction. I close the first one and then take next one (usually the last closed is returned by the pool). On any operation that would register this connection in existing transaction I can see that Atomikos is providing different XID than the first time, which leads to an Error from connection. I tested it on 2 databases: H2 and MySQL with the same results. From looking in the code I can see that when second connection is opened it overwrites XID in SiblingMapper of global transaction. This new, I assume incorrect XID, is then used to operate on the first connection after it is closed and borrowed from pool again. I attach a simple test case (in method testCase). It requires H2 to compile, but it can be easily replaced with MySQL driver. package atomikos; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import javax.sql.XADataSource; import javax.transaction.SystemException; import org.h2.jdbcx.JdbcDataSource; import pl.migi.hibernate.tutorial.Table; import com.atomikos.icatch.jta.UserTransactionManager; import com.atomikos.jdbc.AtomikosDataSourceBean; public class TestCase { private XADataSource dataSource; private UserTransactionManager transactionManager; private AtomikosDataSourceBean dataSourceBean; private Connection connection; private Table table; public void createTransactionManager() throws SystemException { transactionManager = new UserTransactionManager(); transactionManager.setTransactionTimeout(90000000); transactionManager.init(); transactionManager.setTransactionTimeout(90000000); } public void createDataSource() throws SQLException { createH2DataSource(); connection = ((DataSource) dataSource).getConnection(); connection.setAutoCommit(true); dataSourceBean = new AtomikosDataSourceBean(); dataSourceBean.setXaDataSource(dataSource); dataSourceBean.setPoolSize(2); dataSourceBean.setTestQuery("select * from information_schema.tables"); dataSourceBean.setUniqueResourceName("xyz"); } private void createH2DataSource() { JdbcDataSource jdbcDataSource = new JdbcDataSource(); jdbcDataSource.setURL("jdbc:h2:mem:test;LOCK_MODE=1;MVCC=TRUE;DB_CLOSE_DELAY=-1"); jdbcDataSource.setUser("sa"); dataSource = jdbcDataSource; } // private void createMySQLBaseDataSource() { // MysqlXADataSource source = new MysqlXADataSource(); // source.setURL("jdbc:mysql://localhost:3306/BPE?characterEncoding=UTF-8"); // source.setUser("syncron"); // source.setPassword("syncron"); // dataSource = source; // } private void setUp() throws Exception { createTransactionManager(); createDataSource(); } public void testCase() throws Exception { setUp(); transactionManager.begin(); Connection connection1 = dataSourceBean.getConnection(); Connection connection2 = dataSourceBean.getConnection(); connection1.createStatement(); connection2.createStatement(); connection1.close(); connection1 = dataSourceBean.getConnection(); connection1.createStatement(); // this fails connection2.close(); } public static void main(String[] args) throws Exception { new TestCase().testCase(); } } |