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

[jsr372-experts] Re: [jsr372-experts mirror] Re: Set and check component resource rendered via standard API

From: Bauke Scholtz <balusc_at_gmail.com>
Date: Thu, 21 Jul 2016 11:02:41 +0200

While at it, should there be a default implementation too? Both Mojarra and
MyFaces sets it as context attribute. They only do it differently. Mojarra
puts name+library right away as key while MyFaces holds them all in a Map
which in turn is stored as context attribute.

I personally suggest holding a Set<String> or perhaps
Set<ResourceIdentifier> as context attribute.

Cheers, B

On Thu, Jul 21, 2016 at 10:51 AM, Bauke Scholtz <balusc_at_gmail.com> wrote:

> Hi,
>
> I do agree that UIComponent argument should be replaced. I only don't
> strongly agree that it should be a Resource instance as creating it is not
> cheap per se. Basically only the resource identifier (library+name) is
> sufficient for the task. There is however no such model in Java API. In
> OmniFaces there's one:
> https://github.com/omnifaces/omnifaces/blob/625ed0d52c640d7b8a25ba02295c2c77b8f75fe1/src/main/java/org/omnifaces/resourcehandler/ResourceIdentifier.java
> This should also reduce the need of carrying around loose but closely
> related name+library variables through the JSF impl.
>
> What do you guys think about taking over this in JSF API as
> javax.faces.model.ResourceIdentifier? Only, the current API such as
> createResource() would need another overload for that.
>
> Alternatively, we could also just ask for resource name and library
> directly.
>
> abstract void markComponentResourceRendered(FacesContext context, String
> library, String name);
> abstract boolean isComponentResourceRendered(FacesContext context, String
> library, String name);
>
> That's also more consistent with existing ResourceHandler API. I only
> don't particularly like it, but I feel it's kind of too late to introduce a
> ResourceIdentifier as the loose variables are already used over all place
> in JSF API.
>
> Cheers, B
>
> On Wed, Jul 20, 2016 at 8:28 AM, Bauke Scholtz <balusc_at_gmail.com> wrote:
>
>> Hi,
>>
>> I was already doubting between UIComponent or a new ResourceIdentifier
>> model with a.o. name and library properties. This should skip the need for
>> a createResource call.
>>
>> Cheers, B
>>
>> On Wed, Jul 20, 2016, 02:55 Leonardo Uribe <leonardo.uribe_at_irian.at>
>> wrote:
>>
>>> Hi
>>>
>>> I have to change my +1 to +0.
>>>
>>> I just notice there is always a calculation of the underlying Resource
>>> instance,
>>> before call the method, so it looks better if we pass the Resource
>>> instance
>>> as parameter.
>>>
>>> public void markComponentResourceRendered(FacesContext context,
>>> Resource resource, UIComponent componentResource)
>>>
>>> public boolean isComponentResourceRendered(FacesContext context,
>>> Resource resource, UIComponent componentResource)
>>>
>>> The UIComponent instance could be optional. So it could be valid to call:
>>>
>>> ResourceHandler.isComponentResourceRendered(context, resource, null);
>>>
>>> The Resource instance is required, from that one it is easier to
>>> get the libraryName/resourceName. If you have two different component
>>> instances pointing to the same Resource, once the resource is rendered
>>> you don't need to render the other one.
>>>
>>> From a theoretical perspective, a componentResource is a component
>>> that:
>>>
>>> - Can be added to a specific target ("head", "body", "form").
>>> - Could have an associated Resource instance (optional).
>>>
>>> It is just that if you only have the UIComponent instance, how you
>>> calculate
>>> the underlying Resource instance is not clear, and that step can be
>>> different
>>> between components.
>>>
>>> regards,
>>>
>>> Leonardo Uribe
>>>
>>>
>>>
>>> 2016-07-19 18:52 GMT-05:00 Leonardo Uribe <leonardo.uribe_at_irian.at>:
>>>
>>>> +1
>>>>
>>>> 2016-07-19 5:55 GMT-05:00 Bauke Scholtz <balusc_at_gmail.com>:
>>>>
>>>>> Hi,
>>>>>
>>>>> I have rephrased the javadocs on those methods.
>>>>>
>>>>>
>>>>> /**
>>>>> * <p class="changed_added_2_3">
>>>>> * Mark given component resource as rendered. The default
>>>>> implementation must ensure that
>>>>> * {_at_link #isComponentResourceRendered(FacesContext, UIComponent)}
>>>>> will return <code>true</code> when given
>>>>> * component resource has already been rendered during the render
>>>>> response phase of the current view.
>>>>> * </p>
>>>>> * @param context The {_at_link FacesContext} for this request.
>>>>> * @param componentResource The {_at_link UIComponent} representing a
>>>>> {_at_link Resource} instance.
>>>>> * @since 2.3
>>>>> */
>>>>> public abstract void markComponentResourceRendered(FacesContext
>>>>> context, UIComponent componentResource);
>>>>>
>>>>> /**
>>>>> * <p class="changed_added_2_3">
>>>>> * Returns whether given component resource has been rendered. The
>>>>> default implementation must return
>>>>> * <code>true</code> when given component resource has been marked as
>>>>> rendered via
>>>>> * {_at_link #markComponentResourceRendered(FacesContext, UIComponent)}
>>>>> during the render response phase of the current
>>>>> * view.
>>>>> * </p>
>>>>> * @param context The {_at_link FacesContext} for this request.
>>>>> * @param componentResource The {_at_link UIComponent} representing a
>>>>> {_at_link Resource} instance.
>>>>> * @return Whether given component resource has been rendered.
>>>>> * @since 2.3
>>>>> */
>>>>> public abstract boolean isComponentResourceRendered(FacesContext
>>>>> context, UIComponent componentResource);
>>>>>
>>>>>
>>>>> The literal part "current view" is important as this forces the
>>>>> implementation to clear out the marks when the view changes during render
>>>>> response, usually due to an exception which would show an error page view.
>>>>>
>>>>> Cheers, B
>>>>>
>>>>> On Tue, Jul 19, 2016 at 10:18 AM, Bauke Scholtz <balusc_at_gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> After all, adding those methods to ResourceHandler is cleaner API and
>>>>>> allows better abstraction with a custom ResourceHandler.
>>>>>>
>>>>>>
>>>>>> /**
>>>>>> * <p class="changed_added_2_3">
>>>>>> * Mark given component resource as rendered.
>>>>>> * The default implementation stores the resource identifier as
>>>>>> context attribute.
>>>>>> * </p>
>>>>>> * @param context The {_at_link FacesContext} for this request.
>>>>>> * @param componentResource The {_at_link UIComponent} representing a
>>>>>> {_at_link Resource} instance.
>>>>>> * @since 2.3
>>>>>> */
>>>>>> public void markComponentResourceRendered(FacesContext context,
>>>>>> UIComponent componentResource) {
>>>>>> // TODO
>>>>>> }
>>>>>>
>>>>>> /**
>>>>>> * <p class="changed_added_2_3">
>>>>>> * Returns whether given component resource has been rendered.
>>>>>> * The default implementation checks if the resource identifier has
>>>>>> been stored as context attribute.
>>>>>> * </p>
>>>>>> * @param context The {_at_link FacesContext} for this request.
>>>>>> * @param componentResource The {_at_link UIComponent} representing a
>>>>>> {_at_link Resource} instance.
>>>>>> * @return Whether given component resource has been rendered.
>>>>>> * @since 2.3
>>>>>> */
>>>>>> public boolean isComponentResourceRendered(FacesContext context,
>>>>>> UIComponent componentResource) {
>>>>>> // TODO
>>>>>> }
>>>>>>
>>>>>>
>>>>>> If there are no objections, I will take care of it.
>>>>>>
>>>>>> Cheers, B
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Thu, Sep 3, 2015 at 11:08 PM, Bauke Scholtz <balusc_at_gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> I created
>>>>>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1404 on
>>>>>>> this.
>>>>>>>
>>>>>>> Cheers, B
>>>>>>>
>>>>>>> On Wed, Mar 4, 2015 at 6:11 PM, Bauke Scholtz <balusc_at_gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> By just adding it to the set.
>>>>>>>>
>>>>>>>> Cheers, B
>>>>>>>>
>>>>>>>> On 16:25, Wed, Mar 4, 2015 arjan tijms <arjan.tijms_at_gmail.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> Sounds good, but one question:
>>>>>>>>>
>>>>>>>>> If the proposed API just returns a Set<String> where presence of a
>>>>>>>>> resource identifier means that resource has been rendered, how does
>>>>>>>>> the library indicate it wants to suppress rendering of a certain
>>>>>>>>> resource?
>>>>>>>>>
>>>>>>>>> Kind regards,
>>>>>>>>> Arjan
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Wed, Mar 4, 2015 at 4:09 PM, Bauke Scholtz <balusc_at_gmail.com>
>>>>>>>>> wrote:
>>>>>>>>> > In hindsight, that boolean is superfluous. Make it a mutable
>>>>>>>>> > Set<ResourceIdentifier> or Set<String> and just consider the
>>>>>>>>> presence in the
>>>>>>>>> > set as already rendered.
>>>>>>>>> >
>>>>>>>>> > Cheers, B
>>>>>>>>> >
>>>>>>>>> > On Wed, Mar 4, 2015 at 4:05 PM, Bauke Scholtz <balusc_at_gmail.com>
>>>>>>>>> wrote:
>>>>>>>>> >>
>>>>>>>>> >> Hi,
>>>>>>>>> >>
>>>>>>>>> >> Both Mojarra and MyFaces have an internal way to mark a script
>>>>>>>>> or
>>>>>>>>> >> stylesheet resource as rendered (to avoid duplicate rendering).
>>>>>>>>> Mojarra sets
>>>>>>>>> >> it as a context attribute with name+library as key and a
>>>>>>>>> boolean true as
>>>>>>>>> >> value (see a.o. StylesheetRenderer#encodeEnd()). MyFaces sets
>>>>>>>>> it as a
>>>>>>>>> >> context attribute via a Map<String, Boolean> (see a.o.
>>>>>>>>> >> HtmlStylesheetRenderer#encodeEnd() via a ResourceUtils helper
>>>>>>>>> class).
>>>>>>>>> >>
>>>>>>>>> >> For component library developers it would be very useful if this
>>>>>>>>> >> information is available by standard API means so that the
>>>>>>>>> component library
>>>>>>>>> >> can if necessary check and/or suppress the rendering of those
>>>>>>>>> resources. For
>>>>>>>>> >> example to combine those resources via a special resource
>>>>>>>>> handler, or to
>>>>>>>>> >> automatically delegate to a CDN host, or to turn a script
>>>>>>>>> resource into a
>>>>>>>>> >> deferred script, etcetera.
>>>>>>>>> >>
>>>>>>>>> >> I'd propose adding UIViewRoot#getRenderedComponentResources()
>>>>>>>>> which
>>>>>>>>> >> returns a mutable Map<ResourceIdentifier, Boolean> for the
>>>>>>>>> purpose where
>>>>>>>>> >> ResourceIdentifier could also be a String in the standard format
>>>>>>>>> >> library+":"+name.
>>>>>>>>> >>
>>>>>>>>> >> What do others think about it?
>>>>>>>>> >>
>>>>>>>>> >> Cheers, B
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>