users@javaserverfaces-spec-public.java.net

[jsr344-experts mirror] [jsr344-experts] Re: [971-MultiTemplate] config options

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Thu, 8 Nov 2012 14:54:15 -0500

Hi

2012/11/8 Frank Caputo <frank_at_frankcaputo.de>:
> Hi Leonardo,
>
> Am 07.11.2012 um 20:17 schrieb Leonardo Uribe <lu4242_at_gmail.com>:
>
>>> I think the FacesContext can represent any scope, because it has any information it needs to decide about the prefixes:
>>>
>>> - use getExternalContext().getRequest() to make it request scoped
>>> - use getExternalContext().getSession(true) to make it session scoped
>>> - use getViewRoot() to make it view scoped
>>> - use nothing to make it application scoped
>>>
>>> We can support both with a default implementation like
>>>
>>> FacesContext.getResourcePrefixes() {
>>> return getViewRoot().getResourcePrefixes();
>>> }
>>>
>>
>> In my understanding, FacesContext is a "helper" object, more than an
>> object that
>> represent a scope. That does not change the relationship between the view, and
>> the multi-template configuration. Take a look at JSF 2.2 spec section 7.7.2.1
>> ViewDeclarationLanguage.createView() :
>>
>> "... The createView() method must fulfill the following responsibilities.
>>
>> All implementations must:
>>
>> If there is an existing UIViewRoot available on the FacesContext, this method
>> must copy its locale and renderKitId to this new view root. If not, this method
>> must call calculateLocale() and calculateRenderKitId(), and store the results
>> as the values of the locale and renderKitId, proeprties, respectively, of the
>> newly created UIViewRoot. If no viewId could be identified, or the viewId is
>> exactly equal to the servlet mapping, send the response error
>> code SC_NOT_FOUND with a suitable message to the client. ..."
>>
>> In the case of multi-template configuration, the same step as with locale or
>> renderKitId should be done: calculate it and store the values in the view. The
>> multi-template configuration must be saved and restored with the view
>> information.
>> This ensures the view will be restored properly, because the calculation step
>> is done when the view is built by first time.
>>
>> I have been working for a long time on Partial State Saving algorithm,
>> and something that I discover doing a lot of tests was that to ensure the state
>> works correctly, it is absolutely necessary when restore the view to build the
>> view in the same way it was built by first time. The only way to do that, is
>> ensure all information related to the view is available before build the view
>> using facelets algorithm, and modify facelets algorithm to use that
>> information when building the view.
>>
>> In few words, the multi-template configuration is a parameter of the view.
>
> Ok. But we must expose it somehow so that the resource handler can pick it up. That's why I wanted it on the FacesContext. We should simply enforce that FacesContext.getResourcePrefixes() returns the same result once it's calculated.

The viewRoot is already exposed in FacesContext, so the resource
handler check if
exists or not and if that so, it takes the resource prefixes. The same
happens when
it try to get the locale of a resource. In MyFaces see:

http://svn.apache.org/repos/asf/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ResourceHandlerImpl.java

method getLocalePrefixForLocateResource():

in few words, if the request is a resource request it tries do
retrieve the locale
from a query parameter "loc", otherwise check if exists a viewRoot and if
that so it calls facesContext.getViewRoot().getLocale(), otherwise it use
the ViewHandler to calculate it.

As you can see, we can follow the same strategy as with locale. Put the method
in FacesContext doesn't make any difference.

>
>>>>> LU> <ui:insert name="contractB:header"/>
>>>>>
>>>>> Manfred suggested an additional attribute "template". In this case,
>>>>> this would be <ui:insert template="contractB" name="header" />.
>>>
>>> Isn't this implicitly given by the chosen template? Suppose you have:
>>>
>>> /contractA/template.xhtml:
>>>
>>> <html>
>>> <body>
>>> <div>left</div>
>>> <ui:insert name="right"/>
>>> </body>
>>> </html>
>>>
>>> /contractB/template.xhtml:
>>>
>>> <html>
>>> <body>
>>> <ui:insert name="left"/>
>>> <div>left</div>
>>> </body>
>>> </html>
>>>
>>> /home.xhtml:
>>>
>>> <ui:composition template="/template.xhtml>
>>> <ui:define name="left">something on the left</ui:define>
>>> <ui:define name="right">something on the right</ui:define>
>>> </ui:composition>
>>>
>>> So if contractA is chosen, "something on the right" gets inserted, if contractB is chosen, "something on the left" gets inserted.
>>>
>>> One could also define /contractC/template.xhtml:
>>>
>>> <html>
>>> <body>
>>> <ui:insert name="left"/>
>>> <ui:insert name="right"/>
>>> </body>
>>> </html>
>>>
>>> Where both get inserted.
>>>
>>
>> In my understanding the attribute "template" is just optional in those
>> rare cases
>> where the names used for each template are not mutually exclusive. I
>> think it has
>> sense because the page author must be aware of the multi-template
>> contracts used
>> by the view (but he/she should not know anything about the
>> implementation). Since
>> the multi-template contract is defined by a third-party, the page
>> author cannot change
>> the names once defined, so he/she needs a lifesaver in these cases.
>
>
> I still don't get it. From my point of view the page author is defines the contract like this:
>
> I have a template.xhtml which should insert a,b,c. I have also some graphics a.png, b.png and c.png. I have also a footer.xhtml. The multi-template provider can override them all.
>

From facelets perspective, templates only associate some content with some
specific name. So, it is possible to have one template exposing a,b and other
exposing c. How they are resolve depends on the contract between the
multi-template author and the page author. Maybe we need some concrete examples
to see how it works.

regards,

Leonardo

> Ciao Frank
>