in src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java [250:339]
private void updateTransactionStatus() throws SQLException {
// if there is an active transaction context, assure the transaction context hasn't changed
if (transactionContext != null && !transactionContext.isTransactionComplete()) {
if (transactionContext.isActive()) {
if (transactionContext != transactionRegistry.getActiveTransactionContext()) {
throw new SQLException("Connection cannot be used while enlisted in another transaction");
}
return;
}
// transaction should have been cleared up by TransactionContextListener, but in
// rare cases another lister could have registered which uses the connection before
// our listener is called. In that rare case, trigger the transaction complete call now
transactionComplete();
}
// the existing transaction context ended (or we didn't have one), get the active transaction context
transactionContext = transactionRegistry.getActiveTransactionContext();
// if there is an active transaction context, and it already has a shared connection, use it
if (transactionContext != null && transactionContext.getSharedConnection() != null) {
// A connection for the connection factory has already been enrolled
// in the transaction, replace our delegate with the enrolled connection
// return current connection to the pool
@SuppressWarnings("resource")
final C connection = getDelegateInternal();
setDelegate(null);
if (connection != null && transactionContext.getSharedConnection() != connection) {
try {
pool.returnObject(connection);
} catch (final Exception e) {
// whatever... try to invalidate the connection
try {
pool.invalidateObject(connection);
} catch (final Exception ignored) {
// no big deal
}
}
}
// add a listener to the transaction context
transactionContext.addTransactionContextListener(new CompletionListener());
// Set our delegate to the shared connection. Note that this will
// always be of type C since it has been shared by another
// connection from the same pool.
@SuppressWarnings("unchecked")
final C shared = (C) transactionContext.getSharedConnection();
setDelegate(shared);
// remember that we are using a shared connection, so it can be cleared after the
// transaction completes
isSharedConnection = true;
} else {
C connection = getDelegateInternal();
// if our delegate is null, create one
if (connection == null) {
try {
// borrow a new connection from the pool
connection = pool.borrowObject();
setDelegate(connection);
} catch (final Exception e) {
throw new SQLException("Unable to acquire a new connection from the pool", e);
}
}
// if we have a transaction, out delegate becomes the shared delegate
if (transactionContext != null) {
// add a listener to the transaction context
transactionContext.addTransactionContextListener(new CompletionListener());
// register our connection as the shared connection
try {
transactionContext.setSharedConnection(connection);
} catch (final SQLException e) {
// transaction is hosed
transactionContext = null;
try {
pool.invalidateObject(connection);
} catch (final Exception ignored) {
// we are try but no luck
}
throw e;
}
}
}
// autoCommit may have been changed directly on the underlying
// connection
clearCachedState();
}