Skip to content

Connection created by SingleConnectionDataSource with suppressClose=true always returns isClosed=false even if the target connection is closed #24853

@barfoo4711

Description

@barfoo4711

If SingleConnectionDataSource is configured with suppressClose=true it will produce a Connection wrapped in CloseSuppressingInvocationHandler. CloseSuppressingInvocationHandler will always return false if the isClosed() is being triggered on the wrapped connection. This is ok until SingleConnectionDataSource#destroy() is triggered which closed the connection on the wrapped Connection.

I'd therefore suggest to change

/** * Invocation handler that suppresses close calls on JDBC Connections. */ private static class CloseSuppressingInvocationHandler implements InvocationHandler {	private final Connection target;	public CloseSuppressingInvocationHandler(Connection target) {	this.target = target;	}	@Override	@Nullable	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {	// Invocation on ConnectionProxy interface coming in...	if (method.getName().equals("equals")) {	// Only consider equal when proxies are identical.	return (proxy == args[0]);	}	else if (method.getName().equals("hashCode")) {	// Use hashCode of Connection proxy.	return System.identityHashCode(proxy);	}	else if (method.getName().equals("unwrap")) {	if (((Class<?>) args[0]).isInstance(proxy)) {	return proxy;	}	}	else if (method.getName().equals("isWrapperFor")) {	if (((Class<?>) args[0]).isInstance(proxy)) {	return true;	}	}	else if (method.getName().equals("close")) {	// Handle close method: don't pass the call on.	return null;	}	else if (method.getName().equals("isClosed")) {	return false;	}	else if (method.getName().equals("getTargetConnection")) {	// Handle getTargetConnection method: return underlying Connection.	return this.target;	}	// Invoke method on target Connection.	try {	return method.invoke(this.target, args);	}	catch (InvocationTargetException ex) {	throw ex.getTargetException();	}	} } 

to

/** * Invocation handler that suppresses close calls on JDBC Connections. */ private static class CloseSuppressingInvocationHandler implements InvocationHandler {	private final Connection target;	public CloseSuppressingInvocationHandler(Connection target) {	this.target = target;	}	@Override	@Nullable	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {	// Invocation on ConnectionProxy interface coming in...	if (method.getName().equals("equals")) {	// Only consider equal when proxies are identical.	return (proxy == args[0]);	}	else if (method.getName().equals("hashCode")) {	// Use hashCode of Connection proxy.	return System.identityHashCode(proxy);	}	else if (method.getName().equals("unwrap")) {	if (((Class<?>) args[0]).isInstance(proxy)) {	return proxy;	}	}	else if (method.getName().equals("isWrapperFor")) {	if (((Class<?>) args[0]).isInstance(proxy)) {	return true;	}	}	else if (method.getName().equals("close")) {	// Handle close method: don't pass the call on.	return null;	}	// else if (method.getName().equals("isClosed")) {	//	return false;	// }	else if (method.getName().equals("getTargetConnection")) {	// Handle getTargetConnection method: return underlying Connection.	return this.target;	}	// Invoke method on target Connection.	try {	return method.invoke(this.target, args);	}	catch (InvocationTargetException ex) {	throw ex.getTargetException();	}	} } 

Let me know if this change would be ok then I can create a pull request

Metadata

Metadata

Assignees

Labels

in: dataIssues in data modules (jdbc, orm, oxm, tx)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions