6 Replies Latest reply on Jul 21, 2010 7:46 PM by shavo26

    How to bind SelectOneMenu value to object ?

    bossdida

      Hi there,


      I'm quite new in Seam and have read some books but I'm still having troubles in implementation.


      I want to fetch Occupation entitis with factory method.
      Then save Person entity with selected Occupation.



      Here are some codes that I'm using.


      Person.java




      @Entity
      @Table(name="PersonTbl")
      public class Person implements Serializable
      {
          private static final long serialVersionUID = 1L;
          private Long id;
          private String name;
          private String surname;
          private Occupation occupation;
          @Id 
          @GeneratedValue
          @NotNull
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
          @Length(max = 20)
          @NotNull
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
               
          @ManyToOne
          @JoinColumn(name = "occupationId")
          public Occupation getOccupation() {
            return occupation;
          }
      
          public void setOccupation(Occupation occupation) {
           this.occupation = occupation;
          }
      }



      Occupation.java




      @Entity
      @Table(name="OccupationTbl")
      public class Occupation implements Serializable {
      
           private static final long serialVersionUID = 1L;
           private Long Id;
           private String Name;
           public void setId(Long id) {
                Id = id;
           }
      
           @Id
           @GeneratedValue
           @NotNull
           public Long getId() {
                return Id;
           }
      
           public void setName(String name) {
                Name = name;
           }
      
           @NotNull
           @Length(max = 50)
           public String getName() {
                return Name;
           }
      }




      PersonHome.java




      @Name("personHome")
      @Scope(ScopeType.CONVERSATION)
      public class PersonHome {
           private static final long serialVersionUID = 1L;
           private Person person;
           @In
           private EntityManager entityManager;
           
           @Out(required = false)
           private List<Occupation> occupationList;
           
           private List<SelectItem> oList;
      
           @Create
           @Begin(flushMode=FlushModeType.MANUAL)
            public void init() {
                retreiveOccupationList();
           }
           public void setPerson(Person person) {
                this.person = person;
           }
           public Person getPerson() {
                return person;
           }
          
           @SuppressWarnings("unchecked")
           @Factory("occupationList")
           public void retreiveOccupationList() {
                occupationList = entityManager.createQuery("select o Occupation o").getResultList();
           }
           @End
           public void savePerson() {
                entityManager.flush();
           }
      
           public List<SelectItem> getoList() {
                if(oList == null)
                     oList = new ArrayList<SelectItem>();
                
                if(occupationList != null && !occupationList.isEmpty())
                     for(Occupation o : occupationList)
                          oList.add(new SelectItem(o.getId(), o.getName()));
                return oList;
           }
      
           public void setoList(List<SelectItem> oList) {
                this.oList = oList;
           }
      }




      and AddPerson.xhtml




      <h:form>
      <s:decorate id="enterName" template="/layout/edit.xhtml">
           <ui:define name="label">Name:</ui:define>
           <h:inputText id="name" value="#{personHome.person.name}" required="true"/>
      </s:decorate>
      <s:decorate id="enterOccupation" template="/layout/edit.xhtml">
           <ui:define name="label">Occupation:</ui:define>
           <h:selectOneMenu value="#{personHome.person.occupation.id}">
                <f:selectItems value="#{personHome.oList}"/>
           </h:selectOneMenu>
      </s:decorate>
                     
      <h:commandButton action="#{personHome.savePerson}" value="Save" />
      </h:form>
      




      I'm fetching occupation entities wiht factory method and preparing SelectItem list from them for SelectOneMenu during initial request.


      I don't want to assign a long or string to person's occupation, thus declare Occupation field in Person entity, implement mapping ManyToOne.


      In initil request everything is fine, when enter string for name and select a value from SelectOneMenu and try to save Person, it complains about null occupation of person entity during validation phase.


      Isn't it the responsibility of EntityManager to coordinate entitis like Person, Occupation in conversation and set Person's Occupation according to sent SelectOneMenu value ?

      It's actually a simple case, but couldn't manage it.


      Can anybody help me with that please.


      Thanks for any contribution.


        • 1. Re: How to bind SelectOneMenu value to object ?
          herberson

          Don't use <f:selectItems /> tag instad use <s:selectItems />, this way your code will be like this:



          <h:form>
          <s:decorate id="enterName" template="/layout/edit.xhtml">
               <ui:define name="label">Name:</ui:define>
               <h:inputText id="name" value="#{personHome.person.name}" required="true"/>
          </s:decorate>
          <s:decorate id="enterOccupation" template="/layout/edit.xhtml">
               <ui:define name="label">Occupation:</ui:define>
               <h:selectOneMenu value="#{personHome.person.occupation}">
                    <s:selectItems value="#{personHome.oList}" var="item" label="#{_item.Name}"/>
                    <s:convertEntity/>
               </h:selectOneMenu>
          </s:decorate>
                         
          <h:commandButton action="#{personHome.savePerson}" value="Save" />
          </h:form>




          • 2. Re: How to bind SelectOneMenu value to object ?
            bossdida

            A second hand is always helpful. I completely forgot seam tags, I'll check that.
            Thanks a lot

            • 3. Re: How to bind SelectOneMenu value to object ?
              shavo26

              Boss from your code you may be over complicating this function. Like Herberson said you should be calling seam related tag instead of html s:selectItems. You have to define the namespace at the top which you prob have  


              xmlns:s="http://jboss.com/products/seam/taglib"





              But after looking at your code it should be simplified to this:



              @SuppressWarnings("unchecked")
                   @Factory("occupationList")
                   public void retreiveOccupationList() {
                        occupationList = entityManager.createQuery("select o Occupation o").getResultList();
                   }
                   
                   <s:decorate id="enterOccupation" template="/layout/edit.xhtml">
                   <ui:define name="label">Occupation:</ui:define>
                   <h:selectOneMenu value="#{personHome.person.occupation}">
                        <s:selectItems value="#{occupationList}" var="_item" label="#{_item.Name}"/>
                        <s:convertEntity/>
                   </h:selectOneMenu>
              </s:decorate>





              You do not need in your action class getoList as you have a factory with value occupationList to outject to scope. Also be weary of var attribute for element selectItems, you have item and then for label


              _item.Name



              , thats not correct.

              • 4. Re: How to bind SelectOneMenu value to object ?
                shavo26

                See my example below, i have an inquiry entity that has a country drop down.
                So in my action class i have a factory method that retrieves all countries and outjects to event scope to be called in my selectOneMenu.


                InquiryAction class



                     @SuppressWarnings("unchecked")
                    @Factory(value = "countriesList", scope = ScopeType.EVENT)  
                     public List<Country> getCountriesList() {  
                     return entityManager.createNamedQuery("Country.findAll").getResultList();  
                     } 



                Inquiry.xhtml



                 <s:decorate id="countryField" template="layout/edit.xhtml">
                                <ui:define name="label">Country</ui:define>
                                <h:selectOneMenu id="country" value="#{newInquiry.address.countryCode}" required="true">
                <s:selectItems var="_country" value="#{countriesList}"
                label="#{_country.countryName}" noSelectionLabel="-- Select --"/>
                     <s:convertEntity/>           
                     </h:selectOneMenu>
                            </s:decorate>



                Hope this helps.




                • 5. Re: How to bind SelectOneMenu value to object ?
                  bossdida

                  Thanks alot, sure it was helpful.


                  Before I saw your responce, I have tried some combination and


                  <h:selectOneMenu value="#{person.occupation}">
                    <s:selectItems var="_item" value="#{occupationList}" noSelectionLabel="Select..." label="#{_item.name}"/>
                    <s:convertEntity/>
                  </h:selectOneMenu> 



                  this worked like a charm.
                  You are right there is no need for oList, I've just used occupationList from factory.


                  But s:convertEntity tag  did the trick.


                  I knew that it is a simple and common case for web applicatios, but couze I'm inexperienced in Seam I don't know all possibilities yet.


                  I'll check NamedQueries as well.


                  Nice to see there are people willing to help to us.


                  Again thanks a lot.




                  • 6. Re: How to bind SelectOneMenu value to object ?
                    shavo26

                    No worries boss.