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: Tue, 26 Jul 2016 17:00:29 -0500

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