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

[jsr372-experts] Re: [jsr372-experts mirror] Re: Re: Re: Re: Re: Re: Re: [JAVASERVERFACES_SPEC_PUBLIC-1423] Dynamic resource loading in ajax requests

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Mon, 24 Oct 2016 22:42:58 -0500

Hi

Sorry for reopen this topic again (cannot reopen
JAVASERVERFACES_SPEC_PUBLIC-1423), but I notice something that was not
specified fully. The javadoc of PartialViewContext.processPartial(...)
says this:

"... When the indicated phaseId equals PhaseId.RENDER_RESPONSE,
then perform the following tasks in sequence: ..."

"... 5. If isRenderAll() returns false, then write out each
script of getEvalScripts() as an eval element. ..."

The problem is as the javadoc is written, the <eval> scripts are
executed at last, or in other words after the nodes are updated. But
The resource loading should be done "before" the ajax update is applied,
otherwise a javascript exception could be thrown, because the <update>
block could contain references to the resources to be loaded.

Please note the intention of getEvalScripts() is correct (<eval> blocks
created by developers should be executed normally after <update> blocks),
but in this case we want something to load resources dynamically.

The most simple solution is replace getEvalScripts() with two methods:
getFirstEvalScripts() and getLastEvalScripts() or something like that.

regards,

Leonardo Uribe






2016-07-26 17:00 GMT-05:00 Leonardo Uribe <leonardo.uribe_at_irian.at>:

> Hi
>
> Yes, it is clear. +1
>
> regards,
>
> Leonardo
>
> 2016-07-26 3:11 GMT-05:00 Bauke Scholtz <balusc_at_gmail.com>:
>
>> Leo,
>>
>> Please see the updated API proposal in https://java.net/jira/
>> browse/JAVASERVERFACES_SPEC_PUBLIC-1423?focusedCommentId=392837
>>
>> Is it clear that way?
>>
>> Cheers, B
>>
>> On Tue, Jul 26, 2016 at 8:16 AM, Leonardo Uribe <leonardo.uribe_at_irian.at>
>> wrote:
>>
>>> Hi
>>>
>>> Use something like javax.faces.Resource sounds good. After all, what
>>> really matters is the scripts are loaded before perform the ajax operation
>>> and for stylesheet is the same (no matter where the stylesheet are loaded,
>>> preferred under <head> tag).
>>>
>>> regards,
>>>
>>> Leonardo Uribe
>>>
>>> 2016-07-26 0:12 GMT-05:00 Bauke Scholtz <balusc_at_gmail.com>:
>>>
>>>> Hi,
>>>>
>>>> Thank you for your thoughts. Definitely valid. I will take those into
>>>> account.
>>>>
>>>> How about javax.faces.Resource instead of javax.faces.ViewHead?
>>>>
>>>> Cheers, B
>>>>
>>>> On Tue, Jul 26, 2016, 02:31 Leonardo Uribe <leonardo.uribe_at_irian.at>
>>>> wrote:
>>>>
>>>>> Hi
>>>>>
>>>>> BS>> 1. No substantial changes in API/impl are necessary in order to
>>>>> discover
>>>>> BS>> newly added component resources provided that they are all added
>>>>> via
>>>>> BS>> UIViewRoot#addComponentResource().
>>>>>
>>>>> Yes, it looks good. Good idea to use UIViewRoot#processEvent() and
>>>>> PostRestoreStateEvent.
>>>>>
>>>>> The only thing to notice is the simplification done for a component
>>>>> resource
>>>>> in order to be added. I resume it in this sentence:
>>>>>
>>>>> "... If a component resource has "name" and optionally "library"
>>>>> property set
>>>>> and does not have children and ResourceHandler#
>>>>> getRendererTypeForResourceName(
>>>>> String resourceName) and getRendererType() is equals to
>>>>> 'javax.faces.resource.Script' ..."
>>>>>
>>>>> What I mean is the way how the simplification is done must be explicit
>>>>> in the
>>>>> spec. That also means the full algorithm must be somewhere in the
>>>>> javadoc or
>>>>> in the spec pdf, maybe adding some lines in JSF 2.3 section 13 Ajax
>>>>> Integration.
>>>>>
>>>>> I would like a general solution to the problem, but I think a
>>>>> simplification
>>>>> for only .js resources is also valid.
>>>>>
>>>>> BS>> 2. I would like to (re)use the currently unsupported <update
>>>>> BS>> id="javax.faces.ViewHead"> in jsf.js to perform adding of new
>>>>> component
>>>>> BS>> resources.
>>>>>
>>>>> Unfortunately here there is a problem. This has been already specified
>>>>> in the
>>>>> javascript documentation of jsf.ajax.response(request, context);
>>>>>
>>>>> "... If an <update> element is found in the response with the
>>>>> identifier
>>>>> javax.faces.ViewRoot:
>>>>>
>>>>> <update id="javax.faces.ViewRoot">
>>>>> <![CDATA[...]]>
>>>>> </update>
>>>>>
>>>>> Update the entire DOM replacing the appropriate head and/or body
>>>>> sections
>>>>> with the content from the response. ..."
>>>>>
>>>>> The hack done in MyFaces works because this part was specified, so I
>>>>> do not
>>>>> think it is a good idea to change that meaning. Instead, one way to fix
>>>>> the problem is adding the necessary methods to PartialResponseWriter,
>>>>> as
>>>>> suggested before. It is not pretty (update facelet-partialresponse
>>>>> .xsd,
>>>>> fix PartialResponseWriter, update section 13 ...), but I have not found
>>>>> another way to fix it yet.
>>>>>
>>>>> regards,
>>>>>
>>>>> Leonardo Uribe
>>>>>
>>>>>
>>>>> 2016-07-22 11:30 GMT-05:00 Bauke Scholtz <balusc_at_gmail.com>:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I posted a comment on https://java.net/jira/
>>>>>> browse/JAVASERVERFACES_SPEC_PUBLIC-1423 with my new findings and
>>>>>> thoughts.
>>>>>>
>>>>>> In a nutshell:
>>>>>>
>>>>>> 1. No substantial changes in API/impl are necessary in order to
>>>>>> discover newly added component resources provided that they are all added
>>>>>> via UIViewRoot#addComponentResource().
>>>>>> 2. I would like to (re)use the currently unsupported <update
>>>>>> id="javax.faces.ViewHead"> in jsf.js to perform adding of new component
>>>>>> resources.
>>>>>>
>>>>>> Cheers, B
>>>>>>
>>>>>>
>>>>>> On Mon, Jul 4, 2016 at 8:06 PM, Leonardo Uribe <
>>>>>> leonardo.uribe_at_irian.at> wrote:
>>>>>>
>>>>>>> Hi
>>>>>>>
>>>>>>> BS>> As to "render target", isn't PartialViewContext#getRenderIds()
>>>>>>> sufficient
>>>>>>> BS>> for the task? This returns a mutable collection of client IDs
>>>>>>> which need
>>>>>>> BS>> to be updated on current partial request.
>>>>>>>
>>>>>>> I have been thinking about this for some time to see what's missing
>>>>>>> from the
>>>>>>> spec perspective, and the answer is no, getRenderIds() is not enough
>>>>>>> to do
>>>>>>> the job (in my personal opinion).
>>>>>>>
>>>>>>> The reason is getRenderIds() relies on the fact that it should be a
>>>>>>> html tag
>>>>>>> with an id rendered on the client markup that can be updated. If
>>>>>>> there is
>>>>>>> no html tag with id set, an ajax update will not work. Please note
>>>>>>> getRenderIds() works for most cases, but for <head> and <body> tags,
>>>>>>> both
>>>>>>> does not allow an id to be set. It is true that there is a solution
>>>>>>> updating
>>>>>>> the whole content, but the central point is there is a better
>>>>>>> solution that
>>>>>>> could be done with the changes proposed previously in this thread.
>>>>>>>
>>>>>>> In summary, the current algorithm for ajax has these weaknesses
>>>>>>> (sorry if
>>>>>>> you found this too repetitive):
>>>>>>>
>>>>>>> 1. Resource components added as part of a partial update requires to
>>>>>>> add some html markup inside a <head> or <body> tag, and both tags
>>>>>>> does not have
>>>>>>> an id set, and the current API doesn't help to do it without replace
>>>>>>> the whole tag.
>>>>>>> 2. If a new component is added, there is no html tag we can use to
>>>>>>> update it.
>>>>>>>
>>>>>>> The first case we have already discussed.
>>>>>>>
>>>>>>> The second one is more theoretical but goes far beyond what we have
>>>>>>> discussed.
>>>>>>> Anyway, just for clarity sake I'm going to describe it fully and
>>>>>>> give a
>>>>>>> possible solution.
>>>>>>>
>>>>>>> Think about this fragment:
>>>>>>>
>>>>>>> <h:panelGroup id="content" layout="block">
>>>>>>> <c:if test="#{bean.chooseSomething}">
>>>>>>> <h:outputScript name="script2.js"/>
>>>>>>> </c:if>
>>>>>>> <h:commandButton value="Update" actionListener="#{bean.check}">
>>>>>>> <f:ajax />
>>>>>>> </h:commandButton>
>>>>>>> </h:panelGroup>
>>>>>>>
>>>>>>> Now imagine that when an ajax request is triggered, the code inside
>>>>>>> bean.check() changes chooseSomething from false to true. The
>>>>>>> lifecycle looks
>>>>>>> like this:
>>>>>>>
>>>>>>> - Lifecycle Execute (....) invoke bean.check, change chooseSomething
>>>>>>> to true.
>>>>>>> - Call to vdl.buildView() refresh the whole component tree =>
>>>>>>> h:outputScript
>>>>>>> added and PostAddToViewEvent is triggered.
>>>>>>> - f:ajax requires h:commandButton to be rendered, so a partial
>>>>>>> update over the
>>>>>>> commandButton is activated.
>>>>>>>
>>>>>>> What's wrong with this? A new component (h:outputScript) was added
>>>>>>> on a
>>>>>>> partial request. But the component never had the chance to update
>>>>>>> itself, so
>>>>>>> the script was never updated. Ok, you can replace f:ajax with:
>>>>>>>
>>>>>>> <f:ajax render="content"/>
>>>>>>>
>>>>>>> Problem solved, but is all that really necessary? What if
>>>>>>> chooseSomething does
>>>>>>> not change? why update the content in that case?.
>>>>>>>
>>>>>>> Please note every component addition triggers a PostAddToViewEvent.
>>>>>>> It is
>>>>>>> possible to use that event to detect the change. Since the component
>>>>>>> is a new
>>>>>>> one, there is no id on the client side, but probably an ancestor
>>>>>>> could have an
>>>>>>> id set. The problem is the current algorithm does not have a
>>>>>>> standard way to
>>>>>>> check whether it has an id set on the client or not.
>>>>>>>
>>>>>>> But if a method like UIComponent.isClientIdRendered(...) exist, we
>>>>>>> could create
>>>>>>> an algorithm that recursively find the parent that needs to be
>>>>>>> rendered and
>>>>>>> include it into the current ajax request adding it to
>>>>>>> getRenderIds(). In that
>>>>>>> sense, the algorithm could automatically find that "content" needs
>>>>>>> to be
>>>>>>> updated and activate the render automatically.
>>>>>>>
>>>>>>>
>>>>>>> Going back to the main topic, getRenderIds() relies on a logic that
>>>>>>> for each
>>>>>>> id there is an html markup counterpart.
>>>>>>> setRenderTargetComponent(...)
>>>>>>> and getTargetComponentsToRender(...) are different because the
>>>>>>> intention here
>>>>>>> is to say "... this (resource) component needs to be added for this
>>>>>>> target,
>>>>>>> the way how you want to update the client is up to you ...".
>>>>>>>
>>>>>>> regards,
>>>>>>>
>>>>>>> Leonardo
>>>>>>>
>>>>>>> 2016-07-01 13:01 GMT-05:00 Neil Griffin <
>>>>>>> neil.griffin_at_portletfaces.org>:
>>>>>>>
>>>>>>>> Kyle Stiemann will also be commenting on the following issue in
>>>>>>>> JIRA:
>>>>>>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1423
>>>>>>>>
>>>>>>>> Again, please click on the "watch" link in JIRA if you are
>>>>>>>> interested. Thanks.
>>>>>>>>
>>>>>>>> > On Jun 27, 2016, at 7:12 AM, Bauke Scholtz <balusc_at_gmail.com>
>>>>>>>> wrote:
>>>>>>>> >
>>>>>>>> > As to "render target", isn't PartialViewContext#getRenderIds()
>>>>>>>> sufficient for the task? This returns a mutable collection of client IDs
>>>>>>>> which need to be updated on current partial request.
>>>>>>>> >
>>>>>>>> > Cheers, B
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > On Mon, Jun 27, 2016 at 11:56 AM, Leonardo Uribe <
>>>>>>>> leonardo.uribe_at_irian.at> wrote:
>>>>>>>> > Hi
>>>>>>>> >
>>>>>>>> > 2016-06-24 10:35 GMT+02:00 Bauke Scholtz <balusc_at_gmail.com>:
>>>>>>>> > encodePartial() looks OK.
>>>>>>>> >
>>>>>>>> > I only don't understand how RequestViewContext, setRenderTarget()
>>>>>>>> and getComponentsToRender() are useful as compared to UIViewRoot#
>>>>>>>> addComponentResource()/getComponentResources().
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > I haven't found good names for those ones but I'll explain the
>>>>>>>> intention of them.
>>>>>>>> >
>>>>>>>> > setRenderTarget(...) is used to indicate a component inside a
>>>>>>>> specified target needs to be updated on the client in the current partial
>>>>>>>> request. In comparison, addComponentResource(...) is used to add the
>>>>>>>> component to the tree.
>>>>>>>> >
>>>>>>>> > I know both methods look similar but they are not the same. The
>>>>>>>> reason is addComponentResource(...) is used to affect the component tree,
>>>>>>>> so it will be called each time the component tree is build (initial state,
>>>>>>>> delta, ...), and setRenderTarget(...) is used as a flag to indicate how the
>>>>>>>> current partial request must be rendered. Add a resource could cause the
>>>>>>>> flag to be activated, but not every call to addComponentResource(...) cause
>>>>>>>> the flag to be activated.
>>>>>>>> >
>>>>>>>> > Maybe a better name could be setRenderTargetComponent(...)
>>>>>>>> >
>>>>>>>> > getComponentsToRender(...) returns the list of the components
>>>>>>>> bound to an specific target that needs to be rendered on the current ajax
>>>>>>>> request. in comparison UIViewRoot.getComponentResources(...)
>>>>>>>> return all components bound to an specific target in the view.
>>>>>>>> >
>>>>>>>> > Maybe a better name could be getTargetComponentsToRender(...)
>>>>>>>> >
>>>>>>>> > These two methods are in fact more bound to UIViewRoot than to
>>>>>>>> FacesContext, but the data they manage is "transient", which means the data
>>>>>>>> is discarded at the end of the request.
>>>>>>>> >
>>>>>>>> > I also don't understand "You can't use an eval block because the
>>>>>>>> encoding does not work correctly". Which encoding exactly is problematic?
>>>>>>>> (there's at least character encoding, html encoding and javascript encoding
>>>>>>>> involved). Why couldn't that part be fixed instead?
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > If you have a block like this:
>>>>>>>> >
>>>>>>>> > <h:outputScript target="head">
>>>>>>>> > script2 = function(){
>>>>>>>> > alert("script2");
>>>>>>>> > }
>>>>>>>> > </h:outputScript>
>>>>>>>> >
>>>>>>>> > you could try to do in code something like this:
>>>>>>>> >
>>>>>>>> > prwriter.startEval(....);
>>>>>>>> > renderChildren(...);
>>>>>>>> > prwriter.endEval();
>>>>>>>> >
>>>>>>>> > I tried but it doesn't work because you need to encode it
>>>>>>>> properly, but since there is a ResponseWriter outside of your control, you
>>>>>>>> can't encapsulate the script without do some nasty hacks over
>>>>>>>> ResponseWriter/PartialResponseWriter.
>>>>>>>> >
>>>>>>>> > In this case eval(...) does not work, so we need to attach the
>>>>>>>> node (well, if we want to fix this use case, which I think we should).
>>>>>>>> >
>>>>>>>> > regards,
>>>>>>>> >
>>>>>>>> > Leonardo Uribe
>>>>>>>> >
>>>>>>>> > Cheers, B
>>>>>>>> >
>>>>>>>> > On Thu, Jun 23, 2016 at 2:45 PM, Leonardo Uribe <
>>>>>>>> leonardo.uribe_at_irian.at> wrote:
>>>>>>>> > Hi
>>>>>>>> >
>>>>>>>> > Since there is already a solution almost completed in MyFaces
>>>>>>>> (which an small sample
>>>>>>>> > done some time ago) I did a prototype to see how it works and try
>>>>>>>> to find other details
>>>>>>>> > that could give us a better idea about what to do.
>>>>>>>> >
>>>>>>>> > From spec perspective the relevant changes are:
>>>>>>>> >
>>>>>>>> > UIComponent: Add the following methods:
>>>>>>>> >
>>>>>>>> > public void encodePartial(FacesContext context) throws IOException
>>>>>>>> >
>>>>>>>> > Default implementation call startUpdate(), encodeAll(),
>>>>>>>> endUpdate();
>>>>>>>> >
>>>>>>>> > UIComponentBase: Add the following methods:
>>>>>>>> >
>>>>>>>> > public void encodePartial(FacesContext context) throws IOException
>>>>>>>> >
>>>>>>>> > Default implementation if renderer found call
>>>>>>>> Renderer.encodePartial, otherwise call
>>>>>>>> > super.encodePartial(...)
>>>>>>>> >
>>>>>>>> > Renderer: Add the following methods:
>>>>>>>> >
>>>>>>>> > public void encodePartial(FacesContext context, UIComponent
>>>>>>>> component)
>>>>>>>> > throws IOException
>>>>>>>> >
>>>>>>>> > Default implementation call startUpdate(), encodeAll(),
>>>>>>>> endUpdate();
>>>>>>>> >
>>>>>>>> > RequestViewContext: (it could be located in FacesContext)
>>>>>>>> >
>>>>>>>> > public void setRenderTarget(String target, boolean value,
>>>>>>>> > UIComponent component)
>>>>>>>> >
>>>>>>>> > public List<UIComponent> getComponentsToRender(String target);
>>>>>>>> > (it has an internal set to avoid duplicates, find a better name)
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > The remaining tasks are implement encodePartial(...) for
>>>>>>>> h:outputScript,
>>>>>>>> > h:outputStylesheet, and update the implementation in
>>>>>>>> PartialViewContext to call
>>>>>>>> > encodePartial.
>>>>>>>> >
>>>>>>>> > This is a fragment of the generated response when the change
>>>>>>>> > is activated:
>>>>>>>> >
>>>>>>>> > <partial-response id="j_id__v_0"><changes><eval>
>>>>>>>> > <![CDATA[myfaces._impl.core._Runtime.loadScript(
>>>>>>>> > "/client-window-example/javax.faces.resource/script1.js.jsf",
>>>>>>>> null, null,
>>>>>>>> > "UTF-8", false);]]></eval><update id="content"><![CDATA[ ...
>>>>>>>> >
>>>>>>>> > The main page look like this:
>>>>>>>> >
>>>>>>>> > <h:commandLink id="page1" value="Page 1" actionListener="#{
>>>>>>>> ajaxContentBean.setPage1}">
>>>>>>>> > <f:ajax render=":content"/>
>>>>>>>> > </h:commandLink>
>>>>>>>> > ...
>>>>>>>> > <h:panelGroup id="content" layout="block">
>>>>>>>> > <ui:include src="#{ajaxContentBean.page}.xhtml" />
>>>>>>>> > </h:panelGroup>
>>>>>>>> >
>>>>>>>> > And the included page has something like this:
>>>>>>>> >
>>>>>>>> > <h:outputScript name="script1.js" target="head"/>
>>>>>>>> > <h:commandButton type="button" value="MSG" onclick="script1()"/>
>>>>>>>> >
>>>>>>>> > It works well for scripts but try to update something like this:
>>>>>>>> >
>>>>>>>> > <h:outputScript target="head">
>>>>>>>> > script2 = function(){
>>>>>>>> > alert("script2");
>>>>>>>> > }
>>>>>>>> > </h:outputScript>
>>>>>>>> >
>>>>>>>> > or this:
>>>>>>>> >
>>>>>>>> > <h:outputStylesheet name="style3.css"/> (target="head" is
>>>>>>>> implicit)
>>>>>>>> >
>>>>>>>> > is the real problem. You can't use an eval block because the
>>>>>>>> encoding does not work
>>>>>>>> > correctly, so you really need to insert the DOM node. But the
>>>>>>>> current API in
>>>>>>>> > PartialResponseWriter is useless because head tag does not have
>>>>>>>> an id or name where you
>>>>>>>> > can grab.
>>>>>>>> >
>>>>>>>> > Ok, we can try to "make cheat" a little in this part and try:
>>>>>>>> >
>>>>>>>> > prwriter.startInsertAfter("javax.faces.ViewHead");
>>>>>>>> >
>>>>>>>> > but strictly speaking this should insert the html markup after
>>>>>>>> </head>, but we want
>>>>>>>> > the code inside. I just modified the js code to include it inside
>>>>>>>> in this case, but for
>>>>>>>> > a real implementation it is required to add some methods to
>>>>>>>> PartialResponseWriter like:
>>>>>>>> >
>>>>>>>> > public void startInsertFirst(String targetId) throws IOException
>>>>>>>> > public void startInsertLast(String targetId) throws IOException
>>>>>>>> >
>>>>>>>> > (find a better name, or maybe startInsertInsideAfter?, look in
>>>>>>>> another framework how
>>>>>>>> > they name this?)
>>>>>>>> >
>>>>>>>> > There is also another problem: How do you know you need to insert
>>>>>>>> the node instead of
>>>>>>>> > update it? The only clue is the node is processed specially in
>>>>>>>> PartialViewContext like
>>>>>>>> > this:
>>>>>>>> >
>>>>>>>> > List<UIComponent> componentsToRender = rvc.getComponentsToRender("
>>>>>>>> head");
>>>>>>>> >
>>>>>>>> > for (UIComponent resource: componentsToRender)
>>>>>>>> > {
>>>>>>>> > resource.encodePartial(_facesContext);
>>>>>>>> > }
>>>>>>>> >
>>>>>>>> > So, we need some flag or context attribute or something to
>>>>>>>> indicate we are attempting
>>>>>>>> > to include something new on the tree. Something like
>>>>>>>> JAVAX_FACES_INSERT_PARTIAL for
>>>>>>>> > example and something like JAVAX_FACES_UPDATE_TARGET, so the
>>>>>>>> Renderer in encodePartial
>>>>>>>> > can decide how to update the view.
>>>>>>>> >
>>>>>>>> > The partial response markup looks like this:
>>>>>>>> >
>>>>>>>> > <changes><insert><after id="javax.faces.ViewHead"><![CDATA[
>>>>>>>> > <script type="text/javascript">
>>>>>>>> > script2 = function(){
>>>>>>>> > alert("script2");
>>>>>>>> > }
>>>>>>>> > </script>]]></after></insert>
>>>>>>>> >
>>>>>>>> > It should be better
>>>>>>>> >
>>>>>>>> > <changes><insert><last id="javax.faces.ViewHead"><![CDATA[<script
>>>>>>>> type="text/javascript">
>>>>>>>> > script2 = function(){
>>>>>>>> > alert("script2");
>>>>>>>> > }
>>>>>>>> > </script>]]></last></insert>
>>>>>>>> >
>>>>>>>> > And that's it the proposal from MyFaces side. I think it is
>>>>>>>> flexible enough to allow the
>>>>>>>> > algorithm using "two lists comparison", but also enough to allow
>>>>>>>> the implementation
>>>>>>>> > inside MyFaces.
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > But note the issue proposed here:
>>>>>>>> >
>>>>>>>> > JAVASERVERFACES_SPEC_PUBLIC-1404 Add UIViewRoot#
>>>>>>>> getRenderedComponentResources()
>>>>>>>> >
>>>>>>>> > is still valid. But I'll send the comments related to that one in
>>>>>>>> other email.
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > Suggestions are welcomed.
>>>>>>>> >
>>>>>>>> > regards,
>>>>>>>> >
>>>>>>>> > Leonardo Uribe
>>>>>>>> >
>>>>>>>> >
>>>>>>>> >
>>>>>>>> > 2016-06-22 9:19 GMT+02:00 Cagatay Civici <
>>>>>>>> cagatay.civici_at_gmail.com>:
>>>>>>>> > Sure, actually Thomas Andraschko, the reporter of
>>>>>>>> JAVASERVERFACES_SPEC_PUBLIC-1423 has implemented it in PF, I’ve
>>>>>>>> asked him for details and his response briefly is;
>>>>>>>> >> Have a look at:
>>>>>>>> >> org.primefaces.application.resource.DynamicResourcesPhaseListener
>>>>>>>> - it collects the initial resources on the ajax request
>>>>>>>> >> org.primefaces.context.PrimePartialResponseWriter - ln 278;
>>>>>>>> gets the resources again, creates a diff of the initial and new resources,
>>>>>>>> render some JS to load the resources dynamically
>>>>>>>> > Regards,
>>>>>>>> >
>>>>>>>> > Cagatay Civici
>>>>>>>> > PrimeFaces Lead
>>>>>>>> > PrimeTek Informatics
>>>>>>>> > On Wednesday 22 June 2016 at 10:02, Bauke Scholtz wrote:
>>>>>>>> >
>>>>>>>> >> Cagatay, can you point out it in the PrimeFaces codebase? Then I
>>>>>>>> will look at similarities and differences and if necessary optimize the
>>>>>>>> standard solution based on that.
>>>>>>>> >>
>>>>>>>> >> Cheers, B
>>>>>>>> >>
>>>>>>>> >>
>>>>>>>> >> On Wed, Jun 22, 2016, 08:43 Cagatay Civici <
>>>>>>>> cagatay.civici_at_gmail.com> wrote:
>>>>>>>> >>> We also have a custom solution to this in PrimeFaces as it is a
>>>>>>>> very common case. A standard solution would be preferred for sure.
>>>>>>>> >>>
>>>>>>>> >>> Regards,
>>>>>>>> >>>
>>>>>>>> >>> Cagatay Civici
>>>>>>>> >>> PrimeFaces Lead
>>>>>>>> >>> PrimeTek Informatics
>>>>>>>> >>> On Tuesday 21 June 2016 at 22:34, Bauke Scholtz wrote:
>>>>>>>> >>>
>>>>>>>> >>>> Coming to it, a new encodeAjax() method in UIComponent and
>>>>>>>> Renderer (I'd rather call it encodePartial(), in line with the existing
>>>>>>>> API) is a great suggestion which could indeed solve this problem and has
>>>>>>>> potential for solving/optimizing ajax based problems in a much more
>>>>>>>> flexible way. This is indeed a small and easy change in the API (and impl).
>>>>>>>> >>>>
>>>>>>>> >>>> +1 from me.
>>>>>>>> >>>>
>>>>>>>> >>>> Cheers, B
>>>>>>>> >>>>
>>>>>>>> >>>>
>>>>>>>> >>>>
>>>>>>>> >>>>
>>>>>>>> >>>> On Tue, Jun 21, 2016 at 5:22 PM, Bauke Scholtz <
>>>>>>>> balusc_at_gmail.com> wrote:
>>>>>>>> >>>>> As to writer.startEval(), as per
>>>>>>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1412 I've
>>>>>>>> added a PartialViewContext#getEvalScripts() for JSF 2.3. This
>>>>>>>> could be used.
>>>>>>>> >>>>>
>>>>>>>> >>>>> I will think about encodeAjax() and reply later.
>>>>>>>> >>>>>
>>>>>>>> >>>>> Cheers, B
>>>>>>>> >>>>>
>>>>>>>> >>>>> On Tue, Jun 21, 2016 at 4:01 PM, Leonardo Uribe <
>>>>>>>> leonardo.uribe_at_irian.at> wrote:
>>>>>>>> >>>>>> Hi
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> I just wanted to repost a comment from MyFaces issue tracker
>>>>>>>> in 2012 about the issue being discussed now:
>>>>>>>> >>>>>>
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> Luciano Deiru:
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> Thanks for the reply.
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> I don't think it's going to be possible for me to migrate my
>>>>>>>> app to JSF2 without a
>>>>>>>> >>>>>> complete re-write of the frontend. I did a little more
>>>>>>>> digging to see if richfaces was
>>>>>>>> >>>>>> the issue and i can across this section of the richfaces
>>>>>>>> 4.2.2 development guide...
>>>>>>>> >>>>>> ...
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> "JSF 2 does not allow resources such as JavaScript or
>>>>>>>> Cascading Style Sheets (CSS) to
>>>>>>>> >>>>>> be added if the element requiring the resource is not
>>>>>>>> initially present in the JSF
>>>>>>>> >>>>>> tree. As such, components added to the tree via Ajax must
>>>>>>>> have any required resources
>>>>>>>> >>>>>> already loaded. In RichFaces, any components added to the
>>>>>>>> JSF tree should have
>>>>>>>> >>>>>> components with corresponding resources included on the
>>>>>>>> main page initially. To
>>>>>>>> >>>>>> facilitate this, components can use the rendered="false"
>>>>>>>> setting to not be
>>>>>>>> >>>>>> rendered on the page."
>>>>>>>> >>>>>> ...
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> So the only workaround would be to add every possible
>>>>>>>> richfaces and primefaces component
>>>>>>>> >>>>>> to the login page so it loads the JS and css. That's a bit
>>>>>>>> depressing because you
>>>>>>>> >>>>>> can't create a "pure ajax"/dynamic application in JSF2 even
>>>>>>>> tho i was possible in JSF1.
>>>>>>>> >>>>>> It seems like a widely used approach and there are a lot of
>>>>>>>> forum posts about the
>>>>>>>> >>>>>> issue but no one is ever able to get it working without
>>>>>>>> including the hidden components.
>>>>>>>> >>>>>>
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> regards,
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> Leonardo Uribe
>>>>>>>> >>>>>>
>>>>>>>> >>>>>> 2016-06-21 15:55 GMT+02:00 Leonardo Uribe <
>>>>>>>> leonardo.uribe_at_irian.at>:
>>>>>>>> >>>>>>> Hi
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> I see.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> BS>> Also, to avoid duplicates and/or unnecessary
>>>>>>>> re-rendering, all so far rendered
>>>>>>>> >>>>>>> BS>> resources must be remembered in JSF state. AFAIC this
>>>>>>>> is currently not the case.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> Well, this is information related to the view that is
>>>>>>>> implicit there, but you want to
>>>>>>>> >>>>>>> avoid to put it in the state.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> That's the reason why I like the way it is working in
>>>>>>>> MyFaces, because we just keep
>>>>>>>> >>>>>>> track of the change, rather than store that information in
>>>>>>>> the state.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> Write the script directly into the <eval> is possible, but
>>>>>>>> right now from spec
>>>>>>>> >>>>>>> perspective there are not the necessary "building blocks"
>>>>>>>> available.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> Both h:outputScript and h:outputStylesheet are components
>>>>>>>> that are supposed to be
>>>>>>>> >>>>>>> rendered as resources, but both components have Renderer
>>>>>>>> instances, which are
>>>>>>>> >>>>>>> the classes who finally decide how they should be rendered.
>>>>>>>> Even if you have a list,
>>>>>>>> >>>>>>> this list could include javascript/css or whatever and the
>>>>>>>> resources could be rendered
>>>>>>>> >>>>>>> in different ways.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> For example an h:outputScript could have children that
>>>>>>>> could be js code. Or a
>>>>>>>> >>>>>>> h:outputStylesheet could have a "media" property set.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> So if we want a "general" solution to the problem, which
>>>>>>>> includes script, stylesheets
>>>>>>>> >>>>>>> or whatever, it is necessary to know the component instance
>>>>>>>> that needs to be added
>>>>>>>> >>>>>>> or updated, and then ask the component how it should be
>>>>>>>> rendered.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> The problem from the "building blocks" perspective, is
>>>>>>>> there is no way the component
>>>>>>>> >>>>>>> can know the current request is an ajax update.
>>>>>>>> encodeAll(...) just means encode
>>>>>>>> >>>>>>> everything and don't ask questions.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> I would like to have a method in UIComponent/Renderer
>>>>>>>> called encodeAjax(...) for the
>>>>>>>> >>>>>>> component, which by default start and end an <update>
>>>>>>>> section and call by default
>>>>>>>> >>>>>>> to encodeAll(...). Something like this
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> public void encodeAjax(FacesContext _facesContext,
>>>>>>>> PartialResponseWriter writer) {
>>>>>>>> >>>>>>> try
>>>>>>>> >>>>>>> {
>>>>>>>> >>>>>>> writer.startUpdate(target.
>>>>>>>> getClientId(_facesContext));
>>>>>>>> >>>>>>> target.encodeAll(_facesContext);
>>>>>>>> >>>>>>> }
>>>>>>>> >>>>>>> finally
>>>>>>>> >>>>>>> {
>>>>>>>> >>>>>>> writer.endUpdate();
>>>>>>>> >>>>>>> }
>>>>>>>> >>>>>>> }
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> This part is done in PartialViewContext implementation, but
>>>>>>>> if we can move it here
>>>>>>>> >>>>>>> we could ask the component in a gentle way how it should be
>>>>>>>> rendered. Then, from
>>>>>>>> >>>>>>> this location we could override the method and call
>>>>>>>> writer.startEval(...), which is
>>>>>>>> >>>>>>> something is not possible in this moment, because there is
>>>>>>>> no way right now to
>>>>>>>> >>>>>>> customize this step for each component.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> In this way, you could add an script to load the stylesheet
>>>>>>>> and then use the eval
>>>>>>>> >>>>>>> to include it in the response.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> I have already mention this improvement in this mail some
>>>>>>>> time ago:
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> https://java.net/projects/javaserverfaces-spec-public/
>>>>>>>> lists/jsr372-experts/archive/2015-04/message/41
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> It looks we have yet another use case where this could be
>>>>>>>> useful.
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> regards,
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> Leonardo Uribe
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>> 2016-06-21 14:51 GMT+02:00 Bauke Scholtz <balusc_at_gmail.com
>>>>>>>> >:
>>>>>>>> >>>>>>>> Hi,
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> OmniFaces has 3 solutions to dynamically include a
>>>>>>>> (script) resource:
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> 1: Ajax#load() (just write script straight to <eval>)
>>>>>>>> >>>>>>>> 2: Components#addScriptResourceToHead()
>>>>>>>> >>>>>>>> 3: Components#addScriptResourceToBody()
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> Which one to use depends on the moment (which isn't yet
>>>>>>>> refactored into a single utility method, this is TBD). When the request is
>>>>>>>> an ajax request with partial rendering (i.e. ajax with NO @all), then use
>>>>>>>> #1. Else when the current phase is NOT render response, or the view is in
>>>>>>>> BUILDING state, then use #2. Else use #3.
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> This is implemented for the unload script associated with
>>>>>>>> OmniFaces @ViewScoped and this works quite well.
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> Also, to avoid duplicates and/or unnecessary re-rendering,
>>>>>>>> all so far rendered resources must be remembered in JSF state. AFAIC this
>>>>>>>> is currently not the case.
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> Cheers, B
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>> On Tue, Jun 21, 2016 at 2:37 PM, Leonardo Uribe <
>>>>>>>> leonardo.uribe_at_irian.at> wrote:
>>>>>>>> >>>>>>>>> Hi
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> I have seen this issue has been opened in the spec issue
>>>>>>>> tracker
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-
>>>>>>>> 1423
>>>>>>>> >>>>>>>>> Dynamic resource loading in ajax requests
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> I would like to contribute with some thoughts about the
>>>>>>>> topic, since in MyFaces there
>>>>>>>> >>>>>>>>> is a solution that is not perfect (if PartialViewContext
>>>>>>>> is overriden, the code will
>>>>>>>> >>>>>>>>> not work, so some third party libraries will not be able
>>>>>>>> to use it), but it helps to
>>>>>>>> >>>>>>>>> identify the missing points in the spec, and specify it
>>>>>>>> faster.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> This issue could be also relevant for portlets.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> The issue has been reported long time ago in:
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> - https://issues.apache.org/jira/browse/MYFACES-3106
>>>>>>>> >>>>>>>>> Resources not loaded when using a dynamic ui:inlclude and
>>>>>>>> rendered via ajax
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> - https://issues.apache.org/jira/browse/MYFACES-3367
>>>>>>>> >>>>>>>>> Detect when to update head or body target when content
>>>>>>>> has been updated dynamically
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> - https://issues.apache.org/jira/browse/MYFACES-3659
>>>>>>>> >>>>>>>>> Conditional include of scripts and stylesheets
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> The first thing to understand the problem is identify the
>>>>>>>> possible use cases we have:
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> - c:if, ui:include src="#{...}" or facelet tag that
>>>>>>>> dynamically update the tree.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> For example:
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> ...
>>>>>>>> >>>>>>>>> <f:ajax event="onclick" render="box"/>
>>>>>>>> >>>>>>>>> ...
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> <div jsf:id="box">
>>>>>>>> >>>>>>>>> <c:if test="#{...}">
>>>>>>>> >>>>>>>>> <h:outputScript target="head" library="js"
>>>>>>>> name="help.js" />
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> ...
>>>>>>>> >>>>>>>>> </c:if>
>>>>>>>> >>>>>>>>> </div>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> Here we have a case when the components inside the c:if
>>>>>>>> requires some javascript file,
>>>>>>>> >>>>>>>>> but the update comes from an ajax request. The algorithm
>>>>>>>> just somehow put the
>>>>>>>> >>>>>>>>> h:outputScript on the head of the document, but the ajax
>>>>>>>> does not trigger the head
>>>>>>>> >>>>>>>>> refresh, so the component was added to the tree, but the
>>>>>>>> javascript file was not loaded
>>>>>>>> >>>>>>>>> and we finally have a broken panel.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> There are variants of the same example with
>>>>>>>> h:outputStylesheet, or ui:include but the
>>>>>>>> >>>>>>>>> reason is the same.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> - Dynamic but the resource is added by a
>>>>>>>> @ResourceDependency annotation.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> This is similar to the previous case, but the component
>>>>>>>> is added indirectly when
>>>>>>>> >>>>>>>>> Application.createComponent(...) is executed.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> The important thing to keep in mind is there are 3
>>>>>>>> possible targets: "head", "body" and
>>>>>>>> >>>>>>>>> "form". But the only thing we can do with the current
>>>>>>>> spec is just force a full update
>>>>>>>> >>>>>>>>> of each of these targets.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> So, in MyFaces there is a web config param called
>>>>>>>> >>>>>>>>> org.apache.myfaces.STRICT_JSF_2_REFRESH_TARGET_AJAX that
>>>>>>>> when it is activated, and
>>>>>>>> >>>>>>>>> the previous situation happens, it just enable a flag so
>>>>>>>> the target is updated with
>>>>>>>> >>>>>>>>> the ajax request. If the "head" needs to be updated, the
>>>>>>>> whole "head" and the updated
>>>>>>>> >>>>>>>>> content is sent and so on.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> The processing is done on process partial render time,
>>>>>>>> after the ajax request is
>>>>>>>> >>>>>>>>> rendered but before write the state token. Please note if
>>>>>>>> the target is rendered before
>>>>>>>> >>>>>>>>> this code, the algorithm should be able to detect the
>>>>>>>> condition and do not duplicate
>>>>>>>> >>>>>>>>> the response.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> The solution is not perfect because it force render the
>>>>>>>> whole target, when we only
>>>>>>>> >>>>>>>>> need to render the html fragment of the added component
>>>>>>>> (script/stylesheet/
>>>>>>>> >>>>>>>>> other js code). But there is no way to do it with the
>>>>>>>> current API, because <head>
>>>>>>>> >>>>>>>>> or <body> could not have an id and without id, you can't
>>>>>>>> insert. PartialResponseWriter
>>>>>>>> >>>>>>>>> contains these methods:
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> startInsertBefore(String targetId)
>>>>>>>> >>>>>>>>> startInsertAfter(String targetId)
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> But note these two are useless, because what we need is
>>>>>>>> insert "inside" at the beginning
>>>>>>>> >>>>>>>>> or the end.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> For example:
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> <head>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> <script .../>
>>>>>>>> >>>>>>>>> </head>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> <body>
>>>>>>>> >>>>>>>>> <script .../>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> </body>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> Please note there are some cases where the jsf third
>>>>>>>> party library (for example
>>>>>>>> >>>>>>>>> primefaces) provides its own rules to to render the
>>>>>>>> script at first, middle or last. But
>>>>>>>> >>>>>>>>> in this case it doesn't matter those rules, because what
>>>>>>>> we really need is that the
>>>>>>>> >>>>>>>>> resource is added.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> The code that activates the flags to render head, body or
>>>>>>>> form target is on
>>>>>>>> >>>>>>>>> h:outputScript and h:outputStylesheet, specifically in
>>>>>>>> the listener attached to
>>>>>>>> >>>>>>>>> PostAddToViewEvent. This is the best place, because here
>>>>>>>> is the place where
>>>>>>>> >>>>>>>>> UIViewRoot.addComponentResource is done.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> I think what's really important in this problem is
>>>>>>>> provide the API where you can notify
>>>>>>>> >>>>>>>>> that the resource needs to be added. In MyFaces there is:
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> class RequestViewContext {
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> public boolean isRenderTarget(String target);
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> public void setRenderTarget(String target, boolean
>>>>>>>> value);
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> }
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> Which could evolve to something more complex, including
>>>>>>>> the UIComponent instance and
>>>>>>>> >>>>>>>>> so on.
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> I don't really like to do a list comparison, because it
>>>>>>>> can introduce an unnecessary
>>>>>>>> >>>>>>>>> performance overhead. I would like an API that could have
>>>>>>>> some methods to register the
>>>>>>>> >>>>>>>>> component for updated on the target and others to get the
>>>>>>>> changes and do the necessary
>>>>>>>> >>>>>>>>> calculation in PartialViewContext.processPartial(...)
>>>>>>>> (render response).
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> regards,
>>>>>>>> >>>>>>>>>
>>>>>>>> >>>>>>>>> Leonardo Uribe
>>>>>>>> >>>>>>>>
>>>>>>>> >>>>>>>
>>>>>>>> >>>>>>
>>>>>>>> >>>>>
>>>>>>>> >>>>
>>>>>>>> >>>
>>>>>>>> >
>>>>>>>> >
>>>>>>>> >
>>>>>>>> >
>>>>>>>> >
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>
>>
>