Search code examples
ajaxjsfprimefacesview-scope

@ViewScoped @PostContruct is called upon every ajax request


Using Primefaces 5.0, JSF 2.2.7, deployed on EAP 6.1.

I have this Managed Bean below.

import hh.bean.Service;
import hh.dao.ServiceDao;
import hh.dao.impl.ServiceDaoImpl;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class View1 implements Serializable {

    private static final long serialVersionUID = 1L;

    private ServiceDao serviceDao = new ServiceDaoImpl();

    @PostConstruct
    public void init() {
        System.out.println(View1.class.getName() + ": init() " + this);
    }

    public List<Service> getServices(){
        return serviceDao.getAllServices();
    }
}

I'm calling it from the xhtml below.

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>
    <title>Home Web</title>
    <f:facet name="first">
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta http-equiv="Content-Type"
            content="text/html; charset=UTF-8" />
        <meta name="viewport"
            content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
    </f:facet>
</h:head>

<h:body>
    <h:outputStylesheet library="css" name="newcss.css" />
    <p:dataTable var="service" value="#{view1.services}">
        <p:column style="width:16px">
            <p:rowToggler />
        </p:column>
        <p:column headerText="Id">
            <h:outputText value="#{service.id}" />
        </p:column>

        <p:column headerText="xxxx">
            <h:outputText value="#{service.description}" />
        </p:column>

        <p:rowExpansion>
            <p:dataTable var="sv" value="#{view1.services}">
                <p:column headerText="Id">
                    <h:outputText value="#{sv.id}" />
                </p:column>
            </p:dataTable>
        </p:rowExpansion>
    </p:dataTable>
</h:body>
</html>

I noticed every time I expand the row my init() gets called. I thought @ViewScoped lives on when the request stays on the same page.

When I switch to @SessionScoped, init() does not get called when I expand a row.

Edit 1: Put the entire xhtml in, specify jsf version/impl

Edit 2: Fixed this issues by surrounding the p:dataTable with h:form. Not sure why that fixed it...


Solution

  • Fixed this issues by surrounding the p:dataTable with h:form. Not sure why that fixed it...

    The JSF view state is maintained by javax.faces.ViewState hidden input field of the <h:form>. If you don't use a <h:form>, then PrimeFaces won't be able to find that hidden input field in order to pass its value along with the jQuery ajax request.

    If this information is absent in the (ajax) request, then JSF will simply create a brand new view and inherently also all view scoped beans associated with it.