5 Replies Latest reply on Feb 29, 2008 8:15 PM by James Kelly

    using OneToMany in view layer

    Brent Day Newbie

      For all you SEAM experts, I really could use some direction on correct implementation for my problem.


      I am using JBoss A/S 4.2.2GA, JBoss Seam 2.1.0GA and EJB3 entity beans.


      I have 2 entity beans (EJB3), Employee and Department as follows:


      Employee.java


      @Entity
      @Table(name="EMPLOYEES_TBL")
      @Name("employee")
      public class Employee implements Serializable {
      
          @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
          private int id;
          private String name;
          private long salary;
          
          @ManyToOne
          private Department department;
         
          // getters and setters for id, name and salary omitted 
          
          public Department getDepartment() {
              return department;
          }
          
          public void setDepartment(Department department) {
              this.department = department;
          }
      
      }
      



      Department.java


      @Entity
      @Table(name="DEPARTMENTS_TBL")
      @Name("department")
      public class Employee implements Serializable {
      
          @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
          private int id;
          private String name;
      
          @OneToMany(mappedBy="department")
          private Collection<Employee> employees;
         
          // getters and setters for id and name omitted 
          
          public Department getDepartment() {
              return department;
          }
          
          public Collection<Employee> getEmployees() {
              return employees;
          }
      
      }



       
      I want the view layer (via my XHTML file) to display the department name for the employee, and then allow the user to update the department if required - perhaps through an ajax based lookup.


      My plan is to have the following in my view (viewEmployee.xhtml) to accomplish this?:


      <h:inputText id="departmentName" 
                 value=#{employee.department.name}"
              onChange="someUpdateJavaScriptFunction"/>



      Am I out in left field on this one? Any input or examples would be much appreciated.


      Thanks
      Brent




        • 1. Re: using OneToMany in view layer
          Kariem Hussein Newbie

          Besides the JS part, the approach is ok, if you want to change the name of the employee's department. But I think you really want to change the department the employee is assigned to, right?


          If my assumption is correct, you should rather use a selectOneMenu or something similar. Also have a look at the entity converter (documentation on Seam JSF Controls, look for s:convertEntity).

          • 2. Re: using OneToMany in view layer
            James Kelly Newbie

            Quick question on the implications: a user would be able to edit the name of a department that other people may also belong to?


            As for the functionality, Ajax4JSF can handle the asynchronous update. Here's an example of combining Ajax4JSF support with Seam's s:decorate (I ripped this from a seam-gen'ed project, but take a look at the Seam Booking example for more code.)


            <s:decorate id="departmentNameDecoration" template="layout/edit.xhtml">
              <ui:define name="label">departmentName</ui:define>
              <h:inputText id="departmentName" value="#{employee.department.name}">
                <a:support event="onblur" reRender="departmentNameDecoration" />
              </h:inputText>
            </s:decorate>
            



            Binding an input to something like #{employee.department.name} is reasonable, but you're going to need to deal with the case when when employee.department is null. For that case, you will need to add some sort of selectOne element:


            <h:selectOneMenu value="#{employee.department}" required="true">
               <s:selectItems value="#{departments.resultList}" var="departments" label="#{departments.name}" noSelectionLabel="Please Select..."/>
               <s:convertEntity />
            </h:selectOneMenu>
            



            departments is a Query object, an EntityQuery maybe, of all your departments. It may be a weird UI to have both - you may want to restrict functionality on the User page to simply assigning the department. Save editing the department name for a department edit page.


            Oh, and implement equals/hashcode on your entities if you haven't already.

            • 3. Re: using OneToMany in view layer
              Brent Day Newbie

              You are correct - I want to change the department for the employee. I am trying to set up my form so they can enter an employee ID number, click a lookup button. That will in turn load the employee record with the department and then the user can change any data, including the department name.


              If I have a simple lookup/edit form with Employee id and name then I can enter the employee id in the ID field and click my lookup button. This submits to my action bean and reloads the page. However, when I add the following:


              <h:inputText id="departmentName" 
                         value=#{employee.department.name}"/>



              I get this error:



              "10:53:35,234 WARN  [lifecycle] /employeeEdit.xhtml @42,101 value="#{employee.department.name}": Target Unreachable, 
              'department' returned null on 'com.brentday.model.Employee'
              javax.el.PropertyNotFoundException: /employee.xhtml @42,101 value="#{employee.department.name}": Target Unreachable, 'market' returned null on 'com.brentday.model.Employee'"



              Any ideas?


              Thanks again.
              Brent



               

              • 4. Re: using OneToMany in view layer
                Brent Day Newbie

                You addressed one of my issues. However, what if they want to be taken out of the department (thinking of another case where I may have a relationship that allows the foreign key to be non-existent.


                • 5. Re: using OneToMany in view layer
                  James Kelly Newbie

                  Uh, you should be able to get away with:


                  <s:selectItems value="#{departments.resultList}" 
                    var="departments" label="#{departments.name}"
                    noSelectionLabel="Unassigned" hideNoSelectionLabel="false"/>
                  



                  Selecting Unassigned should null the department - afaicr - but I dont' have a working example infront of me. Oh, and remove the required="true" from the h:selectOneMenu.