3 Replies Latest reply on Apr 21, 2009 7:42 AM by Stuart Douglas

    Why does s:selectItems not work in this case?

    Thai Dang Vu Apprentice

      @Name("locations")
      @Scope(ScopeType.PAGE)
      public class Locations implements Serializable {
          @In private EntityManager entityManager;
      
          private List<Location> allLocations;
      
          public List<Location> getAllLocations() {
      /*
              if (allLocations == null) {
                  allLocations = entityManager.createQuery("select l from Location l").getResultList();
              }
              return allLocations;
      */
              return entityManager.createQuery("select l from Location l").getResultList();
          }
      }





      @Name("addDepartmentForm")
      @Scope(ScopeType.EVENT)
      public class AddDepartmentForm implements Serializable {
          private String departmentName;
          private Location location;
          private String managerName;
          ... getters and setters
      }
      



      <h:selectOneListbox value="#{addDepartmentForm.location}" size="1">
          <f:selectItem itemLabel="" itemValue="-1"/>
          <s:selectItems value="#{locations.allLocations}" var="l" label="#{l.longAddress}"/>
          <s:convertEntity/>
      </h:selectOneListbox>


      If I use the code which is commented in the `locations' component, I get a FacesMessage of validation error for the selectOneListBox. If I use the code which is not commented, everything is fine. Why is that?


      Thank you.

        • 1. Re: Why does s:selectItems not work in this case?
          Stuart Douglas Master
          Because page scope is evil.

          Basically after you render the page for the first time the entityManager is closed and the entities in allLocations become detached.

          When you submit the page the entityConverter calls find to get return the entity, which is a different instance to the object in the list (i.e. newObject != oldObject even though newObject.getId() == oldObject.getId()).

          The selectOneListBox has a check in it to make sure that the object returned by a converter is equal (using .equals) to an object in the item list, as they are not it fails.

          If you override .equals to compare based on primary key then this should start working, however do not do this without reading the article on the hibernate site about the pitfalls of doing this (once hibernate.org comes back up).

          You could also implement a custom converter that specifically returns an item from the original list.


          • 2. Re: Why does s:selectItems not work in this case?
            Thai Dang Vu Apprentice

            Thank you very much for your explanation.


            Could you tell me (or give me links) why page scope is evil?


            Thanks again.

            • 3. Re: Why does s:selectItems not work in this case?
              Stuart Douglas Master

              It is not evil so much, you just have to be very very careful with it.


              The most common problems that people have with it are due to entities becoming detached, like you were having here.


              Also in client side state saving the page scope is serialized and sent to the client, meaning that you cannot trust anything in page scope if you are using client side state saving.


              Also the page scope has no well defined life cycle.


              I have found that a good rule of thumb is not to use the page scope for anything that cannot be considered UI specific logic.