Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-6078

AnnotationUtils.getAnnotatedMethod for abstract classes not inherit from interface

Attach filesAttach ScreenshotVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.7.13
    • 3.0.3, 2.7.14, 3.1
    • JAX-RS
    • None
    • Unknown

    Description

      I created the special junit test to demonstrate this bug.

      Suppose we have NameService with annotated methods: 'get' and 'set'.

      NameServiceImpl that implements NameService and only 'get' method.

      AbstractNameServiceImpl that implements 'set' method.

      NameServiceImpl extends AbstractNameServiceImpl.
      AbstractNameServiceImpl does not implement NameService.

      For this case AnnotationUtils.getAnnotatedMethod returns wrong annotatedMethod for 'set'. It is actually same method as requested one, but not the 'set' method from the interface.

      m = public javax.ws.rs.core.Response NameServiceImpl.get(java.lang.String)
      a = public abstract javax.ws.rs.core.Response NameService.get(java.lang.String)
      m = public javax.ws.rs.core.Response AbstractNameServiceImpl.set(java.lang.String)
      a = public javax.ws.rs.core.Response AbstractNameServiceImpl.set(java.lang.String)

      JDK1.7.0_51

      It happens because AnnotationUtils.getAnnotatedMethod has only single argument Method, that is the method 'set' from super class AbstractNameServiceImpl. It does not have information about NameServiceImpl itself and does not check hierarchy of the NameServiceImpl as well. In fact, logically it checks superclass AbstractNameServiceImpl only, but really we are using NameServiceImpl as a service class. This is the bug.

      Solution:
      AnnotationUtils.getAnnotatedMethod needs additional Class<?> serviceClass argument to check hierarchy of service class to find annotated method, that's because Method argument can be from any level of super class of the serviceClass and there is no guarantee that it implements base RESTful interface with annotated methods.

      It actually affects ResourceUtils.createClassResourceInfo
      that calls AnnotationUtils.getAnnotatedMethod to detect annotated method in the loop

      private static void evaluateResourceClass(ClassResourceInfo cri, boolean enableStatic) {
      MethodDispatcher md = new MethodDispatcher();
      for (Method m : cri.getServiceClass().getMethods()) {

      Method annotatedMethod = AnnotationUtils.getAnnotatedMethod(m);

      It knows about ServiceClass, but does not use this information to walk in classes hierarchy.
      For me, this bug leads to the situation that not all methods have mapping in the application.

      Attachments

        1. NameServiceImpl.java
          0.2 kB
          Alexander Shvid
        2. NameService.java
          0.5 kB
          Alexander Shvid
        3. AnnotationUtilsTest.java
          0.4 kB
          Alexander Shvid
        4. AbstractNameServiceImpl.java
          0.2 kB
          Alexander Shvid

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            sergey_beryozkin Sergey Beryozkin
            alexshvid Alexander Shvid
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Slack

                Issue deployment