JSF 2.0 ViewScoped life cycle
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.selectedNod开发者_如何学Pythone}">
<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
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.
精彩评论