Search code examples
scopecdipostconstruct

Scope of Stateless Bean


I got a stateless bean like the following:

@Stateless
public class MyBean implements IMyBean {

    @Inject
    private SomeClass someClass;
    @EJB
    private MyRepository myRepository;
    @Production
    @Inject
    private SomeFacade someWorker;

    @PostConstruct
    private void init() {
       // some logic ...
    }

    // some more logic...
}

IMyBean is annotated with @Local. I am running a JBoss Server. I got a .bat-file which uses MyBean. Only in the first execution of this bat-file the @PostConstruct gets called. Why is that? Which scope has MyBean? It seems like it's at least ApplicationScoped. I thought it would be RequestScope...


Solution

  • Your bean is an EJB before being a CDI bean. Therefore it follows the lifecycle of stateless EJB. The first time you request it, the container create it and call the @PostConstruct callback. When it's not needed anymore, it's not destroyed by returned to the EJB stateless pool, ready to be reused. From the CDI perspective it's a @Dependent bean: it's CDI part (proxy) is recreated each time you inject it, but the EJB part is provided by the EJB container from the pool. Looking at CDI spec, the section related to Lifecycle of stateless and singleton session beans states this regarding creation:

    When the create() method of a Bean object that represents a stateless session or singleton session bean is called, the container creates and returns a container-specific internal local reference to the session bean. This reference is not directly exposed to the application.

    and regarding the the destruction:

    When the destroy() method is called, the container simply discards this internal reference.

    Internal reference is discarded but the EJB container keep the bean for futur reuse. If more than one user ask for this bean at the same time a new EJB might be created and the @PostConstruct will be called. So from the user point of view postConstruct calls may seem random.

    The best solution is to put your stateless bean in @ApplicationScoped to avoid strange behavior.