I have a simple Databean like this:
@Model
Class DataBean{
private List<Elements> elements;
@PostConstruct
private void loadElements(){
//fetch data from database.
}
}
im using Primefaces datatable to display the data, like this:
<h:form>
<p:dataTable
value="#{dataBean.elements}"
var="element" >
<p:column sortBy="#{element.id}"
sortFunction="#{sortingHelper.sortNumericCallback}">
<f:facet name="header">ID</f:facet>
<p:commandLink action="#{pageController.navigateToDetailView(element)}"
value="#{element.id}">
</p:commandLink>
</p:column>
</p:datatable>
</h:form>
pageController.navigateToDetailView(element)
simple sets the selected element on the next page's databean, so the detailView has its data prepared, and then returns the detail-Navigation-Outcome.
Now: The Problem: If i click on one of the commandLinks without any sorting, all is fine. If i sort by id and click on the details-link, the following is happening:
- Request Started
- Databean loaded (postconstruct) (sorting gone)
Now - in the second request - the page is rebuild again (in order to fire the navigateToDetailView-Action) And the datatable "knows", that i clicked on row 5. But without sorting it again, row 5 is now a different entry, since the bean gets reconstructed.
Console Output for different Points.
First I click on the page showing the Datatable. the "."'s are one comparision of my custom sort function, just to indicate the collection is sorted.
13:47:56,046 INFO [stdout] (http--0.0.0.0-8090-1) -- Started Request --
13:47:56,047 INFO [stdout] (http--0.0.0.0-8090-1) ---- Started RESTORE_VIEW 1 ----
13:47:56,048 INFO [stdout] (http--0.0.0.0-8090-1) ---- Started RENDER_RESPONSE 6 ----
13:47:56,087 INFO [stdout] (http--0.0.0.0-8090-1) PostConstruct DataBean
13:47:56,566 INFO [stdout] (http--0.0.0.0-8090-1) -- Finished Request --
That's fine. Now im sorting by clicking the id header
13:48:15,008 INFO [stdout] (http--0.0.0.0-8090-2) -- Started Request --
13:48:15,009 INFO [stdout] (http--0.0.0.0-8090-2) ---- Started RESTORE_VIEW 1 ----
13:48:15,051 INFO [stdout] (http--0.0.0.0-8090-2) ---- Started APPLY_REQUEST_VALUES 2 ----
13:48:15,052 INFO [stdout] (http--0.0.0.0-8090-2) PostConstruct DataBean
13:48:15,124 INFO [stdout] (http--0.0.0.0-8090-2) ..............................................................
13:48:15,124 INFO [stdout] (http--0.0.0.0-8090-2) ---- Started PROCESS_VALIDATIONS 3 ----
13:48:15,126 INFO [stdout] (http--0.0.0.0-8090-2) ---- Started UPDATE_MODEL_VALUES 4 ----
13:48:15,127 INFO [stdout] (http--0.0.0.0-8090-2) ---- Started INVOKE_APPLICATION 5 ----
13:48:15,127 INFO [stdout] (http--0.0.0.0-8090-2) ---- Started RENDER_RESPONSE 6 ----
13:48:15,387 INFO [stdout] (http--0.0.0.0-8090-2) -- Finished Request --
That's fine, too. The Table is now sorted as it should be. Now i'm clicking on the 10th row to pick the item with the id 53;
13:48:28,295 INFO [stdout] (http--0.0.0.0-8090-4) -- Started Request --
13:48:28,296 INFO [stdout] (http--0.0.0.0-8090-4) ---- Started RESTORE_VIEW 1 ----
13:48:28,361 INFO [stdout] (http--0.0.0.0-8090-4) ---- Started APPLY_REQUEST_VALUES 2 ----
13:48:28,363 INFO [stdout] (http--0.0.0.0-8090-4) PostConstruct DataBean
13:48:28,487 INFO [stdout] (http--0.0.0.0-8090-4) ---- Started PROCESS_VALIDATIONS 3 ----
13:48:28,501 INFO [stdout] (http--0.0.0.0-8090-4) ---- Started UPDATE_MODEL_VALUES 4 ----
13:48:28,514 INFO [stdout] (http--0.0.0.0-8090-4) ---- Started INVOKE_APPLICATION 5 ----
13:48:28,514 INFO [stdout] (http--0.0.0.0-8090-4) navigateToDetail() called
13:48:28,516 INFO [stdout] (http--0.0.0.0-8090-4) Constructing ElementEditDataBean
13:48:28,517 INFO [stdout] (http--0.0.0.0-8090-4) Setting ActiveElement to 42
13:48:28,518 INFO [stdout] (http--0.0.0.0-8090-4) ---- Started RENDER_RESPONSE 6 ----
13:48:28,748 INFO [stdout] (http--0.0.0.0-8090-4) -- Finished Request --
Note, that AFTER PostConstruct DataBean
no sorting is done. (I assume since i use a form
in the table, the datatable is not aware, that the sorting might have changed.)
As a result, element with id 42 is passed. (Element 42 is in the 10th position for an unsorted case)
As a result, navigateToDetailView(element) is now fired with another elementthan expected...
The Problem is ofc. that the sorted collection gets reset by the postconstruct method. I also know, that it can be solved with Conversation scope.
But I wonder if there isnt a stateless way of doing this? (I don't want to launch conversations for every sorting / page2page navigation)
Any Ideas?
Edit 1: SortingHelper is a own class, just looking like this:
@Named
public class SortingHelper {
/**
* Sorts two integers correctly.
* @param o1 integer 1
* @param o2 integer 2
* @return negative value if o1 is less, 0 if equal, or positive value if greater
*/
public int sortNumericCallback(Object o1, Object o2) {
System.out.print(".");
int i1 = Integer.parseInt((String) o1);
int i2 = Integer.parseInt((String) o2);
return (i1 == i2) ? 0 : (i1 > i2) ? 1 : -1;
}
}
(Primefaces Datatable fails on sorting integers, or lets say it sorts numbers lexicographic: 11 < 5 etc.)
But even if i do not mind about the sorting and using NO custom sort function the outcome is the same.