DexClassLoader - invoke method with parameter - java

I have met some tutorials on the web, which are invoking simple methods and all I need is to invoke method "startDownload" which accepts Context as a parameter. I am now calling it:
Class<?> loaded = cl.loadClass("com.test.someclass");
Method m = loaded.getDeclaredMethod("startDownload", null);
m.invoke(this, null);
where c1 is DexClassLoader. But no success. I am getting error of NoSuchMethodException, I know I have to add parametres somewhere, but don't know where... any advices?
Thanks

I suggest looking at that post.
The parameters are passed after the method name when calling Class.getMethod(name, ...), as described here. You can directly use the class member of the Class you have to pass:
Method myMethod = myClass.getMethod("doSomethingWithAString", String.class);
Maybe you forgot some of them: the method won't be found if the signature (so the parameters) are not correct.

Related

How to use methods of a wildcard class<?> result

I am trying to build a generic tool that finds a hibernate class and uses its methods by means of metadata.
So from the database I get 1: "TABLENAME" 2. "methodname"
Step 1. Finding the hibernate is done.
Class<?> result = generator.getClassFromTableName("TABLENAME");
Step 2. using the methods that are in the class that is returned is something I do not get.
Do i need to use classloader or finding it through result.getConstructors?
Easiest would be if I end up with an instance of 'TableName' and be able to acces all its methods. Hope it is clear!
Thanks #rsp for the reassurance to look within Reflection. First time to dive into it and in the end it was pretty straightforward.
Classloader to load class from string parameter
getConstructor to
find the right constructor and use it with newInstance()
getDeclaredMethod to find the right method and use it with Invoke and
the object instance
Class< ? > testdataClass = getClass().getClassLoader().loadClass(testDataClassname);
Constructor<?> tesdataClassConstructor = Objects.requireNonNull(testdataClass).getConstructor(datacontext);
Object testdataClassObject = tesdataClassConstructor.newInstance(dc);
Method buildMethod = testdataClass.getDeclaredMethod("build");
return buildMethod.invoke(testdataClassObject);

Can we mock a spy object using mockito?

