1 2 Previous Next 18 Replies Latest reply on Apr 7, 2006 7:40 AM by gavin.king

    Cannot use @DataModel and sorting functionality for Tomahawk

    newion

      Hello!
      dataTable from Tomahawk library requires to provide name of a method inside "value" attribute. This method is called to sort the table. But Seam requires to provide name of variable inside "value" attribute to link table with data model defined with @DataModel.

      <t:dataTable
       preserveDataModel="false"
       preserveSort="false"
       value="#{projectsList}"
       var="proj"
       sortColumn="#{sortableProjects.sortColumn}"
       sortAscending="#{sortableProjects.ascending}"
      >
      


      Sorting doesn't work in the code above, since "projectsList" is not a method.

      Do you have any idea how to solve this problem?

      Pawel Kaczor

        • 1. Re: Cannot use @DataModel and sorting functionality for Toma

          I've got the same problem. Did you already solve it or has anybody else an idea?

          I don't want to miss the benefits which are provided by @DataModel, @DataModelSelection and @DataModelSelectionIndex. But I want ot sort my model too.

          I think it would be possible to write a method for every column which should be sortable and refer to them. But it's the very last option.

          • 2. Re: Cannot use @DataModel and sorting functionality for Toma

            OK. I just found a solution. Just write a normal getter for your DataModel and remove its @Factory annotation. In the JSP-page you've to replace the DataModels name by its getter method.

            • 3. Re: Cannot use @DataModel and sorting functionality for Toma
              newion

              Could you paste the essential source code here?
              I have already tried to implement the solution described by you and it didn't work.
              I'm glad to hear that you have succeeded! Congratulations!

              Best wishes,

              Pawel Kaczor

              • 4. Re: Cannot use @DataModel and sorting functionality for Toma

                I got it. But today I changed something which causes that I don't get the @DataModelSelection and @DataModelSelectionIndex injected. I always get the first item.

                But here we go:

                @Stateful
                @Scope(ScopeType.SESSION)
                @LoggedIn
                @Name("testactionDeveloper")
                @Interceptors(SeamInterceptor.class)
                public class TestactionDeveloperAction implements TestactionDeveloper, Serializable {
                 @PersistenceContext(unitName = "aresDatabase")
                 private EntityManager em;
                
                 @In @Valid
                 private User user;
                
                 @DataModel(scope=ScopeType.PAGE)
                 private List<Testaction> testactions;
                 @DataModelSelectionIndex
                 private int testactionIndex;
                 @DataModelSelection
                 private Testaction testaction;
                
                 @In(required=false)
                 private Release selectedRelease;
                
                 private Long lastSelectedReleaseID;
                
                 private boolean renderSaveButtons;
                 private String sortColumn = "id";
                 private boolean ascending=true;
                
                
                // @Factory("testactions")
                 public List<Testaction> getTestactions() {
                 renderSaveButtons = true;
                 if(selectedReleaseChanged() || testactions == null) {
                 if(selectedRelease != null) {
                 testactions = em.createQuery(
                 "from Testaction where TACT_DEV_USR_ID=:dev and TACT_REL_ID=:rel and (TACT_REV_ID is null or TACT_REV_ID=9) order by TACT_ID asc"
                 ).setParameter("dev", user.getID()).setParameter("rel", selectedRelease.getID()).getResultList();
                 } else {
                 testactions = em.createQuery(
                 "from Testaction where TACT_DEV_USR_ID=:dev and (TACT_REV_ID is null or TACT_REV_ID=9) order by TACT_ID asc"
                 ).setParameter("dev", user.getID()).getResultList();
                 }
                 lastSelectedReleaseID = (selectedRelease == null) ? null : selectedRelease.getID();
                 }
                 Collections.sort(testactions, new TestactionComparator(sortColumn, ascending));
                 return testactions;
                 }
                //getters/setters for sortColumn/ascending omitted


                <t:dataTable value="#{testactionDeveloper.testactions}" var="testaction_var" rendered="#{not empty testactionDeveloper.testactions}" sortColumn="#{testactionDeveloper.sortColumn}" sortAscending="#{testactionDeveloper.ascending}">
                 <h:column>
                 <f:facet name="header">
                 <t:commandSortHeader columnName="id">
                 <h:outputText value="#{ares_messages.label_testaction_ID}" />
                 </t:commandSortHeader>
                 </f:facet>
                 <h:commandLink value="#{testaction_var.ID}" action="#{testactionDeveloper.select}" />
                 </h:column>
                <!-- and so on -->


                Do you need sth. else?

                • 5. Re: Cannot use @DataModel and sorting functionality for Toma
                  gavin.king

                  What did you change?

                  • 6. Re: Cannot use @DataModel and sorting functionality for Toma
                    newion

                    Are you sure, it worked in the past?
                    I have exactly the same problem in my application...That's why I've asked you for your source code.

                    Cheers,
                    Pawel Kaczor

                    • 7. Re: Cannot use @DataModel and sorting functionality for Toma

                      Why don't we live millions of years ago? At a time where there was only one continent; we could discuss almost in realtime.

                      OK. I don't know what exactly I've changed, because I changed not only one thing. A little bit here, a little bit there, you know?
                      But I'll try to find it out today (yeah, it's 9am in Germany).

                      But this problem seems to be a common one. I found several posts in the mailing lists of myFaces about this. They solved it with bindings or an javax.faces.model.DataModel instead of a List.
                      I think this problem has to do with myFaces. I don't really know how Seam and myFaces work. IMHO Seam takes the DataModel from myFaces and injects @DataModelSelection and @DataModelSelectionIndex by calling the correspondant methods on the DataModel delivered by myFaces.

                      I tried to change my List to a DataModel, but a call to getRowIndex() returned 0 everytime. So I've to fiddle out, in which cases this happens.

                      • 8. Re: Cannot use @DataModel and sorting functionality for Toma

                        Hi,

                        I saw something similar when playing around on this issue:

                        http://jboss.org/index.html?module=bb&op=viewtopic&t=79980&postdays=0&postorder=asc&start=0

                        When clicking the commandLink, the view component tree will be reconstructed, calling your getTestactions.
                        Is there any chance the query is being run again? (eg problem in selectedReleaseChanged())

                        In my case the query results were being thrown away, and the query was being re-run.
                        The result list would be different to the one I selected from - resulting in a 0 selection index/first item selection

                        • 9. Re: Cannot use @DataModel and sorting functionality for Toma

                          I debugged into some methods of UIData and after that I'm wondering how the DataModel ever knew which row had been selected.

                          It seems that the rowIndex ist set to -1 at the very beginning and the very end of the "Apply Request Values", "Process Validations" and "Process Updates" phases. processDecodes, processValidations and processUpdates of UIData call setRowIndex(-1) twice.

                          So for me the only point where the DataTable saves the selected index seems to be the "Invoke Application" phase. I debugged into broadcast of UIData and only when it's calles in this phase, the eventRowIndex is assigned the real selected index. This index is saved in the DataTable via setRowIndex(eventRowIndex). currentRowIndex gets the index before, which is -1.
                          But then it happens. A further method is called in a try-finally-block. The finally-part calls setRowIndex(currentRowIndex), where currentRowIndex is -1.

                          That's confusing. Before the "Invoke Application" phase the index is continously set to -1. So it can't have another value until the "Invoke Application" phase begins. Then it is set to the real selected index. 7 lines later it is reset to -1.

                          Where is the dataTable opposed to get its selected index? I'm convinced I overlooked sth. but what?

                          • 10. Re: Cannot use @DataModel and sorting functionality for Toma

                            OK. I think I've a nice workaround. I'll use it until the Seam and myFaces developers worked together to solve this problem ;)

                            Here it is:

                            @Stateful
                            @Scope(ScopeType.SESSION)
                            @LoggedIn
                            @Name("testactionDeveloper")
                            @Interceptors(SeamInterceptor.class)
                            public class TestactionDeveloperAction implements TestactionDeveloper, Serializable {
                             @PersistenceContext(unitName = "aresDatabase")
                             private EntityManager em;
                            
                             @In @Valid
                             private User user;
                            
                             @DataModel(scope=ScopeType.PAGE)
                             private List<Testaction> testactions;
                             @DataModelSelectionIndex
                             private int testactionIndex;
                             @DataModelSelection
                             private Testaction testaction;
                            
                             @In(required=false)
                             @Out(required=false, scope=ScopeType.SESSION)
                             private Testaction currentTestaction;
                            
                             private List<Testaction> currentTestactions;
                             private int currentTestactionIndex;
                            
                             @In(required=false)
                             private Release selectedRelease;
                            
                             private Long lastSelectedReleaseID;
                            
                             private transient List<Testcase> testcases;
                             private transient List<User> developers;
                             private transient List<Revisionclass> revisions;
                             private transient List<Release> devReleases;
                             private transient List<Buildnumber> devBuilds;
                             private transient List<Defectcause> defectCauses;
                            
                             private boolean renderSaveButtons;
                             private String sortColumn = "id";
                             private boolean ascending=true;
                            
                            
                             @Factory("testactions")
                             public List<Testaction> getTestactions() {
                             renderSaveButtons = true;
                             if(selectedReleaseChanged() || testactions == null) {
                             if(selectedRelease != null) {
                             testactions = em.createQuery(
                             "from Testaction where TACT_DEV_USR_ID=:dev and TACT_REL_ID=:rel and (TACT_REV_ID is null or TACT_REV_ID=9) order by TACT_ID asc"
                             ).setParameter("dev", user.getID()).setParameter("rel", selectedRelease.getID()).getResultList();
                             } else {
                             testactions = em.createQuery(
                             "from Testaction where TACT_DEV_USR_ID=:dev and (TACT_REV_ID is null or TACT_REV_ID=9) order by TACT_ID asc"
                             ).setParameter("dev", user.getID()).getResultList();
                             }
                             lastSelectedReleaseID = (selectedRelease == null) ? null : selectedRelease.getID();
                             }
                             Collections.sort(testactions, new TestactionComparator(sortColumn, ascending));
                             return testactions;
                             }
                            
                             public String select() {
                             devBuilds = null;
                             currentTestaction = testaction;
                             currentTestactions = testactions;
                             currentTestactionIndex = testactionIndex;
                             return "selected";
                             }


                            <t:dataTable value="#{testactions}" var="testaction_var" renderedIfEmpty="false" sortColumn="#{testactionDeveloper.sortColumn}" sortAscending="#{testactionDeveloper.ascending}">
                             <h:column>
                             <f:facet name="header">
                             <t:commandSortHeader columnName="id">
                             <h:outputText value="#{ares_messages.label_testaction_ID}" />
                             </t:commandSortHeader>
                             </f:facet>
                             <h:commandLink value="#{testaction_var.ID}" action="#{testactionDeveloper.select}" />
                             </h:column>
                            
                             <h:column>
                             <f:facet name="header">
                             <t:commandSortHeader columnName="sev">
                             <h:outputText value="#{ares_messages.label_testaction_SevID}" />
                             </t:commandSortHeader>
                             </f:facet>
                             <h:outputText value="#{testaction_var.sevID}" />
                             </h:column>


                            Just aks if you need more. The @DataModelSelectionIndex now gets the correct value, but the @DataModelSelection doesn't. But this is not really a problem since I can retrieve it from the list in the select method. That's what I'll implement now.

                            • 11. Re: Cannot use @DataModel and sorting functionality for Toma

                              Now I discovered some kind of magic.

                              In the previous post I wrote the code from my jsp:

                              <!-- <t:dataTable value="#{testactionDeveloper.testactions}" var="testaction_var" renderedIfEmpty="false" sortColumn="#{testactionDeveloper.sortColumn}" sortAscending="#{testactionDeveloper.ascending}"> -->
                               <t:dataTable value="#{testactions}" var="testaction_var" renderedIfEmpty="false" sortColumn="#{testactionDeveloper.sortColumn}" sortAscending="#{testactionDeveloper.ascending}">


                              Everything works fine. But as soon as I remove the comment resulting in:
                              <t:dataTable value="#{testactions}" var="testaction_var" renderedIfEmpty="false" sortColumn="#{testactionDeveloper.sortColumn}" sortAscending="#{testactionDeveloper.ascending}">

                              the list can't be sorted anymore. Perhaps I've to say that I use Facelets with facelets.SKIP_COMMENTS set to false.

                              • 12. Re: Cannot use @DataModel and sorting functionality for Toma
                                gavin.king

                                 

                                Guys, I'm not quite sure what the problem here is. I got sorting in t:dataTable working quite quickly once I figured out how t:dataTable was supposed to be used.



                                Ugh forget it, my solution is bogus, sorry.



                                • 13. Re: Cannot use @DataModel and sorting functionality for Toma
                                  gavin.king

                                  OK, here is the real solution:

                                  @Name("sort")
                                  public class Sort
                                  {
                                   private String column = "title";
                                   private boolean ascending = true;
                                  
                                   public boolean isAscending()
                                   {
                                   return ascending;
                                   }
                                   public void setAscending(boolean ascending)
                                   {
                                   if ( ascending!=this.ascending ) data=null;
                                   this.ascending = ascending;
                                   }
                                   public String getColumn()
                                   {
                                   return column;
                                   }
                                   public void setColumn(String column)
                                   {
                                   if ( !column.equals(this.column) ) data=null;
                                   this.column = column;
                                   }
                                  
                                   private void sort(List data)
                                   {
                                   Collections.sort(data, new Comparator<Message>() {
                                  
                                   public int compare(Message x, Message y)
                                   {
                                   if (!ascending)
                                   {
                                   Message temp = y;
                                   y = x;
                                   x = temp;
                                   }
                                   if ("title".equals(column))
                                   {
                                   return x.getTitle().compareTo(y.getTitle());
                                   }
                                   else if ("datetime".equals(column))
                                   {
                                   return x.getDatetime().compareTo(y.getDatetime());
                                   }
                                   else
                                   {
                                   return new Boolean( x.isRead() ).compareTo( y.isRead() );
                                   }
                                   }
                                  
                                   });
                                   }
                                  
                                   private List data;
                                  
                                   @Factory("sortedMessageList")
                                   public void init() {
                                   data = ....; //get the message list!!
                                   sort(data);
                                   }
                                  
                                   @DataModel
                                   public Object getSortedMessageList()
                                   {
                                   return data;
                                   }
                                  
                                   @DataModelSelection
                                   private Message selectedMessage;
                                  
                                   @DataModelSelectionIndex
                                   private int indx;
                                  
                                   public void print()
                                   {
                                   System.out.println(indx + " " + selectedMessage.getTitle());
                                   }
                                  }



                                  <t:dataTable var="msg" value="#{sortedMessageList}" rendered="#{sortedMessageList.rowCount>0}"
                                   sortColumn="#{sort.column}" sortAscending="#{sort.ascending}" preserveSort="true">
                                   <h:column>
                                   <f:facet name="header">
                                   <t:commandSortHeader columnName="read" arrow="true">
                                   <h:outputText value="Read"/>
                                   </t:commandSortHeader>
                                   </f:facet>
                                   <h:selectBooleanCheckbox value="#{msg.read}" disabled="true"/>
                                   </h:column>
                                   <h:column>
                                   <f:facet name="header">
                                   <t:commandSortHeader columnName="title" arrow="true">
                                   <h:outputText value="Title"/>
                                   </t:commandSortHeader>
                                   </f:facet>
                                   <h:commandLink value="#{msg.title}" action="#{sort.print}"/>
                                   </h:column>
                                   <h:column>
                                   <f:facet name="header">
                                   <t:commandSortHeader columnName="datetime" arrow="true">
                                   <h:outputText value="Date/Time"/>
                                   </t:commandSortHeader>
                                   </f:facet>
                                   <h:outputText value="#{msg.datetime}">
                                   <f:convertDateTime type="both" dateStyle="medium" timeStyle="short"/>
                                   </h:outputText>
                                   </h:column>
                                   </t:dataTable>


                                  1 2 Previous Next