Jiri Hofman
Jiri Hofman

Reputation: 45

CDI 1.2 (WildFly 8.2), javax.enterprise.inject.Instance<SomeIFace> does not get beans which do not implement SomeIFace directly

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

Answers (1)

fxnn
fxnn

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.

  • For managed (non-EJB) beans, the spec explicitly states that "all directly or indirectly" implemented interfaces are a bean type of the bean. To me, this means that 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.
  • For session (EJB) beans, the spec is a bit vague in my eyes. However, to me, "all local interfaces of the bean" reads like the interface 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).
  • But also note that, if you add 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

Related Questions