Composable pages and the Cache feature

The Cache feature provided by Play, in both versions, is very well known. It is so important, that has its own page in the documentation. Just to give a quick description. Once you have put the @Cache annotation in your action, after the first request, the html generated will be stored and reused for the consecutive requests. The same thing applies to the Scala version.

The downside of this approach is that, almost every page in our application, has a relation with the current logged user. So, if you put the name of the user in the home page, like in GUJ(brazilian java forum), you just lost the opportunity to use the cache feature. You always have to remember, this cache is global. One approach could be create cache entries related with the current user, but this will imply an explosion of entries in the cache implementation.

In one of my posts, that was related with the Big Pipe idea presented in the talk given by Linkedin, it was demonstrated how you can compose your pages, loading each piece from a different request. Something like Page as a Service :). If you follow this approach you can gain another thing, the ability to cache just certain pagelets from your page!

Let’s see how we could compose the home page of GUJ using the “big pipe” approach implemented by Linkedin.

    public static Result index() {
      F.Promise news = ServiceClientJ.makeServiceCall("recent/news");
      F.Promise recentTags = ServiceClientJ.makeServiceCall("recent/tags");
      F.Promise availableJobs = ServiceClientJ.makeServiceCall("jobs");
      F.Promise infoqNews = ServiceClientJ.makeServiceCall("infoqnews");

      F.Promise newsHtmlPromise = render(news,;
      F.Promise recentTagsHtmlPromise = render(recentTags, views.html.guj.recent_tags.f());
      F.Promise availableJobsHtmlPromise = render(availableJobs,;
      F.Promise infoqNewsHtmlPromise = render(infoqNews, views.html.guj.infoq_news.f());

      HtmlStream newsStream = Pagelet.renderStream(newsHtmlPromise, "news");
      HtmlStream recentTagsStream = Pagelet.renderStream(recentTagsHtmlPromise, "recentTags");
      HtmlStream availableJobsStream = Pagelet.renderStream(availableJobsHtmlPromise, "availableJobs");
      HtmlStream infoqNewsStream = Pagelet.renderStream(infoqNewsHtmlPromise, "infoqNews");

      HtmlStream body = HtmlStream.interleave(Arrays.asList(newsStream, recentTagsStream,availableJobsStream,infoqNewsStream));

      return ok(HtmlStream.toChunks(;

As you can see, the page is built based on several requests! If you, for example, want to cache the “recent tags” pagelet, just put the @Cache annotation in this controller’s action.

    public class RecentTags extends Controller{

    	@Cached(key = "recent_tags", duration = 3600)
    	public static Result index(){
    		return ok(views.html.tags.index.render(;

Now you are taking advantage of the cache feature! I really like this approach and I will try to use it in my next projects :).


2 thoughts on “Composable pages and the Cache feature

  1. Alberto, boa tarde

    Muito bom o seu post. Fiquei apenas com uma dúvida: você fala para colocarmos o @Cached no controller que invoca a view que queremos fazer cache. Porém, onde você faz o vínculo do pagelet com este controller? Não consegui ver isto explicitamente no seu código de exemplo.

  2. Oi Andre,

    Seria nessa linha aqui => ServiceClientJ.makeServiceCall(url); Aqui você está fazendo o request para algum controller e na action desse controller você poderia usar o @Cache :). Qualquer dúvida é só falar!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s