JSF рекурсивный интерфейс: включить выходное дерево беспорядка при множественной обратной передаче

У меня есть отчет, который отображает информацию о зачислении в колледж в расширяемом древовидном формате. При нажатии на префикс отображается префикс курса с итоговыми номерами зачисления и номерами зачисления на конкретный курс. Отчет работает нормально при первом запуске. Однако, если вы решите снова запустить отчет для другого сеанса, все начнет сбиваться с толку.

Когда запускается первый отчет, это правильно. Когда запускается второй отчет (для другого сеанса тот же сеанс работает нормально), обратите внимание, что второй содержит дублированные / отсутствующие элементы. Оба этих отчета будут работать правильно, если они выполняются "первыми", т. Е. В этом сеансе пользователей не было выполнено ни одного другого отчета.

Я использую рекурсивно включенную страницу для построения дерева. Вот соответствующий код из 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>

Соответствующие части поддерживающего компонента, 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 обеспечивает простое отслеживание данных, родительских и дочерних классов. Я могу опубликовать этот код, если это необходимо, но я считаю, что в настоящее время он излишен.

Во время устранения этой проблемы я проверил, что данные отчета, из которых построено дерево отчетов в компоненте, всегда верны. Используя класс Logger, я убедился, что дерево генерируется правильно (записывая в журнал сервера каждую строку, которая была обработана в дереве). Я даже проверил правильность reportTreeData после каждого запуска, записав дерево в журнал сервера после того, как дерево было построено.

Я могу только заключить, что что-то идет не так на этапе ответа на визуализацию жизненного цикла JSF, так как я заметил, что если я изменю компонент поддержки с @SessionScoped в @RequestScoped, отчет генерируется правильно каждый раз. Я бы предпочел не использовать это в качестве исправления, так как у меня есть ссылка "Загрузить CSV", которая использует уже сгенерированные данные отчета в компоненте поддержки, поэтому логику отчета не нужно повторно запускать для генерации CSV.

Кто-нибудь знает, почему это происходит и что я могу сделать, чтобы исправить это поведение? Я использую JSF 2.2 с Java EE 7 в GlassFish Open Source Edition 4.1 (сборка 13)

ОБНОВЛЕНИЕ 24/24/15

Я проходил через код JSF фазы ответа рендеринга, и кажется, что выражение EL просто оценивается с неверными данными во втором прогоне отчета. Я вижу, где выполняется вызов функции для оценки выражения EL, и он возвращается с неверными данными. Я постараюсь получить исходный код weld-osgi-bundle.jar, чтобы позже перейти к этому вызову функции.

1 ответ

Основываясь на большом количестве отладок и исследований, но, в частности, на этом ответе, я предполагаю, что моя проблема как-то связана с состоянием представления, пытающимся быть восстановленным, и рекурсия, которую я использую, затрудняет в структуре JSF правильное обновление компонента. модель дерева.

Другие вопросы по тегам