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: Bauke Scholtz <balusc_at_gmail.com>
Date: Thu, 28 Jul 2016 10:09:16 +0000

Leo,

Thank you for your investigation and insights. It's after all a very good
idea to override component's findComponent method to detect the iteration
index which the component itself is internally already aware of. I will
experiment with it.

Cheers, B

On Thu, Jul 28, 2016, 05:41 Leonardo Uribe <leonardo.uribe_at_irian.at> wrote:

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