I have compiled a class at runtime which I would like to use on the fly, provided that its constructor takes one parameter
package com.notmycompany;
import com.mycompany.Manager;
import com.mycompany.Processor;
import com.mycompany.Event;
public class CustomProcessor extends Processor {
public CustomProcessor( Manager m) {
super( m);
}
@Override
public void process( Event evt) {
// Do you own stuff
System.out.println( "My Own Stuff");
}
}
Compilation goes fine and I can load the class right away. But the constructor is giving me a hard time.
Class<?> clazz = urlClassLoader.loadClass("com.notmycompany.CustomProcessor");
Constructor<?> constructor = clazz.getConstructor( com.mycompany.Manager.class);
this.customProcessor = (Processor) constructor.newInstance( this.manager);
In this case, getConstructor
throws a NoSuchMethodException
I tried using getConstructors
instead, which only gets me one step further with IllegalArgumentException
during newInstance
call (of course this.manager is com.mycompany.Manager)
Constructor<?> list[] = clazz.getConstructors();
Constructor<?> constructor = list[0];
this.customProcessor = (Processor) constructor.newInstance( this.manager);
Watever I do, there is a mismatch between Manager object at runtime and compilation
How can I fix this constructor signature?
Edit 1: getParameterTypes output
for( Class<?> c : constructor.getParameterTypes()) {
System.out.println( c);
}
outputs
class com.mycompany.Manager
Edit 2: I removed constructor parameter as a temporary workaround
Now the code throws ClassCastException
complaining that com.notmycompany.CustomProcessor cannot be cast to com.mycompany.Processor
when constructor is invoked:
Constructor<?> constructor = clazz.getConstructor();
this.customProcessor = (Processor) constructor.newInstance();
This all seems to be part of the same problem where runtime classes seem inconsistent with compilation's, although names match.
Your CustomProcessor class has no constructor because the name of the method you believe to be your constructor is different.
Should be changed to
Because the name of your class is CustomProcessor. Constructor's names must match the name of their containing class exactly.
I have been able to get it to work eventually after using a URL that uses the currentThread as parent (as opposed to a URLClassLoader created from scratch with URLs)
I hope this can save you 2 days!