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
3
  • 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 <h:outputScript> and <h:outputStylesheet>), 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. Commented Feb 26, 2015 at 17:28
  • I think that could be a workaround to your question: stackoverflow.com/questions/4268345/… Commented Feb 27, 2015 at 1:33
  • @Tarik Thank you so much! I didn't know about the <resource-handler> decorator. I used it to point to my own ResourceHandler implementation, where I overrode getRendererTypeForResourceName so it could handle query strings. Commented Feb 27, 2015 at 18:49

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

1 Comment

This code worked perfectly for me, although I'm extending javax.faces.application.ResourceHandlerWrapper instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.