users@javaserverfaces-spec-public.java.net

[jsr344-experts mirror] [jsr344-experts] Re: Thoughts about FaceletCache, ResourceResolver, ResourceHandler and Multitemplating (FaceletCache interface does not handle "relativeLocations" logic from DefaultFaceletFactory)

From: Frank Caputo <frank_at_frankcaputo.de>
Date: Sun, 8 Jul 2012 16:50:55 +0200

Hi Leonardo,

having localized composite components is a great idea and goes with my skinning idea. But I still can't see, why we should limit skinning to templates. We should make a resource identifier contain a skinPrefix, to have a nice fallback scenario as with the locale:

[skinPrefix]/[localePrefix/][libraryName/][libraryVersion/]resourceName[/resourceVersion]

This way we don't need any configuration for skinning just a skin detecting method in the FacesContext as I mentioned earlier.


Ciao Frank

Am 29.06.2012 um 17:39 schrieb Leonardo Uribe:

> Hi
>
> I hope somebody is reading specially this mail. This is important feedback.
>
> Thinking more about, I think the trick with this is just allow
> facelets to get templates directly from ResourceHandler. But the
> current implementation adding only createViewResource(String
> resourceName) is incomplete.
>
> Some time ago, in MyFaces (thanks to Michael Kurz) we found this issue:
>
> https://issues.apache.org/jira/browse/MYFACES-3308
>
> Allow localized composite components
>
> Here is the comment:
>
> "... I tried to make a localized composite components for dynamic
> localization of content on my pages (that goes beyond resource
> bundles). The basic idea is to be able to create composite components
> with static text and/or components (links, images...) for different
> languages. As a composite component basically is a resource I thought
> something like this should be possible:
>
> /resources/fragments/fragment01.xhtml
> /resources/de/fragments/fragment01.xhtml
>
> IMO the spec is a bit unclear on this but I would say it should work.
> I tried it - it did not work. The problem is, that
> CompositeComponentResourceTagHandler gets a resource in the
> constructor that will be used till the death of the webapp. No chance
> to switch locales. ...."
>
> I added this feature in MyFaces, because it comply with the spec. The
> idea is you have always to provide a default implementation of the
> composite component and then you can just create a localized copy.
> Then inside the code, each time the component is created when
> buildView() is called (inside CompositeComponentResourceTagHandler), I
> do something like this:
>
> Resource resourceForCurrentView =
> faceletContext.getFacesContext().getApplication().
>
> getResourceHandler().createResource(_resource.getResourceName(),
> _resource.getLibraryName());
>
> So, I have already one instance from compile time, and on build view
> time the idea is retrieve it the "localized" resource instance, right?
> It does not matter if in compile time I get a localized one, because
> I'm using it only to check if the composite component exists.
>
> There is only one theorical pitfall with this strategy: if you change
> the locale inside a POST, and you have a localized composite
> component, there is a chance that the view could not be restored
> correctly, because you change a part of the component tree. So, if you
> do a change in the locale, just do a PRG or a GET call, and things
> will work as expected.
>
> ... déjà vu .... doesn't that sound too familiar?. I think it also
> goes into the same direction as the current javadoc in
> ResourceHandler, right?
>
> Try to imagine this. As with UIViewRoot.getLocale(), you have a
> property called UIViewRoot.getMultiTemplateLibrary(), that can be
> assigned to a ValueExpression in some way, for example:
>
> <f:view multiTemplateLibrary="#{someBean.someOption}">
>
> or maybe in WEB-INF/faces-config.xml , in the same way as is possible
> to define a skin in trinidad-config.xml
>
> <mult-template-library-name>some.library.location</mult-template-library-name>
>
> Or maybe in some way setup multiple locations, or something like that,
> but I hope you get the idea.
>
> Then, the idea could be add some methods in ResourceHandler to load
> facelets templates, just like with composite components. One idea
> could be add the code in DefaultFaceletFactory.resolveURL(), but it
> could be better just to use ResourceHandler API directly from the
> related TagHandler, get the right Resource instance and then the URL.
>
> The idea of multiTemplateLibrary is "... deal with this library as a
> valid location to load views, templates or whatever facelet resource
> as it was located inside root webapp folder ...". In this way, you
> could have multiple jar files with a multi template library in each
> one, or just one jar file with many multi templates. Note this should
> be done carefully, to prevent load a resource in a multi-template
> library, but maybe we could just create another directory specially
> for that. Instead store in META-INF/resource, let's use something like
> META-INF/multi-templates? Maybe it is a good idea to set a special
> folder in the webapp to deal with multi templates (for example,
> instead /resources use /multi-templates)
>
> The nice part about do it in this way is you can change skins on the
> fly (with GET or PRG, but not in a POST, unless we can force discard
> and rebuild the view if the multi template (or the locale) has
> changed). If you are using maven jetty plugin or something like that
> you can also edit them and see the results just with a refresh on the
> browser, without recompile. There is no need to do any big changes
> into facelets compiler, just fix some spots to use the new API in
> ResourceHandler and that's it.
>
> I hope this helps.
>
> regards,
>
> Leonardo Uribe
>
> 2012/6/27 Leonardo Uribe <lu4242_at_gmail.com>:
>> Hi
>>
>> Today this issue has been created in MyFaces issue tracker:
>>
>> https://issues.apache.org/jira/browse/MYFACES-3575
>>
>> Inside the discussion, I realized a flaw it has FaceletCache API.
>>
>> The original code from facelets 1.1.x has a logic to cache the
>> "conversion" between logical identifiers to find a specific facelet
>> and its related URL.
>>
>> So inside DefaultFaceletFactory there is a map like this:
>>
>> private Map<String, URL> _relativeLocations;
>>
>> Checking the code in deep, I notice this cache store also the values
>> of ResourceResolver.
>>
>> Now suppose an scenario where you has a custom FaceletCache
>> implementation, and by some coincidence there is some mechanism to
>> load / unload some facelets by whatever reason. Once a facelet is
>> called, relativeLocations will hold the same key/value pair, so if a
>> facelet is unloaded and then another one is loaded and it has the same
>> association, it will fail.
>>
>> A realistic scenario that will be part of JSF 2.2 spec is if you have
>> a jar with some composite components and facelet files. For two
>> different skins, there will be facelets with the same "logical
>> identifiers", but with different URL. This issue prevents change the
>> skins on the fly, because you can't clean that map.
>>
>> Who should hold that map? It should be hold by FaceletCache, not by
>> FaceletFactory, because FaceletCache is the responsible to load/unload
>> and hold facelets into memory.
>>
>> But things get more confusing when you think about the changes done
>> into javax.faces.application.ResourceHandler. In the latest javadoc
>> draft there is one method:
>>
>> Resource createViewResource(String resourceName)
>>
>> Again, the "resourceName" is in practice the same "logical identifier"
>> that is missing in the spec. For an specific view is the physical
>> viewId, but if the view is composed by other facelets bundled in the
>> same jar, we need that concept too in the spec, and a way to deal with
>> that logic too.
>>
>> I hope you can see the relationship between FaceletCache and
>> ResourceHandler. The intention is use ResourceHandler to load facelet
>> definitions on the fly, but there is a logic involved in compile them
>> store in memory, and finally dispose them that maybe is being ignored,
>> right?
>>
>> I know this is a topic still under discussion, but I just wanted to
>> warn you guys about the problem.
>>
>> regards,
>>
>> Leonardo Uribe
>