Caching - enable browsers to cache until the file changes

496 views
Skip to first unread message

Alex Black

unread,
Feb 29, 2012, 11:58:30 AM2/29/12
to wro4j
Outside of wro4j, we append a query parameter to our css and
javascript references, like ?q=<hash> where hash is the md5 hash of
the underlying resource, that way if the contents of the css or js
change (say on a deploy) then all browsers fetch the new resource.

Does wro4j offer anything like this? Or perhaps I could adapt my
current solution to work with wro4j? My current solution opens the
resources from the file system and hashes them, instead I wonder how I
could access the processed wro4j output...

Alex Objelean

unread,
Feb 29, 2012, 1:08:34 PM2/29/12
to wr...@googlegroups.com

Though there is no support out of the box  (it will be implemented at some point, check out this opened issue ). it is possible to customize it in order to achieve your requirements.

The NamingStrategy interface should help you to do that. There are several implementations, like: TimestampNamingStrategy, HashEncoderNamingStrategy (used to hash using MD5 or CRC32). It is quite easy to implement a new naming strategy based on your needs.

You will also have to update the GroupExtractor interface which is responsible for extracting the group name from request. 

Let me know if you need any help or questions.

Cheers,
Alex

PS: It is possible to use this feature with maven plugin:  http://code.google.com/p/wro4j/wiki/OutputNamingStrategy .

Alex Black

unread,
Feb 29, 2012, 1:48:04 PM2/29/12
to wro4j
HashEncoderNamingStrategy sounds promising. How would I go about
modifying my HTML to reference the css group via the new name? Is
that what GroupExtractor is for?

On Feb 29, 1:08 pm, Alex Objelean <alex.objel...@gmail.com> wrote:
> Though there is no support out of the box  (it will be implemented at some
> point, check out this opened issue<http://code.google.com/p/wro4j/issues/detail?id=206> ).

Alex Objelean

unread,
Feb 29, 2012, 1:56:12 PM2/29/12
to wr...@googlegroups.com
I was thinking about a jsp tag which would be responsible for generating the resource url (if you use jsp). It is up to you how you generate the url to resource (this is the tricky part of this task :). This also depends on framework you use (plain jsp, ftl, jsf, wicket or whatever.

The GroupExtractor is responsible for understanding the hashed url and extract the group name correctly. 

I know that putting all the things together is not easy and is quite challenging :)

Alex

Alex Black

unread,
Feb 29, 2012, 2:01:14 PM2/29/12
to wro4j
Thanks.. what about:

1. I see that wro4j sets eTags, I'm not too familiar with eTags, but,
I would have thought they could solve this problem? E.g. the eTag
probably represents a hash of the resource, and the browser could then
request the resource each time, specifying the eTag, and be told that
the resource hasn't changed? Even if that does work, its probably not
as efficient as just having the browser cache it.

2. What about this angle to solving the problem: in theory wro4j
doesn't even need to do anything, all that needs to happen is that I
put a parameter on the url representing the MD5 of the resource's
contents. Can we think of any way for my scala code to get the MD5 of
the resource?
a) maybe it could make a HTTP request for it, that seems really ugly
b) Maybe it could some how get the wro4j manager instance and ask it
directly?

Alex Objelean

unread,
Feb 29, 2012, 2:17:26 PM2/29/12
to wr...@googlegroups.com
ns1. ETags works exactly as you described (sets a header containing hash of the resource content for caching). The only disadvantage is that browser still have to request the server to ask if resource has changed. When using aggressive caching technique, you can set the expiry headers far in the future and the browser will not even bother to issue a new request for each page render.

2. In order to know the hash code of resource, you have ask wroManager to process the group you are interested in. This can be achieved either with httpRequest (indeed ugly), or programmatically invoke the manager and extract the hash (probably using cacheStrategy). I know this is not very friendly and it can be improved to make it more easier. If you see how the API can be improved, let me know.

Thanks,
Alex

leonard...@gmail.com

unread,
Mar 15, 2012, 5:18:25 PM3/15/12
to wr...@googlegroups.com
Hello Alex and everybody else

I discovered wro4j yesterday and I'm pretty happy with it so far. Thanks for your good work and this amazing tool.

