super_seabass
super_seabass

Reputation: 1116

Getting the actual class used for a MethodInvocation rather than the declaring class

I'm digging through a web application in an effort to fix some problems. The application uses Tomcat, Jersey and Guice. One of the issues is occurring in a MethodInterceptor used for authorization purposes. Here's the method, trimmed to the relevant part:

public Object invoke(MethodInvocation invoc) throws Throwable {
    // ...

    //Check that the annotation actually exists
    if(! invoc.getMethod().getDeclaringClass().isAnnotationPresent(Tool.class))
    {
        throw new BaseException("...");
    }

    // ...
}

Now the problem is that some of the "web-facing" methods are inherited from a parent class without being overridden in the child. If I understand getDeclaringClass() correctly, it will return the parent class in this case, but what we really want here is the child class. Some testing seems to confirm this--if I override the method in the child class everything is fine, but if I don't put in the override the exception is thrown.

So, given a MethodInvocation object, is there a way to trace it back to the "actual" class instantiated, rather than the class where the method was declared? Or is some other approach necessary? Worst-case, I could just annotate each method as necessary rather than annotating the class.

Sorry if this is a long-winded question for an easy answer - my Java is pretty rusty.

Upvotes: 4

Views: 5123

Answers (2)

super_seabass
super_seabass

Reputation: 1116

Simple enough, needed to use getThis().getClass() on the MethodInvocation instead of getMethod().getDeclaringClass():

    if(! invoc.getThis().getClass().isAnnotationPresent(Tool.class))
    {
        throw new BaseException("...");
    }

Although in my case, Guice complicated things a bit by putting in an auto-generated child class (e.g., a class name ending in "$$EnhancerByGuice..." That was fixed by moving one up the tree with getSuperclass():

    if(! invoc.getThis().getClass().getSuperclass().isAnnotationPresent(Tool.class))
    {
        throw new BaseException("...");
    }

Upvotes: 8

BrownFurSeal
BrownFurSeal

Reputation: 515

It looks like that the answer is No. I created simple test to check it:

    class Run implements Runnable {
        @Override
        public void run() {
        }
    }
    class Run2 extends Run{}
    Method method = Run2.class.getMethods()[0];
    System.out.println(method);

As we can see in debug window method doesn't have any information of class Run2:

Method in debug window

I guess it would be better to stick on actual methods with its annotations rather then on actual class instances where these methods get invoked.

Upvotes: 0

Related Questions