Search code examples
javadependency-injectionejbentitymanager

Inject @Named , @Stateful to @Singleton EJB


Is there any way to inject @Named bean to Singleton?

Here's the class that needs to be injected

@Named
@Stateful
@ConversationScoped
public class PlaySessionBean implements Serializable {
    @PersistenceContext(unitName = "test-persistence-unit", type = PersistenceContextType.EXTENDED)
    private EntityManager entityManager;
....
}

The bean is used for view utility (generated by Forge)

The problem is that I need to access the PlaySessionBean from @Startup @Singleton

@Startup
@Singleton
public class StartupBean {
  private static final Logger LOGGER = Logger.getLogger(StartupBean.class.getName());

  private EntityManager entityManager;
  private static EntityManagerFactory factory =
      Persistence.createEntityManagerFactory("wish-to-paris-persistence-unit");
  private List<PlaySession> playSessions;

  @PostConstruct
  public void run() {
    this.entityManager = factory.createEntityManager();
    CriteriaQuery<PlaySession> criteria =
        this.entityManager.getCriteriaBuilder().createQuery(PlaySession.class);
    this.playSessions =
        this.entityManager.createQuery(criteria.select(criteria.from(PlaySession.class)))
            .getResultList();
    this.entityManager.close();
  }
 ....

But it always failed and complained that PlaySession is not an Entity

Is there a way to inject the Named Stateful bean to Singleton? If not, is there any workaround for it?

Thanks


Solution

  • You are mixing CDI scoping with EJB states. I would rather that you choose either CDI or EJB but not mix the 2. For one, transaction management is different between the 2 architectures. Also, the life cycle of each objects are completely different.

    If you are going to use EJB and call the respective session bean, you can annotate your @Stateful Session Bean as a @LocalBean since your session bean as no interface inheritance.

    Example:

    @Stateful
    @LocalBean
    public class PlaySessionBean implements Serializable {
    
    }
    

    Then on your @Startup Singleton bean, you can simply reference it by:

    @EJB
    private PlaySessionBean playSessionBean;
    

    The EJB Session Bean will still be stateful.