-
1. Re: Cannot use @DataModel and sorting functionality for Toma
newlukai Mar 30, 2006 6:53 AM (in response to newion)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
newlukai Mar 31, 2006 6:06 AM (in response to newion)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 Mar 31, 2006 9:47 AM (in response to 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
newlukai Apr 3, 2006 10:55 AM (in response to newion)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 Apr 3, 2006 1:15 PM (in response to newion)What did you change?
-
6. Re: Cannot use @DataModel and sorting functionality for Toma
newion Apr 3, 2006 1:46 PM (in response to 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
newlukai Apr 4, 2006 3:00 AM (in response to newion)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.nicholls Apr 4, 2006 5:38 AM (in response to newion)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
newlukai Apr 4, 2006 5:43 AM (in response to newion)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
newlukai Apr 5, 2006 4:37 AM (in response to newion)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
newlukai Apr 5, 2006 4:57 AM (in response to newion)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 Apr 5, 2006 9:27 AM (in response to newion)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 Apr 5, 2006 9:59 AM (in response to newion)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>