Tuesday, January 31, 2017
Full page caching in Grails with Ehcache Web
Full page caching in Grails with Ehcache Web
Im on the verge of releasing a new version of the Springcache plugin that will feature a pretty cool new annotation-driven page fragment caching feature based on Ehcache-web. However one of the things that came up during discussions on the mailing list was full page caching. I mentioned that it was pretty straightforward and promised to blog about how to do it, so
Install Ehcache-web
Add the following to your dependencies in BuildConfig.groovy:runtime("net.sf.ehcache:ehcache-web:2.0.0") {
excludes "ehcache-core"
}
Install Grails templates
Run:grails install-templates
Set up a page caching filter
Edit src/templates/war/web.xml and add this to the filters section:<filter>And this as the first entry in the filter-mappings section:
<filter-name>MyPageCachingFilter</filter-name>
<filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
<init-param>
<param-name>cacheName</param-name>
<param-value>myPageCache</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyPageCachingFilter</filter-name>
<url-pattern>/controller/action/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Configure the cache
Unfortunately you cant configure the cache in grails-app/conf/spring/resources.groovy using EhCacheFactoryBean instances as the servlet filter initialises before the Spring context. The cache definitions need to be added to a ehcache.xml which would normally be placed in grails-app/conf. Here is an example that works for the filter definitions above:<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="5"
timeToLiveSeconds="10"
overflowToDisk="true"
/>
<cache name="myPageCache"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="10000"
timeToLiveSeconds="10000"
overflowToDisk="true">
</cache>
</ehcache>
You will need to add another filter and filter-mapping and potentially another cache for each URL pattern you want to cache separately.
Full page caching is fine for simple pages but isnt as flexible as fragment caching. For example, any authenticated state (such as a "Welcome back xxx" label) on the page would get cached across all users. Because Grails uses Sitemesh and has the <g:include> tag for including output from other controllers a fragment caching solution is a good fit. The 1.2 release of the Springcache plugin will add fragment caching functionality. However, I can imagine using full-page caching like this for things like RSS feeds.
Available link for download