JSF 2.0:为什么我的 ViewScope Bean 被重新创建,即使仍在同一视图上

发布于 2024-12-14 02:26:57 字数 2720 浏览 4 评论 0原文

在我的 .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>

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>

这是我的 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"));
        ...
    }
}

如您所见,我的 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>
....

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

单挑你×的.吻 2024-12-21 02:26:57

造成这种情况的可能原因有很多,最终都归结为先有鸡还是先有蛋的问题,如 中所述。 JSF 问题 1492。您正在使用 将 UI 组件绑定到视图范围的托管 bean 属性,或者您正在绑定标记处理程序的属性,例如 等到视图作用域托管 bean 属性。

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

另请参阅:

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:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文