I have a class called RadiationControl and I created a spy for it in the following way.
RadiationControl radCtrl = new RadiationControl();
RadiationControl spyRadCtrl = Mockito.spy(radCtrl);
I have a chained method call inside a different class called StationMonitor which is being called by using the RadiationControl object. When I am trying to use the above created spy and trying to access that which has method parameters and they vary from time to time.
StationMonitorObject stationMonitorObject = radCtrl.getStationMonitorLoader().retrieveCVStationMonitorObject(Long.parseLong(syngId), status);
Thus with the above syntax when I try to stub the spy for that method call it's complaining to stub properly.
StationMonitorLoader stationMonitorLoader = StationMonitorLoader.getLoader(domain);
Mockito.doReturn(stationMonitorLoader).when(spyRadCtrl).getStationMonitorLoader();
Mockito.doReturn(stationMonitorObject).when(stationMonitorLoader).retrieveCVStationMonitorObject(any(Long.class), null);
Is there any better approach to deal such scenario ?
Is there any better approach to deal such scenario ?
Yes.
The problem here is:
radCtrl.getStationMonitorLoader()
.retrieveCVStationMonitorObject(Long.parseLong(syngId), status);
This is a violation of the law of demeter (aka don't talk to strangers!).
The method retrieveCVStationMonitorObject() should be available in class RadiationControl and delegate the call to its dependency (which looks like being a StationMonitorLoader...)

Java reflection, call method from superClass?

I've seen a lot of examples, and I know what has been discussed.
I do everything right, but I receive an error. Why is that? What am i doing wrong?
Class superClass = rootObject.getSuperclass();
Method addErrorMethod = superClass.getDeclaredMethod("addErrorMessage", ErrorType.class, String.class, String.class, String.class);
_log.info(addErrorMethod.getName());
addErrorMethod.invoke(superClass, ErrorType.FIELD, propertyName, message, "");
I get method, but when you call the invoker. I get the following error.
java.lang.IllegalArgumentException: object is not an instance of declaring class
Thanks.
When you call Method.invoke the first parameter must be either:
when method is non-static instance of the class which contains the method
when method is static null or class itself.
Since you pass the class itself and you got error it suggests that method you are trying to invoke is not static, so you should invoke it like
addErrorMethod.invoke(rootObject, ErrorType.FIELD, propertyName, message, "");
// ^^^^^^^^^^- assuming it is instance on which we want to invoke this method
You did not do everything right:
addErrorMethod.invoke(superClass, ErrorType.FIELD, propertyName, message, "");
should read
addErrorMethod.invoke(rootObject, ErrorType.FIELD, propertyName, message, "");
superClass is an instance of Class, to which has no addErrorMessage() method, as the error message is telling you. The first parameter to the method is a reference to the object that will be used as this within the method.

Generic List and reflection

I'd like to call via reflection the following method, but I have problem to specify the correct signature:
public void executeRule(List<Node> params, SomethingStrangeFound callMeBack) throws IOException
{
...
}
I tried something like this:
Class partypes[] = new Class[2];
partypes[0] = Class.forName("java.util.List");
partypes[1] = Class.forName("vp.SomethingStrangeFound");
Method meth = cls.getMethod("executeRule", partypes);
It doesn't work because I use "java.util.List" when it must be "List<Node>", but I have no idea how to specify it.
If I just use "java.util.List", I have the following error calling cls.getMethod("executeRule", partypes):
NoSuchMethodException: vp.RuleWebXmlContextParamFacesPortletRenderStyles.executeRule(java.util.List, vp.SomethingStrangeFound)
Any help?
P.S.
At debug time, I see "List<Node>" is resolved with:
(Ljava/util/List<Lorg/w3c/dom/Node;>;Lit/vp/SomethingStrangeFound;)V
but it doesn't help me.
If both parameter classes are available at compile time you can initialize parameter array like this:
Class partypes[] = new Class[] { List.class, SomethingStrangeFound.class };
Method meth = cls.getMethod("executeRule", partypes);
This will guarantee that you have not mistyped qualified class names.
If this still does not work, check available methods in your class using Class#getMethods() method:
for (Method method : cls.getMethods()) {
System.out.println(method);
}
I ran your code and it worked for me.
You have not provided the definition of cls, but I assume it is something like
Class cls = RuleWebXmlContextParamFacesPortletRenderStyles.class;
Since you get a NoSuchMethodException, Class.forName already passed successfully, so no typo there (unless you have multiple SomethingStrangeFound classes, which would mean that you got the package wrong).
Because of this the last thing that comes to my mind is that perhaps you compiled RuleWebXmlContextParamFacesPortletRenderStyles before adding the method in question. Clean your code and recompile.
With partypes of size 2, getMethod will search for a method called "executeRule" with 2 parameters, one of type "java.util.list" and other of type "vp.SomethingStrangeFound"
But your method has only 1 parameter. You need to add a second parameter of type "vp.SomethingStrangeFound" to your method or set partypes size to 1.

Java Reflection with Object... as a parameter

I'm wanting to use Java reflection to call a method on a class of mine that has the following signature:
public Object execute(Object...params)
In my loader class, I have the class loaded, but I'm not sure how to setup my getMethod call. Currently, I have something like this:
Method classEntry = _loadedClass.getMethod("execute", new Class[]{Object[].class});
I then try to invoke this method after creating a newInstance of my class by calling:
Object classObj = _loadedClass.newInstance();
classEntry.invoke(classObj, params); // params comes in from the method as Object...params
This is giving me a java.lang.NoSuchMethodException Exception. I know that my issue lies in my getMethod call. How should I set that up to accept a params object?
If params is of type Object [] then you need to call invoke like this:
classEntry.invoke(classObj, new Object [] {params});
But this does not explain NoSuchMethodException

Categories