2

I want to implement cache busting via string query with the file version, but I also want to use @ResourceDependency. So this is what I have:

@ResourceDependency(name = "scrypt.js?v=version", library = "mylib", target = "head")

I know mojarra had trouble with string queries before for the <f:outputScript>, but this has been fixed (stackoverflow question). But apparently they never really supported string queries for the annotation.

The problem is in ResourceDependencyHandler#createComponentResource. It calls ResourceHandler#getRendererTypeForResourceName that returns null if the name provided has a string query attached to it. This actually goes back all the way to ServletContext#getMimeType. That is the guy who can't realize the mime type is application/javascript when there is a query string attached to the file name.

Does anybody knows a workaround for this? I'm currently working with Mojarra 2.2.8.

Thank you.


The fully qualified names of the classes I mentioned:

com.sun.faces.application.annotation.ResourceDependencyHandler
javax.faces.application.ResourceHandler
Community
  • 1
  • 1
Fred Porciúncula
  • 8,533
  • 3
  • 40
  • 57
  • Apparently there is no solution for that. They came up with the idea of having one single annotation for Javascript and CSS files instead of one different annotation for each resource type (like and ), so they rely on ServletContext#getMimeType to figure out the content type. The sad thing is that ServletContext#getMimeType implementations normally do not know how to handle query strings (i.e. "?v=version"), thus breaking the whole thing. – Fred Porciúncula Feb 26 '15 at 17:28
  • I think that could be a workaround to your question: http://stackoverflow.com/questions/4268345/how-can-i-implement-css-versioning-to-solve-cache-issues-using-jsf-2-houtpu – Tarik Feb 27 '15 at 01:33
  • @Tarik Thank you so much! I didn't know about the decorator. I used it to point to my own ResourceHandler implementation, where I overrode getRendererTypeForResourceName so it could handle query strings. – Fred Porciúncula Feb 27 '15 at 18:49

1 Answers1

2

Answering the question based on @Tarik's comment.

I added this to my faces-config.xml:

<application>
  <resource-handler>my.package.MyResourceHandlerImplementation</resource-handler>
</application>

MyResourceHandlerImplementation looks like this:

import com.sun.faces.application.resource.ResourceHandlerImpl;

public class MyResourceHandlerImplementation extends ResourceHandlerImpl {

    @Override
    public String getRendererTypeForResourceName(String resourceName) {
        if (hasQueryString(resourceName)) {
            resourceName = removeQueryString(resourceName);
        }
        return super.getRendererTypeForResourceName(resourceName);
    }

    private boolean hasQueryString(String resourceName) {
        return resourceName.indexOf('?') != -1;
    }

    private String removeQueryString(String resourceName) {
        return resourceName.substring(0, resourceName.indexOf('?'));
    }

}

And this is how you make @ResourceDependency support query strings (thus supporting cache busting).

Fred Porciúncula
  • 8,533
  • 3
  • 40
  • 57