1

I am working with Primefaces 3.5, Spring 3.2, JSF 2.2 and Apache is my server.

My problem is that whenever i click on the row, the row select event is never triggered in my backing bean and my store details panel is never updated.

My backing bean is in request scope and contains onRowSelect method. However when i change my backing bean to sessions scope(it requires a few changes in backing bean), instant row selection works.

For the simplicity of my question i have modified my code to include only relevant part. In my param, for the sake of testing i just put existing customer with ID 35 in my test page.

Here is my dialog.xhtml

    <h:form id="customerListingsForm">

    <p:dialog id="manageStoresDialog"
            header="Manage #{manageStoreBean.store.owner.name}'s Stores"
            widgetVar="manageStoresDlg"
            modal="true"
            resizable="false">


        <p:panelGrid id="storePanel" rendered="#{manageStoreBean.owner != null}">
            <f:facet name="header">
                <p:row>
                    <p:column>Store Details</p:column>
                    <p:column>Customer Store List</p:column>
                </p:row>
            </f:facet>

            <p:row>
                <p:column>
                    <p:panelGrid id="storeDetails">         
                        <p:row>
                            <p:column>Name: </p:column>
                            <p:column>
                                <h:inputText value="#{manageStoreBean.store.name}" />
                            </p:column>
                        </p:row>

                        <p:row>
                            <p:column>Description: </p:column>
                            <p:column>
                                <h:inputText value="#{manageStoreBean.store.description}" />
                            </p:column>
                        </p:row>

                        <p:row>
                            <p:column>Short Code: </p:column>
                            <p:column>
                                <h:inputText value="#{manageStoreBean.store.shortCode}" />
                            </p:column>
                        </p:row>

                        <p:row>
                            <p:column>Owner name:</p:column>
                            <p:column>
                                <h:inputText value="#{manageStoreBean.store.owner.name}" readonly="true" />
                            </p:column>
                        </p:row>

                        <p:row>
                            <p:column>Store Type: </p:column>
                            <p:column>
                                <p:selectOneMenu
                                        id="storeTypeSelected"
                                        value="#{manageStoreBean.placeType}"
                                        var="storeType"
                                        style="height:25px"
                                        converter="#{placeTypeConverter}">
                                    <f:selectItems 
                                            value="#{manageStoreBean.typeList}"
                                            var="storeTypeItem"
                                            itemLabel="#{storeTypeItem.code}"
                                            itemValue="#{storeTypeItem}"/>
                                    <p:column>#{storeType.description}</p:column>
                                </p:selectOneMenu>
                            </p:column>
                        </p:row>

                        <p:row>
                            <p:column>Country: </p:column>
                            <p:column>
                                <p:selectOneMenu
                                        id="storeCountrySelected"
                                        value="#{manageStoreBean.country}"
                                        var="country"
                                        style="height:25px"
                                        converter="#{countryConverter}">
                                    <f:selectItems 
                                            value="#{manageStoreBean.countryList}"
                                            var="countryItem"
                                            itemLabel="#{countryItem.isoNumericCode}"
                                            itemValue="#{countryItem}"/>
                                    <p:column>#{country.isoNumericCode}</p:column>
                                </p:selectOneMenu>
                            </p:column>
                        </p:row>

                        <p:row>
                            <p:column>Localisation: </p:column>
                            <p:column>
                                <p:selectOneMenu
                                        id="storeLocalisationSelected"
                                        value="#{manageStoreBean.localisationData}"
                                        var="storeLocal"
                                        style="height:25px"
                                        converter="#{localisationConverter}">
                                    <f:selectItems 
                                            value="#{manageStoreBean.localisationList}"
                                            var="local"
                                            itemLabel="#{local.regionCode}"
                                            itemValue="#{local}"/>
                                    <p:column>#{storeLocal.id} - #{storeLocal.regionCode}</p:column>
                                </p:selectOneMenu>
                            </p:column>
                        </p:row>
                    </p:panelGrid>
                </p:column>

                <p:column style="width:250px">
                    <p:dataTable id="stores" 
                            var="store" 
                            value="#{manageStoreBean.storeList}" 
                            rowKey="#{store.id}"
                            scrollHeight="240"
                            scrollable="true"
                            selectionMode="single"
                            selection="#{manageStoreBean.selectedStore}"
                            lazy="true">

                        <p:ajax event="rowSelect" immediate="true" 
                                listener="#{manageStoreBean.onRowSelect}"
                                update=":customerListingsForm:storeDetails"/>

                        <p:column headerText="Salon Name">
                            <h:outputText value="#{store.name}" />
                        </p:column>
                        <p:column headerText="ID">
                            <h:outputText value="#{store.id}" />
                        </p:column>
                    </p:dataTable>
                </p:column>
            </p:row>
        </p:panelGrid>

        <p:commandButton 
                value="Save"
                action="#{manageStoreBean.saveStore}"
                oncomplete="manageStoresDlg.hide()">
                <f:param name="storeCustomerId" value="#{manageStoreBean.owner.id}" />
        </p:commandButton>

        <h:outputText value="&nbsp;&nbsp;&nbsp;" />

        <p:commandButton 
                value="Close" 
                oncomplete="manageStoresDlg.hide()"/>
    </p:dialog>


    <p:commandButton value="Add Store" 
            oncomplete="manageStoresDlg.show()"
            update=":customerListingsForm:manageStoresDialog"
            process="@this">
        <f:param name="storeCustomerId" value="35" />
    </p:commandButton>


