1 Reply Latest reply on Nov 14, 2016 3:31 AM by mkouba

    Adding an annotation to a method via an extension: surprises

    ljnelson

      For posterity I thought I would record this here.

       

      I am futzing around with an extension that programmatically turns JSR-330 Providers into producer methods.  I am not entirely sure where I'm going with this yet—just kind of exploring, and it's feeling like a dead end—but it has been a great way to get into the nitty gritty details of the CDI SPI.

       

      Anyway, so I wrote an observer method that does this:

       

      public <T extends Provider<?>> void replaceGuiceProviderWithProducerMethod(@Observes final ProcessAnnotatedType<T> event) {

        if (event != null) {

          final Stream<AnnotatedMethodConfigurator<? super T>> methodStream = event.configureAnnotatedType().filterMethods(m -> {

              return m.getJavaMember().getName().equals("get");

            });

          System.out.println("*** get() method count: " + methodStream.count()); // prints 2!

          methodStream.forEach(m -> {

              m.add(PRODUCES_LITERAL); // an annotation literal implementing the Produces annotation; this fires twice

            });

        }

      }

       

      One of the more interesting things I found was that if you have a Provider implementation (public class Foo implements Provider<Bar>), that has exactly one declared method in it (public Bar get() { return bar; }), its declared method count is…two.  Whaaa…?

       

      If you examine the methods in the stream, you'll see that one is declared, effectively:

       

      public Object get();

       

      …and the other is declared, effectively:

       

      public Bar get();

       

      This was surprising to me.  Then I read more deeply about bridge methods and it made sense.

       

      My question, I guess, is: as you can see above, I'm adding @Produces onto the get() method (in the abstract).  But do I add it onto both of these AnnotatedMethods, or just the one that returns Bar?  I don't want there to be a producer method that manufactures java.lang.Object!