3 Replies Latest reply on Aug 2, 2018 7:50 AM by manovotn

    BeforeBeanDiscovery.addQualifier() question


      I'm doing awful things with JPA and CDI.  :-)


      One experiment that I am working on starts like this:


      private final void beforeBeanDiscovery(@Observes final BeforeBeanDiscovery event) {

        if (event != null) {

          event.addQualifier(PersistenceContext.class); // don't judge :-)




      private final void processAnnotatedType(@Observes @WithAnnotations(PersistenceContext.class) final ProcessAnnotatedType<?> event) {

        if (event != null) {


            .filterFields(af -> af.getAnnotation(PersistenceContext.class) != null && af.getAnnotation(Inject.class) == null)

            .forEach(afc -> afc.add(InjectLiteral.INSTANCE)); // don't judge :-)




      I don't want to talk about whether this is a good idea (it almost certainly is not :-)).


      When my extension runs, I can see that both of these methods fire.  That's good.


      But then Weld says that PersistenceContext is not a qualifier:


      org.jboss.weld.exceptions.IllegalArgumentException: WELD-001301: Annotation QualifierInstance {annotationClass=interface javax.persistence.PersistenceContext, values={name=, synchronization=SYNCHRONIZED, type=TRANSACTION, unitName=test, properties=[Ljavax.persistence.PersistenceProperty;@3ad017e8}} is not a qualifier

          at org.jboss.weld.resolution.ResolvableBuilder.checkQualifier(ResolvableBuilder.java:221)

          at org.jboss.weld.resolution.ResolvableBuilder.addQualifier(ResolvableBuilder.java:188)

          at org.jboss.weld.resolution.ResolvableBuilder.addQualifiers(ResolvableBuilder.java:214)

          at org.jboss.weld.resolution.ResolvableBuilder.<init>(ResolvableBuilder.java:90)

          at org.jboss.weld.manager.BeanManagerImpl.getBeans(BeanManagerImpl.java:517)

          at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:376)


      I thought the whole point of BeforeBeanDiscovery#addQualifier(Class<? extends Annotation>) was to make a non-Qualifier-annotated annotation (like PersistenceContext) indistinguishable (to Weld) from a Qualifier-annotated annotation?  Is this a bug (I doubt it) or have I misunderstood something?


      (I should add that I'm well aware that I can do custom injection using ProcessInjectionTarget events but I'm curious why the above doesn't work.)




        • 1. Re: BeforeBeanDiscovery.addQualifier() question

          Now, that's interesting.

          It seems that the exception is only thrown when you actually attempt to inject something, right?

          The addition of qualifier via extension works just fine.

          Do you perform any further tempering with the injection itself? Might be worth a bit of debugging.


          Because BeforeBeanDiscovery.addQualifier() works just like you described.

          And we of course have tests that try to do pretty much the same thing - take an annotation class and register it as a qualifier.

          For instance this one, and it works as expected.


          I also know that PersistenceContext is one of the annotations we use to indicate an EE resource, so there may be some possible clashes while processing such IP.

          But like you said, trying to convert PersistenceContext into a Qualifier is not exactly common ;-)

          • 2. Re: BeforeBeanDiscovery.addQualifier() question

            I believe the problem is javax.persistence.PersistenceContext.properties() - array-valued members of a qualifier type should be annotated @Nonbinding in a portable application. And Weld does not support this ATM and simply treats the qualifier as invalid. If you enable debug logging you should see something like "Member of array type or annotation type must be annotated @NonBinding..."

            • 3. Re: BeforeBeanDiscovery.addQualifier() question

              Yea, Martin is right, that seems to be the thing.

              I've created a JIRA ticket to have qualifier validation performed early on so that we report this back during bootstrap and not just in runtime (assuming this wasn't done on some purpose)