[英]JSF recursive ui:include jumbles output tree on multiple postback
我有一個報告,以可擴展的樹格式顯示大學課程注冊信息。 單擊前綴時,它會顯示課程前綴以及摘要注冊號和特定的課程注冊號。 該報告在首次運行時工作正常。 但是,如果您決定為另一個會話再次運行該報告,事情就會變得混亂起來。
運行報表一時 ,它是正確的。 當運行Report 2 (對於不同的會話,同一會話運行正常)時,請注意第二個具有重復/缺失元素。 如果這兩個報告都是“第一”運行的,則它們將正確運行,即,在該用戶會話中未運行任何其他報告。
我正在使用遞歸包含的頁面來構建樹。 這是來自報告頁面本身enrollment.xhtml的相關代碼:
<div id="resultSet" class="treeContainer">
<c:if test="${EnrollmentBean.reportRan}">
<ui:include src="/WEB-INF/includes/reportTree.xhtml">
<ui:param name="nodes" value="#{EnrollmentBean.reportTreeData.getChildren()}" />
<ui:param name="isHidden" value="false" />
</ui:include>
</c:if>
</div>
包含的reportTree.xhtml代碼(使用CSS / jQuery完成的樹擴展代碼):
<ul class="${isHidden ? 'hidden' : ''}">
<c:forEach items="#{nodes}" var="node">
<li><a href="#" class="reportTreeLabel">#{node.getData().getKey()}
<span class="reportTreeData">#{node.getData().getValue()}</span>
</a>
<c:if test="#{node.hasChildren()}">
<ui:include src="/WEB-INF/includes/reportTree.xhtml">
<ui:param name="nodes" value="#{node.getChildren()}" />
<ui:param name="isHidden" value="true" />
</ui:include>
</c:if>
</li>
</c:forEach>
</ul>
支持bean EnrollmentBean.java的相關部分:
@Named("EnrollmentBean")
@SessionScoped
public class EnrollmentBean implements Serializable {
/** Holds Report Data */
private List< List<String> > reportData;
/** Hold Report Data in tree format */
private TreeNode<SimpleEntry<String, Integer>> reportTreeData;
private void buildReportTree() {
this.reportTreeData = new TreeNode<SimpleEntry<String,Integer>>();
String prefix = "";
Integer prefixEnrollSum = 0;
// Stores the tree data for the prefix being processed. Once all the data has been processed, this is added as a child to the reportTreeData field.
TreeNode<SimpleEntry<String,Integer>> PrefixTree = null;
SimpleEntry<String,Integer> data = null;
for (List<String> line : this.reportData) { // for each raw data line
String course = line.get(0);
Integer enrollments = Integer.parseInt(line.get(1));
if (!prefix.equals(this.getPrefix(course)) ) { // if the prefix changed since the last line that was processed
prefix = this.getPrefix(course); // set the new prefix
if (PrefixTree != null) { // if we're not dealing with the very first line of data
// set the sum of enrollments gathered for this prefix and reset the counter for the next prefix.
PrefixTree.getData().setValue(prefixEnrollSum);
prefixEnrollSum = 0;
}
// prepare a data element for the prefix summary node, then create the node, passing in the data and the parent for this node.
data = new SimpleEntry<String,Integer>(prefix, 0);
PrefixTree = new TreeNode<SimpleEntry<String,Integer>>(data);
this.reportTreeData.addChild(PrefixTree);
} // end prefix changed
data = new SimpleEntry<String,Integer>(course, enrollments);
PrefixTree.addChild(data);
prefixEnrollSum += enrollments;
} // end for each data line
// If there was data to process, upon processing the final row, assign the summed enrollments to the final prefix tree.
if (PrefixTree != null) { PrefixTree.getData().setValue(prefixEnrollSum); }
}
}
TreeNode類是我創建的類,它提供對數據,父級和子級的簡單跟蹤。 如果需要,我可以發布該代碼,但是我認為這是多余的。
在解決此問題的過程中,我已經驗證了在支持bean中建立的報告樹所建立的reportData始終正確。 通過使用Logger類,我已經驗證了樹的生成正確(通過向服務器日志寫入正在處理到樹中的每一行)。 我什至通過構造樹后將樹寫到服務器日志中來驗證每次運行后reportTreeData是正確的。
我只能得出結論,在JSF生命周期的“渲染響應”階段出現了問題,因為我確實注意到,如果將后備bean從@SessionScoped
更改為@RequestScoped
,則每次都會正確生成報告。 我不希望這是我的解決辦法,因為我有一個“下載CSV”鏈接,該鏈接使用支持Bean中已經生成的報告數據,因此報告邏輯無需重新運行即可生成CSV。
有誰知道為什么會這樣,我該怎么做才能糾正這種現象? 我在GlassFish Open Source Edition 4.1(內部版本13)上將JSF 2.2與Java EE 7一起使用
更新12/24/15
我已經完成了渲染響應階段的JSF代碼,似乎EL表達式只是在第二次運行報表時使用錯誤的數據進行評估。 我可以看到它在哪里調用函數來評估EL表達式,並且返回錯誤的數據。 我將嘗試獲取weld-osgi-bundle.jar源,以便以后可以進入該函數調用。
基於大量的調試和研究,但特別是這個答案 ,我認為我的問題與試圖還原的視圖狀態有關,而我正在使用的遞歸使JSF框架難以正確更新組件樹模型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.