Monday, September 1, 2008

XStream and Dynamic Proxies

So I've been bragging a bit (yeah, just a bit) about XStream because I'm currently using it in my unit testing framework. I started out with the original DynamicProxyConverter and there is already a very good post on how to use it from Straun's blog. But then I soon ran into problems trying to set a super class for the resulting proxy object for the following class hierarchy:

public interface MyObjectInterface { void doSomething(); }

public class MyObjectBase { public void intialize() {} }

public class MyObjectImpl extends MyObjectBase implements MyObjectInterface {
public void doSomething() {}
}

The solution is to clone DynamicProxyConverter.java and replace the last line of code in the unmarshall() method:

return Proxy.newProxyInstance(classLoader, interfacesAsArray, handler);

With

return newProxyInstance(superClass, interfacesAsArray, handler);

Where newProxyInstance is a method which utilized javaassist package to create the proxy instance in the cloned DynamicProxyConverter:

private Object newProxyInstance(Class superClass, Class[] interfaces, InvocationHandler handler)
{
ProxyFactory factory = new ProxyFactory();

if (superClass != null) {
factory.setSuperclass(superClass);
}

factory.setInterfaces(interfaces);

Class clazz = factory.createClass();

Object proxy = clazz.getConstructor().newInstance();
((ProxyObject) proxy).setHandler((MethodHanlder) handler);

return proxy;
}

For this to work, your InvocationHandler class should also need to implement MethodHandler interface, ie.

public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args)
throws Throwable
{
if (proceed == null) {
return invoke(self, thisMethod, args);
} else {
return proceed.invoke(self, args);
}
}

No comments: