Reputation: 45
I am already stuck solving injection of bean implementations into javax.enterprise.inject.Instance<SomeIFace>
. I have couple of beans (EJB Singletons) which extend an abstract class which implements the SomeIFace - see the scenario below.
public interface SomeIFace {
void doStuff();
}
Then there is an abstract class adopting the SomeIFace
as follows:
public abstract class SomeAClass implements SomeIFace {
@Resource
private TimerService ts;
public TimerService getTimerService() {
return ts;
}
@Timeout
public void timeout() {
doStuff();
}
}
Actual implementation of a managed bean extends the abstract class SomeAClass
as follows:
@Singleton
@Startup
@TransactionManagement(TransactionManagementType.BEAN)
public class SomeClass extends SomeAClass {
/**
* {@inheritDoc}
*/
@Override
public void doStuff() {
...
}
}
Then in another class I want to get references to all managed beans implementing the SomeIFace
, i.e.:
@Inject
@Any
private Instance<SomeIFace> beans;
The problem is that the beans
is empty!
When I add the SomeIFace
to the implementing bean class explicitly again (i.e. public class SomeClass extends SomeAClass implements SomeIFace
), the beans
is not empty and a reference appears.
Is anyone able to explain, why I need to repeat the SomeIFace
interface directly on bean implementations again to get CDI 1.2 working? In previous version of CDI it was working fine.
Thank you in advance!
Jiri
UPDATE:
This strange injection issue happens only for beans which are EJB Singletons (@javax.ejb.Singleton
). When the bean is annotated with @javax.inject.Singleton
or @javax.enterprise.context.ApplicationScoped
then it is not needed to repeat the interface declaration and beans are discovered OK. However, the TimerService
can not be injected into non-EJB beans
Upvotes: 1
Views: 1481
Reputation: 1127
Seems like the new behaviour is as specified in CDI 1.2 Spec:
3.1.2: The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all interfaces it implements directly or indirectly. (...) 3.2.2: The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their superinterfaces. If the session bean has a no-interface view, the unrestricted set of bean types contains the bean class and all superclasses. (...)
Note the difference in the definition of bean type for managed beans and session beans.
SomeIFace
(which is implemented by SomeAClass
, which is extended by SomeClass
) would be a bean type of SomeClass
, if SomeClass
was a managed (non-EJB) bean.SomeIFace
is only a bean type of the EJB SomeClass
, if SomeClass
directly implements it (as opposed to it only extends SomeAClass
which, in turn, implements SomeIFace
).SomeIFace
directly to SomeClass
, the bean cannot be injected via @Inject SomeClass
anymore! This is as only if "the session bean has no-interface view", the bean class itself is a bean type -- otherwise, only "all local interfaces of the bean and their superinterfaces" (and java.lang.Object
) are bean types.Therefore, the behaviour you observe conforms to the spec.
Upvotes: 0