3

My problem is that one of my ViewScoped bean is created several time within the same view. The constructor of ViewScopedBean is created every time I select a node in the tree.

<h:form>
    <p:tree value="#{treeBean.root}" var="node"  
        selectionMode="single" selection="#{viewScopedBean.selectedNode}">  
        <p:ajax event="select" update="selectedNode, treeBeanUpdate, otherBeanUpdate, panel" listener="#{treeBean.onNodeSelect}" /> 
        <p:treeNode>  
            <h:outputText value="#{node}" />  
        </p:treeNode>  
    </p:tree>  
    Selected Node: <h:outputText value="#{viewScopedBean.selectedNode}" id="selectedNode"/><br/>
    Current TreeBean: <h:outputText value="#{treeBean}" id="treeBeanUpdate"/><br/>
    Current OtherBean: <h:outputText value="#{viewScopedBean}" id="otherBeanUpdate"/><br/>
    <p:outputPanel id="panel">
        <ag:profileComponent managedBean="#{viewScopedBean.profileBean}"/>
    </p:outputPanel>
</h:form>

If I remove this part (reference to a composite component), the constructor of ViewScopedBean is not called:

    <p:outputPanel id="panel">
        <ag:profileComponent managedBean="#{viewScopedBean.profileBean}"/>
    </p:outputPanel>

All the beans used are set as @ViewScoped.

@ManagedBean
@ViewScoped
public class ViewScopedBean implements Serializable {

    private TreeNode selectedNode;
    private ProfileBean profileBean;

    public ViewScopedBean() {
        System.out.println("Constructor of ViewScopedBean " + this);
    }

    @PostConstruct
    public void init() {
        System.out.println("ViewScoped init" + this);
        profileBean = new ProfileBean();
    }
}

Is it the correct behaviour? If not what can cause it?

Update: I tried to use an empty composite, and I have the same problem.

<?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:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">

      <composite:interface>
            <composite:attribute name="managedBean" required="true"/>
      </composite:interface>

      <composite:implementation>
      </composite:implementation>

</html>

But if I made the managedBean not required, that's fine.

Another thing I don't get is when the constructor is called, it seems that the object created is not used.

Initiating the view (console output):

Constructor of ViewScopedBean xxx.bean.ViewScopedBean@4e1d2b8e

2 clicks on the tree:

Constructor of ViewScopedBean xxx.bean.ViewScopedBean@4eb64f2e
Constructor of ViewScopedBean xxx.bean.ViewScopedBean@66863941

Then I open the debug window <ui:debug/>, the viewScopedBean is set to xxx.bean.ViewScopedBean@4e1d2b8e

Sydney
  • 11,964
  • 19
  • 90
  • 142
  • hmmm. This is VERY interesting. Can you try and throw an exception during the second (or third) instantiation? It would be good to see the stacktrace and see WHO is creating the ViewScopedBean and where. – fdreger Aug 03 '11 at 10:14
  • If I disabled the partial state saving, the constructor is actually called only once. – Sydney Aug 03 '11 at 14:57
  • [This answer](https://stackoverflow.com/questions/15265433/how-and-when-is-a-view-scope-bean-destroyed-in-jsf/15391453#15391453) to the question *"How and when is a view scope bean destroyed in JSF?"* might be relevant. – Lii Jan 20 '16 at 16:08

1 Answers1

1

The view scoped bean will be recreated on every request from/to the same view, when you use JSTL tags like <c:if>, <c:forEach> and so on in the view, or when you bind a JSF component as a property of the view scoped bean using binding attribute. That's apparently what's happening in your composite component.

You need to rewrite your composite component as such that it does not utilize any JSTL tags. Binding some JSF component as a property of the bean can also be avoided in many ways, but if that is really not avoidable, then disabling the partial state saving in web.xml should work in most of the cases:

<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>

If that doesn't work for you, then you really have to share your composite component implementation code with us so that we can point out the caveats and propose the right approaches.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    I updated my answer. I am not using JSTL. It seems that the same bean is shared within the same view but I don't understand why the constructor is called. – Sydney Aug 02 '11 at 18:21
  • What JSF impl/version exactly? Did you try disabling the partial state saving? – BalusC Aug 02 '11 at 18:22
  • I tried to disable the partial state saving. INFO: Initializing Mojarra 2.1.0 (FCS 20110303). For a `ViewedScope` bean, the constructor should be called only once when the view is displayed, is that right? – Sydney Aug 02 '11 at 18:37
  • I actually take that back, it's working with disabling partial state saving. Eclipse did not refresh the `web.xml` file. – Sydney Aug 03 '11 at 14:56
  • You're welcome. As to Eclipse, the `web.xml` is read only once during server's startup. You really need to restart the server after editing it! Only when you're using JRebel and a supported container, then you don't need to do that. – BalusC Aug 03 '11 at 15:02