Hi

The problem is caused by use c:forEach tag, iterating over something
that is not "application scoped".

The reason why c:forEach should be avoided in cases like the one
shown here is Partial State Saving (PSS) algorithm works under the
assumption that the same view can be generated between requests,
so when the delta is applied, it can be applied over the same
components.

The issue has been widely studied and the conclusion has been that
c:forEach cannot really be fixed because c:forEach does not have an
underlying UIComponent instance that encapsultate what's inside
and in that way generate unique stable ids.

Create a custom component that works in MyFaces and Mojarra is not
really possible, because the component requires to know some
implementation details.

Is there any solution? maybe something like this (I don't know if the EL
is correct, but I hope you get the idea):

<c:if test="#{empty sessionBean.values ? false :
sessionBean.values.get(0)  eq null ? false : sessionBean.values.get(0)
}">
    <ui:include src="#{....}"/>
</c:if>
<c:if test="#{empty sessionBean.values ? false :
sessionBean.values.get(1)  eq null ? false : sessionBean.values.get(1)
}">
    <ui:include src="#{....}"/>
</c:if>

And repeat the same code as many times as options you can put
on sessionBean.values. In that way, PSS algorithm will reserve the
necessary slots.

In theory, a variant of c:forEach can be created to fix this problem, but
it requires to store sessionBean.values into delta view state, to ensure
stability of PSS algorithm. The previous example works because the
values of src="#{...}" are stored into the state and unique ids are
generated per each slot (by c:if effect).

Note any variant of c:forEach will add a strong dependency of the code
with MyFaces, so that's the reason why it hasn't been done before.

Other alternative to make it work is disable PSS, or use
org.apache.myfaces.REFRESH_TRANSIENT_BUILD_ON_PSS_PRESERVE_STATE
web config param, but that is one step back, because without PSS the
state in session will not be optimally used.

regards,

Leonardo Uribe

2013/2/16 Nicolas Labrot <nith...@gmail.com>:
> Hello,
>
> I'm glad to post my first message on this ml ;)
>
> I have the infamous but well known duplicate id behaviour with the
> following code:
>     <h:form>
>         <p:commandButton action="#{sessionBean.add}" value="add"
> update=":myForm"/>
>         <p:commandButton action="#{sessionBean.reset}" value="reset"
> update=":myForm"/>
>     </h:form>
>
>     <h:form id="myForm">
>         <c:forEach items="#{sessionBean.values}" var="value">
>             <ui:include src="#{value}"/>
>         </c:forEach>
>     </h:form>
>
> At the beginning "sessionBean.values" is empty.
> Action 1 : User clicks on "add", the add action adds "form0.xhtml" to
> "sessionBean.values".
> Action 2 : User clicks on "add", the add action adds "form1.xhtml" to
> "sessionBean.values".
>
> *form0.xhtml contains : *
> <p:fileUpload auto="false"  mode="advanced" required="true"
>                       fileUploadListener="#{sessionBean.handleFileUpload}"/>
> *
> *
> *form1.xhtml contains :*
> <h:outputText value=""/>
>
> My issue is action 2 returns a duplicate id exception:<partial-response>
>
> <error><error-name>java.lang.IllegalStateException</error-name>
> <error-message><![CDATA[component with duplicate id "j_id4" found]]>
> </error-message></error></partial-response>
>
>
> j_id4 is the stylesheet of the fileUpload component :
> @ResourceDependency(library="primefaces", name="fileupload/fileupload.css"),
>
> This stylesheet is inserted with action 1. And it seems myfaces tries to
> insert it with action 2 too.
>
> Do I do something wrong ?
>
> Thanks for your help!
>
> Nicolas

Reply via email to