Using Cache-Headers plugin in a non-english server

| Comments

UPDATE: This problem has been fixed in version 1.1.3 of the plugin. Thanks Marc and Luke Daley!

This week I tried the Marc Palmer’s excelent plugin Cache-Headers, and it really rocks! Using it I can make all my server-side generated images be cached on the client, reducing significantly the bandwidth and cpu-power necessary by my application.

But there’s a little gotcha: The plugin (as of version 1.1.2) uses a SimpleDateFormat to generate and check the Last-Modified header, and the implementation creates this SimpleDateFormat with the system’s default Locale, in my case Portuguese. This causes errors like this:

1
2
3
4
5
6
7
8
9
java.lang.IllegalArgumentException: Ter, 21 dez 2010 15:10:33 GMT
    at com.grailsrocks.cacheheaders.CacheHeadersService.withCacheHeaders(CacheHeadersService.groovy:140)
    at com.grailsrocks.cacheheaders.CacheHeadersService$withCacheHeaders.call(Unknown Source)
    at CacheHeadersGrailsPlugin$_addCacheMethods_closure7_closure11.doCall(CacheHeadersGrailsPlugin.groovy:61)
    at org.weceem.controllers.WcmContentController$_closure3.doCall(WcmContentController.groovy:172)
    at org.weceem.controllers.WcmContentController$_closure3.doCall(WcmContentController.groovy)
    at org.apache.shiro.web.servlet.ShiroFilter.executeChain(ShiroFilter.java:687)
    at org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:616)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)

The workaround I found was to override the construction of that SimpleDateFormat. Luckily it’s been created in a small class, that is easy to extend:

package com.deluan.grails.util

import java.text.SimpleDateFormat
import com.grailsrocks.cacheheaders.DateFormatterThreadLocal

/**
 * This class is used to force CacheHeadersService (from the cache-headers 
 * plugin) to generate http-dates in english. It MUST be used when the 
 * locale of your server is not English.
 * <p/>
 * To use it, put the following configuration in your Config.groovy:
 * <pre>
 * beans {
 *    cacheHeadersService {
 *        dateFormatters = new com.deluan.grails.util.EnglishDateFormatterThreadLocal()
 *    }
 * }
 * </pre>
 * 
 * @author Deluan
 */
class EnglishDateFormatterThreadLocal extends DateFormatterThreadLocal {
    SimpleDateFormat initialValue() {
        def v = new SimpleDateFormat(RFC1123_DATE_FORMAT, Locale.ENGLISH)
        v.timeZone = TimeZone.getTimeZone('GMT')
        return v
    }
}

All you have to do is put this class in your project (in the src/groovy folder) and add the following configuration override in your Config.groovy:

1
2
3
4
5
beans {
    cacheHeadersService {
        dateFormatters = new com.deluan.grails.util.EnglishDateFormatterThreadLocal()
    }
}

I already filled a bug report here: http://jira.codehaus.org/browse/GRAILSPLUGINS-2707, and probably this post will be obsolete in a near future :)

Comments