Grails In-Memory Cache using Google’s Guava Library

Post by Matt Nohr

In a Grails application, there are a couple of cases where you may want to consider storing data in a in-memory cache. For example:

If it is expensive to read/create the data (reading across the network)

If the data will be used more than once

If multiple users need to access the data so you need to store it outside of a single user session

Here I will give you one example of how to use an in-memory cache. This can greatly improve performance but there are a couple of things you must keep in mind.

Scoped Services

One approach for storing the data is in an instance variable in a service. By default, Grails services are singletons, so only one instance of the service ever exists. Because of this, you could do something like this:

class MyService {
private def cache
public MyService() {
//initialize the cache
}
public getValue(String key){
//load value if it is not in cache
//return value from cache
}
}

Every request from a controller that accesses the service will be accessing the same instance, and therefore will be accessing the same “cache” variable.

Cache Considerations

This can be pretty powerful, and can help performance considerably, but there are some considerations you must think about.

Concurrency – Since all requests are going to be accessing the same instance, you must ensure that the “cache” variable is accessed in a thread-safe way or correctly handles concurrency

Memory Size – Since there will only ever be one instance, there should be a mechanism for removing old entries from the cache and/or limiting the size of the cache.

This cache (a LoadingCache object) will have a maximum of 500 entries and each entry will expire after 60 minutes. If the value is not already in the cache, the “load()” method will be called and the result (a MyExpensiveObject in this case) will be returned. There are other configurations to expire cache entries well explained in the documentation.

To use the cache then you would just do this:

def getValue(String key){
return cache.get(key)
}

You do not need to check if the object is in the cache because if it is not it will automatically be loaded.

Conclusion

Using an instance variable on a singleton service can serve as an in-memory cache, and by using the Guava libraries you can overcome the most complicated issues surrounding caching.

Notify me of followup comments via e-mail. You can also subscribe without commenting.

At refactr we believe in the value of connection, the utility of agile processes, and the power of great ideas. We are creating the next generation of software for people who expect more from their web applications.