Hi all,
I'm currently working on a project using MyFaces without Facelets and we
have some problems when dealing with includes and I want to see if it's on
our side on in MyFaces. The issue is that I get ids looking like:
"popDelj_id_1" when I really want it to be "popDel". I traced the code and
found the following in UIComponentClassicTagBase:
private String createUniqueId(FacesContext context, UIComponent parent)
throws JspException
{
String id = getId();
if (id == null)
{
id = getFacesJspId();
}
else if (isIdDuplicated(id))
{
if (isInAnIterator)
{
setId(createNextId(id));
id = getId();
}
...
So, in my case getId() returns "popDel" so the first if fails and
isIdDuplicated(id) gets called:
private boolean isIdDuplicated(String componentId)
{
boolean result = false;
if (_parentClassicTag != null)
{
if (_parentClassicTag.isInAnIterator)
{
return true;
}
...
In my case, the tag indeed has a parent and the parent is marked as in an
iterator. This last part is wrong, although it IS in an included page
there's no iteration component anywhere in the hierarchy relative to the
popDel. So I went and checked what set the isInIterator attribute and found
the following method, called automatically when the setJspId method gets
called:
private void checkIfItIsInAnIterator(String jspId)
{
Set<String> previousJspIdsSet = getPreviousJspIdsSet();
if (previousJspIdsSet.contains(jspId) || isIncludedOrForwarded())
{
isInAnIterator = true;
}
else
{
previousJspIdsSet.add(jspId);
isInAnIterator = false;
}
}
Now, since jspId is local to the page and my component exists in an included
page, the jspId received by the method is indeed already used in the
request, and the isIncludedOrForwarded would return true anyway even if the
Set wasn't containing the id. So now it gets back up to the first code
snippet and the following gets executed:
setId(createNextId(id));
id = getId();
where createNextId concatenate my id with a generated one. I can understand
why that's needed in a foreach, however I don't see why this is needed in
case of includes, especially if it was itself placed within a
NamingContainer like a <f:subview/>. Am I missing anything or is that a bug?
>From My point of view I'd say it's a bug and would modify the
getPreviousJspIdsSet method to return a Set local to the closest
NamingContainer and remove the isIncludedOrForwarded completely so that the
code would still work in case someone included a page without using a
<f:subview/>.
Can anyone confirm or infirm?
Thanks,
~ Simon
p.s. I thought about posting that on dev list, but since I'm not sure if it
works as designed and since I found it while being a user, I post it here.