You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Simon Lessard <si...@gmail.com> on 2009/03/23 21:08:48 UTC

UIComponentClassicTagBase componentId strategy

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.

Re: UIComponentClassicTagBase componentId strategy

Posted by Simon Lessard <si...@gmail.com>.
Hi Leonardo,

Wow, so much for me showing the good example >.<. I should have checked JIRA
first. Thanks, I'll check what version I'm using and see if the problem is
still there in my case and if it's then I'll attempt to make a patch.


Thanks,

~ Simon

On Mon, Mar 23, 2009 at 6:21 PM, Leonardo Uribe <lu...@gmail.com> wrote:

> Hi
>
> Look this issue:
>
> http://issues.apache.org/jira/browse/MYFACES-1834
>
> regards
>
> Leonardo Uribe
>
>
> On Mon, Mar 23, 2009 at 3:08 PM, Simon Lessard <si...@gmail.com>wrote:
>
>> 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.
>>
>
>

Re: UIComponentClassicTagBase componentId strategy

Posted by Leonardo Uribe <lu...@gmail.com>.
Hi

Look this issue:

http://issues.apache.org/jira/browse/MYFACES-1834

regards

Leonardo Uribe

On Mon, Mar 23, 2009 at 3:08 PM, Simon Lessard <si...@gmail.com>wrote:

> 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.
>