MyFaces Core
  1. MyFaces Core
  2. MYFACES-3493

Cache info about non-existant resources in org.apache.myfaces.application.ResourceHandlerImpl.createResource()

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 2.1.6
    • Fix Version/s: None
    • Component/s: Extension Feature
    • Labels:
      None
    • Environment:
      Linux FC15

      Description

      The existent resources are cached in the public Resource createResource(String resourceName, String libraryName, String contentType) method,
      which is good, but the information about resources, which are not existent ( deriveResourceMeta(loader, resourceName, libraryName, localePrefix) returned null ) is not cached.
      Thus at the next requests for the same resource the same resource lookup operations will happen, which may be expensive.
      In my case, for example (Tomcat + Spring + MyFaces + Tomahawk), for every html tag, lookup on the file system and in all classpaths (including ~30 jars) is performed (and failing), which de-gradates response time by factor of 25!

        Activity

        Hide
        Leonardo Uribe added a comment -

        This modification is questionable. In theory, the components will always register resources that exists. Use the same cache used to save information related to Resource classes doesn't sound good, because asking for non existent resources it is possible to clean that cache, and that is not the idea.

        Instead, it is responsibility of the ResourceLoader implementation to minimize the associated overhead. In this case, the cache should be implemented in org.apache.myfaces.shared.resource.ClassLoaderResourceLoader.

        Anyway, it seems something more related to your particular environment, and not something to solve from MyFaces side. I suggest to create a custom ResourceHandler implementation, reusing the api provided by MyFaces into its shared package.

        Suggestions are welcome.

        Show
        Leonardo Uribe added a comment - This modification is questionable. In theory, the components will always register resources that exists. Use the same cache used to save information related to Resource classes doesn't sound good, because asking for non existent resources it is possible to clean that cache, and that is not the idea. Instead, it is responsibility of the ResourceLoader implementation to minimize the associated overhead. In this case, the cache should be implemented in org.apache.myfaces.shared.resource.ClassLoaderResourceLoader. Anyway, it seems something more related to your particular environment, and not something to solve from MyFaces side. I suggest to create a custom ResourceHandler implementation, reusing the api provided by MyFaces into its shared package. Suggestions are welcome.
        Hide
        Mike Kienenberger added a comment -

        Maybe it makes sense to cache non-existence in Production mode, but not in the other mode(s)?

        Show
        Mike Kienenberger added a comment - Maybe it makes sense to cache non-existence in Production mode, but not in the other mode(s)?
        Hide
        Martin Kočí added a comment -

        As Leonardo said, components will always register resources that exists.

        Normally myfaces produce warning like "Resource referenced by resourceName ... not found in call to ResourceHandler.createResource ...It will be silenty ignored" in Non-Production stage. Author of view is responsible for solving this problem before application goes to production.
        @Dmitry, do you have an use case, where previous doesn't apply?

        All caches are automatically disabled in myfaces in Development stage to allow development without servers restart.

        Show
        Martin Kočí added a comment - As Leonardo said, components will always register resources that exists. Normally myfaces produce warning like "Resource referenced by resourceName ... not found in call to ResourceHandler.createResource ...It will be silenty ignored" in Non-Production stage. Author of view is responsible for solving this problem before application goes to production. @Dmitry, do you have an use case, where previous doesn't apply? All caches are automatically disabled in myfaces in Development stage to allow development without servers restart.
        Hide
        Dmitry Kukushkin added a comment -

        In fact there is a use case:
        During the xhtml compilation, tags from the document are processed through the chain of known namespaces, to find out if there is a handler for this tag implemented in this tag library.
        This goes OK, until a tag library, declaring composite-tag-library name is met (in our case this is Tomahawk).
        Then MyFaces, is trying to load a resource with the name like /resources/<composite-tag-library>/<tag>.xhtml
        For every tag, which wasn't handled, this operation will be performed (including also lookups on the file system and in jars).
        Simply for every standard html tag like <a>, <br>, <div> etc this operation will be failing every time (for us it was a factor of 25 in the response time increase).

        I was initially thinking of submitting this issue to the Tomahawk's jira,
        But then I thought that it's better to implement this caching in the MyFases itself, to avoid such a performance issues, should some tag library, implementing composite tags, have similar implementation issues.

        Show
        Dmitry Kukushkin added a comment - In fact there is a use case: During the xhtml compilation, tags from the document are processed through the chain of known namespaces, to find out if there is a handler for this tag implemented in this tag library. This goes OK, until a tag library, declaring composite-tag-library name is met (in our case this is Tomahawk). Then MyFaces, is trying to load a resource with the name like /resources/<composite-tag-library>/<tag>.xhtml For every tag, which wasn't handled, this operation will be performed (including also lookups on the file system and in jars). Simply for every standard html tag like <a>, <br>, <div> etc this operation will be failing every time (for us it was a factor of 25 in the response time increase). I was initially thinking of submitting this issue to the Tomahawk's jira, But then I thought that it's better to implement this caching in the MyFases itself, to avoid such a performance issues, should some tag library, implementing composite tags, have similar implementation issues.
        Hide
        Dmitry Kukushkin added a comment -

        here is the place where MyFaces is trying to load resource for the tag:
        org.apache.myfaces.view.facelets.compiler.TagLibraryConfig.containsTagHandler(String ns, String localName)

        Show
        Dmitry Kukushkin added a comment - here is the place where MyFaces is trying to load resource for the tag: org.apache.myfaces.view.facelets.compiler.TagLibraryConfig.containsTagHandler(String ns, String localName)
        Hide
        Leonardo Uribe added a comment -

        Interesting. One question, are you using <f:validateBean > in "wrap" mode?:

        <f:validateBean ...>
        .........
        </f:validateBean>

        I think in this case the cache should be added in TagLibraryConfig, instead add it on ResourceHandler.

        Show
        Leonardo Uribe added a comment - Interesting. One question, are you using <f:validateBean > in "wrap" mode?: <f:validateBean ...> ......... </f:validateBean> I think in this case the cache should be added in TagLibraryConfig, instead add it on ResourceHandler.
        Hide
        Leonardo Uribe added a comment -

        I found the source of the problem in MYFACES-3208, which was fixed in 2.1.2 / 2.0.8. Please update your myfaces version to 2.1.6 or 2.0.12. I checked and a cache in that location is not necessary. I think we can close this issue as won't fix, because the problem was MYFACES-3208, which was already fixed.

        Show
        Leonardo Uribe added a comment - I found the source of the problem in MYFACES-3208 , which was fixed in 2.1.2 / 2.0.8. Please update your myfaces version to 2.1.6 or 2.0.12. I checked and a cache in that location is not necessary. I think we can close this issue as won't fix, because the problem was MYFACES-3208 , which was already fixed.

          People

          • Assignee:
            Leonardo Uribe
            Reporter:
            Dmitry Kukushkin
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development