I have 2 producer-methods, one has only 1 qualifier and one has 2 qualifiers, the one from the first producer and an additional one:
@ApplicationScoped
public class MyProducer {
@Produces
@Qualifier1
MyBean produce1(InjectionPoint injectionPoint) {
...
}
@Produces
@Qualifier1
@Qualifier2
MyBean produce2(InjectionPoint injectionPoint) {
...
}
}
If I try to @Inject
MyBean with both qualifiers, everything works fine, produce2
is called. But when injecting MyBean with only @Qualifier1
, I get an AmbiguousResolutionException
. In my opinion, produce2
should only be called when injection point has both qualifiers. Why isn't that the case and what can I do to make it work?
Unfortunately I can not change producer-method 1, because it is in a library. The basic plan is to call my own producer if the injection point has my additional qualifier and if not, call the one from the library.
I think the observed behavior is clearly specified in CDI 2.0, ch.2.3.4 "Specifying qualifiers of an injected field":
A bean may only be injected to an injection point if it has all the qualifiers of the injection point.
Assuming an injection point:
@Inject @Qualifier1 MyBean myBean;
Then the beans produced by both produce1
and produce1
"have all the qualifiers of the injection point", i.e. @Qualifier1
, so both are eligible for injection there, resulting in the AmbiguousResolutionException
.
In fact, the spec gives an example exactly as the one in the question in ch.2.3.6 "Repeating qualifiers".
So what can you do?
For starters, do you really need to qualify produce2
with @Qualifier1
? If you have no good reason, just drop @Qualifier1
from produce2
and you are done - injection points with @Qualifier1
select MyBean
from the library, injection points with @Qualifier2
select the one from your code. Your injection points cannot have both @Qualifier1
and @Qualifier2
.
If you still want to inject MyBean
from produce2
to injection points that have both @Qualifier1
and @Qualifier2
, you can still do it [DISCLAIMER: Haven't actually tried this, it will probably need tweaking]. It's a bit more involved: You have to write a portable extension, which is not a hard thing at all. Brief implementation points:
producer2
must be annotated ONLY with @Qualifier2
ProcessInjectionPoint
eventevent.getInjectionPoint().getQualifiers()
contains both @Qualifier1
and @Qualifier2
event.configureInjectionPoint().qualifiers(...)
to remove @Qualifier1
from the set of qualifiers.The effect is that you remove the @Qualifier1
when it is present together with @Qualifier2
at runtime.