I have two classes.
class A {
}
class B extends A {
}
And in my producer class I declared like this.
@Produces A produceA(InjectionPoint ip) {
return new A();
}
void disposeA(@Disposes A a) {
// empty
}
@Produces B produceB(InjectionPoint ip) {
return new B();
}
void disposeB(@Disposes B b) {
// empty
}
And Weld complains.
....DefinitionException: WELD-000077: Cannot declare multiple disposal methods for this producer method.
Producer method: org.jboss.weld.bootstrap.BeanDeployer@41e68d87
Disposal methods:
- Disposer method [[BackedAnnotatedMethod] ....Producer.disposeA(@Disposes A)],
- Disposer method [[BackedAnnotatedMethod] ....Producer.disposeB(@Disposes B)]
Is this normal? How can I solve it?
This is a typesafe resolution matter and it works as intended. From the specification, 3.4.3. Disposer method resolution:
A disposer method is bound to a producer method or producer field if:
In your specific case, you have the producer method
produceB
which creates a bean whose types are going to be{B, A, Object}
. The types are derived from the return type and will contain the type itself, all super classes and all implemented interfaces (as stated here in CDI spec).You then have two disposer methods, one with the disposer parameter
A
, the other withB
. You can think of those parameters as injection points if that helps - yourproduceB
producer method creates a bean that fits both of these disposers hence creating ambiguity because Weld needs at most one disposer method for each bean.If you want to read more in how exactly typesafe resolution works, look here.
As for how to "solve" this situation, I can think of two approaches from the top of my head (there is likely more ways to do this):
@Typed
on the producer and limit the types ofproduceB
to onlyB.class
which should resolve this situation as well but the bean will no longer be eligible for injection into any injection point with typeA
.