Play-CMS supports powerful caching mechanisms at the block level. Caching is disabled by default, it can be enabled globally via configuration and refined per block class.
Caching uses Play's Ehcache plugin, but also accesses Ehcache's API via ch.insign.commons.CacheManager. The block's render() output (Html) is stored in-memory (currently no serialisation and disk storage).
Every block has a .render() method which tries to return a cached version first, and falls back to display if no cache is available.
Steps
block.render() executed
block.markModified()
, which invlidates all existing cache for this block.The most crucial part in caching is creating a proper cache key which is unique for the different content variants while trying to keep the cache entries to a minimum. BlockCache offers various settings, and in addition the block class can overwrite the .getKey() method to further control the key generation.
Setting
|
Meaning
|
Default
|
---|---|---|
setEnabled | turn caching on/off | false |
ignoreGETParams | List of get params which should be ignored, when deciding if block should be cached If all params for a url are in this list - it would be cached even with @handleGET disabled. |
[ ] |
handlePOST | Cache responses to POST requests | false |
handleGET | Cache responses to requests that contain GET parameters. If enabled, separate cache entry would be created for each unique parameters combination (excluding those listed in ignoreGETParams) |
false |
ignoreUser | Do not create per- (authenticated) user cache entries | false |
ignoreGroups | TODO: Do not create per set of user-group entries (Warning: Do not ignore users and groups or everybody will see e.g. frontend edit controls if they happen to get cached) |
false |
ignoreLanguage | Do not create per-language cache entries | false |
ignoreUrl | By default, caching is done on per-url basis. Enable this option to prevent it. | false |
ignoreModifiedUrls | List of urls, which should be excluded from automatic block cache invalidation. Such block caches would require manual flushing via ModifiedBlockCacheRemover Use [ ] for disabled, use ["*"] for all urls |
[ ] |
## Block cache settings
cms.blockcache.enabled = true
cms.blockcache.ignoreGETParams = []
cms.blockcache.size = 512 # MB (LRU strategy will evict least recently used entries when the size limit is reached)
cms.blockcache.ttl = 604800 # sec. (1 week)
cms.blockcache.handleGET = false
cms.blockcache.handlePOST = false
cms.blockcache.ignoreUser = false
cms.blockcache.ignoreGroups = false
cms.blockcache.ignoreLanguage = false
cms.blockcache.ignoreUrl = false
cms.blockcache.ignoreModifiedUrls = []
BlockCacheFactory is responsible for BlockCache and BlockCacheKey management. If default implementation does not satisfy needed use case - it needs to be overriden.
Usage
In general, caching needs proper configuration, but not much implementation.
<logger name="ch.insign.cms" level="DEBUG" />
to logger.xml
to analyze the caching behaviour. Check entries like ?cache=false
GET parameter to disable caching for this requestBlockCache.flush()
to flush the entire cache (the cache is also flushed upon a play restart)Often your main site layout contains dynamic per-user content, such as username, login state, cart content, feedback messages from flash scope etc. For these cases, you can define uncached live partials, which are not directly rendered when the page is rendered. Instead, during rendering, a live partial placeholder is placed in the template (Example: [uncached:miniCart]). Before output, these placeholders are replaced with the rendered content of these live partials, no matter whether the page's template was just rendered or comes from cache.
Example:
1. Define your uncached live partials in your CMSApiLifecycle implementation:
MyCMSApiLifecycle.java
@Override
public void registerUncachedPartials(CMSApi cmsApi) {
cmsApi.getUncachedManager()
.register("miniCart", () -> views.html.shared.miniCart.render())
.register("myAccountBox", () -> views.html.shared.myAccountBox.render())
}
2. In your template (often the main layout):
@Template.addUncached("miniCart")
Note: If you use your main layout file for both cms and non-cms pages, then use:
@Template.addUncached("miniCart", page)
Where page is the instance of the Page interface. addUncached will then determine if the current page is a cms page (instace of PageBlock) and use the live partial mechanism. If it's not a cms page, then it will render and add the partial directly.