Saving computation time using cache

Using a cache can help you to avoid computing things several times. Web applications support two kinds of caches: server-side and client-side caches. The latter can save HTTP round trips. In both cases, dealing with expiration can be a complex task!

Play provides a minimal cache library and some controller level caching features that can help you leverage both client-side and server-side caches. The implementation uses EhCache under the hood and, by default, caches things in memory only. You'll find more about EhCache at http://ehcache.org/.

To use it, you first need to add it to your build dependencies:

libraryDependencies += cache

The cache basically works as a key-value store. You can store values for a given duration and retrieve them using a key. Let's use it in the Application.index action that just displays a static HTML page:

import play.api.cache.Cache
val index = Action {
  Ok(Cache.getOrElse("main-html")(views.html.main()))
}

The getOrElse method retrieves the value associated with the given key, or if not found, computes it and sets it in the cache. By default, the storage duration is infinite but you can set a custom duration in seconds, for example, 1 hour:

Cache.getOrElse("main-html", 3600)(…)

The Java equivalent is as follows:

public static Result index() throws Exception {
  return ok(Cache.getOrElse("main-html", () -> views.html.main.render(), 0));
}

Note

In Java, the storage duration is mandatory.

The cache API also has set, get, and remove methods, to store, retrieve, and remove a value, respectively.

Nevertheless, this part of the API does not help you to deal with client-side caching mechanisms; though our main page is always the same, web browsers don't cache it and always send an HTTP request to retrieve it. Our server computes the page content only once, but it is always sent through the wires to the clients. By relying on a client-side cache, you can save some bandwidth.

Client-side caching mechanisms are based on the HTTP requests and response headers, so their responsibility falls to the controller layer.

There are different ways to describe how HTTP clients can cache a result. You can, for example, provide an expiration date. In this case, web browsers won't even send an HTTP request to retrieve the resource as long as it didn't expire. However, it is difficult to predict how long time a resource will be valid. Alternatively, you can indicate when the resource was last modified, or associate a unique ETag value to each version of your resource. In this case, the browser sends a request indicating the last version it has in its cache, giving the HTTP server the opportunity to reply with a 304 (Not Modified) response if the resource hasn't been modified since then. The first approach saves HTTP round trips but might lead clients to see outdated content. The second solution always requires an HTTP request (the response is empty if the resource hasn't changed) but ensures that clients always sees up-to-date content. The second approach can also be harder to manage if you can't easily track the modifications of your content.

You can combine the second approach for client-side caching with server-side caching by using the Cached action combinator:

val index = Cached("main-html") {
  Action {
    Ok(views.html.main())
  }
}

In Java, annotate your action with the @Cached annotation:

@Cached(key = "main-html")
public static Result index() {
    return ok(views.html.main.render());
}

The preceding code stores the whole HTTP response in the server cache and adds an ETag and an Expires header to the response. By default, the expiration duration is set to 1 year, but you can supply a custom duration.

By default, the Scala Cached function caches the result returned by the action irrespective of whether it was a successful result or not. You might not want to cache error results; in such a case, you can specify which status codes should be cached:

Cached.status(OK, "main-html") { … }

The preceding code caches only responses with a 200 (OK) status code. There is no equivalent in the Java API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.37.154