每次我在dataTable中单击commandButton时,都会重新创建ViewScoped bean

问题描述:

我使用原版3.1.1,Mojarra 2.1.3,Netbeans 7.0.1,Glassfish Server 3.1。

Im using primefaces version 3.1.1, Mojarra 2.1.3, Netbeans 7.0.1, Glassfish Server 3.1.

我的测试应用程序正在使用一个面版模板,左,内容,右和底部布局与原始div和CSS。用户使用容器管理的jdbcrealm登录后,将会显示使用该模板的主index.html。

My test application is using a facelet template with top, left, content, right and bottom layout with raw divs and css. After user logs in with container managed jdbcrealm, they will be presented with the main index.html which use the said template.

我在左侧面板上放置一个导航菜单,随后在点击菜单时用ajax更新中心面板内容。通过使用sessionScoped NavigationBean ,中心面板将以< ui:include> 动态更新。

I put a navigation menu on the left panel which will subsequently update center panel content with ajax upon clicking menuitem. The center panel will be updated dynamically in <ui:include> by using sessionScoped NavigationBean.

在其中一个页面 clientList.xhtml 中,我放了一个< p:dataTable> 通过弹出一个< p:dialog> 来查看细节。 Im使用viewCoped bean来保存dataTable上显示的数据列表。

In one of the page clientList.xhtml, I put a <p:dataTable> with a button to view the detail by popping up a <p:dialog>. Im using a viewCoped bean to hold the data list displayed on the dataTable.

问题是,当我点击按钮在每一行的最后一个列中选择一行时,对话框根本不会出现,而我的 p:ajaxStatus gif图像不间断地滚动。当我使用netbeans调试程序时,我注意到,再次调用构造函数,并且单击按钮后,前一个实例已经消失。

The problem is, when I click on the button to select a row in the last colum of every row, the dialog does not appear at all, and my p:ajaxStatus gif image kept on rolling unendingly. When I debug the program with netbeans, I notice the constructor is called again and the previous instance is gone after clicking the button.

这是我的 index.xhtml 使用facelets模板。

This is my index.xhtml using facelets template.

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:composition template="/BySalesAutomationTemplate.xhtml">
    <ui:define name="title">
        <h:outputText value="Facelet Index Page"></h:outputText>
    </ui:define>
    <ui:define name="top">
        TOP
    </ui:define>
    <ui:define name="left">
        <ui:include src="users/menu#{request.isUserInRole('ADMIN') ? 'Admin' : 'User'}.xhtml" />
    </ui:define>
    <ui:define name="right">
        <h:outputText value="Cuba2 daan"></h:outputText>
    </ui:define>
    <ui:define name="maincontent">
        <c:if test="#{navigationBean.page!=null}">
            <ui:include src="#{navigationBean.page}.xhtml" />
        </c:if>
    </ui:define> 
    <ui:define name="bottom">
        <center>2012</center> 
    </ui:define>
  </ui:composition>
</html>

这是 clientList.xhtml 页面在左侧面板中点击菜单上的链接后,会显示在index.xhtml的中心面板中。

This is the clientList.xhtml page which is displayed in the center panel of my index.xhtml upon clicking a link on the menu in the left panel.

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
<h:head>
    <title>Client Listing</title>
</h:head>
<h:body>
    <p>Client List</p>
    <h:form>
        <h:commandButton action="#{authBackingBean.logout}" value="Logout" />
    </h:form>
    <f:view>
        <h:form id="formdetail" prependId="false">
            <p:ajaxStatus>
                <f:facet name="start">
                    <h:graphicImage value="images/loading.gif" />
                </f:facet>
                <f:facet name="complete">
                    <h:outputText value="" />
                </f:facet>
            </p:ajaxStatus>
            <p:growl id="growl" showDetail="true"/>
            <p:dataTable id="dtClientList" value="#{saClientController.lazyModel}" rowsPerPageTemplate="10,20,30,50" 
                         paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" 
                         paginatorAlwaysVisible="false" var="item" paginator="true" rows="10">
                <f:facet name="header">
                    <h:outputText value="Client List"/>
                </f:facet>
                <p:column filterBy="#{item.idSaClient}">
                    <f:facet name="header">
                        <h:outputText value="IdSaClient"/>
                    </f:facet>
                    <p:commandLink action="#{saClientController.showDetails(item)}" value="#{item.idSaClient}" target=":maincontent"/>                        
                </p:column>
                <p:column filterBy="#{item.saClientName}">
                    <f:facet name="header">
                        <h:outputText value="saClientName"/>
                    </f:facet>
                    <h:outputText value="#{item.saClientName}"/>
                </p:column>
                <p:column filterBy="#{#item.saClientAddress}">
                    <f:facet name="header">
                        <h:outputText value="SaClientAddress"/>
                    </f:facet>
                    <h:outputText value="#{item.saClientAddress}"/>
                </p:column>
                <p:column style="width:40px">  
                    <h:panelGrid columns="3" styleClass="actions" cellpadding="2">  
                        <p:commandButton id="selectButton" update=":formdetail:display" oncomplete="clientDialog.show()" icon="ui-icon-search" title="View">                                  
                            <f:setPropertyActionListener value="#{item}" target="#{saClientController.selectedSaClient}" />  
                        </p:commandButton>  
                    </h:panelGrid>  
                </p:column>  
                <f:facet name="footer">
                    <h:outputText value="Client List"/>
                </f:facet>
            </p:dataTable>                      
        </h:form>

        <p:dialog id="clientDialog" header="Client Detail" widgetVar="clientDialog" resizable="false" showEffect="explode" hideEffect="explode">
            <h:panelGrid id="display" columns="2" cellpadding="4"> 
                 <f:facet name="header"> 
                     <h:outputText value="Selected Row" />
                 </f:facet> 
                 <h:outputText value="ID" />
                 <h:outputText value="#{saClientcontroller.selectedSaClient.idSaClient}" />
                 <h:outputText value="NAME:" /> 
                 <h:outputText value="#{saClientcontroller.selectedSaClient.saClientName}" /> 
                 <h:outputText value="DESCRIPTION:" />  
                 <h:outputText value="#{saClientcontroller.selectedSaClient.saClientAddress}" />  
             </h:panelGrid>
        </p:dialog>                   

    </f:view>
  </h:body>
