I want to invoke a method which inside a external .jar by using reflection.
This is a sample code which inside the jar.
public class HelloFunction implements Runnable, RequestHandler<Request> {
@Override
public void handle(final Request request) {
System.out.println("handle : " + request);
}
@Override
public void run() {
System.out.println("run......");
}
}
Then i loaded this jar in a separate java program and tried to invoke HelloFunction.handle() method. This is the sample code for that part.
public class App {
public static void main(String[] args) {
test();
}
public static void test(){
try{
final Class<?> functionClass = getClassFromFunctionJar("com.hello.HelloFunction");
final Object functionClassObject = functionClass.newInstance();
if(functionClassObject instanceof RequestHandler){
@SuppressWarnings("unchecked")
final RequestHandler<Object> handler = RequestHandler.class.cast(functionClassObject);
final Object inputObject = getRequestClass(functionClass).newInstance();
handler.handle(inputObject);
}
}catch(final Exception e){
System.err.println(e.getMessage());
}
}
public static Class<?> getRequestClass(final Class<?> cls) throws FunctionInvokerException{
try{
final Type[] types = cls.getGenericInterfaces();
for(Type type : types){
//check RequestHandler
if(type.getTypeName().contains(RequestHandler.class.getName())){
final ParameterizedType parameterizedType = (ParameterizedType) type;
// [0]=> Request Type
final String inputClassName = parameterizedType.getActualTypeArguments()[0].getTypeName();
return getClassFromFunctionJar(inputClassName);
}
}
throw new Exception("UNABLE_TO_FIND_REQUEST_TYPE");
}catch(final Exception e){
throw new FunctionInvokerException(e);
}
}
private static Class<?> getClassFromFunctionJar(final String className) throws ClassNotFoundException, MalformedURLException{
final ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:" + "/jar-location/hello.jar")}, App.class.getClassLoader());
return Class.forName(className, true, classLoader);
}
}
You can see here i used getClassFromFunctionJar() method to load Class from a jar. And getRequestClass() method is used to find class type of the HelloFunction.handle() method's input parameter. Everything is fine until invoking handle() method.
Finally i got an error which says "com.hello.Request cannot be cast to com.hello.Request". Could you please help me to solve this issue.
The same class definition loaded by different class loaders is seen as two distinct classes by the JVM.
your code "URLClassLoader.newInstance" while get different class loaders
the first(handler#parameter) is: URLClassLoader#1 & com.hello.Request
the second(inputObject) is: URLClassLoader#2 & com.hello.Request
"com.hello.Request cannot be cast to com.hello.Request".
The actual error is
"URLClassLoader#2 com.hello.Request cannot be cast to URLClassLoader#1 com.hello.Request"
and suggest this:
private static final ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:" + "/jar-location/hello.jar")}, App.class.getClassLoader());
private static Class<?> getClassFromFunctionJar(final String className) throws ClassNotFoundException, MalformedURLException{
return Class.forName(className, true, classLoader);
}