Question

I'm trying to understand why a viewscoped view is recreating on every ajax call.

I have a test case, and it's working fine without composition templating.

I find questions that seem similar to my problem but the solutions don't work for me, like setting javax.faces.PARTIAL_STATE_SAVING to false or javax.faces.STATE_SAVING_METHOD to client.

Here's a sample:

page.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>

<h:body>
    <h:form id="pageForm">

        <p:commandButton 
            value="Choose an option..."
            actionListener="#{pageController.handleOptionChoose}" 
            update="selectedOption"
        />

        <br/>

        <h:panelGrid columns="2" cellpadding="3">
            <p:outputLabel for="selectedOption" value="Selected option: "/>
            <p:outputLabel id="selectedOption" value="#{pageController.selectedOption}"/>
        </h:panelGrid>

        <br/><br/>  

        <p:commandButton 
            value="Edit option"
            actionListener="#{pageController.doAnythingWithTheOption}" 
            update="editedOption"
        />

        <br/>

        <h:panelGrid columns="2" cellpadding="3">
            <p:outputLabel for="editedOption" value="Edited option: "/>
            <p:outputLabel id="editedOption" value="#{pageController.editedOption}"/>
        </h:panelGrid>

    </h:form>

    <p:dialog 
        id="dialogOption_Dialog" 
        header="Choose an option" 
        widgetVar="dialogOption_Widget"
        modal="true"
        appendTo="@(body)"
    >
        <h:form id="dialogOption_Form">
            <h:panelGrid columns="1">

                <p:selectOneButton id="dialogOptionChoose" value="#{pageController.selectedOption}" >
                    <f:selectItem itemLabel="Option 1" itemValue="Option 1" />
                    <f:selectItem itemLabel="Option 2" itemValue="Option 2" />
                    <f:selectItem itemLabel="Option 3" itemValue="Option 3" />
                </p:selectOneButton>

                <p:spacer width="0" height="20" />

                <p:commandButton 
                    value="Done"
                    action="#{pageController.showOption}"
                    update=":pageForm:selectedOption"
                    oncomplete="dialogOption_Widget.hide();"
                />

            </h:panelGrid>
        </h:form>  
    </p:dialog>

</h:body>

</html>

content.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:mj="http://mojarra.dev.java.net/mojarra_ext"
    xmlns:o="http://omnifaces.org/ui"
    xmlns:of="http://omnifaces.org/functions">
<h:body>
    <ui:composition template="/layout.xhtml">
        <ui:define name="content">
            <ui:include src="page.xhtml" />
        </ui:define>
    </ui:composition>
</h:body>

</html>

layout.xhtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:o="http://omnifaces.org/ui"
      xmlns:of="http://omnifaces.org/functions">

    <f:view contentType="text/html" transient="true">
        <h:head>
            <h:outputStylesheet name="theme.css" library="css" />
            <f:facet name="first">
                <f:metadata>
                    <meta http-equiv="X-UA-Compatible" content="IE=8" />
                </f:metadata>
                <title>Teste</title>
                <link rel="icon" type="image/png" href="resources/css/icons/favicon.ico" />
            </f:facet>
        </h:head>


        <h:body>
            <p:layout fullPage="true" >

                <p:layoutUnit id="top" position="north" size="50" style="border: 2px solid Black !important;">
<!--                <ui:insert name="menubar" /> -->
                </p:layoutUnit>

                <p:layoutUnit id="center" position="center" style="border: 2px solid Black !important;">
                    <ui:insert name="content" />
                </p:layoutUnit>

                <p:layoutUnit id="bottom" position="south" size="60" resizable="true" collapsible="true" style="border: 2px solid Black !important;">
<!--                <ui:insert name="footer" /> -->
                </p:layoutUnit>

            </p:layout>

        </h:body>

    </f:view>
</html>

PageController.java

package com.ericsantanna.grendel.mBeans;

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

import org.primefaces.context.RequestContext;

/**
 * @author Eric Sant'Anna
 *
 */
@ManagedBean
@ViewScoped
public class PageController {

    private String selectedOption;

    private String editedOption;

    public PageController() {
        System.out.println("RECREATING VIEW");
    }

    public void showOption()    {
        System.out.println("Selected option number: " + selectedOption.substring(7));
    }

    public void doAnythingWithTheOption()   {
        System.out.print("Trying to a substring in the selected option: ");
        editedOption = selectedOption.substring(7);
        System.out.println(editedOption);
    }

    public void handleOptionChoose()    {
        RequestContext.getCurrentInstance().execute("dialogOption_Widget.show();");
    }

    public String getSelectedOption() {
        return selectedOption;
    }

    public void setSelectedOption(String selectedOption) {
        this.selectedOption = selectedOption;
    }

    public String getEditedOption() {
        return editedOption;
    }

    public void setEditedOption(String editedOption) {
        this.editedOption = editedOption;
    }

}

JBoss log (setup):

17:45:29,494 INFO  [org.jboss.ejb.client] (MSC service thread 1-7) JBoss EJB Client version 1.0.5.Final
17:45:29,550 INFO  [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-8) Inicializando Mojarra 2.2.4 ( 20131003-1354 https://svn.java.net/svn/mojarra~svn/tags/2.2.4@12574) para o contexto '/JobSchedulerWeb'
17:45:30,344 INFO  [org.hibernate.validator.util.Version] (MSC service thread 1-8) Hibernate Validator 4.2.0.Final
17:45:30,367 INFO  [org.primefaces.webapp.PostConstructApplicationEventListener] (MSC service thread 1-8) Running on PrimeFaces 4.0
17:45:30,368 INFO  [org.omnifaces.eventlistener.VersionLoggerEventListener] (MSC service thread 1-8) Using OmniFaces version 1.5

To reproduce this code, simply choose an option and click "Edit option" to do a substring in the backing bean, only to get a NullPointerException when using facelets templating. (Look at the console in each step)

Anyone can help?

Was it helpful?

Solution

This,

<f:view ... transient="true">

turns off JSF state saving for the current view. Essentially, this JSF view is stateless. As there's no view state, there's no means of a view scope and the logical consequence is that the view scoped bean instance can't be saved anywhere. It'll disappear in nowhere by end of the request and thus behave like a request scoped bean.

The observed symptoms are thus fully expected. If that wasn't your intent, then you need to remove the transient="true" attribute. It defaults to false.

This has completely nothing to do with templating. The <ui:composition> plays no significant role here. You'd have had exactly the same problem when merging the templates into a single template without <ui:composition>, <ui:define>, etc while keeping the same markup.

See also:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top