hk2
  1. hk2
  2. HK2-101

Qualified binding injection seems to fail (at least in some cases).

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Works as designed
    • Affects Version/s: 2.1.*
    • Fix Version/s: 2.1.*
    • Component/s: None
    • Labels:
      None

      Description

      I have an empty qualifier annotation @ and I'm binding a Factory of some type T to the T and new AnnotationLiteral<Q>() {}.
      Then I'm trying to @Inject @Q Provider<T> provider, but the injected provider.get() returns null.

      I traced the problem to HK2 Utilities.annotationContainsAll(...) method called from ServiceLocatorImpl.narrow(...). In the annotationContainsAll a JDK collection containsAll is invoked. This performs equality of JDK annotation instance Q1 with the annotation literal in descriptor Q2, which fails (i.e. Q1.equals(Q2) == false in HashMap.getEntry(...)).

        Activity

        Hide
        jwells added a comment -

        This looks to me like a bug in the JDK. I have written a simple test that shows that an EMPTY annotation shows up as not equals with the JDK implementation against the AnnotationLiteral version. However, the AnnotationLiteral version works fine against the JDK empty one. The hashCode works out the same.

        I've also shown that an annotation that is NOT empty does NOT have this problem (i.e., the JDK annotation equals works fine). So, this is a bug in the JDK. I will enter a bug into the JDK database and do some sort of work-around for this.

        Here is the simple test that shows the problem:

        Q qJdk = ClassWithQ.class.getAnnotation(Q.class);

        Assert.assertEquals((new AnnotationLiteral<Q>(){}).hashCode(), qJdk.hashCode());

        Assert.assertTrue((new AnnotationLiteral<Q>(){}).equals(qJdk));

        // Currently fails, looks like a bug in the JDK
        Assert.assertTrue(qJdk.equals(new AnnotationLiteral<Q>(){}));

        Show
        jwells added a comment - This looks to me like a bug in the JDK. I have written a simple test that shows that an EMPTY annotation shows up as not equals with the JDK implementation against the AnnotationLiteral version. However, the AnnotationLiteral version works fine against the JDK empty one. The hashCode works out the same. I've also shown that an annotation that is NOT empty does NOT have this problem (i.e., the JDK annotation equals works fine). So, this is a bug in the JDK. I will enter a bug into the JDK database and do some sort of work-around for this. Here is the simple test that shows the problem: Q qJdk = ClassWithQ.class.getAnnotation(Q.class); Assert.assertEquals((new AnnotationLiteral<Q>(){}).hashCode(), qJdk.hashCode()); Assert.assertTrue((new AnnotationLiteral<Q>(){}).equals(qJdk)); // Currently fails, looks like a bug in the JDK Assert.assertTrue(qJdk.equals(new AnnotationLiteral<Q>(){}));
        Hide
        jwells added a comment -

        Sorry, I was wrong. This is an invalid case. An implementation of AnnotationLiteral must do two things:

        1. It must extend AnnotationLiteral and have the target annotation as its generic type
        2. It must implement the type of the target annotation

        So the code above:

        new AnnotationLiteral<Q>() {}

        is not sufficient because it does not do #2 above. Instead you would need a class definition like this:

        public class QImpl extends AnnotationLiteral<Q> implements Q {
        }

        If there is a bug here it is that the AnnotationLiteral equals method considers (new AnnotationLiteral<Q>() {}) to be equal to an instance of Q. So if you fix your code to ensure that your AnnotationLiteral implements Q then your qualifier should work.

        Show
        jwells added a comment - Sorry, I was wrong. This is an invalid case. An implementation of AnnotationLiteral must do two things: 1. It must extend AnnotationLiteral and have the target annotation as its generic type 2. It must implement the type of the target annotation So the code above: new AnnotationLiteral<Q>() {} is not sufficient because it does not do #2 above. Instead you would need a class definition like this: public class QImpl extends AnnotationLiteral<Q> implements Q { } If there is a bug here it is that the AnnotationLiteral equals method considers (new AnnotationLiteral<Q>() {}) to be equal to an instance of Q. So if you fix your code to ensure that your AnnotationLiteral implements Q then your qualifier should work.

          People

          • Assignee:
            jwells
            Reporter:
            Marek Potociar
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: