Content Caching
An introduction to the Cachius library
A common characteristic of page-centric web-applications is the fact that large parts of the displayed data are unpersonalized and therefore are the same for all users. To improve performance and scalability it is desirable that time-consuming operations are performed only once and the results are reused for subsequent requests.
Cachius does not cache Java objects, it caches content. No matter whether its HTML, XML, CSS, JavaScript or binary data like generated images or PDFs. It has a very small memory footprint, as all data is directly written to the disk. Since no object serialization is involved, the cached content can be directly streamed from the filesystem.
It also supports applications that use URL-based session tracking by keeping an anonymized version of the output (without the actual session id) in cache. When the cached content is sent to the client, the current session id is inserted.
Caching Controllers
Unlike other caching libraries, Cachius is aware of the MVC pattern. The idea is that the controller, that provides a view with data, should decide whether a previously rendered version is still up-to-date.
In order to be cached, a controller must implement the CacheableController interface that defines the following three methods:
The first method, getCacheKey() returns a key that uniquely identifies the requested content. Therefore it must include all attributes that govern the output, such as request parameters, the requested URL or the controller's name. The key itself is not interpreted in any way and thus can have an arbitrary format.
The second method, getLastModified() returns the last-modified date for a given request. The controller will not be executed unless this date is newer than the timestamp of the cached version.
The third method, getTimeToLive() returns the number of milliseconds that must have elapsed since the last up-to-date check, before getLastModified() is invoked again.
Caching Views
There are some situations where the controller doesn't do a lot, but the rendering of the view can still be quite time consuming. A good example are navigation menus. The only information you need in order to render a menu is the current page, which is available in all FreeMarker templates via the pages.currentPage variable.
<#list pages.currentPage.siblings as p>
<li><@pages.link p /></li>
</#list>
</ul>
All we have to do in order to cache this snippet is to put it inside a template block, as template blocks are cached by default.
<html>
<body>
<@template.block name="navigation">
<ul><!-- insert code from above here --></ul>
</@template.block>
</body>
</html>
</@template.root>
Unlike controllers, views can't provide any last-modified information, so how does Cachius know whether the cached snippet is still up-to-date?
The answer is that Riot invalidates cache items as soon as any of the data involved in the generation of the cached content is modified. Refer to the next part to learn how this works.
Item Tagging and Invalidation
The Cachius API allows you to classify cache items by adding metadata in form of tags. These tags can then be used to invalidate a set of items.