Using @ApplicationScoped @Named @Eager
, my @EJB
-injected @Stateless
beans are not properly instantiated and evaluate to null
.
I had an @ApplicationScoped @ManagedBean(eager=true)
that was used to schedule a few jobs. Some @Stateless
beans were injected using @EJB
annotation, and that worked fine.
In the move to CDI annotations, I added the OmniFaces @Eager
annotation as substitute for @ManagedBean(eager=true)
which is missing in standard CDI:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.omnifaces.cdi.Eager;
@Named
@ApplicationScoped
@Eager
public class MyScheduler implements Serializable {
@EJB
private MyService myService;
@Inject
private MyNamedBean myNamedBean;
@PostConstruct
public void init() {
setupSchedulers();
}
@PreDestroy
public void destroy() {
destroySchedulers();
}
//...
}
Using this setup, the @PostConstruct
method is correctly called on application startup (though it seems to run even before the context is initialized), but then myService
evaluates to null
.
In the log, the following warnings appear:
Severe: No valid EE environment for injection of org.omnifaces.cdi.eager.EagerBeansRepository
Severe: No valid EE environment for injection of my.package.MyScheduler
Info: Initializing Mojarra 2.2.8 ( 20140814-1418 https://svn.java.net/svn/mojarra~svn/tags/2.2.8@13507) for context '/tagific'
Since I need to access this bean from other ones, I couldn't use the @Singleton
and @Schedule
annotations.
How could I properly inject @Stateless
beans in an @Named
applications scoped bean that would be instantiated on application startup?
This looks like an initialization ordering bug in GlassFish. The
@Eager @ApplicationScoped
runs in aServletContextListener
. Apparently at that point GlassFish hasn't EJBs ready for injection. This construct works in e.g. WildFly.However, in CDI's name of unifying various different depency injection approaches throughout Java EE, you can also just use
@Inject
instead of@EJB
. The CDI proxy is capable of delegating further to the right@Stateless
instance.You can also use
@Inject
inside EJBs itself, but as of now (Java EE 7) it doesn't yet support self-referencing for e.g.@Asynchronous
methods. For that you have still to stick to@EJB
.That said, are you aware that Oracle stopped commercial support on GlassFish and that you'd better not use it for production environments? See also this blog.