</html>

这是我的Backing Bean。

This is my Backing Bean.

public class SaClientController implements Serializable {

    @EJB
    private SaClientFacade saClientFacade;
    private SaClient selectedSaClient;
    private LazyDataModel<SaClient> lazyModel;
    private List<SaClient> saclients;

    /** Creates a new instance of SaClientController */
    public SaClientController() {
    }

    @PostConstruct
    public void Init() {
        saclients = saClientFacade.Retrieve();
        lazyModel = new LazyDataModelImp(saclients);
    }

    public LazyDataModel<SaClient> getLazyModel() {
        return lazyModel;
    }

    public List<SaClient> getClients() {
        return saClientFacade.Retrieve();
    }

    public SaClient getDetails() {
        return selectedSaClient;
    }

    public String showDetails(SaClient selectedSaClient) {
        this.selectedSaClient = selectedSaClient;
        return "DETAILS";
    }

    public String update() {
        System.out.println("###UPDATE###");
        selectedSaClient = saClientFacade.Update(selectedSaClient);
        return "SAVED";
    }

    public String list() {
        System.out.println("###LIST###");
        return "LIST";
    }

    public SaClient getSelectedSaClient() {
        return selectedSaClient;
    }

    public void setSelectedSaClient(SaClient selectedSaClient) {
        this.selectedSaClient = selectedSaClient;
    }

    public String dummyAction()
    {
        return null;
    }
}

这是 LazyModelImp class

public class LazyDataModelImp extends LazyDataModel<SaClient> {

    private List <SaClient> datasource;

    public LazyDataModelImp(List<SaClient> datasource) {
        this.datasource = datasource;
    }

    @Override
    public SaClient getRowData(String rowKey) {
        for (SaClient saclient : datasource) {
            if (saclient.getIdSaClient().toString().equals(rowKey)) {
                return saclient;
            }
        }
        return null;
    }

    @Override
    public Object getRowKey(SaClient saclient) {
        return saclient.getIdSaClient().toString();
    }

    @Override
    public List<SaClient> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        List<SaClient> data = new ArrayList<SaClient>();
        //filter        
        for (SaClient saclient : datasource) {
            boolean match = true;
            for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                try {                    
                    String filterProperty = it.next();
                    String filterValue = filters.get(filterProperty);
                    String fieldValue = String.valueOf(saclient.getFilterSortFieldValue(filterProperty));
                    if (filterValue == null || fieldValue.startsWith(filterValue.toUpperCase()) || fieldValue.startsWith(filterValue.toLowerCase())) {
                        match = true;
                    } else {
                        match = false;
                        break;
                    }
                } catch (Exception e) {
                    match = false;
                }
            }
            if (match) {
                data.add(saclient);
            }
        }
        //rowCount
        int dataSize = data.size();
        this.setRowCount(dataSize);
        //paginate
        if (dataSize > pageSize) {
            try {
                return data.subList(first, first + pageSize);
            } catch (IndexOutOfBoundsException e) {
               return data.subList(first, first + (dataSize % pageSize));
            }
        }
        else {
            return data;
        }
        //sort
        //if (sortField != null) {
        //    Collections.sort(data, new LazySorter(sortField, sortOrder));
        //}       
        //return data;
    }
}

我已经禁用部分状态保存在 web.xml

I've already disabled the partial state saving in web.xml.

<context-param> 
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
    <param-value>false</param-value> 
</context-param> 

在第一次单击dataTable的最后一列的view detail commandButton时,backingBean被重新初始化在 clienList.xhtml 中。而对话框根本不显示。但按F5后。对话框可以显示但没有任何内容,对话框中显示的唯一标签是outputText,但不是bean值,它们是空的。对不起新手问题。我会非常高兴,如果有人可以建议我做什么是错误的,也许有一点建议导航,以及我的策略显示在 index.xhtml (所以我只有一个视图id始终是 index.xhtml ,对吗?)是对的。

The backingBean is reinitialized the first time I click on the view detail commandButton in the last column of the dataTable in clienList.xhtml. And the dialog does not display at all. But after pressing F5. The dialog can be displayed but without any content, the only thing displayed in the dialog is the label outputText but not the bean values, they are empty. Sorry for newbie question. I will be extremely glad if anyone could advise what im doing is wrong, and maybe a little advise on the navigation and whether my strategy of displaying everything in index.xhtml (so I only have 1 view id all the time which is index.xhtml, right?) is right.

这可能是您的PrimeFaces对话框的问题,您有一个 h:form 围绕 p:dialog 。我注意到,当一个表单元素的子元素时,PrimeFaces对话框无法正常工作。

This may be the issue with your PrimeFaces dialog that you have an h:form surrounding the p:dialog. I have noticed the PrimeFaces dialog does not work properly when a child of a form element.

尝试将此对话窗体放在对话框的内容中。

Try placing this dialog form inside of the contents of the dialog.

<p:dialog id="clientDialog" header="Client Detail" widgetVar="clientDialog" resizable="false" showEffect="explode" hideEffect="explode">
  <h:form id="formdialog" prependId="false">
    <h:panelGrid id="display" columns="2" cellpadding="4">
    ...