How will I call a method using reflection in Java where the method has 2 parameters? - reflection

I am trying to call a method of the Level class in Apache log4j using reflection, which has 2 parameter values. How do I do it?

Using an example with the Level class fron Log4j2 .
The following calls the method isInRange(Level, Level) to determine if a log level is in between a set of two other log levels.
Level warn = Level.WARN;
boolean range = warn.isInRange(Level.ERROR, LEVEL.INFO);
can be done using Reflection with:
Level warn = Level.WARN;
Method method = warn.getClass().getMethod("isInRange", Level.class, Level.class);
boolean range = method.invoke(warn, Level.ERROR, Level.INFO);
In this case both arguments are Level objects, so the class reference Level.class is used twice in getMethod (as the types of the two arguments).
Then the method is invoked with method.invoke(warn, Level.ERROR, Level.INFO).
The first argument is the instance we want to invoke the method on (in this case warn).
If the method we are invoking is static null can be used.
The second two arguments are the arguments of the actual function isInRange.

Related

Idiomatic way to invoke methods through reflection in Kotlin

I have a piece of Kotlin code that is trying to reflectively invoke a method using Java's Reflection package:
val arguments = arrayOfNulls<Any>(numberOfParams)
// Populate arguments
try {
fooMethod.invoke(fooClass, arguments)
} catch (e: Exception) {
// Panic
}
It keeps failing with an IllegalArgumentException of "wrong number of parameters".
I did some reading on the issue and it seems the spread operator of the invoke() method refuses to unpack Array<Any> because it's not equivalent to Object[]. I could try to use a standard Object[] from Java, but it makes me wonder, is this the only way? Is it the best way? Is there some way I can do this with Kotlin's types?
What is the most idomatic way to achieve what I want in Kotlin?
You need to add the spread operator * to your call:
fooMethod.invoke(fooClass, *arguments)
Using arguments without prefixing it with * will cause a new array of length 1 containing arguments as its single element to be created and passed as args to invoke. Prefixing it with the spread operator causes the arguments array to be passed to invoke as args.
See Variable number of arguments (Varargs) - Functions - Kotlin Programming Language for more details.

Only this and nothing more with Prophecy?

So I have this in a PhpUnit test:
$alias_manager = $this->prophesize(AliasManagerInterface::class);
$alias_manager->cacheClear($source)->shouldBeCalledTimes(1);
And I would like to tell Prophecy that this is all the alias manager should be called with, no other methods should be called nor this method with any other argument. The latter I can do
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(1);
but how do I say "nothing else" for Prophecy?
With Prophecy, if you call reveal() on the object prophet immediately, the object is assumed to be a dummy object. This means that it'll return null for all public methods of the object it's prophesizing.
However, as soon as you add one method prophet (e.g. by doing your shouldBeCalled...() call or a willReturn() call), the returned object will be a mock or a stub object. In this case, only the configured calls will work and all other calls that are executed will trigger failure.
In other words: You don't have to do anything, this is the standard behaviour.

Interception messages in Squeak

I am trying to understand better reflection in Smalltalk. I am using the latest version of Squeak (v4.3). I want to intercept every message sent to instances of one of my classes. I assumed that I could override the method ProtoObject>>withArgs:executeMethod but Stéphane Ducasse explained me that for performance reason, this method is not used (this is my own summary of his answer). Which method should I override / how could intercept sent messages?
Here is the code of my attempt:
Object subclass: #C
instanceVariableNames: 'i'
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.
C class compile: 'newWithi: anInt
^(self new) i: anInt ; yourself.'.
C compile: 'withArgs: someArgs executeMethod: aMethod
Transcript show: ''Caught: ''.
^ super withArgs: someArgs executeMethod aMethod.'.
C compile: 'foo: aText
Transcript show: aText.
Transcript show: i.
Transcript cr.'.
C compile: 'i: anInt
i := anInt.'.
o := C newWithi: 42.
o foo: 'This is foo: '.
Executing this entire piece of code yields:
This is foo: 42
When I would like to have:
Caught: This is foo: 42
There's no build-in way to intercept messages to objects like that. There are two ways we commonly use to do this kind of trick.
First, you can create a wrapper object which responds to doesNotUnderstand:. This object usually has nil for the superclass so it doesn't inherit any instance methods from Object. The doesNotUnderstand: handler would delegate all its messages to the target object. It has the option of performing code before and after the call. All references to the original object would now point to the new "proxy" object. Messages to self wouldn't be intercepted and the proxy would need to test for objects that return self and change the returned object to be the proxy instead.
The second approach is to use a mechanism called Method Wrappers. Method Wrappers allows you to replace all of the methods in a set of classes with methods that do some other operations before and after calling the original method. This approach can provide fairly seemless results and intercepts all messages including those send to self.
MethodWrappers is available for VisualWorks and VASmalltalk. I believe it's also available for Squeak and Pharo but I'm not positive.
The three main techniques are:
Dynamic proxies
Method wrapper
Bytecode instrumentation
For a good comparision of all possible approaches, have a look at "Evaluating Message Passing Control Techniques in Smalltalk" by Stephane Ducasse (you already know him, apparently).
Of interest is also "Smalltalk: A Reflective Langauge" by F. Rivard, that shows how to implement pre- and post-conditions using bytecode rewriting. This is also a form of interception.

need clarity implementing interface GridTask<T,R>

I need clarity in implementing reduce() and map() methods of GridTask,
How can we Pass arguments to these methods,
Map<? extends GridJob, GridNode>
map(List<GridNode> subgrid, T arg) throws GridException
R reduce(List<GridJobResult> results) throws GridException
Specifically, I need to know, how to pass/ invoke reduce method, or if it is invoked implicitly, then how and what arguments are passed to it.
The arguments are passed from GridProjection.execute(...) method.
Every time a GridJob completes, its result is passed to GridTask.result(...) method. The reduce() method is invoked whenever all results from GridJobs are received. You can also force to reduce sooner by returning REDUCE policy form GridTask.result(...) method.

Can I pass an array to a function using the ... rest* construction?

I'm making multiple similar calls with similar results to one remote object. Because these calls are so similar and very changeable, I've been keeping the name of the remote method in a config file, and when I need to make the call I use getOperation() on the remote object, and call send() on the operation object. However, the requirements have changed so that not all of the calls will have the same number of parameters.
Because send uses ..., will I be able to continue using the same formation and pass an array, or will send() treat that as passing one argument of type array?
The Operation class also has an "arguments" property that you can use. That way you can prefill it before calling send(). The send() method then requires not extra arguments.
var operation:Operation = Operation(remoteObject.getOperation(methodName));
operation.arguments = parameters;
var token:AsyncToken = operation.send();
var responder:Responder = new Responder(resultHandler, faultHandler);
token.addResponder(responder);
you can use the ...rest
that will give you an array with a bunch of objects. I would recommend tat you make the first item [0] always the ID. This ID should identify either the sender or the type of object being passed. you can easily do a switch/case for each type of item. You could also do a more sophisticated way of dealing with this, but this should work.

Resources