Given the following classes
private static class ProducedInSubClass {
}
private static class ProducedInSuperClass {
}
public static class SuperClass {
@Produces
public ProducedInSuperClass producedInSuperClass = new ProducedInSuperClass();
}
public static class SubClass extends SuperClass {
@Produces
ProducedInSubClass producedInSubClass = new ProducedInSubClass();
}
public static class BeanWithSubClass {
@Inject
SubClass subClass;
@Inject
ProducedInSuperClass producedInSuperClass;
@Inject
ProducedInSubClass producedInSubClass;
}
The injection of ProducedInSuperClass stays unsatisfied. That is consistent with the CDI-Spec Chapter 4.2, I know.
To make this work, I need to extend SubClass by
@Produces
ProducedInSuperClass producedInSuperClassInSubClass = producedInSuperClass;
can anybody give an explanation for that? Why are Injects, Annotations Interceptors... inherited but not Producers?
Why are ... inherited but not Producers?
Excerpt from JavaDoc of @Produces:
Producer methods and fields are not inherited by bean subclasses.
If producer methods and fields would be inherited then there would exist multiple beans ... eligible for injection to the injection point which CDI treats as ambiguous dependency.
On the other hand, CDI supports producer method specialization:
@Mock
public class MockShop extends Shop {
@Override @Specializes
@Produces
PaymentProcessor getPaymentProcessor() {
return new MockPaymentProcessor();
}
@Override @Specializes
@Produces
List<Product> getProducts() {
return PRODUCTS;
}
...
}
Is there any reason why you operate on static classes only? Producer needs to be placed on an actual CDI bean to be recognized. Your sample is torn from context so I cannot say if they will actually be recognized as beans.
However, transferring your sample to a non-static test case (with some @Vetoed beans and producers for them), it will run just as you expect it - both producers would be found and produce injectable beans. So maybe you need to share a complete reproducible sample and we can go from there.
I suspect the inheritance you are asking about is not the actual problem here.
Anyway, it is designed like that since CDI 1.0 so finding a discussion on that would be troublesome at best (no JIRA issue at least, I did check there).
But one reason coming to mind right away - assume inheritance was in place for producers. Then your above scenario would have a producer for ProducedInSuperClass
in SuperClass
but due to inheritance also in SubClass
. Assuming both are legitimate for injection (none is disabled via specialization), then you are now facing an ambiguous dependency exception as you have two producers for same bean type with same bean qualifiers because SuperClass
and SubClass
are two different beans and both contain a producer.
I would say that's fair reason for disabling inheritance on producers. Furthermore, still with inheritance on, you could then override the method in subclass and more questions arise - do you keep both or do you disable original one? If you keep them, what would be the limitations on the new method? What if you decide for either and then you @Vetoed
one of the beans?
From my perspective it is simply a design decision. Probably in place to prevent further confusion. While I know this isn't the answer so you are probably looking for, questioning so old designs rarely comes with more accurate answers :-)