We have been using the apache commons pool to hold our Avro proxy objects, and
we recently upgraded to commons-pool2. This exposed an issue with
SpecificRequestor.
In a nutshell, commons-pool2's GenericKeyedObjectPool.create() attempts to put
pool object wrappers into a map, keying off the original object:
objectDeque.getAllObjects().put(p.getObject(), p);
The put() calls hashCode() which is not handled in the invoke method of
SpecificRequestor. For a quick workaround, I extended SpecificRequestor and
checked for hashCode, equals and toString. But this could easily be applied
directly to SpecificRequestor. Most of this is taken from the Java source in
RemoteObjectInvocationHandler, with a small change in toString() to display the
Avro proxy url if available:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
String name = method.getName();
if (name.equals("hashCode")) {
return hashCode();
} else if (name.equals("equals")) {
Object obj = args[0];
return proxy == obj || (obj != null &&
Proxy.isProxyClass(obj.getClass()) && equals(Proxy.getInvocationHandler(obj)));
} else if (name.equals("toString")) {
return proxyToString(proxy);
} else {
return super.invoke(proxy, method, args);
}
}
private String proxyToString(Object proxy) {
Class<?>[] interfaces = proxy.getClass().getInterfaces();
if (interfaces.length == 0) {
return "Proxy[" + this + "]";
}
String iface = interfaces[0].getName();
if (iface.equals("java.rmi.Remote") && interfaces.length > 1) {
iface = interfaces[1].getName();
}
int dot = iface.lastIndexOf('.');
if (dot >= 0) {
iface = iface.substring(dot + 1);
}
try {
InvocationHandler handler = Proxy.getInvocationHandler(proxy);
if (handler instanceof Requestor) {
String url = ((Requestor)
handler).getTransceiver().getRemoteName();
return "Proxy[" + iface + "," + url + "]";
}
} catch (IOException e) {
}
return "Proxy[" + iface + "," + this + "]";
}
Apologies if this has already been discussed: the archives search did not
appear to be working. Thanks,
Mark