I ran into additional issues w/ Oracle XA datasources while figuring out the 
JMX stats issue, but this seems distinct enough to separate into its own thread.

Oracle's XA driver returns true to isSameRM() in 
oracle.jdbc.xa.OracleXAResource if two XAResource's are on the same Oracle 
instance, even if they're using different login credentials.  This seems to be 
a long standing bug/misfeature in Oracle's JDBC driver going back to at least 
2010 [https://community.oracle.com/message/4226001].  

When using two datasources which point to the same Oracle instance but have 
different credentials, 
org.apache.geronimo.transaction.manager.TransactionImpl#enlistResource() tries 
to TMJOIN the transactions because isSameRM() returns true.  This fails with  
"ORA-24774: cannot switch to specified transaction" (see longer stack below) if 
the datasources aren't using the same credentials.

Coming from a JBoss background, there was a kludge in the JBoss datasource 
descriptor of adding "<isSameRM-override-value>false</isSameRM-override-value>" 
which forced it to always assume isSameRM=false without actually calling the 
underlying XAResource's implementation.  This assumed two Oracle datasources 
were on different transaction managers and ran them with two-phase commit 
instead of trying to TMJOIN them.  There was a performance hit in cases where 
the credentials were the same AND the connections were on the same instance, 
but it at least didn't fail outright.

Looking through the source of TomEE & Geronimo-Transaction, it doesn't like 
like there's any existing mechanism to override the "TMJOIN if isSameRM=true" 
behavior.  This means it's not possible to include two Oracle datasources on 
the same instance with different credentials in one transaction.  It works if 
the creds are the same OR if the datasources are on different instances.


I'm not sure how best to address this or whether the change ultimately lies in 
TomEE or Geronimo-Transaction.  Our DBA's prefer one user per schema and 
multiple connection pools, even when things are on the same instance.  We can 
push to change that practice, but it seems like there should be a way to make 
this case work.

Any thoughts?

Here's what the stack looks when it fails:

16:32:12,206 WARN  [Transaction] Unable to enlist XAResource 
oracle.jdbc.driver.T4CXAResource@27a7b18f, errorCode: -3
oracle.jdbc.xa.OracleXAException
        at 
oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1229)
        at 
oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:246)
        at 
org.apache.geronimo.transaction.manager.TransactionImpl.enlistResource(TransactionImpl.java:202)
        at 
org.apache.openejb.resource.jdbc.managed.local.ManagedConnection.invoke(ManagedConnection.java:132)
        at com.sun.proxy.$Proxy249.prepareStatement(Unknown Source)
        at 
ucs.util.ormap.db.JDBCClientImpl.prepareStatement(JDBCClientImpl.java:31)
        at 
ucs.util.ormap.db.SQLGenerator.getPreparedStatement(SQLGenerator.java:1867)
[...]
Caused by: java.sql.SQLException: ORA-24774: cannot switch to specified 
transaction
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:392)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:385)
        at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:1018)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
        at oracle.jdbc.driver.T4CTTIOtxse.doOTXSE(T4CTTIOtxse.java:164)
        at oracle.jdbc.driver.T4CXAResource.doStart(T4CXAResource.java:188)
        at 
oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:241)
        ... 81 more


Best regards,
Zac Bedell

Reply via email to