</h:form>

Also i'm new to primefaces and web dev, but did a lot of learning myself before i started this project. I spent 2 days try to understand what's wrong and searched all web but could not find any solution. May be i'm missing something or doing wrong not sure.

Any help is much appreciated.

2 Answers2

1

Try making your bean view scoped.

If you are making it request scoped, then you are telling JSF to throw out all of your existing data every time the user is done talking to your server. So it makes no sense to have JSF run a listener on an existing page. In particular, PrimeFaces has a tendency to malfunction when it encounters an odd set of scopes.

See also Difference between View and Request scope in managed beans

Community
  • 1
  • 1
patstuart
  • 1,931
  • 1
  • 19
  • 29
  • I thought about this but if i got to this way i would need to implement view scope for spring managed beans. But i want to avoid this. On the other hand i have another page similar to this one and it works perfectly fine with request scope bean. – Alexandr Dunaiskiy Aug 05 '13 at 02:25
  • There really isn't a good way around it. You should be able to call another bean which is session (or application) scoped, but you would be trying to fit a square peg into a round hole. If you run an ajax event on a request-scoped bean, then the only way the event will get called is if it creates *an entirely new bean*, meaning you can't reference any of your data. And calling a row select event on empty data doesn't make any sense. – patstuart Aug 05 '13 at 02:56
  • yes, you are correct. if i put my customer ID in bean constructor(for the sake of testing), the instant row selection works as it knows how to reload the table again. So i'm a bit confused? Why would it need to reload table again in order to make selection? – Alexandr Dunaiskiy Aug 05 '13 at 03:12
  • Because that's how you told it to behave when you said it was request-scoped. :) If you make something request-scoped, the server-side code will immediately delete any information it has as soon as it's done with each separate HTTP request. Try looking at this flow: - User makes request to load the page (HTTP request) - Server is done with HTTP request, so it deletes the bean - User selects a row. This creates an AJAX request. - Server creates a new bean to deal with the request. This bean doesn't have any of the information from the first bean. – patstuart Aug 05 '13 at 03:21
  • Ok, i see. Thanks for clearing some stuff for me. I'm still learning all this stuff. Is there anyway how i can pass param with my table, so that when new request is executed on row selection it will also include(in my case) customer id? – Alexandr Dunaiskiy Aug 05 '13 at 03:27
  • See [How do you pass a value into an ajax listener primefaces](http://stackoverflow.com/questions/9472212/how-do-you-pass-a-value-into-an-ajax-listener-primefaces) – patstuart Aug 05 '13 at 03:39
  • I know about setPropertyActionListener and i use it in my project but how i can add it to the table so it will be called before row select is called and my bean is prepared with list? what is a proper way to do that or event i need to call with ajax? – Alexandr Dunaiskiy Aug 05 '13 at 03:50
  • ``. But again, I'm not even sure this will work in a request-scoped bean. I really think your best option is view-scoped. – patstuart Aug 05 '13 at 03:58
  • still i need to add PropertyActionListenet to a parent of the type ActionSource and datatable is not. i get this error: Parent is not of type ActionSource, type is: org.primefaces.component.datatable.DataTable@55ecdb51 – Alexandr Dunaiskiy Aug 05 '13 at 04:15
  • If you read the link I posted, you'll see that the actionlistener is set on the p:ajax, not on the datatable. – patstuart Aug 05 '13 at 13:11
  • thanks for clearing this out. i knew about that. I just thought may be there is some trick you where talking about. The main problem is that "selection" in datatable happens always before any ajax rowSelect or rowUnselect happens. So I cannot use this ajax events to pass param. I did not realise that this is very hard, probably impossible. – Alexandr Dunaiskiy Aug 05 '13 at 21:25
0

By searching a lot of stuff on the internet i came to conclusion that datatable does not work very well with backing bean in request scope when table is loaded using dynamic argument. That is very shame. I do not see any other option but to implement viewscope in spring for my beans.