Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke method by reflection with dynamic parameters

I'm invoking some method of Class's instance using the method.invoke(instance, args...) way but for each method inside the instance, as the invoke Javadoc rightly points out, each argument must be manually specified.

Thinking about Spring... how it could valorize parameters in controller's method behind the hood during HTTP calls? (but surely it does in a completely different way I think...)

I wonder if there's any way in Java to dynamically pass parameters in reflection (or not even reflection) without specifying each of them singularly.

EDIT

The instance class declaration is something like:

public class Something {

    public void doSth(String par1, String par2, Integer par3) {
        //....
    }

    public void doSthElse(String par1, Boolean par2) {
        //....
    }

    public void doSthElseMore(Integer par1) {
        //....
    }

}

How I'm invoking each method:

...
for (Method method : instance.getDeclaredMethods()) {
    Object[] array = //BL: build array of values to pass to the invoke method.
//1. doSth may be new Object[] {"abc", "def", 123}
//2. doSthElse iteration may be new Object[] {"abc", false}
//3. doSthElseMore iteration may be new Object[] {123}
    return method.invoke(instance, array);
}
...

As shown above, each method inside Something class (instance) have a different number of parameters.

On each iteration, the array have a different number of values to pass to the invoke.

like image 610
Andrea Grimandi Avatar asked Oct 11 '25 23:10

Andrea Grimandi


1 Answers

Actually as @Boris says all I had to do to complete my job was to convert each parameters to the correct type. In this way Java managed to invoke the correct method of the Something class with the correct parameters types.

My project is a Vert.x application using Vavr and jodd but the last return statement shows how I managed to solve.

public Object invokeMethod(Object service, Method method, RoutingContext routingContext) throws Exception {
        MultiMap queryParams = routingContext.queryParams();
        Map<String, String> pathParams = routingContext.pathParams();
        Buffer body = routingContext.getBody();

        // 1. type, 2. name, 3. value
        List<Tuple3<Class<?>, String, Object>> list = List.empty();

        for (Parameter par : method.getParameters()) {
            ParamQuery paramQuery = par.getAnnotation(ParamQuery.class);
            if (paramQuery != null) {
                list = list.push(new Tuple3<Class<?>, String, Object>(par.getType(), paramQuery.value(),
                        queryParams.get(paramQuery.value())));
            }
        }

// TypeConverterManager used to "covnert" each object (String) from the HTTP call to the correct data type
        return method.invoke(service, list.reverse()
                .map(mapper -> TypeConverterManager.lookup(mapper._1()).convert(mapper._3())).toJavaArray());
    }

However, this project can be found on GitHub

like image 57
Andrea Grimandi Avatar answered Oct 14 '25 15:10

Andrea Grimandi