JSF 2.0:为什么我的 ViewScope Beans 仍然在同一个 View 上重新创建 [英] JSF 2.0: Why my ViewScope Beans is re-created even though still on same View

查看:17
本文介绍了JSF 2.0:为什么我的 ViewScope Beans 仍然在同一个 View 上重新创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 .xhtml 页面中,我有以下形式:

<ui:define name="formContent"><h:形式><p:dataGrid var="item" value="#{mrBean.items}" columns="3"><p:列><p:panel header="#{item.name}"><h:panelGrid columns="1" style="width:100%">...<h:commandButton value="添加到购物车" actionListener="#{cartBean.addItem(item.id)}"/>...</h:panelGrid></p:面板></p:列></p:dataGrid></h:form></ui:define></ui:composition>

CustomerTemplate.xhtml 是:

<h:头><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>...//导入 css、js 文件</h:head><h:body>...//页面上的其他内容<div class="grid_9 内容"><ui:insert name="contentTitle"></ui:insert><ui:insert name="formContent"></ui:insert>

...</h:body>

这是我的 ManagedBean:

@ManagedBean@ViewScoped公共类 MrBean {...私人列表项目;...@PostConstruct公共无效prepareItemList(){...映射<字符串,字符串>params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();partnerID = Long.parseLong(params.get("partnerID"));...}}

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

如果有人可以就如何解决这个问题给我建议,我将不胜感激.

更新:我设法通过将 commandButton 包裹在 ajax 标签中来使该函数正常工作,如下所示:

<代码>...<f:ajax listener="#{cartManagedBean.addItem(item.id)}"><h:commandButton value="加入购物车"/></f:ajax>....

解决方案

造成这种情况的原因有很多,最终都归结为 JSF 问题 1492.您正在使用 <h:someHtmlComponent binding="..."> 将 UI 组件绑定到视图范围的托管 bean 属性,或者您正在绑定标记处理程序的属性,例如, 等一个视图范围的托管 bean 属性.

这计划在 JSF 2.2 中修复.在此之前,最好的办法是寻找替代方法或将上下文参数 javax.faces.PARTIAL_STATE_SAVING 设置为 false.

另见:

In my .xhtml page, I have the following form:

<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>

The CustomerTemplate.xhtml is:

<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>

And this is my 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"));
        ...
    }
}

As you can see, my MrBean is a ViewScoped ManagedBean. I expected that the @PostContruct function will only be called once when the page is 1st rendered. However, when I click the Add To Cart button, I ran into the null exception at the line Long.parseLong(params.get("partnerID")) even though I am still on the same View.

I'd be very grateful if someone could give me an advice on how to tackle this problem.

UPDATE: I managed to get the function working by wrapping the commandButton inside an ajax tag like following:

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

解决方案

There are a lot of possible reasons for this which all ultimately boils down to the chicken-egg issue as described in JSF issue 1492. You are using <h:someHtmlComponent binding="..."> to bind an UI component to a view scoped managed bean property, or you are binding an attribute of a tag handler like <c:if test="...">, <ui:include src="...">, etc to a view scoped managed bean property.

This is scheduled to be fixed in JSF 2.2. Until then, your best bet is to look for alternative approaches or to set the context parameter javax.faces.PARTIAL_STATE_SAVING to false.

See also:

这篇关于JSF 2.0:为什么我的 ViewScope Beans 仍然在同一个 View 上重新创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