JSF 2.0:为什么我的ViewScope Bean重新创建,即使它仍然在同一个View上

Mr.*_*mes 7 java scope exception jsf-2

在我的.xhtml页面中,我有以下表格:

<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
            template="./../template/CustomerTemplate.xhtml"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:p="http://primefaces.prime.com.tr/ui">

    <ui:define name="formContent">
        <h:form> 
            <p:dataGrid var="item" value="#{mrBean.items}" columns="3">
                <p:column>
                    <p:panel header="#{item.name}">
                        <h:panelGrid columns="1" style="width:100%">
                            ...
                            <h:commandButton value="Add To Cart" actionListener="#{cartBean.addItem(item.id)}" />
                            ...
                        </h:panelGrid>
                    </p:panel>
                </p:column>
            </p:dataGrid> 
        </h:form> 
    </ui:define>

</ui:composition>
Run Code Online (Sandbox Code Playgroud)

CustomerTemplate.xhtml是:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        ... // import css, js files
    </h:head>

    <h:body>
        ... // Other things on the page
        <div class="grid_9 content">
            <ui:insert name="contentTitle"></ui:insert>
            <ui:insert name="formContent"></ui:insert>
        </div>
        ...
    </h:body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是我的ManagedBean:

@ManagedBean
@ViewScoped
public class MrBean {
    ...
    private List<ItemState> items;
    ...

    @PostConstruct
    public void prepareItemList() {
        ...
        Map<String,String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
            partnerID = Long.parseLong(params.get("partnerID"));
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我的MrBean是一个ViewScoped ManagedBean.我预计@PostContruct函数只会在第一次呈现页面时调用一次.但是,当我单击Add To Cart按钮时,Long.parseLong(params.get("partnerID"))即使我仍然在同一个视图上,我也会遇到该行的null异常.

如果有人能就如何解决这个问题给我一个建议,我将非常感激.

更新:我设法通过将commandButton内部包装成ajax如下标记来使函数正常工作:

...
<f:ajax listener="#{cartManagedBean.addItem(item.id)}">
    <h:commandButton value="Add To Cart" /> 
</f:ajax>
....
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 7

这有很多可能的原因,最终归结为JSF问题1492中描述的鸡蛋问题.您正在使用<h:someHtmlComponent binding="...">绑定的UI组件到视图范围内管理bean的属性,或者你正在结合标记处理程序等的属性<c:if test="...">,<ui:include src="...">等等,以期范围内管理bean属性.

计划在JSF 2.2中修复.在此之前,您最好的选择是寻找替代方法或将上下文参数设置javax.faces.PARTIAL_STATE_SAVINGfalse.

也可以看看:

  • 我不是那个意思.我的意思是宁愿做`<h:commandButton value ="添加到购物车"action ="#{cartManagedBean.addItem(item.id)}"> <f:ajax /> </ h:commandButton>`.您的问题更新仅显示不完整的代码.它必须是最小的copy'n'paste'n'runnable片段,它仍然可以重现问题.您必须将现有代码复制到单个测试视图和bean中,然后逐步删除部分,直到问题不再发生,然后再退一步并发布.同时删除不相关的属性,如类,样式等,将有助于最大限度地减少代码段. (4认同)
  • @BalusC你在过去4年中多次挽救了我的生命...非常感谢你... (3认同)