Skip to content
JakeHoward edited this page Jul 16, 2015 · 1 revision

Caching explained

Caching helps you scale your application to millions of users leveraging existing Web infrastructure with minimal effort on your side (you only need to set appropriate response headers). Because some resources don't change their state very often, it makes sense to store their representations closer to consumers and serve them from there. Proxies on the path between a consumer and an origin server (reverse proxies, forward proxies, CDNs) can store frequently accessed data as long as their copies are fresh. With properly implemented caching you can reduce load on your servers as most of the data can be served from caches. Caches are closer to consumers so latency is reduced. Finally, if your origin server goes down, caches can still serve content.

To control caching behaviour such as who can cache data and for how long we use two response headers:

  • Expires: Sat, 10 Jun 2012 19:25:01 GMT

This header contains absolute date indicating when cached response becomes invalid (for caches supporting HTTP 1.0)

  • Cache-Control: public, max-age=3600

This header contains relative time in seconds indicating how long the response is fresh once it's left the server (for caches supporting HTTP 1.1)

Caching in Utterlyidle

The easiest way to enable caching in Uterrlyidle applications is to add com.googlecode.utterlyidle.modules.PerformanceModule. This module automatically adds caching for the resource with the following media types:

  • text/css
  • text/javascript
  • image/x-icon
  • image/jpeg
  • image/gif
  • image/png

Default caching time is 60 seconds.

PerformanceModule adds ETag support and GZip support in addition to caching support but we'll cover them in later sections of this documentation.

If you don't want to use a default performance module but still want to have a generic caching mechanism you can decorate HttpHandler with CacheControlHandler and inject caching policy:

import com.googlecode.utterlyidle.HttpHandler;
import com.googlecode.utterlyidle.MediaType;
import com.googlecode.utterlyidle.handlers.CacheControlHandler;
import com.googlecode.utterlyidle.handlers.CachePolicy;
import com.googlecode.yadic.Container;

import static com.googlecode.utterlyidle.PathMatcher.path;
import static com.googlecode.utterlyidle.handlers.CachePolicy.cachePolicy;
import static com.googlecode.utterlyidle.sitemesh.ContentTypePredicate.contentType;

public class MyCustomCachingModule implements RequestScopedModule {
    @Override
    public Container addPerRequestObjects(Container container) throws Exception {
        container.addInstance(CachePolicy.class, cachePolicy(60).
                add(path("foo/bar")).
                add(contentType(MediaType.TEXT_JAVASCRIPT)).
                add(contentType(MediaType.TEXT_CSS)));
        container.decorate(HttpHandler.class, CacheControlHandler.class);
        return container;
    }
}

In the example above all javascript/css files and all resources with foo/bar path will be cached for 60 seconds. Utterlyidle will automatically set the Expires and Cache-Control headers. Please note that CacheControlHandler adds caching headers to the response only when the request method is GET.

You can alway override default caching policy by setting Expires and Cache-Control header on individual responses in your resources.

Clone this wiki locally