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

[jsr372-experts] Re: [jsr372-experts mirror] Re: getResourcePaths like method for ResourceResolver

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 4 Aug 2016 14:20:39 +0200

Hi,

Thanks for the response Leonardo! As soon as I can find the time I'll look
at implementing the proposal then.

As for the current Mojarra implementation, likely using different chains as
MyFaces seems to do is a better, but because of the complicated nature of
the code I'm wary of touching it for now. Maybe later ;)

Kind regards,
Arjan Tijms




On Thu, Aug 4, 2016 at 7:18 AM, Leonardo Uribe <leonardo.uribe_at_irian.at>
wrote:

> Hi
>
> I just wanted to mention that the algorithm in MyFaces does not have any
> Faces Flow specific logic.
>
> There is an algorithm that uses a set of "ResourceLoader" and
> "ContractResourceLoader" instances, and there is a cache to reduce overhead.
>
> But the chain used for createResource(...) and createViewResource(...) is
> different, because the ordering is also different.
>
> So, the proposal here has sense from spec perspective and looking MyFaces
> code it is easy to walk through the different sets.
>
> regards,
>
> Leonardo Uribe
>
> 2016-07-28 12:09 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>
>> Hi,
>>
>> I took a look at the current ResourceHandler implementation in Mojarra,
>> and for view resources eventually what's being called for the #create()
>> method is nothing more than:
>>
>> URL url = externalContext.getResource(path);
>>
>> Since this is by definition equal to ServletContext#getResource, it means
>> that the default ResourceHandler can just call the ServletContext#getResourcePaths
>> method.
>>
>> I do wonder a bit if complexity wise the ResourceHandler is not slightly
>> sub-optimal, at least from an implementation perspective in Mojarra. While
>> essentially only externalContext.getResource(path) is called, the
>> following stack was necessary for that:
>>
>> Resource.getResourceUrl(FacesContext, String) line: 105
>> FaceletWebappResourceHelper.findResource(LibraryInfo, String, String,
>> boolean, FacesContext) line: 121
>> ResourceManager.findResource(LibraryInfo, String, String, boolean,
>> boolean, FacesContext) line: 539
>> ResourceManager.getResourceInfo(String, String, String, String, boolean,
>> boolean, FacesContext, LibraryInfo) line: 320
>> ResourceManager.doLookup(String, String, String, boolean, boolean,
>> List<String>, FacesContext) line: 285
>> ResourceManager.findResource(String, String, String, boolean,
>> FacesContext) line: 214
>> ResourceHandlerImpl.createViewResource(FacesContext, String) line: 124
>> ResourceHandlerImpl.createViewResource(FacesContext, String) line: 72
>>
>> Now a slightly deeper stack is not always a problem, but here all the
>> classes involved are rather big and the methods have a very high cyclomatic
>> complexity (number of paths through each method). Many methods take many
>> parameters and then entire flows through the code each time do something
>> based on whether say parameter one is not null and parameter 4 is false.
>>
>> Because of this it's not entirely trivial to see e.g. the "create view
>> resource" flow in the above stack. Naming is a tad problematic too, e.g.
>> what's the semantic difference between a "handler", "manager" and "helper"?
>> And the helper is called FaceletWebappResourceHelper, but shouldn't this
>> be something like ViewResourceHelper? (the call chain is supposed to be VDL
>> neutral, isn't it?)
>>
>> There's also code there like shown below:
>>
>> boolean keepGoing = true;
>> FacesContext context = FacesContext.
>> getCurrentInstance();
>> Application application = context.getApplication();
>> FlowHandler fh = application.getFlowHandler();
>> Flow currentFlow = fh.getCurrentFlow(context);
>> do {
>> if (null != currentFlow && 0 < currentFlow.
>> getDefiningDocumentId().length()) {
>> String definingDocumentId = currentFlow.
>> getDefiningDocumentId();
>> ExternalContext extContext =
>> context.getExternalContext();
>> ApplicationAssociate associate =
>> ApplicationAssociate.getInstance(extContext);
>> if (associate.urlIsRelatedToDefiningDocumentInJar(url,
>> definingDocumentId)) {
>> keepGoing = false;
>> doNotCache = true;
>> } else {
>> if (matches.hasMoreElements()) {
>> url = matches.nextElement();
>> } else {
>> keepGoing = false;
>> }
>> }
>> } else {
>> keepGoing = false;
>> }
>> } while (keepGoing);
>>
>> I'm not a big expert on flows, but shouldn't the ExternalContext and
>> ApplicationAssociate be obtained once outside the loop, or can they change?
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>> On Wed, Jul 27, 2016 at 4:33 PM, arjan tijms <arjan.tijms_at_gmail.com>
>> wrote:
>>
>>> Hi,
>>>
>>> On Wed, Jul 27, 2016 at 3:38 PM, Bauke Scholtz <balusc_at_gmail.com> wrote:
>>>
>>>> +1 only if it's visitable/filterable a la Files#walk
>>>>
>>>
>>> Noted, thanks! Files#walk is indeed an important cornerstone.
>>>
>>> Kind regards,
>>> Arjan Tijms
>>>
>>>
>>>
>>>>
>>>> Cheers, B
>>>>
>>>> On Wed, Jul 27, 2016 at 3:27 PM, arjan tijms <arjan.tijms_at_gmail.com>
>>>> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> On Wednesday, July 27, 2016, Leonardo Uribe <leonardo.uribe_at_irian.at>
>>>>> wrote:
>>>>>
>>>>>> Just some small comments. There is a method called ResourceHandler.createViewResource(...)
>>>>>> that returns a ViewResource instance, which is an interface with a method
>>>>>> getURL(). This call ResourceResolver internally.
>>>>>>
>>>>>
>>>>> Practically speaking indeed. I wrote about that here:
>>>>> http://jdevelopment.nl/jsf-22/#809
>>>>>
>>>>> Theoretically speaking I think the spec doesn't require this, does it?
>>>>>
>>>>>
>>>>>> There is nothing to scan for (possible) view resources or templates,
>>>>>> but I suppose this feature should modify ResourceHandler instead
>>>>>> ResourceResolver.
>>>>>>
>>>>>
>>>>> For the best compatibility we may have to involve the
>>>>> ResourceResolver. The primary change would be adding the method to
>>>>> ResourceHandler though.
>>>>>
>>>>> Kind regards,
>>>>> Arjan Tijms
>>>>>
>>>>>
>>>>>
>>>>>> regards,
>>>>>>
>>>>>> Leonardo Uribe
>>>>>>
>>>>>> 2016-07-26 17:38 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> The ServletContext has a method to acquire all paths to resources
>>>>>>> within a web application; getResourcePaths().
>>>>>>>
>>>>>>> In JSF resources are handled by the ResourceResolver. This has a
>>>>>>> method createViewResource that takes a path and effectively returns a URL,
>>>>>>> just like ServletContext has a getResource method taking a path and
>>>>>>> returning a URL.
>>>>>>>
>>>>>>> In both cases, the usage is to abstract the actual location of
>>>>>>> resources, which could therefor transparently be on a local or remote
>>>>>>> filesystem, in a database, custom jar location, or whatever.
>>>>>>>
>>>>>>> The JSF specific ResourceResolver however does not have a
>>>>>>> getResourcePaths() equivalent. I'd like to propose to rectify this by
>>>>>>> introducing such method for JSF view resources.
>>>>>>>
>>>>>>> Since we're targeting JDK 8 such method could take inspiration from
>>>>>>> Files#walk (https://docs.oracle.com/javase/8/docs/api/java/nio/
>>>>>>> file/Files.html#walk-java.nio.file.Path-java.nio.file.
>>>>>>> FileVisitOption...-)
>>>>>>>
>>>>>>> At least one use case would be for something like the FaceViews
>>>>>>> feature in OmniFaces, but I'd like to design this feature not just for
>>>>>>> that, of course. Another use case for instance would be for help in
>>>>>>> debugging (providing a list of all resources handled by the system could be
>>>>>>> handy to check for omissions or unexpected entries)
>>>>>>>
>>>>>>> Thoughts?
>>>>>>>
>>>>>>> Kind regards,
>>>>>>> Arjan Tijms
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>
>>
>