Add a ConnectionWrapper interface to allow access to the underlying connection from a BorrowedConnectionProxy

Description

The borrowConnection functionality now prevents us from accessing the native connection to perform necessary operations (LOB handling, OAQ integration). Instead of just returning a simple proxy the implements java.sql.Connection the proxy could additionally implement an interface that allows users to access the wrapped connection returned by the ConnectionManager.

i.e.

public interface BorrowedConnection extends java.sql.Connection
{
java.sql.Connection getTargetConnection()
}

public class BorrowedConnectionProxy implements InvocationHandler {

private final ConnectionManager connectionManager;
private boolean useable = true;

public BorrowedConnectionProxy(ConnectionManager connectionManager) {
this.connectionManager = connectionManager;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "close".equals( method.getName() ) ) {
connectionManager.releaseBorrowedConnection();
return null;
}
if ( "getTargetConnection".equals( method.getName() ) ) {
return connectionManager.getConnection();
}
// should probably no-op commit/rollback here, at least in JTA scenarios
if ( !useable ) {
throw new HibernateException( "connnection proxy not usable after transaction completion" );
}
try {
return method.invoke( connectionManager.getConnection(), args );
}
catch( InvocationTargetException e ) {
throw e.getTargetException();
}
}

public static Connection generateProxy(ConnectionManager connectionManager) {
BorrowedConnectionProxy handler = new BorrowedConnectionProxy( connectionManager );
return ( Connection ) Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class[] { BorrowedConnection.class },
handler
);
}

public static void renderUnuseable(Connection connection) {
if ( connection != null && Proxy.isProxyClass( connection.getClass() ) ) {
InvocationHandler handler = Proxy.getInvocationHandler( connection );
if ( BorrowedConnectionProxy.class.isAssignableFrom( handler.getClass() ) ) {
( ( BorrowedConnectionProxy ) handler ).useable = false;
}
}
}
}

We could always get access to the connectionManager field of the invocation handler via reflection, but this is not supportable or maintainable.

Activity

Steve EbersoleMarch 21, 2011 at 7:05 PM

Bulk closing stale resolved issues

Adrian RileyDecember 4, 2006 at 4:25 PM

Yes, sorry, I realised that after posting. Thanks

Steve EbersoleDecember 4, 2006 at 3:20 PM

Of course its "working" when using C3P0; at least this is the same behavior Hibernate always exhibited here. The wrapped connection, from Hibernate's perspective, is the C3P0 wrapped connection (C3P0 defines this NewProxyConnection, not HIbernate).

Adrian RileyDecember 4, 2006 at 2:16 PM

Sorry, of course it does work when using the built in JDBC connection pool, but not when using C3P0.

Adrian RileyDecember 4, 2006 at 2:09 PM

Maybe I'm being stupid here, but this doesn't seem to work.

Calling getWrappedConnection() results in a call to the invoke() method of BorrowedConnectionProxy, which then calls ConnectionManager.getConnection(). This returns the NewProxyConnection which wraps the underlying Oracle Connection instance, and not the underlying connection itself. Calling ArrayDescriptor.createArrayDescriptor passing this connection results in a ClassCastException, exactly as before.

Have I missed something?

Fixed

Details

Assignee

Reporter

Components

Fix versions

Affects versions

Priority

Created May 10, 2006 at 8:12 PM
Updated March 21, 2011 at 7:05 PM
Resolved November 3, 2006 at 6:23 PM