次のような単純な Databean があります。
@Model
Class DataBean{
private List<Elements> elements;
@PostConstruct
private void loadElements(){
//fetch data from database.
}
}
次のように、Primefacesデータテーブルを使用してデータを表示します。
<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 は、選択した要素を次のページの databean に設定するため、detailView はそのデータを準備してから、detail-Navigation-Outcome を返します。
現在: 問題: ソートせずに commandLinks の 1 つをクリックすると、すべて問題ありません。ID で並べ替えて詳細リンクをクリックすると、次のことが起こっています。
- リクエスト開始
- 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 --
AFTERPostConstruct DataBean
はソートされないことに注意してください。(テーブルでフォームを使用しているため、データテーブルは認識されず、並べ替えが変更された可能性があると思います。)
その結果、id 42 の要素が渡されます。(エレメント 42 は、ソートされていないケースの 10 番目の位置にあります)
その結果、navigateToDetailView(element) が予想外の別の要素で起動されるようになりました...
問題はオフです。ソートされたコレクションが postconstruct メソッドによってリセットされること。また、会話スコープで解決できることも知っています。
しかし、これを行うステートレスな方法はないのでしょうか? (ソート/ページ 2 ページ ナビゲーションごとに会話を開始したくありません)
何か案は?
編集 1: SortingHelper は次のような独自のクラスです。
@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 は整数のソートに失敗するか、数字を辞書式にソートするとしましょう: 11 < 5 など)
しかし、ソートを気にせず、カスタムソート機能を使用しない場合でも、結果は同じです。