Hi, folks

[NOT A CONTRIBUTION]


JDBC Pool Version: 9.0.49
Database: Oracle
JDBC Version:  19.3.0.0
OS: Mac, Linux


The problem I'm running into:
We are using Tomcat JDBC Pool. When getting the network failure between server 
and database something like 'Connection Reset by Peer' ORM framework we are 
using  'abort' method from JDBC Connection which goes through the 
ProxyConnection class. As a result underlying physical connection to DB is 
closed but PooledConnection is not return to the pool.

The reason to using 'abort' is that oracle PhysicalConnection in case of 
network failure sometimes goes to the inconsistent state and calling plain 
'close' throws an unexpected exception.

Seems like ProxyConnection is missing special handling for the 'abort' method 
which should call abort on the underlying connection and return PoolConnection 
to the pool afterwards.

According to JDBC specification link - 
https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#abort-java.util.concurrent.Executor-
calling 'abort' should perform close on the connection.

As a workaround we have fixed that using interceptor:

[NOT A CONTRIBUTION]

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
    Object invoke = super.invoke(proxy, method, args);
    if (compare(ABORT_VAL, method) && findProxyConnectionInChain().isPresent()) 
{
        ProxyConnection proxyConnection = findProxyConnectionInChain().get();
        proxyConnection.getDelegateConnection().setDiscarded(true);
        try {
            super.invoke(proxy, 
Connection.class.getDeclaredMethod(ProxyConnection.CLOSE_VAL), args);
        } catch (Exception e) {
                  // Error handling
        }

    }
    return invoke;
}

private Optional<ProxyConnection> findProxyConnectionInChain() {
    JdbcInterceptor next  = getNext();

    while (next != null) {
        if (next instanceof ProxyConnection) return  
Optional.of((ProxyConnection) next);
        next = next.getNext();
    }

    return Optional.empty();
}


Can someone confirm this is an issue and can be reported as a bug?

Alexey


PS 

I've patch ready for that:

[NOT A CONTRIBUTION]

if (compare(CLOSE_VAL,method) || compare(ABORT_VAL,method)) {
            if (connection==null) return null; //noop for already closed.
            if (compare(ABORT_VAL,method)) {
                invokeRealMethod(method, args);
            }
            PooledConnection poolc = this.connection;
            this.connection = null;
            pool.returnConnection(poolc);
            return null;
        }

private Object invokeRealMethod(Method method, Object[] args) throws Throwable {
    try {
        PooledConnection poolc = connection;
        if (poolc!=null) {
            return method.invoke(poolc.getConnection(), args);
        } else {
            throw new SQLException("Connection has already been closed.");
        }
    } catch (Throwable t) {
        if (t instanceof InvocationTargetException) {
            throw t.getCause() != null ? t.getCause() : t;
        } else {
            throw t;
        }
    }
}




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to