Permalink
Browse files

more docs

  • Loading branch information...
1 parent af580e3 commit 87666b4fa35bac395ba5d3102d8c2477309529d3 Burt Beckwith committed May 21, 2012
Showing with 73 additions and 2 deletions.
  1. +69 −0 src/docs/guide/implementation.gdoc
  2. +2 −0 src/docs/guide/toc.yml
  3. +2 −2 src/docs/guide/usage.gdoc
@@ -0,0 +1,69 @@
+All of the plugin's classes are designed for extensibility; the classes are all public, and fields and methods are mostly public or protected. Consider subclassing existing classes to reuse as much as possible instead of completely rewriting them.
+
+h4. Cache manager
+
+The core cache plugin registers a @grailsCacheManager@ Spring bean, and the extension plugins replace this bean with one that creates and manages caches for that implementation. The default implementation is an instance of @grails.plugin.cache.GrailsConcurrentMapCacheManager@ which uses @grails.plugin.cache.GrailsConcurrentMapCache@ as its cache implementation. It uses a @java.util.concurrent.ConcurrentHashMap@ to store cached values.
+
+You can customize the cache manager by replacing the @grailsCacheManager@ Spring bean in @resources.groovy@ with your own; either subclass @GrailsConcurrentMapCacheManager@ (e.g. to override the @createConcurrentMapCache()@ method) or by implementing the @grails.plugin.cache.GrailsCacheManager@ interface.
+
+h4. Controller caching
+
+The controller caching is implemented with a filter registered as @grailsCacheFilter@ in @web.xml@ and it is backed by the Spring bean of the same name. The implementation class is @grails.plugin.cache.web.filter.simple.MemoryPageFragmentCachingFilter@.
+
+The content that is cached is the response generated by GSP (or directly by the controller if a response is rendered programmatically) before Sitemesh applies its template(s).
+
+h5. Key generation
+
+Controller caching uses a key generator, a class that implements the @grails.plugin.cache.web.filter.WebKeyGenerator@ interface (by default a @grails.plugin.cache.web.filter.DefaultWebKeyGenerator@). This is registered as the @webCacheKeyGenerator@ Spring bean, so customizing the key generation is simply a matter of subclassing @DefaultWebKeyGenerator@ or re-implementing the interface and registering your own @webCacheKeyGenerator@ bean in @resources.groovy@.
+
+h4. Fragment caching
+
+You can cache partial GSP page sections with the @<cache:block>@ tag. You can specify a key when using this tag but it's in general unnecessary. This is because the block will be rendered with its own Closure, and the default key is the full closure class name. This is unique since the closures aren't re-used; for example these two blocks will be cached independently, even in the same GSP:
+
+{code}
+<cache:block>
+foo
+</cache:block>
+
+<cache:block>
+bar
+</cache:block>
+{code}
+
+You can cache the content of templates with the @<cache:render>@ tag. You can specify a key when using this tag but like the @block@ tag, it's in general unnecessary because the default key is the full template class name.
+
+h4. Service caching
+
+You can cache the return value of a service method by annotating it with @Cacheable@.
+
+h5. Key generation
+
+The default implementation of the @org.springframework.cache.interceptor.KeyGenerator@ used to generate keys for service method calls is @org.springframework.cache.interceptor.DefaultKeyGenerator@. This is only used if there is no @key@ attribute specified in the annotation for the method. It generates a numeric key, with the following logic:
+
+{code}
+public Object generate(Object target, Method method, Object... params) {
+ if (params.length == 1) {
+ return (params[0] == null ? 53 : params[0]);
+ }
+
+ if (params.length == 0) {
+ return 0;
+ }
+
+ int hashCode = 17;
+ for (Object object : params) {
+ hashCode = 31 * hashCode + (object == null ? 53 : object.hashCode());
+ }
+ return hashCode;
+}
+{code}
+
+This is very generic and somewhat risky, since two no-arg methods that use the same cache will store values under the same key (0), and different methods with similar signatures can easily generate the same key for different return values. So it's best to either specify the @key@ attribute in the annotation, or use separate caches.
+
+h4. DSL parsing
+
+The cache plugin's DSL is very basic; only the cache name can be specified. But you could extend it (for example if you customized the cache or cache manager implementation, although a new plugin would probably make more sense) by replacing the @grailsCacheConfigLoader@ Spring bean in @resources.groovy@. The default implementation is a @grails.plugin.cache.ConfigLoader@.
+
+h4. Annotation SpEL expression evaluator
+
+You can extend or customize what is SpEL expressions are supported by re-defining the @webExpressionEvaluator@ Spring bean in @resources.groovy@. The default implementation is an instance of @grails.plugin.cache.web.filter.ExpressionEvaluator@.
View
@@ -12,3 +12,5 @@ cacheTags:
grailsCacheAdminService:
title: Grails Cache Admin Service
clearingCaches: Clearing Caches
+implementation:
+ title: Implementation Details
@@ -1,6 +1,6 @@
-The cache plugin adds Spring bean method call, page fragment, and taglib caching to Grails applications. You configure one or more caches in @Config.groovy@ and/or one or more Groovy artifact files with names ending in CacheConfig.groovy (for example FooCacheConfig.groovy, BarCacheConfig.groovy, and these can also be in packages) in @grails-app/conf@ (or a subdirectory if in a package) using an implementation-specific DSL, and annotate methods (either in Spring beans (typically Grails services) or controllers) or taglib closures to be cached.
+The cache plugin adds Spring bean method call, controller action, and GSP page fragment and template caching to Grails applications. You configure one or more caches in @Config.groovy@ and/or one or more Groovy artifact files with names ending in CacheConfig.groovy (for example FooCacheConfig.groovy, BarCacheConfig.groovy, and these can also be in packages) in @grails-app/conf@ (or a subdirectory if in a package) using an implementation-specific DSL, and annotate methods (either in Spring beans (typically Grails services) or controllers) to be cached. You can also wrap GSP sections in cache tags and render cached templates.
-There are three annotations; [Cacheable|api:grails.plugin.cache.Cacheable], [CachePut|api:grails.plugin.cache.CachePut], and [CacheEvict|api:grails.plugin.cache.CacheEvict]. You use \@Cacheable to mark a method or taglib closure as one that should check the cache for a pre-existing result, or generate a new result and cache it. Use \@CachePut to mark a method or taglib closure as one that should always be evaluated and store its result in the cache regardless of existing cache values. And use \@CacheEvict to flush a cache (either fully or partially) to force the re-evaluation of previously cached results. The annotations are based on the annotations with the same name from Spring ([Cacheable|http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/cache/annotation/Cacheable.html], [CachePut|http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/cache/annotation/CachePut.html], and [CacheEvict|http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/
+There are three annotations; [Cacheable|api:grails.plugin.cache.Cacheable], [CachePut|api:grails.plugin.cache.CachePut], and [CacheEvict|api:grails.plugin.cache.CacheEvict]. You use \@Cacheable to mark a method as one that should check the cache for a pre-existing result, or generate a new result and cache it. Use \@CachePut to mark a method as one that should always be evaluated and store its result in the cache regardless of existing cache values. And use \@CacheEvict to flush a cache (either fully or partially) to force the re-evaluation of previously cached results. The annotations are based on the annotations with the same name from Spring ([Cacheable|http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/cache/annotation/Cacheable.html], [CachePut|http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/cache/annotation/CachePut.html], and [CacheEvict|http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/
springframework/cache/annotation/CacheEvict.html]) and support the same syntax but may support extended functionality in the future.
This 'core' cache plugin uses an in-memory implementation where the caches and cache manager are backed by a thread-safe @java.util.concurrent.ConcurrentMap@. This is fine for testing and possibly for low-traffic sites, but you should consider using one of the extension plugins if you need clustering, disk storage, persistence between restarts, and more configurability of features like time-to-live, maximum cache size, etc. Currently the extension plugins include [cache-ehcache|http://grails.org/plugin/cache-ehcache], [cache-redis|http://grails.org/plugin/cache-redis], and [cache-gemfire|http://grails.org/plugin/cache-gemfire].

0 comments on commit 87666b4

Please sign in to comment.