10

I'm starting to work with JSF 2 so I wanted to give a try to h:outputStylesheet. It works fine but then I tried to apply the "pattern" or trick of adding a query string to the request which changes with the file version to force browsers to fetch changes.

Something like what is used here.

Unfortunately I haven't been able to do it. Actually, when using that tag it doesn't generate a simple URL but a computed one which already has a query string. I've found some info about versioning of resouces in JSF 2 both in the spec and here, but it seems to refer to multiple versions of a resource which is not what I need.

Of course I can always go back to NOT use the new tag. But I wanted to share this here for discussion.

Update 1 - some example:

What I've tried is something like this:

<h:outputStylesheet library="css" name="estilo.css?v=1" target="head"/>

Which renders as:

<link type="text/css" rel="stylesheet" href="RES_NOT_FOUND" />

Quite descriptive. ;-)

What I try to get is something like this:

<link rel="stylesheet" type="text/css" href="../css/estilo.css?v=1"/>

Which, using JSP, I used to put this way:

<link rel="stylesheet" type="text/css"
 href="<c:url value='/css/estilo.css?v=${initParam.version}'/>"/>
Community
  • 1
  • 1
sargue
  • 5,695
  • 3
  • 28
  • 43
  • Can you post an example of what you've tried? :) – Martijn Verburg Nov 24 '10 at 15:37
  • Reeeally curious about this. This feature should be bundled in every web framework. Are you adding expires HTTP header to static resources already or why do you need this (otherwise the clients would always make a request to check if the files has changed and update if it has... wouldn't they)? – Tuukka Mustonen Nov 24 '10 at 15:57
  • @Tuuka: This is somehow a trick developing web apps with dynamic content. If you change something inside 'estilo.css' and publish a new version the users who had recently visited you would probably not download the new version right away. This is even worse for JS as it may break funcionality. This "trick" uses the fact that browsers use the query string to decide wether to download or not the resource. So the query string (which can be whatever) really does nothing. You just have to change it when the content changes. And is easy to change the URL because you already are generating the HTML. – sargue Nov 24 '10 at 17:17
  • I so much agree this. I was about to report an enhancement request at Mojarra project page, but it's currently disabled due to its future migration to another site. I have a theory to fix this, but I have to try it myself first. – BalusC Nov 25 '10 at 02:39
  • @Sergi @BalusC yes, but isn't the browser creating a request every time anyway? I don't know how server or browser compares the cached file with the one browser requested, but if there is change (in file size, some hash, I don't know), the browser *should* download the new one. Thus, I don't think this is needed for other cases than when you have expires HTTP header set and in effect, and browser will not even do the check request it normally does. Correct? – Tuukka Mustonen Nov 27 '10 at 15:18

1 Answers1

10

Facing the same challenge, I ended up extending javax.faces.application.ResourceHandlerWrapper and javax.faces.application.ResourceWrapper to append "&v=x.y.z" to the result of ResourceWrapper#getRequestString().

I saw this kind of solution implemented by Primefaces and Openfaces. Just take a look at the source of

org.primefaces.application.PrimeResourceHandler#createResource(String resourceName, String libraryName)

and

org.primefaces.application.PrimeResource#getRequestPath()

Available here.

Don't forget to add your implementation to faces-config.xml:

<application>
  <resource-handler>your.package.YourResourceHandlerWrapper</resource-handler>
</application>
Selaron
  • 6,105
  • 4
  • 31
  • 39