Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8199392

javac incorrectly report annotation as not a repeatable when code transitively depend on guice inject, but not in cp, and processor exists

XMLWordPrintable

    • x86_64
    • windows

      FULL PRODUCT VERSION :
      java version "9.0.4"
      Java(TM) SE Runtime Environment (build 9.0.4+11)
      Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.16299.248]

      A DESCRIPTION OF THE PROBLEM :
      The issue appears under a combination of conditions:
      1. Construct a Annotation Processor class (it could be a do nothing Processor), specify such in javax.annotation.processing.Processor, and make it a jar, so that it could be in classpath in later compiling.
      2. Construct another jar with classes using guice inject annotation ProvidedBy.
      3. Develop a 3rd project, where it imports the class defined in step 2 explicitly (such that class would be loaded - I believe). In this project, define some repeatable annotation and its container annotation, and some classes using that annotation repeatedly.
      4. When compiling 3rd project, have the jar from step 1 being in classpath (such that Annotation Processor would be on), jar from step 2 in class path (since 3rd project has explicit dependency on it), but do not include the javac.inject, and guice jar in classpath. It would complain that the Repeatable Annotation defined in project 3 as "not a repeatable annotation type".
      5. Note that: without the Annotation Processor from 1st jar, 3rd project would compile OK; without the 3rd project explicitly depending on 2nd jar, it would also compile OK; if the guice and inject jars are in the compilation classpath for the 3rd project, it would also compile OK.

      REGRESSION. Last worked in version 8u161

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Construct a Annotation Processor class (it could be a do nothing Processor), specify such in javax.annotation.processing.Processor, and make it a jar, so that it could be in classpath in later compiling.
      2. Construct another jar with classes using guice inject annotation ProvidedBy.
      3. Develop a 3rd project, where it imports the class defined in step 2 explicitly (such that class would be loaded - I believe). In this project, define some repeatable annotation and its container annotation, and some classes using that annotation repeatedly.
      4. When compiling 3rd project, have the jar from step 1 being in classpath (such that Annotation Processor would be on), jar from step 2 in class path (since 3rd project has explicit dependency on it), but do not include the javac.inject, and guice jar in classpath. It would complain that the Repeatable Annotation defined in project 3 as "not a repeatable annotation type".
      5. Note that: without the Annotation Processor from 1st jar, 3rd project would compile OK; without the 3rd project explicitly depending on 2nd jar, it would also compile OK; if the guice and inject jars are in the compilation classpath for the 3rd project, it would also compile OK.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      It probably could be said as a classpath issue- though there is likely more to it. - But it should not mistakenly report a perfectly defined Repeatable Annotation as "not a repeatable annotation type".
      ACTUAL -
      Properly developed Repeatable Annotation is incorrectly reported as "not repeatable".

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      error: RepeatedAnnotation is not a repeatable annotation type

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      Project 1:
      A. class TestAnnotationProcessor
      package com.test.processors;

      import javax.lang.model.SourceVersion;
      import java.util.Set;
      import javax.annotation.processing.*;
      import javax.lang.model.element.TypeElement;

      @SupportedSourceVersion(SourceVersion.RELEASE_9)
      public class TestAnnotationProcessor extends AbstractProcessor
      {

          @Override
          public synchronized void init(ProcessingEnvironment processingEnv) {
      // Do nothing processor is sufficient to show the issue
          }

          @Override
          public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment)
          {
      // Do nothing processor is sufficient to show the issue
              return true;
          }

      }

      B. include a single line in META-INF/services/javax.annotation.processing.Processor:
      com.test.processors.TestAnnotationProcessor

      Compile the above into a jar, call it annotation.jar

      2. Project 2 has dependency on guice-4.1.0-no_aop.jar and javax.inject.jar:
      A: Something class:
      package com.test;

      import com.test.inject.SomethingProvider;
      import com.google.inject.ProvidedBy;

      @ProvidedBy(SomethingProvider.class)
      public class Something
      {
          public static Something getSomething()
          {
      return null;
          }
      }


      B. SomethingProvider class:
      package com.test.inject;

      import com.test.Something;

      import javax.inject.Provider;

      public class SomethingProvider implements Provider<Something> {
          @Override
          public Something get() {
              return Something.getSomething();
          }
      }


      compile these into 2nd jar, call it inject.jar

      3. 3rd project
      A. RepeatedAnnotation class
      package com.test.annotation;

      import java.lang.annotation.ElementType;
      import java.lang.annotation.Inherited;
      import java.lang.annotation.Repeatable;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;

      @Retention(RetentionPolicy.RUNTIME)
      @Target({ ElementType.METHOD, ElementType.TYPE })
      @Repeatable(RepeatedAnnotationSet.class)
      @Inherited
      public @interface RepeatedAnnotation {
          String value() default "";
      }

      B. RepeatedAnnotationSet class
      package com.test.annotation;

      import java.lang.annotation.ElementType;
      import java.lang.annotation.Inherited;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;

      @Retention(RetentionPolicy.RUNTIME)
      @Target({ ElementType.METHOD, ElementType.TYPE })
      @Inherited
      public @interface RepeatedAnnotationSet {
          RepeatedAnnotation[] value();
      }

      C: UsingRepeatedAnnotation class:
      package com.test;

      import com.test.Something;

      import com.test.annotation.RepeatedAnnotation;

      @RepeatedAnnotation("A")
      @RepeatedAnnotation("B")
      public interface UsingRepeatedAnnotation {
      }

      compile project 3 with 1st jar and 2nd jar in classpath but not


      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Including the javax.inject.jar and guice-4.1.0-no_aop.jar in compilation classpath for project 3 get around this issue.

            jlahoda Jan Lahoda
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: