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 10:51:56 +0200

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