Search code examples
jakarta-eeconstructorcdimanaged-bean

Why is constructor of CDI bean class called more than once


I have annotated a class with @ApplicationScoped. With @Inject I get instances of this class injected into several @RequestScopded JAX-RS services:

@ApplicationScoped
public class MySingleton {
  MySingleton() {
    System.out(this + " created.");
  }
}

@RequestScoped
public class MyRS {
  @Inject MySingleton mySingleton;
  public void someMethod() {
    // do something with mySingleton
  }
}

Basically this works fine. Howeger, at least when I run this in WebSphere 8.5 the constructor of MySingleton is invoked twice, resulting in output like

my.package.MySingleton_$$_javassist_26@cddebf9b created.
my.package.MySingleton@e51e26d1 created.

I planned to do some expensive initialization in the constructor, which would obviously be executed twice.

I believe that one of the constructor calls is for generating some kind of proxy for the actual "worker" instance. But how can I avoid having my initialization code executed twice? The "solution" to do a lazy initialization in all methods of MySingleton is not very attractive.


Solution

  • The constructor of managed beans may be called by the container also for creating proxies. For any "real" initialization Java EE therefore provides the annotation @PostConstruct. In an @ApplicationScoped bean a method annotated with @PostConstruct is called exactly once by the container:

    @ApplicationScoped
    public class MySingleton {
      MySingleton() {
        System.out(this + " created.");
      }
      @PostConstruct
      init() {
        System.out(this + " initd.");
      }
    }
    

    Output:

    my.package.MySingleton_$$_javassist_26@cddebf9b created.
    my.package.MySingleton@e51e26d1 created.
    my.package.MySingleton@e51e26d1 initd.
    

    Related question: Why use @PostConstruct?