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

[jsr372-experts] Re: [jsr372-experts mirror] Re: [JAVASERVERFACES_SPEC_PUBLIC-1404] Add UIViewRoot#getRenderedComponentResources()

From: Bauke Scholtz <balusc_at_gmail.com>
Date: Fri, 24 Jun 2016 10:26:34 +0200

Storing it in the view state is the only server side way. Relying on a
rebuilt view is insufficient as it doesn't reveal which components and
associated resources have been conditionally rendered/toggled during all
previous postbacks. Whether that's "cheap" is a second.

Cheers, B


On Fri, Jun 24, 2016 at 9:19 AM, Leonardo Uribe <leonardo.uribe_at_irian.at>
wrote:

> But that means the resource path could be sent over and over per each ajax
> request. If there is a cheap way to check it from the server without a
> network overhead we should take it.
>
> If we fix the dynamic resource loading without fix this we will fall in
> this situation.
> On Jun 23, 2016 7:05 PM, "Bauke Scholtz" <balusc_at_gmail.com> wrote:
>
>> Another way would be passing resource path to JS and have it check if
>> it's already in DOM and if not, then dynamically create script element.
>>
>> Cheers, B
>>
>> On Thu, Jun 23, 2016, 16:20 Leonardo Uribe <leonardo.uribe_at_irian.at>
>> wrote:
>>
>>> Hi
>>>
>>> I have seen this issue opened:
>>>
>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1404
>>> Add UIViewRoot#getRenderedComponentResources()
>>>
>>> I would like to contribute with some thoughts about this issue that
>>> could help to solve
>>> some issues we already have in this part, and that could be fixed on the
>>> way.
>>>
>>> In MyFaces as you already know there is also a map that is used to
>>> indicate when
>>> a resource has been already rendered in the response.
>>>
>>> This solution is far from being perfect. It just check if a resource has
>>> been rendered
>>> more that once on the current request but:
>>>
>>> - On each request this map is filled over and over and over again. By
>>> performance
>>> reasons, this map is not saved on the state, but in fact each resource
>>> has one or
>>> many associated components that just point to each resource, so this
>>> information is
>>> in the tree structure, but there is no standard way to calculate it from
>>> the current
>>> view.
>>>
>>> - If you are building the whole view, you want this map to be empty
>>> before render the
>>> view, but on an ajax request things change, because in this case you
>>> assume there is
>>> already a view built on the client with the scripts, so you want this
>>> map already filled
>>> but before render the ajax fragment.
>>>
>>> If we remember the case "Dynamic resource loading in ajax requests", if
>>> we don't solve
>>> this problem some scripts could be loaded over and over even if they
>>> have been already
>>> there by other components.
>>>
>>> So, this is a "transient" HashSet that should be cleared and filled when
>>> the view is fully
>>> built. But in an ajax request, we need something to rebuild the set
>>> before render the ajax
>>> fragments. We don't need to traverse the whole tree, because we know
>>> that all resource
>>> components that matters can be retrieved from
>>> UIViewRoot.getComponentResources(...)
>>> (look with target=head, body or form).
>>>
>>> I can imagine a custom component event to register the resources on the
>>> map and a
>>> @ListenerFor annotation of each renderer (h:outputScript and
>>> h:outputStylesheet). It is not
>>> necessary to traverse the whole component tree, just a small fragment of
>>> the tree, and
>>> it is necessary to give each component a way to register themselves on
>>> the map. Again,
>>> this requires some changes on the spec. The reason why the components
>>> must register
>>> themselves is there are the case where h:outputScript renders as a
>>> script block so the
>>> algorithm should skip those components and the only way to know that is
>>> ask to each
>>> component itself.
>>>
>>> regards,
>>>
>>> Leonardo Uribe
>>>
>>