jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: [jsr372-experts mirror] Re: Re: Validate client IDs in f:ajax execute and render

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Wed, 27 Jul 2016 22:40:55 -0500

Hi Bauke

I have tested an example in both implementations and now I can see what's
wrong.

MyFaces f:ajax ClientBehaviorRenderer implementation relies on
UIComponent.findComponent(...) to locate the component pointed by "execute"
or "render" attribute. The exception is thrown because the lookup algorithm
does
not take into account "virtual" components, so it never has the chance to
find
the component, because UIComponent.findComponent(...) is not overriden in
UIData
to include components according to its model, so any component inside
ui:repeat
or h:dataTable with an index is just ignored. Mojarra behaves different, so
I suppose there is something different there, in fact I was suprised by this
behavior.

In JSF 2.2 facelets taglib documentation, in the description of f:ajax it
says
this:

"... The String value for ids specified for execute and render may be
specified
as a search expression as outlined in the JavaDocs for
UIComponent.findComponent(). The implementation must resolve these ids as
specified for UIComponent.findComponent(). ..."

MyFaces is doing what the spec says, but it is clear the syntax proposed is
valid.
The problem is change the behavior of UIComponent.findComponent(...) is
problematic, because there is a lot of code that depends on it. We need a
new
lookup method that works in some cases like UIComponent.findComponent(...),
but
behaves like invokeOnComponent(...).

Let me think a bit about it, so I can make a proposal we can discuss.

regards,

Leonardo Uribe



2016-07-27 4:58 GMT-05:00 Bauke Scholtz <balusc_at_gmail.com>:

