Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF 2.0: Why my ViewScope Beans is re-created even though still on same View [duplicate]

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>
....
like image 288
Mr.J4mes Avatar asked Nov 06 '11 09:11

Mr.J4mes


1 Answers

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:

  • Communication in JSF 2.0 - @ViewScoped fails in tag handlers
like image 134
BalusC Avatar answered Nov 06 '22 18:11

BalusC