I'm trying to port some C#
code to Java
and I'm having trouble with a proxy implementation.
I have this class:
public class Comic
{
public int ComicID;
private List<Volume> _volumes;
public List<Volume> GetVolumes()
{
return _volumes;
}
public void SetVolumes(List<Volume> volumes)
{
_volumes = volumes;
}
}
And I'm trying to add an interceptor to a specific Method call for this entity, but I also need access to it's fields since I'll be using them.
After looking around for how to implement proxies in Java, I got this:
public void Load(Class<?> type)
{
// - type is a Comic.class
ClassLoader appLoader = this.getClass().getClassLoader();
MyProxyHandler proxyHandler = new MyProxyHandler();
Object proxy = Proxy.newProxyInstance(appLoader, new Class[] { ComicInterface.class }, proxyHandler);
}
The problem is, the type
is dynamic so I don't know which will be, and I don't want the code to have a requirement of having interfaces of everything, so I looked up on how to build a dynamic interface:
public class InterfaceLoader extends ClassLoader
{
public InterfaceLoader(ClassLoader loader)
{
super(loader);
}
public Class<?> GetInterface(Class<?> type) throws Exception
{
String interfaceName = type.getName() + "$Proxy";
Class<?> interfaceType = null;
interfaceType = findLoadedClass(interfaceName);
if (interfaceType != null) { return interfaceType; }
// - According to the link
byte[] classData = new InterfaceBuilder().BuildInterface(interfaceName, type.getDeclaredMethods());
return defineClass(interfaceName, classBytes, 0, classBytes.length);
}
}
And then I'd use it with the Proxy:
public void Load(Class<?> type)
{
// - type is a Comic.class
ClassLoader appLoader = this.getClass().getClassLoader();
InterfaceLoader loader = new InterfaceLoader(appLoader);
Class<?> dynamicInterface = loader.GetInterface(type);
// - dynamicInterface on debug is "console.Comic$Proxy", seems fine
MyProxyHandler proxyHandler = new MyProxyHandler();
Object proxy = Proxy.newProxyInstance(appLoader, new Class[] { dynamicInterface }, proxyHandler);
}
The exception I get is
java.lang.IllegalArgumentException: interface console.Comic$Proxy is not visible from class loader
I've looked up the exception but only found two solutions, which is to make sure the name doesn't conflict with any type (and I'm sure it doesn't) and to use this.getClass().getClassLoader()
instead of type.getClass().getClassLoader()
(same error).
What am I doing wrong?
And another issue is, how can I get the "original" object so I can get/set values from fields like ComicID
? Using the above proxy method I can intercept methods fine, but I lose access to it's fields.
I've read about it here to get the InvocationHandler, but I don't know how to get the object from the handler and I couldn't find an example with it.