javacdiweldweld2weld-junit5

How can I handle multiple disposal methods for inherited types?


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?


Solution

  • 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 with B. You can think of those parameters as injection points if that helps - your produceB 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):