使用更新的Mojarra 2.1.27重复ID错误

时间:2014-03-06 21:12:30

标签: jsf-2 primefaces composite-component mojarra

在描述我遇到的问题之前,我先给出一些背景信息。

环境是JSF,Primefaces 3.5和GlassFish 3.1.2.2。

我正在处理用于编辑数据的应用程序。数据在几个表单之间分开,每个表单都在tabView的选项卡中。数据模型非常丰富,在某些情况下有几个嵌套的tabView。

为了简化开发,应用程序有一个描述表单字段的复合组件。它将字段的标签,输入,工具提示和其他图形组件分组。表单包含其中几个复合组件。

该应用程序使用GlassFish 3及其提供的Mojarra(版本2.1.6)进行设计和编码。首先,它广泛使用JSTL标签(c:if,c:forEach和c:choose),这些标签非常便于动态构建页面内容,具体取决于具体情况。

因此,复合组件有许多c:if标签来构建字段,具体取决于其类型(输入文本,组合框,日历......)。同样,应用程序最复杂的屏幕(使用3个嵌套的tabViews)是使用大量的c:if和c:选择标签构建的。

使用Mojarra 2.1.6,应用程序可以正常工作。但是在复杂的屏幕中,由于a bug in older Mojarra versions,应用程序的性能非常差。然后我们决定将Mojarra升级到最新的2.1版本,即2.1.27。

由于升级我们遇到问题,最重要的是在表单加载和AJAX更新期间出现重复的ID错误。重复ID始终涉及复合组件的内部组件。似乎复合组件连续两次使用相同的clientId进行实例化。显示示例的部分组件树如下:

+id: DataDashboard
 type: org.primefaces.component.dashboard.Dashboard@58a26f8d
  +id: Data_property
   type: org.primefaces.component.panel.Panel@1049bf71
    +id: j_idt1286
     type: javax.faces.component.html.HtmlPanelGrid@59b79c11
      +id: j_idt1287
       type: javax.faces.component.UINamingContainer@7071dc24
        +id: j_id4
         type: javax.faces.component.UIPanel@25674e1b
          +id: j_idt1288
           type: javax.faces.component.html.HtmlPanelGrid@2138e1cc
            +id: j_idt1289
             type: com.sun.faces.facelets.tag.ui.ComponentRef@1d70291e
              +id: j_idt1290
               type: <html xmlns="http://www.w3.org/1999/xhtml">

              +id: hType  <===============
               type: javax.faces.component.html.HtmlInputHidden@2e9b7fab
              +id: lId
               type: javax.faces.component.html.HtmlOutputLabel@54c26622
              +id: j_idt1299
               type: org.primefaces.component.tooltip.Tooltip@26bf6da7
              +id: j_idt1300
               type: org.primefaces.component.tooltip.Tooltip@61b802d0
(...)
          +id: j_idt3300
           type: javax.faces.component.html.HtmlPanelGrid@5a4da336
            +id: j_idt3301
             type: com.sun.faces.facelets.tag.ui.ComponentRef@1f165c8b
              +id: j_idt3302
               type: <html xmlns="http://www.w3.org/1999/xhtml">

              +id: hType  <===============
               type: javax.faces.component.html.HtmlInputHidden@7515b99e

在阅读本网站上的文章后,例如this oneBalusC's blog,我决定摆脱可能涉及问题的JSTL标签(但我不能当然);无论如何这都会“更好”(或者是吗?)。

所以,而不是

<c:if test="#{someCriterion}">
  (some stuff)
</c:if>

我将另一个名为someStuff.xhtml的文件外化(某些东西)并写入

<ui:include src="#{someCriterion ? 'someStuff.xhtml' : ''}" />

测试中使用的标准是复合组件的属性,Session Scoped Bean的属性,或上述标准的衍生物(函数或三元运算符)。

据我所知,我已经使用此方法转换了所有JSTL标记,并且应用程序的行为与转换前的行为相同。不幸的是,这包括重复的ID错误。

我还尝试使用测试用例应用程序复制错误,遗憾的是我还没有设法这样做。似乎简单的应用程序可以工作。

我很失落如何解决这个问题。任何帮助将不胜感激。

非常感谢。

编辑:添加了部分组件树。

1 个答案:

答案 0 :(得分:1)

你遇到的问题很长。我很惊讶地看到它在Mojarra一次又一次地失败,我已经看到多年来同样问题的报道,而且随着时间的推移会更多。它之所以如此难以解决,是因为有必要对facelets原始算法进行一些重大改动,并将其与JSF 2.0 PSS算法混合使用,这样做真的很难。如果你使用c:if,c:choose或ui:include,它将无法按照你想要的方式使用Mojarra并启用PSS。

您可以尝试的一个选项是关闭Mojarra中的部分状态保存(PSS)(javax.faces.PARTIAL_STATE_SAVING web配置参数)。这样,PSS和facelets算法之间的问题消失了(因为你不再使用它,但性能不会是最好的)。有一个名为javax.faces.FULL_STATE_SAVING_VIEW_IDS的参数,可用于指示需要完全状态保存的视图,因此如果您有一个具有重复ID异常的视图,只需在参数中设置视图即可。

问题的最佳解决方案是切换到Apache MyFaces。 JSF for 2.0.x和2.1.x的实现解决了这个问题,两者都非常稳定。在JSF 2.2中,它完成了使用c:forEach标记的解决方案,但是最近修复了一次,所以如果你使用这些工件,请尝试使用2.2.1或更高版本。

我个人强烈推荐Apache MyFaces有很多原因。最新的代码非常稳定。如果您正在寻找最佳性能,请查看JSFCentral上的这篇文章Understanding JSF Performance。我希望它有所帮助。