> Hi Leo,
>
> I just took the opportunity to test MyFaces 2.2.10 on this. It throws an
> exception on this.
>
> javax.faces.FacesException: Component with id::form:list:1:item not found
> at
> org.apache.myfaces.renderkit.html.HtmlAjaxBehaviorRenderer.getComponentId(HtmlAjaxBehaviorRenderer.java:495)
> at
> org.apache.myfaces.renderkit.html.HtmlAjaxBehaviorRenderer.build(HtmlAjaxBehaviorRenderer.java:467)
> at
> org.apache.myfaces.renderkit.html.HtmlAjaxBehaviorRenderer.mapToString(HtmlAjaxBehaviorRenderer.java:439)
> at
> org.apache.myfaces.renderkit.html.HtmlAjaxBehaviorRenderer.makeAjax(HtmlAjaxBehaviorRenderer.java:158)
> at
> org.apache.myfaces.renderkit.html.HtmlAjaxBehaviorRenderer.getScript(HtmlAjaxBehaviorRenderer.java:102)
> at
> javax.faces.component.behavior.ClientBehaviorBase.getScript(ClientBehaviorBase.java:101)
>
>
> It's exactly that validation which's being discussed here. Mojarra removed
> the validation, but I find that it should be brought back because starters
> start complaining that ajax "doesn't work". It appears that this validation
> is nowhere in the spec (at least, Manfred said so in
> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1372
>
> Cheers, B
>
>
> On Wed, Jul 20, 2016 at 9:04 AM, Bauke Scholtz <balusc_at_gmail.com> wrote:
>
>> > In my understanding, it works in MyFaces. Am I missing something?
>>
>> I meant the use case of specifying an absolute client ID referring a
>> specific iteration round. E.g.
>>
>> <h:form id="form">
>> <ui:repeat id="list" value="#{['one','two','three']}" var="item">
>> <h:outputText id="item" value="#{item}" /><br/>
>> </ui:repeat>
>>
>> <h:commandButton value="Update second item">
>> <f:ajax render=":form:list:1:item" />
>> </h:commandButton>
>> </h:form>
>>
>> Cheers, B
>>
>>
>>
>> On Wed, Jul 20, 2016 at 1:49 AM, Leonardo Uribe <leonardo.uribe_at_irian.at>
>> wrote:
>>
>>> Hi
>>>
>>> I would like to mention some issues mentioned in MyFaces some time ago,
>>> related
>>> to the behavior of this part of the spec.
>>>
>>> The discussion comes from this issue:
>>>
>>> - https://issues.apache.org/jira/browse/MYFACES-3542
>>> The render attribute of AjaxBehavior should support late
>>> value expression evaluation
>>>
>>> The issue is all about when "execute" and "render" attributes should be
>>> evaluated. This point is critical if you want to validate the clientids
>>> properly.
>>>
>>> The first point to remember is the values stored in f:ajax "execute" or
>>> "render"
>>> attribute are not clientIds. Instead, they are relative references to
>>> component
>>> instances, that in some cases, where the components are inside a
>>> ui:repeat or
>>> a h:dataTable, they are "virtual" or "row-specific".
>>>
>>> Checking MyFaces, there is a validation check inside f:ajax
>>> ClientBehaviorRenderer. This validation throws a FacesException if the
>>> component cannot be found. The algorithm use the existing findComponent,
>>> but it is called twice, once with the reference and the other with the
>>> separator and the reference.
>>>
>>> Let's take a look at the proposed options:
>>>
>>> BS>> 1. Strip off anything which matches the iteration index :[0-9]+:
>>> from
>>> BS>> f:ajax execute/render client ID before passing to findComponent()
>>> for
>>> BS>> validation.
>>>
>>> It won't work, because there is no reliable way to remove that, at least
>>> with the current spec.
>>>
>>> BS>> 2. Improve findComponent to recognize the iteration index and act
>>> BS>> accordingly.
>>>
>>> It looks like a simplification of UIComponent.invokeOnComponent(...) or
>>> visitTree(...), but after you have the UIComponent instance, you don't
>>> have
>>> the context set, so it will not be the "real" instance. I don't see how
>>> it
>>> can fit in the spec.
>>>
>>> But at this point, I have to say I think there is another bug on the RI.
>>>
>>> I found it was reported long time ago here:
>>>
>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-865
>>> Ajax inside a DataTable (getClientId append rowIndex)
>>>
>>> And MyFaces fixed it in 2.0.1 (see MYFACES-2744 for details)
>>>
>>> BS>> Being able to reference a specific ui:repeat/h:dataTable item
>>> BS>> via f:ajax render is absolutely a major step forward.
>>>
>>> In my understanding, it works in MyFaces. Am I missing something?
>>>
>>> regards,
>>>
>>> Leonardo Uribe
>>>
>>> 2016-07-19 1:58 GMT-05:00 Bauke Scholtz <balusc_at_gmail.com>:
>>>
>>>> There are basically two ways to solve this:
>>>>
>>>> 1. Strip off anything which matches the iteration index :[0-9]+: from
>>>> f:ajax execute/render client ID before passing to findComponent() for
>>>> validation.
>>>> 2. Improve findComponent to recognize the iteration index and act
>>>> accordingly.
>>>>
>>>> The first way is trivial. The second way, however, is best to implement
>>>> if all repeater components (UIData and UIRepeat at least) share a common
>>>> interface such as UIIterable. Only, this is not really nice for backwards
>>>> compatibility.
>>>>
>>>> What do you think?
>>>>
>>>> Cheers, B
>>>>
>>>>
>>>> On Mon, Jul 11, 2016 at 6:00 AM, Josh Juneau <juneau001_at_gmail.com>
>>>> wrote:
>>>>
>>>>> +1, I think that since this change will help to clarify the spec for
>>>>> newcomers, it is a good idea.
>>>>>
>>>>> Josh Juneau
>>>>> juneau001_at_gmail.com
>>>>> http://jj-blogger.blogspot.com
>>>>> https://www.apress.com/index.php/author/author/view/id/1866
>>>>>
>>>>>
>>>>> On Sun, Jul 10, 2016 at 5:39 AM, Bauke Scholtz <balusc_at_gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> Since Mojarra 2.2.5 (
>>>>>> https://java.net/jira/browse/JAVASERVERFACES-2958) the f:ajax
>>>>>> stopped validating client IDs in execute and render attributes with the
>>>>>> reason to support updating a specific ui:repeat/h:dataTable iteration round
>>>>>> such as render="form:repeat:0:item" which updates only the first item of
>>>>>> ui:repeat.
>>>>>>
>>>>>> However, this has the side effect that new JSF users now start asking
>>>>>> questions why f:ajax execute and/or render doesn't seem to have any effect
>>>>>> while there's a clear syntax error or typo in the execute and/or render
>>>>>> attribute. Previously they are been notified about this much sooner by a
>>>>>> clear exception. It appears that this validation is not part of JSF spec.
>>>>>>
>>>>>> Therefore I propose to bring back validation of client ID in f:ajax
>>>>>> execute and render attributes and make it part of the spec. I already
>>>>>> created an issue on this:
>>>>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1372
>>>>>>
>>>>>> I only wonder what's the best place in spec to state that.
>>>>>> AjaxBehavior class?
>>>>>>
>>>>>> Cheers, B
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>