On Mon, 2008-04-28 at 08:46 -0700, mjovanov wrote:
> After upgrading to MyFaces 1.2.2 I am getting a “duplicate id in the faces
> tree” error. I have isolated it to the following section of code:
>
> <t:column id="${fieldName}" styleClass="${columnStyleClass}"
> rendered="${renderValue}">
>
> <f:facet name="header">
> <t:commandSortHeader columnName="${fieldName}" arrow="true"
> actionListener="#{backingBean.sortChanged}"
> immediate="true"
> styleClass="cellDataHeader">
> ${label}
> </t:commandSortHeader>
> </f:facet>
>
> <c:choose>
> ...
> ...
> <c:when test="${empty secondaryFieldName}">
>
> <c:if test="${not empty linkAction}">
> <h:commandLink action="#{backingBean.details}" immediate="true">
> <c:choose>
> <c:when test="${not empty dateFormat}">
> <h:outputText value="${entity[fieldName]}">
> <f:convertDateTime type="date" timeZone="${timeZone}"
> dateStyle="${dateFormat}"
> pattern="${datePattern}" />
> </h:outputText>
> </c:when>
>
> <c:when test="${not empty currencyPattern}">
> <h:outputText value="${entity[fieldName]}">
> <f:convertNumber pattern="${currencyPattern}" />
> </h:outputText>
> <br />
> </c:when>
>
> <c:otherwise>
> <h:outputText value="${entity[fieldName]}" />
> </c:otherwise>
> </c:choose>
>
> <f:param name="itemType" value="${linkAction}" />
> <f:param name="fieldName" value="${fieldName}" />
> <f:param name="addParam" value="${addParam}" />
> </h:commandLink>
>
> The sections marked in bold indicate the components for which duplicate ids
> are being generated. I should also mention we are using facelets + xhtml,
> and the code listed above is in a facelet that is being invoked from the
> main page.
>
> Reading some previous posts is seems the problem is most likely caused by
> mixing JSTL and JSF tags; ideally I would want to remove the JSTL tags, but
> the facelet in question was not written by me and is quite long so I would
> only want to do this as a last resort.
>
> My question is: can anyone suggest an alternative solution to rewriting the
> facelet without JSTL tags? I realize I could also solve this issue by
> explicitly naming the components but would like to understand better how the
> auto id generation works in MyFaces.
>
> Also, if the only "right" solution is to remove the JSTL tags, can someone
> suggest how to do this, considering they appear to be used extensively
> (c:if, c:when…)?
The only right solution is to remove the JSTL tags.
Conditional tags are dangerous with any JSF component. And they are
totally incompatible with JSF looping components like tables; this
applies to JSF1.1 too.
JSF is fundamentally a two-pass system (build component tree, then
render component tree). This was only partially true in JSF1.1, but is
completely true in JSF1.2. But JSTL is a one-pass system, and so
conditional statements interacts very badly with JSF components that
have significant behaviour in the second pass.
I suggest that where a c:when or c:if wraps just one JSF component, then
move the condition into a "rendered" attribute on that component. When
it wraps more than one, then replace the JSTL tag with an h:panelGroup
or t:div, and move the condition into the rendered attribute of that new
tag. In most cases, that will do the trick.
Note that JSTL *can* be used with JSF in some cases, but you really need
to re-read and understand both the JSP specification bits about how tags
work, and the JSF specification bits about the JSF lifecycle. So in
general, it's best to avoid mixing them.
Regards,
Simon