Duplicate ID error with updated Mojarra 2.1.27

*爱你&永不变心* 提交于 2019-12-08 07:40:48

问题


I will give some context first before describing the issue I'm experiencing.

The environment is JSF, Primefaces 3.5 and GlassFish 3.1.2.2.

I am working on an application used for editing data. The data is split between several forms, each form being in a tabView's tab. The data model is very rich, and in some cases there are several nested tabViews.

To ease development, the application has one composite component describing a form field. It groups the field's label, input, tooltips and other graphic components. The form contains several of these composite components.

The application has been designed and coded with GlassFish 3 and its supplied Mojarra (version 2.1.6). At first, it extensively used JSTL tags (c:if, c:forEach and c:choose), which are very convenient for building a page's content dynamically, depending on the circumstances.

Therefore, the composite component has many c:if tags to build the field depending on its type (input text, combobox, calendar...). Similarly, the application's most complex screen (which uses 3 nested tabViews) is built using a lot of c:if and c:choose tags.

With Mojarra 2.1.6, the application works as desired. However in the complex screens the application's performance is very poor, due to a bug in older Mojarra versions. We then have decided to upgrade Mojarra to the latest 2.1 version, namely the 2.1.27.

Since the upgrade we experience problems, the most critical being a duplicate ID error during form loading and AJAX updating. The duplicate IDs always involve the composite component's inner components. It seems the composite component is instanciated twice in a row with the same clientId. The partial component tree showing an example follows :

+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

After reading articles on this site, such as this one or on BalusC's blog, I have decided to get rid of the JSTL tags, which may be involved in the problem (but I can't be sure); this would be "better" anyway (or is it ?).

So, instead of

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

I externalize (some stuff) in another file called someStuff.xhtml and write

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

The criteria used in the tests are the composite component's attributes, Session Scoped Bean's properties, or derivatives of the aforementioned criteria (functions or ternary operators).

As far as I know, I have converted all JSTL tags using this method, and the application behaves the same as before the conversion. Unfortunately, this includes the duplicate ID error.

I have also tried to replicate the error using a test-case application, unfortunately I haven't managed to do so yet. It seems that simple applications work.

I'm quite lost as how to solve this issue. Any help would be appreciated.

Many thanks.

EDIT : added a partial component tree.


回答1:


The problem you have is a long story. I'm not surprised to see it keep failing over and over again in Mojarra, I have seen reports of the same problem for years and it will be more over the time. The reason why it has been so hard to fix is it is necessary to do some big changes over facelets original algorithm and mix that with the JSF 2.0 PSS algorithm, and do that is really tough. It doesn't matter if you use c:if, c:choose or ui:include, it will not work the way you want using Mojarra with PSS enabled.

One option you could try is switch off Partial State Saving (PSS) in Mojarra (javax.faces.PARTIAL_STATE_SAVING web config parameter). In that way, the problem between PSS and facelets algorithm dissapear (because you are not using it anymore, but the performance will not be the best). There is a param called javax.faces.FULL_STATE_SAVING_VIEW_IDS that can be used to indicate the views that needs full state saving, so if you have a view with the duplicate id exception just set the view in the param and that's it.

The best solution to the problem is switch to Apache MyFaces. The implementations of JSF for 2.0.x and 2.1.x has solved the problem and both are very stable. In JSF 2.2 it was done a solution for use c:forEach tag, but a recent fix was done, so if you use these artifacts, try with 2.2.1 or later version.

I personally strongly recommend Apache MyFaces by many reasons. The latest code is very stable. If you are looking for the best performance take a look at this article Understanding JSF Performance at JSFCentral. I hope it helps.



来源:https://stackoverflow.com/questions/22236093/duplicate-id-error-with-updated-mojarra-2-1-27

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!