The constructor of `io.agroal.pool.ConnectionHandler(XAConnection, Pool)` releases the `XAConnection` handed to it after obtaining a logical `Connection` (via `XAConnection.getConnection()`) and an `XAResource` (via `XAConnection.getXAResource()`). This essentially means that the `XAConnection` itself can never be closed properly.
According to the JDBC spec/docs the `XAConnection` must be closed directly when the pool/middleware has determined the physical connection is no longer needed; this is because an `XAConnection` is also a `PooledConnection`. Both interfaces share a common `getConnection()` method which the docs say should return a connection handle that does not close the connection but instead notifies it's listeners of the close event which the pool/middleware can listen to and decide if the physical connection should be closed.
`ConnectionHandler` only keeps a reference to the connection handle and therefore only closes the connection handle. It also never registered a listener on the `XAConnection` that it can use to be notified of connection close events.
The pool cannot rely upon finalize and/or leak detection to close physical database connections because under heavy load these facilities may be delayed by a significant amount of time which in turn can cause connection starvation issues on the server (e.g. too many open connections).