6 Replies Latest reply on Feb 20, 2007 12:30 AM by gavin.king

    Problems Nesting <h:dataTable>

      I'm trying to nest <h:dataTable> with <s:link> elements without success. Actually I can render a 2-level nested data table but if I click on the innermost links I get null passed to the action method. Clicking on the top-level links works fine and the expected objects are passed tomy action method. Frustrating!

      The rendered nested tables look something like this (everything rendered is a clickable s:link element--bold represents the outer table and regular text the inner nested tables):

      One
       Big Projects
       Small Projects
      Two
       Hot
       Cold
      Three
       Misc
      


      A list of trivial Blah objects holds the One/Two/Three. Each Blah also has a list of Bucket objects. This is supposed to simulate a 1-to-m Entity relationship loaded from a database. I also have a stateful session bean, Year, that manages things.

      Here's the important clip from my xhtml that renders the tables.
      <h:dataTable id="outerTable"
       var="z"
       value="#{list}">
       <h:column>
       <s:link value="#{outer.name}" action="#{year.selectItem(outer)}"/>
       <h:dataTable id="innerTable"
       var="inner"
       value="#{outer.buckets}">
       <h:column>
       <s:link value="#{inner.name}" action="#{year.selectBucket(inner)}"/>
       </h:column>
       </h:dataTable>
       </h:column>
      </h:dataTable>
      


      Here are the important bits from Year.java
      @Stateful
      @Name("year")
      @Scope(ScopeType.SESSION)
      public class YearBean implements Year {
       @DataModel
       private List<Blah> list;
      
       @Create
       public void init() {
       // Create & populate 2-tier data structure simulating loaded Entites
       list = new ArrayList<Blah>();
       List<Bucket> b = new ArrayList<Bucket>();
       b.add( new Bucket("Big Projects"));
       b.add( new Bucket("Small Projects"));
       list.add(new Blah("One",b));
      
       b = new ArrayList<Bucket>();
       b.add( new Bucket("Hot"));
       b.add( new Bucket("Cold"));
       list.add(new Blah("Two",b));
      
       b = new ArrayList<Bucket>();
       b.add( new Bucket("Misc"));
       list.add(new Blah("Three",b));
       }
      
       public String selectBucket(Bucket bucket) {
       if( bucket == null )
       System.out.println("+++>>> Null Bucket Selected! ");
       else
       System.out.println("++++>>> Bucket selected: " + bucket.getName());
       return "bucket";
       }
      
       public String selectItem(Blah blah) {
       if( blah == null )
       System.out.println("+++>>> Null Blah Selected! ");
       else
       System.out.println("++++>>> Blah selected: " + blah.getName());
       return "blah";
       }
      
      }
      


      And finally Blah.java and Bucket.java:
      @Name("blah")
      public class Blah {
       private String name;
      
       @DataModel
       private List<Bucket> buckets;
      
       public Blah(){}
      
       public Blah(String name, List<Bucket> buckets) {
       this.name = name;
       this.buckets = buckets;
       }
       public String getName() { return name; }
       public List<Bucket> getBuckets() { return buckets; }
      }
      
      
      @Name("bucket")
      public class Bucket {
       private String name;
      
       public Bucket(){}
      
       public Bucket(String name) {
       this.name = name;
       }
       public String getName() { return name; }
      }
      
      


        • 1. Re: Problems Nesting <h:dataTable>
          gavin.king

          Is #{outer.buckets} a DataModel?

          If not, make it one.

          • 2. Re: Problems Nesting <h:dataTable>
            seto

            @DataModel can be used in entity?

            • 3. Re: Problems Nesting <h:dataTable>
              gavin.king

              I didn't say @DataModel. I meant the class DataModel. You would probably want to instantiate it using new, not our annotation.

              • 4. Re: Problems Nesting <h:dataTable>

                These classes can't derive from DataModel. In the real project they're Entities and have their own class hierarchy. Any solution needs to be a separate concern from the entity object model.

                Based on some examples I saw in my seam-gen code I'm trying something a little different. I'm passing the entity id as a <f:param> in the <s:link> element. This is working on the outermost table but now my inner objects aren't rendering.

                Here's my code:

                 <ice:dataTable id="departmentListResults" width="100%" cellspacing="1"
                 value="#{departmentList.resultList}"
                 var="dept">
                 <ice:column>
                 <ice:dataTable id="projectListResults" width="100%" cellspacing="1"
                 value="#{dept.projects}" var="proj">
                 <ice:column>
                 <!-- This is where my s:link and f:param would normally go...if the rendering was working. -->
                 <ice:outputText value="Nothing here" rendered="#{proj == null}"/>
                 <ice:outputText value="#{proj.projectId}" rendered="#{proj != null}"/>
                 </ice:column>
                 </ice:dataTable>
                 </ice:column>
                 <ice:dataTable>
                


                departmentList is the seam-gen EntityQuery object that pulls back a list of Department objects (@Entity). Within each Department is a Set (1-m relationship between Department and Project).

                I get a javax.faces.el.PropertyNotFoundException on proj.projectId. I can output just "#{proj}" and get something like this: com.foobar.spurs.model.Project@1bf446e, so I know there's a non-null Object there and its type is Project.

                So why am I getting an exception when I try to access any of Project's properties? (There are full JavaBean getters/setters for each property I'm trying to access thanks to seam-gen.)

                The strange thing is this rendering was working fine when my objects were trivial (non-Entity) classes, and I could easily access properties from the "inner" list (proj in this example).

                Many thanks in advance for any ideas!

                • 5. Re: Problems Nesting <h:dataTable>

                  My bad! DataTable, or at least <ice:dataTable> doesn't seem to like the seam-gen generated default of Set<> for 1-m relationships in Entities.

                  In my Department code if I change Set to List throughout then like magic the data table works.

                  What was happening is that with Set<> the Set itself was being bound to the var attribute in the dataTable, not iterating through the Set and binding each item to var.

                  I'm not sure why it works this way but now that I know I'll just keep it in mind. :-)

                  • 6. Re: Problems Nesting <h:dataTable>
                    gavin.king

                    JSF datatables require Lists, or DataModels. Not Sets.