Search code examples
javajdbcdistributed-transactionsxabitronix

does jdbcConnection have ExceptionListener support, similar to jmsConnection?


We use XA/distributed transaction, and I'm trying to notify/update global transaction status, should a participating xaResource-branch throw an exception.

A good example can be found in JMS Connection#setExceptionListener(), (ref.link), which offers notification hook in the ExceptionListener. I'm looking for something similar in JDBC specification, but I haven't been able to find any.

XA Transaction processing is single-threaded in our application, and a given global transaction can touch multiple xaResource-branches. Assuming UOW happens in the order of rA, rB and rC, it happens we might have a slow query running on rB, causing rA timeout before rC starts. Because of the single threaded nature (and the limitation of the TM we use), rC still proceeds while the fate of the global transaction has already been determined (to rollback). We are trying to notify the global transaction of the fact rA has already been rolled back so that rC can be skipped.

If the JDBC specification doesn't offer something similar to JMS's ExceptionListener, one option I can think of would be using async thread(s) to test the JDBC connection with a certain frequency. The closest example I've found so far is described in this PostgreSQL documentation (ref.link), which uses asynchronous thread(s) to test/poll JDBC connection. It probably satisfies my need, but wondering if there's any other option I missed in the JDBC specification.


Solution

  • JDBC doesn't provide this for normal connections, so that is why you can't find it. JDBC does support listeners on PooledConnection (and XAConnection) objects (ConnectionEventListener and StatementEventListener), but those listeners are for communication from the pooled connection to the pool manager (or transaction manager), and are not for general use.

    If you want something like this, you would need to write it yourself. For example wrap the connection in a proxy, and decorate it with something that catches exceptions, notifies a listener and rethrows the exception.

    Alternatively, check if your resource manager already provides support for this. However, given the single-threaded nature of your handling, I guess it would be impossible for you to detect that rA timed out while you are handling rB through something like an exception listener: the resource will be waiting for the commit, and won't communicate the timeout until you actually try to commit.

    Asynchronously checking connections sounds like a big race condition waiting to happen, and that even assumes that the error you are checking for is something that is verifiable in that way. A logical exception might leave the connection in a working state.