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

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

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 28 Jul 2016 19:09:26 +0200

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
>>>>>
>>>>
>>>>
>>
>