Search code examples
jsfjsf-2annotationsmanaged-bean

Bean annotations like @ManagedProperty and @PostConstruct doesn't work when manually instantiating the bean from another bean


I instantiated a request bean from another request bean,

new LoginManager();

But the property which is annotated with @ManagedProperty doesn't get the value from the asked reference, only in case of instantiation through the above way. It just contains null, causing NPE later in code. Also @PostConstruct won't be invoked. Why is it so & how should I deal with this?

@ManagedBean(name = "loginManager")
@RequestScoped
public class LoginManager {

    private String userid;
    private String password;

    @ManagedProperty(value="#{currentSession}")
    private UserSessionManager userSession;

}

But userSession can't read from the session scoped bean when this bean was instantiated using: new LoginManager();

However I can read the value using FacesContext!


Solution

  • You should not manually instantiate (manage) beans using new operator. You should let JSF do the job of managing the beans and instead grab the JSF-managed (JSF-instantiated) instance.

    Either by @ManagedProperty in the bean where you need it:

    @ManagedProperty("#{loginManager}")
    private LoginManager loginManager;
    

    Or by invoking EL programmatically (which is pretty borderline in your particular case):

    LoginManager loginManager = context.getApplication().evaluateExpressionGet(context, "#{loginManager}", LoginManager.class);
    // ...
    

    If you insist in instantiating and managing the bean yourself, you should do all dependency injections yourself, also invoking the @PostConstruct yourself, if any, and finally also putting the bean in the desired scope yourself. E.g.

    LoginManager loginManager = new LoginManager();
    loginManager.setUserSession(userSession);
    // Now use reflection to find and invoke @PostConstruct method.
    // Finally store in the map which conforms the bean's scope.
    externalContext.getRequestMap().put("loginManager", loginManager);
    

    This boilerplate is exactly what JSF is supposed to take away from your hands. Make use of it.