I've implemented a build time solution using a renaming strategy to achieve aggressive caching and all worked as expected until I reached my static html files. In those files I can't include the generated resource path at run time. So, what is the best approach here? Maybe chaining a final step to replace the file names in my static files? please give some advice in this matter.

thanks again and keep the excellent job

Leonardo

Alex Objelean

unread,
Mar 15, 2012, 5:44:10 PM3/15/12
to wr...@googlegroups.com
Hi Leonardo,

if you want to replace the resource url dynamically in runtime, you have to use some sort of templating language (jsp, jsf, freemarker, etc). 

As described in earlier posts, it is up to each user to implement this behaviour. There is something on the roadmap to provide a default integration using jsp tag.

The solution for your particular use-case may depend on many things. Each use-case is different. If you want, you can share the details here. Based on your feedback or ideas, the library may evolve the way it solves user requirements.

Cheers,
Alex

Dmitry Erman

unread,
May 9, 2012, 12:08:10 PM5/9/12
to wr...@googlegroups.com
Reviving a slightly old thread. 

I'm looking at how eTag support is being handled by my runtime application. Shouldn't the eTag value change when the files in the group being requested change on the file system? 

Example scenario. I call for MyGroup1 and get eTagValue1 returned in the response header. One of the files being referenced in MyGroup1 changes on the file system due to a deployment. I request MyGroup1 again. Should I still be receiving a 304 with eTagValue1 or should I now receive a 200 response code with eTagValue2? 

Basically, I don't see the eTag value changing in my local testing when I change the files on the file system. Since we're not using a "version" strategy in the request URI it's important that the eTag properly changes when the underlying content changes.

Thanks again!

Dmitry

Alex Objelean

unread,
May 9, 2012, 12:12:26 PM5/9/12
to wr...@googlegroups.com
The expected behavior is to get the correct ETag value for each request. In other words, if the resource was changed (due to a deployment) and the cache (holding resources) was flushed, the subsequent requests should respond with status code 200 and eTagValue2.

The only reason why the eTagValue1 is returned, is because the cache is not flushed after resources redeployment. 

Alex

--
You received this message because you are subscribed to the Google Groups "wro4j" group.
To view this discussion on the web visit https://groups.google.com/d/msg/wro4j/-/nsGzFG_cf30J.

To post to this group, send email to wr...@googlegroups.com.
To unsubscribe from this group, send email to wro4j+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/wro4j?hl=en.

Dmitry Erman

unread,
May 9, 2012, 12:14:44 PM5/9/12
to wr...@googlegroups.com
How would you recommend as the best approach for flushing the cache? Through jconsole (jmx is enabled) on deployment or setting a 60 second cacheUpdatePeriod for the application?

Dmitry

Alex Objelean

unread,
May 9, 2012, 12:22:07 PM5/9/12
to wr...@googlegroups.com
I would recommend flushing the cache through JMX. Setting cacheUpdatePeriod to something greater than 0 should work also, but I wouldn't recommend it in deployment yet, because it triggers the processing after each flush and can be quite CPU expensive. The next release (1.4.6) fixes this problem. 

Btw, you can also create your own CacheStrategy (Ehcache?) and control the cache expiry the way you find most appropriate for your use-case.

Cheers,
Alex

Dmitry Erman

unread,
May 9, 2012, 12:35:18 PM5/9/12
to wr...@googlegroups.com
Since you brought up 1.4.6 - when is it due out and does it include the RubySassProcessor? :) 

Also, how does 1.4.6 fix the problem; I'm curious about the implementation change.

Dmitry

Alex Objelean

unread,
May 9, 2012, 12:39:04 PM5/9/12
to wr...@googlegroups.com
Of course it includes RubySassProcessor :)..

I think it is ready for release. I think this week I'll release it.

The change in 1.4.6 related to cacheUpdatePeriod is that after each X seconds the cache is flushed only (no processing is triggered), thus the subsequent request to a resource will trigger the processing since the cache is clear.

Alex

Dmitry Erman

unread,
May 9, 2012, 12:44:02 PM5/9/12
to wr...@googlegroups.com
Perfect and thank you. The updated cache implementation is exactly what I'm looking for. 

Dmitry
Reply all
Reply to author
Forward
0 new messages