Injecting @EJB in OmniFaces @Eager bean causes “Se

2019-06-22 16:03发布

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?

1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-06-22 16:29

This looks like an initialization ordering bug in GlassFish. The @Eager @ApplicationScoped runs in a ServletContextListener. 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.

@Inject
private MyService myService;

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.

查看更多
登录 后发表回答