JSF递归ui:在多个回发中包含混乱的输出树



我有一个报告,它以可扩展的树格式显示大学课程注册信息。单击前缀时,它会显示带有摘要注册号和特定课程注册号的课程前缀。该报告在首次运行时运行良好。然而,如果您决定在另一个会话中再次运行报告,事情就会变得一团糟。

运行Report One时,它是正确的。当Report Two运行时(对于不同的会话,相同的会话运行正常),请注意第二个会话有重复/丢失的元素。如果这两个报告都是"先"运行的,也就是说,在该用户会话中没有运行其他报告,那么它们都可以正常工作。

我正在使用一个递归包含的页面来构建树。以下是来自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类是我创建的,它提供了对数据、父级和子级的简单跟踪。如果需要的话,我可以发布那个代码,但我认为现在它是多余的。

在解决这个问题的过程中,我已经验证了在backingbean中构建报告树的reportData始终是正确的。通过使用Logger类,我已经验证了树是否正确生成(通过将处理到树中的每一行写入服务器日志)。我甚至在构建树后将树写入服务器日志,从而验证了每次运行后reportTreeData的正确性。

我只能得出结论,JSF生命周期的"渲染响应"阶段出现了问题,因为我确实注意到,如果我将backingbean从@SessionScoped更改为@RequestScoped,那么每次都会正确生成报告。我宁愿不把它作为我的解决方案,因为我有一个"下载CSV"链接,它使用了backingbean中已经生成的报告数据,因此不需要重新运行报告逻辑来生成CSV。

有人知道为什么会发生这种情况吗?我能做些什么来纠正这种行为?我在GlassFish Open Source Edition 4.1(build 13)上使用JSF 2.2和Java EE 7

更新12/24/15

我已经逐步完成了呈现响应阶段的JSF代码,在第二次运行报告时,EL表达式似乎只是用错误的数据进行了评估。我可以看到它在哪里进行函数调用来评估EL表达式,结果返回了错误的数据。我将尝试获取weld-osgi-bundle.jar源代码,以便稍后可以进入该函数调用。

基于大量的调试和研究,特别是这个答案,我认为我的问题与试图恢复的视图状态有关,而我使用的递归使JSF框架很难正确更新组件树模型。

相关内容

  • 没有找到相关文章

最新更新