Trouble with Java invocations using reflection

The WTF

In a mocked UnitTest, I created a mock on a logger interface to control its invocations. However, in addition to that, I wanted to reach every invocation through to a _real_ log4j backend of that logger interface since those log messages could contain information needed to find errors…

The idea is to lookup the invoked methods on the _real_ logger using reflection, so I don’t have to adapt the testCase whenever I change the log interface, it is just passing through anyway, right? I left polymorphism out of the mix to simplify the code (I don’t use polymorphism in log interfaces anyway).

Compilation is absolutely fine but at rumtime I got:

java.lang.IllegalArgumentException: argument type mismatch

Can you spot the error?

public Object execute(String invokedMethod, List parameterValues) throws Exception {
    // Invoke the method on the real logger
    MyLogger realLogger = new MyLoggerLog4jBackend();
    Method[] methods = realLogger.getClass().getMethods();

    // Ignore polymorphism in method lookup for now...
    Method method = null;
    for (int i = 0; i < methods.length && method == null; i++) {
        if (methods[i].getName().equals(invokedMethod)) {
            method = methods[i];
        }
    }

    if (method != null) {
        method.invoke(realLogger, parameterValues);
    }
}

Oh yes, the parameter of the invocation at runtime is actually a java.lang.IllegalArgumentException and MyLogger looks something like:

public interface MyLogger {

    [.. other irrelevant methods...]

    void fatalError(Exception e);

}

The Solution

It’s the invocation in itself:

method.invoke(realLogger, parameterValues);

If you take a close look at the invoke method’s declaration, you’ll see it’s:

public Object invoke(Object obj, Object... args);

But since parameterValues is a java.util.List, it used that list as a parameter in itself instead of unwrapping it! And since java.util.List and java.lang.Exception are not type compatible, boom!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s