The only place I can find that would be able to wrap the XAResource is in org.apache.openejb.resource.jdbc.managed.local.ManagedConnection#newConnection(). The assignment xaResource = xaConnection.getXAResource(); (line 186) could interpose a wrapper or proxy. It looks like everything that needs the xaResource including the enlistResource() call in invoke() would get the wrapped XAResource which could like about isSameRM().
I don't see any way from ManagedConnection to access datasource properties or other attributes that would allow triggering that behavior non-globally. Neither of the standard interfaces for XAResource nor Connection have a way to get the username of the connection without doing reflective things on Oracle internals. Any thoughts on where to get configuration information to control the isSameRM override? FWIW, I cooked up a local version of geronimo-transaction based on the 3.1.3 tag with isSameRM modified to always return false if a system property is set. Replacing the version in TomEE & setting the system property makes my Oracle XA connections work. -Zac > On Nov 2, 2016, at 19:28, Romain Manni-Bucau <[email protected]> wrote: > > Ji > > There is a useEqual option on the connectionmanager of the ra in geronimo > but these datasource dont use a resource adapter so easiest solution is to > wrap the xadatasource to have this behavior > > Le 2 nov. 2016 21:53, "Zachary Bedell" <[email protected]> a écrit : > >> 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 >> >>
