2

I have recently started looking into Java Web Services and found the following puzzling:

If I have an method defined in a interface which has an @Consumes annotation and I then implement the interface, the service works correctly, as if the @Consumes is inherited.

However, from reading various articles and here, it appears annotations are not inherited.

I knocked up the following test to check this out:

interface ITestAnnotationInheritance {
    @Consumes
    void test();
}

class TestAnnotationInheritanceImpl implements ITestAnnotationInheritance {
    @Override
    //@Consumes     // This doesn't appear to be inherited from interface
    public void test() {}

    public static void main(String[] args) throws SecurityException, NoSuchMethodException {
        System.out.println(TestAnnotationInheritanceImpl.class.getMethod("test").getAnnotation(Consumes.class));
    }
}

and the result is:

null

If I uncomment the @Consumes in the TestAnnotationInheritanceImpl class is the output is:

@javax.ws.rs.Consumes(value=[*/*])

This proves that annotations are not inherited, but how come the web services works fine?

Many Thanks

Community
  • 1
  • 1
Dave Whittingham
  • 338
  • 3
  • 11

1 Answers1

2

Assuming you are talking about web services annotations on methods, then the framework is presumably using reflection to find the annotations on the declared method in the superclass ... or even chasing up through the inheritance hierarchy looking for annotations declared on implemented or overridden methods with the same signature. (You could probably figure out what exactly is going on by looking at the framework source code ...)


Try this variation of your example:

class TestAnnotationInheritance {
    @Consumes
    public void test() {}
}

class TestAnnotationInheritance2 extends TestAnnotationInheritance {
    public static void main(String[] args) 
    throws SecurityException, NoSuchMethodException {
        System.out.println(TestAnnotationInheritance2.class.getMethod("test").
                           getAnnotation(Consumes.class));
    }
}

I think this will show that the annotation is present on the method. (The difference here is that we are not overriding the method declaration that has the @Consumes annotation with another declaration that does not have it.)


Note that annotations on classes are not normally inherited, but they are if they are declared with the @Inherited annotation; see JLS 9.6.3.3 and the javadoc.

IMO, the concept of inheritance for annotations is all a bit rubbery. But fortunately it doesn't impact on the core Java type system and computational model.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216