aschoerk
aschoerk

Reputation: 3593

Weld CDI: Producers in superclasses of alternatives are effective despite cdi-spec

Given

public class BeanContainer {
   @Produces
   Bean bean = new Bean();
}

and its alternative:

@Alternative
public class BeanContainerAlt extends BeanContainer {
    @Produces
    int producerInt = 10;
}

where Bean is

public class Bean {
    boolean didPostConstruct = false;
    @PostConstruct
    public void postConstruct() {
        didPostConstruct = true;
    }
}

injected into MainClass:

public class MainClass {
    @Inject
    Bean bean;
    @Inject
    Integer producedInt;
}

Then:

  Weld weld = new Weld()
            .disableDiscovery()
            .addBeanClass(MainClass.class)
            .addBeanClass(BeanContainer.class)
            .addBeanClass(BeanContainerAlt.class)
            .alternatives(BeanContainerAlt.class);
    WeldContainer container = weld.initialize();
    final MainClass mainClass = container.select(MainClass.class).get();
    assertFalse(mainClass.bean.didPostConstruct);
    assertEquals(10, (long)mainClass.producedInt);
    BeanContainer containerObject = container.select(BeanContainer.class).get();
    assertEquals(BeanContainerAlt.class, containerObject.getClass());

gives no error. I would have expected that Bean.class would have to be added using addBeanClass to be able to satisfy the inject in MainClass. The explanation is that the Superclass of BeanContainerAlt whose Producers should imO not be effective, produces the Bean-Object. Is that behavior intended or even according to the spec (I did not find it), is it probably defined in the weld-documentation?

The sourcecode can be found in examplesrc

mvn clean install -Dtest=ReproProducersInSuperclasses 

in that project should make it run

Upvotes: 1

Views: 126

Answers (1)

Illya Kysil
Illya Kysil

Reputation: 1756

Indeed, the fields and methods annotated with @Producer are not inherited - as discussed in the accepted answer to Why are Producers not inherited in CDI

However, according to the CDI specification:

5.1.2. Enabled and disabled beans

A bean is said to be enabled if:

  • (E1) it is deployed in a bean archive, and
  • (E2) it is not a producer method or field of a disabled bean, and
  • (E3) it is not specialized by any other enabled bean, as defined in Specialization, and either
  • (E4) it is not an alternative, or it is a selected alternative of at least one bean archive or the application.

Otherwise, the bean is said to be disabled.

According to these definitions and code above:

  • BeanContainer is not an alternative (E4) and therefore is enabled managed bean
  • BeanContainerAlt is a selected alternative (E4) and therefore is enabled managed bean
  • Bean and int are enabled because they are not a producer method or field of a disabled bean (E2), as BeanContainer and BeanContainerAlt are both enabled (E4)

Therefore producer fields in both BeanContainer and BeanContainerAlt are used to resolve dependencies.


The test fails as shown below when BeanContainer is not deployed (E1):

WELD-001408: Unsatisfied dependencies for type Bean with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject
net.oneandone.iocunit.testalt.MainClass.bean

The test fails as shown below when BeanContainerAlt is not selected (E4):

WELD-001408: Unsatisfied dependencies for type Integer with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject
net.oneandone.iocunit.testalt.MainClass.producedInt

Upvotes: 0

Related Questions