users@javaserverfaces-spec-public.java.net

[jsr344-experts mirror] [jsr344-experts] Loading Facelets via ResourceHandler (Part 2)

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Sat, 2 Feb 2013 14:50:25 -0500

Hi

The second big problem is how to resolve a facelet that is loaded in a relative
way, or in other words, taking into account the location of the current
facelet that is asking for the resource.

How a template is loaded in a absolute way?:

<ui:include src="/path/to/template.xhtml">
<ui:decorate template="/path/to/template.xhtml">
<ui:composition template="/path/to/template.xhtml">

How a template is loaded in a relative way?:

<ui:include src="path/to/template.xhtml">
<ui:decorate template="path/to/template.xhtml">
<ui:composition template="path/to/template.xhtml">

The difference between an absolute and a relative reference is just the
absolute one starts with '/' character.

Taking into account JSF 2.2 section 10.1.3, it says this:

"... JSF defines a system called "resource library contracts" for applying
facelet templates to an entire application in a reusable and interchangeable
manner. A configurable set of Facelet VDL views in the application will be
able to declare themselves to be template-clients of any template in a resource
library contract. Facelet VDL views in the application can also make use of
resources contained in a resource library contract, but the feature has
ample value when only used with templates. ..."

The point is if a template is loaded in a relative way, in the process
it is necessary to take into account if the template is defined in a resource
library contract. For example:

webapp/
    WEB-INF/
        classes/
            myfile.jar!META-INF/
                contracts/
                    contract-a/
                        dir1/
                            template1.xhtml
                        custom.css
                        mylogo.png
    dir1/
        y.xhtml
        template1.xhtml

And in y.xhtml there is a declaration like this:

<ui:include src="template1.xhtml"/>

The question is if the template to load should be the one in
/dir1/template1.xhtml or the one inside the contract.

After the previous discussions, in my opinion the resources in a resource
library contract takes precedence, in order to honor the spirit of a resource
library contract.

Now look this example:

webapp/
    resources/
        dir1/
            template1.xhtml
        custom.css
        mylogo.png
    dir1/
        y.xhtml
        template1.xhtml

Again: which template should be loaded? At start I thought that the one in
/dir1/template1.xhtml, but after think about part 1, I have changed my mind,
because load the second option becomes at the end more flexible and a lot
simpler.

Looking on the bad side, there is a chance that the directory /dir1 and the
library /resources/dir1 are not related, for example:

webapp/
    resources/
        mycc/
            mycc.xhtml
            template1.xhtml
        custom.css
        mylogo.png
    mycc/
        y.xhtml
        template1.xhtml

Here we have a clash, because the library name (mycc) is used as a folder
in the webapp. In this case, a relative reference from y.xhtml to
template1.xhtml should not take the template located in mycc.

But that's unlikely, because JSF libraries always use a descriptive name
(for example all libraries in myfaces starts with "oam." or jsf library
is "java.faces"), and if there is an overlap, the developer can just
change the path locally and that's it. I think it is a good trade-off.

And what happen with a resource library contract?

webapp/
    WEB-INF/
        classes/
            myfile.jar!META-INF/
                contracts/
                    contract-a/
                        mycc/
                            template1.xhtml
    resources/
        mycc/
            mycc.xhtml
            template1.xhtml
            template2.xhtml
        custom.css
        mylogo.png
    mycc/
        y.xhtml
        template1.xhtml
        template3.xhtml

If there is a relative call from mycc.xhtml to template1.xhtml, the one in
the resource library contract must be choosen. If there is a relative
call from contract-a/mycc/template1.xhtml to template2.xhtml, the one in
resources must be choosen, but if there is a call from
contract-a/mycc/template1.xhtml to template2.xhtml the one in webapp/mycc
should be ignored. Why? Because the call occur outside its context.

In that sense, if contract-a/mycc/template1.xhtml requires template3.xhtml
to work, the call must be done in a absolute way.

I think this solution ensures a consistent and flexible way to load templates
in a relative way. Resolve templates in a relative way will just be some
string manipulation, maybe a call to the function getLocalePrefix() as
described in JSF 2.2 section 2.6.1.4 to identify in a resourceId when the
locale prefix should be considered and that's it.

It could be very useful to add to Resource class a method to get the
resourceId ( Resource.getResourceId() ).

Also, it is clear that if the template was found under webapp/ or under
resources/ or contracts/<contract-name> affect how to load the template
and the scope of the search.

A key point is define that the content of a contract could have the same
structure of resources/, because that makes possible override composite
components even if they are inside libraries, or provide localized
versions of a template inside a resource library contract.

regards

Leonardo Uribe