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

    Pawel Kaczor Newbie

      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
          Jens Weintraut Apprentice

          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
            Jens Weintraut Apprentice

            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
              Pawel Kaczor Newbie

              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
                Jens Weintraut Apprentice

                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?

                • 6. Re: Cannot use @DataModel and sorting functionality for Toma
                  Pawel Kaczor Newbie

                  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
                    Jens Weintraut Apprentice

                    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
                      Simon Newbie

                      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
                        Jens Weintraut Apprentice

                        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
                          Jens Weintraut Apprentice

                          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
                            Jens Weintraut Apprentice

                            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 Master

                               

                              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 Master

                                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