7 Replies Latest reply on Aug 24, 2009 9:39 PM by christofvanhove

    s:selectItems doesn't reload when object is added to backing collection

    coresystems_rit

      Hi


      I have a question about s:selectItems and reloading its content.


      JSF source:


      "<ice:selectOneMenu id="itBusinessPartnerDefaultContact"
                         value="#{selectedBusinessPartner.businessPartnerDefaultContact.contact}"
                         partialSubmit="true">
           <s:selectItems var="contact" value="#{selectedBusinessPartner.contacts}" label="#{contact.name}"/>
           <s:convertEntity/>
      </ice:selectOneMenu>"



      The strange behaviour is this: If I add an object to the selectedBusinessPartner.contacts collection, the ui doesn't update the selectOneMenu. As far as I understand this, the s:selectItem doesn't reload the data. If I replace the selectedBusinessPartner.contacts collection with a new one (get the old one, create a new list, put all the objects from the old collection into it, set the new collection as contacts, it reloads the data. Why is this behaviour?


      (Tha backing collection is a LinkedList)

        • 1. Re: s:selectItems doesn't reload when object is added to backing collection
          gena

          Hi,


          i've got a similar behaviour. I sent onchange an ajax event from such a selectOneMenu (it's a h:selectOneMenu but i don't think, this difference does matter) and after all i updated the selectItems collection. But i also found out: as soon as i submit new value from a selectOneMenu (the converter works and retrieves the selectItems collecton during applying the request values or so), after response, the corresponding part of response page is not updated correctly (other selectItems were also modified within the controller during the same request, but haven't submitted some meaningful new value and were also updated correctly after rerendering them).


          I will try you suggestion with the replacement of a collection with a new one, but i think, this is not the finest way to resolve the problem.


          Gena

          • 2. Re: s:selectItems doesn't reload when object is added to backing collection
            coresystems_rit

            Hi Gena


            We are using ICEfaces so we don't send a manual ajax event. But it looks like we experience the same problem. The collection behind the selectOneMenu gets updated by a different part of the same site (s:link which calls a method on the backing seam component).


            It is definitly not a solution to the problem, but as a workaround. I am not sure if this is a problem with the seam framework or with my understanding of the s:selectItems (or better say the architecture of s:selectItems).


            Could this be a problem because we use the ICEfaces framework? Or better say, who is responsible for rerendering the selectItems tag?

            • 3. Re: s:selectItems doesn't reload when object is added to backing collection
              jguglielmin

              would this not depend on which scope the list was in?  Do you really want the list updated each and every time the view is refreshed or just when the list is changed which, with ICEfaces, you could simply implement a push (using OnDemandRenderer or SessionRenderer) from the backing bean upon successful update of the list (or any change in the list for that matter).  But...this push would have to include the generation of a new list of course. 

              • 4. Re: s:selectItems doesn't reload when object is added to backing collection
                gena

                Hi Thierry,


                it's a bug the line 159 within the Method Object org.jboss.seam.ui.component.UISelectItems.getValue():


                Line 159: if (selectItems == null || originalValue == null || !originalValue.equals(super.getValue())) 
                
                



                and as you can see, originalValue.equals(super.getValue()) is always true as of implementation of AbstractList


                Line 479: AbstractList.equals  if (o == this) return true



                So if our base collection still be the same, selectItems doesn't refresh. And this occurs, if the selectItems was already initialized within the same request but with another count of elements (ie. for validate/convert the applied request values) there is no chance to refresh the selectItems unless recreating the collecion - so it's a bug. The new collection resolves the problem, because is not equals to cached one as of AbstractList contract.


                Gena

                • 5. Re: s:selectItems doesn't reload when object is added to backing collection
                  coresystems_rit

                  Hi Gena


                  Thanks for your answer! Now it is clear. I haven't found an issue in the jira of Seam. Is this behaviour intended by the developers or should one open a bug report?


                  Thanks for the help, haven't seen this if check in the UISelectItems source code.


                  Thierry

                  • 6. Re: s:selectItems doesn't reload when object is added to backing collection
                    lbilger

                    Hi all,


                    note that this is even more of a problem if the change is not in the structure of the list, but in an element within the list. What I mean is something like this:




                    public class MyEntity {
                        private String name;
                        //...
                    // getters and setters
                    }
                    
                    public class MyBackingBean {
                        private List<MyEntity> myEntities;
                    // getters and setters
                        public void renameSomeEntity() {
                            myEntities.get(0).setName("new name");
                        }
                    }
                    
                    <ice:selectOneMenu value="#{myBackingBean.foo}" partialSubmit="true">
                        <s:selectItems var="item" value="#{myBackingBean.myEntities}" label="#{item.name}"/>
                        <s:convertEntity/>
                    </ice:selectOneMenu>



                    Even if I did add myEntities = new ArrayList<MyEntity>(myEntities) before the change, that would not work around the issue in this case, because both lists would still reference the same MyEntity and originalValue.equals(super.getValue()) would return true.


                    The only workaround I could come up with is something like this:



                        public void renameSomeEntity() {
                            List<MyEntity> oldMyEntities = myEntities;
                            myEntities = new ArrayList<MyEntity>(myEntities);
                            oldMyEntities.clear();
                            myEntities.get(0).setName("new name");
                        }



                    I replace the list and change the old list (that is referenced by UISelectItems.originalValue) so that it's not equal to the new list any longer. This really isn't something I like having to do, but the only way I could think of.


                    I guess fixing this bug isn't really that simple. Creating a copy of the original list for the originalValue property would fix the first problem (update if the list itself is changed), but not the second (update if an element in the list changes). Creating a deep copy is probably not feasible. Maybe there should be a method in UISelectItems to manually trigger a reload (set originalValue to null).

                    • 7. Re: s:selectItems doesn't reload when object is added to backing collection
                      christofvanhove

                      I've created an jira issue for this: https://jira.jboss.org/jira/browse/JBSEAM-4382


                      Best regards,


                      Christof