Search code examples
jsfconstructormanaged-bean

Why is the bean constructor called twice?


Why 'UserBean' is created twice? It happens when I visit the page first time. Next times the bean creates once. It has a default constructor with system out. So why does it happen?

<h:body>
    <h3>#{userBean.requestParametr}</h3>

    <h:form id="form">
        <p:panel id="panel">
            <h:panelGrid columns="3">
                <h:outputLabel for="email" value="E-mail: " />

                <p:inputText id="email"
                             value="#{userBean.email}"
                             required="true"
                             label="E-mail">
                </p:inputText>

                <h:outputLabel for="password" value="#{msg['_password']}: " />

                <p:inputText type="password" id="password"
                             value="#{userBean.password}"
                             label="#{msg['_password']}"
                             required="true">
                </p:inputText>
            </h:panelGrid>

            <p:commandButton id="btn" value="#{msg['_enter']}" update="panel"
                             action="#{userBean.login}" />
        </p:panel>
    </h:form>
</h:body>

Solution

  • It has a default constructor with system out

    That will happen when you're using a bean management framework which uses proxies, such as CDI (i.e. the bean is annotated with @Named, this is also confirmed by looking at your previous question). It'll during the first-time use create an instance in order to inspect the instance before creating a proxy. All subsequent instantiations are done through the proxy class.

    You're at least not supposed to do anything in the bean constructor. Instead, use a method annotated with @PostConstruct if you intend to hook on managed bean initialization. And, use a method annotated with @PreDestroy if you intend to hook on managed bean destroyment.

    @Named
    public class Bean {
    
        @PostConstruct
        public void init() {
            // ...
        }
    
        @PreDestroy
        public void destroy() {
            // ...
        }
    
    }
    

    Method names are free to your choice. The above are just canonical names, taken over from several existing APIs, such as servlets and filters, hereby improving self-documentability of the code.