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

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

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Wed, 7 Nov 2012 14:17:18 -0500

Hi

2012/11/7 Frank Caputo <frank_at_frankcaputo.de>:
> Hi All,
>
> Am 07.11.2012 um 02:25 schrieb Leonardo Uribe <lu4242_at_gmail.com>:
>
>> 2012/11/6 Edward Burns <edward.burns_at_oracle.com>:
>>>>>>>> On Sun, 4 Nov 2012 20:32:46 -0500, Leonardo Uribe <lu4242_at_gmail.com> said:
>>> LU> Basically, the discussion about how this feature should looks like
>>> LU> is about these three points. The position of the EG about them will
>>> LU> decide the final result. Personally, I'm willing to support full
>>> LU> multi-templating proposal, because I believe it is possible to
>>> LU> design an intermediate solution, but at the end is up to the members
>>> LU> of the EG to decide which route should be taken.
>>>
>>>>>>>> On Mon, 5 Nov 2012 16:29:37 +0100, Frank Caputo <frank_at_frankcaputo.de> said:
>>>
>>> FC> I think having more than one contract is hard to maintain.
>>>
>>> Ok, this is something I am going to decide right now: zero, one, or
>>> more-than-one. We need more-than-one. There you have it.
>>>
>>> The feature is called *multi* templating, after all.
>
> OK. But I'm still a little bit confused, how multiple contracts should be used in ONE request?
>

To be more precise, one view can have more-than-one multi-template
contracts, but there is
only one active implementation per contract at the same time.

>>>
>>>>>>>> On Mon, 5 Nov 2012 14:31:01 -0500, Leonardo Uribe <lu4242_at_gmail.com> said:
>>> LU> What do we need to support multiple multi-template contracts?
>>>
>>> LU> Instead of a single value, we should define a list of values, in
>>> LU> this case, a list of libraryNames that identify each multi-template
>>> LU> contract to apply on the view, maybe separated by comma. For
>>> LU> example:
>>>
>>> LU> <faces-config ....>
>>> LU> <application>
>>> LU> <default-multi-template-contract>contractA:impl1,
>>> LU> contractB:impl2</default-multi-template-contract>
>>> LU> </application>
>>> LU> </faces-config>
>>>
>>> LU> or
>>>
>>> LU> <f:view multiTemplateContract="contractA:impl1, contractB:impl2"/>
>>>
>>> Both of these answer the question, "How does Page Author indicate that
>>> their pages should be influenced by a multi-template?"
>>>
>>> Frank's original reduced scope idea was to have a property on the
>>> FacesContext. We could keep that idea and make the property be able to
>>> return a list of resource prefixes. Frank's idea, call it
>>> multi-template-zero-config for discussion, was for the spec to say
>>> nothing about how this property was to be set. In practice, he felt
>>> that people could decorate the FacesContextFactory to set it.
>>>
>>> Is that acceptable?
>>
>> Isn't better use a EL expression bound to a bean than override FacesContext?
>> The problem is conceptually speaking, FacesContext has "request scope" ,
>> but this is a "view scope" value.
>
> 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.

>> Suppose a view that has a multi-template
>> contract implementation applied and you change the implementation in a
>> POST. The view becomes unstable and that will lead to exceptions. The same
>> happens when you change the locale and you use a localized composite
>> component, or when you change the renderkit (because components added
>> using @ResourceDependency annotation depends on the renderer classes).
>
> Sure, the prefixes must not change during the request.
>
>>> ACTION: Can we get away with just doing multi-template-zero-config for
>>> JSF 2.2?
>
> I still think so.
>
>>> LU> Now, suppose both contracts implement "header" definition. In this case,
>>> LU> the header defined in contractA will be resolved first, but to get the
>>> LU> one in contractB we can just change a little bit the syntax to allow
>>> LU> something like this:
>>>
>>> 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.

regards,

Leonardo Uribe

>
>>> I need some others to weigh in!
>
> This would be cool.
>
> Ciao Frank
>
>
> -
>
> Frank Caputo
> Johann-Mohr-Weg 24d
> 22763 Hamburg
>
> Mobil +49 177 61 61 81 3
> E-Mail info_at_frankcaputo.de
>