Tuesday, April 1, 2014

How I set up ehCache

Ehcache is a nice way to cache method responses. This is nice for example if one of your methods calls a web service or takes very long to execute.

I used ehcache with Spring, so I had to do some extra stuff so the annotations would work.

First I added ehcache and google's ehcache annotations for spring to my pom


Then in my Spring context file I added:
<beans xmlns="http://www.springframework.org/schema/beans"

    <ehcache:annotation-driven cache-manager="ehCacheManager"/>
    <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>

This allows us to use the @Cacheable and @TriggersRemove annotations that come from google.
I then placed ehcache.xml in my classpath (Putting it in WEB-INF didnt work)

My ehcache.xml looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    <diskStore path="java.io.tmpdir/ClavisCaches"/>
    <cache name="personCache" maxElementsInMemory="9000" eternal="true" overflowToDisk="false"/>

By setting the eternal value to true, this cache never expires unless I specifically trigger remove (see below). There are other ways to have the cache expire on a time limit. Please see the ehcache docs for this.

Then I created a Cache class that returned the Collection object that I wanted to cache:

import com.googlecode.ehcache.annotations.Cacheable;
import com.googlecode.ehcache.annotations.TriggersRemove;


@Cacheable(cacheName = "personCache")
public Collection<CacheElement> getPersonCacheSet() {

    List<Person> personList = wsClient.getSomeExpensiveCall();
    Collection<CacheElement> personCacheSet = new HashSet<CacheElement>(personList.size());

    for (Person person : personList) {
        CacheElement cacheElement = new CacheElement();

    return personCacheSet;

@TriggersRemove(cacheName = "personCache", when = When.AFTER_METHOD_INVOCATION, removeAll = true)
public void clearPersonCache() {
    // Intentionally blank

Note that the cacheable methods need to be called from a different class, because of the way the proxy is set up.

In my Spring configuration, I annotated this Cache class as a Service. This means Spring took care of initializing this class for me as a singleton on startup, so I could just autowire it and call the methods when needed.

Here is my jUnit file:

    private PersonCache personCache;

    public void testGetPersonCacheSet() {

        // The first call makes the expensive call, the second call gets the result from the cache
        Collection<CacheElement> personCacheSet0 = personCache.getPersonCacheSet();
        Collection<CacheElement> personCacheSet1 = personCache.getPersonCacheSet();

        assertSame(dealerCacheSet0, dealerCacheSet1);

    public void testClearCache() {

        // fill the cache

        // The first call gets the result from the cache
        Collection<PersonCacheElement> personCacheSet0 = personCache.getPersonCacheSet();


        // second call makes the expensive call
        Collection<CacheElement> personCacheSet1 = personCache.getPersonCacheSet();

        assertNotSame(personCacheSet0, personCacheSet1);

No comments:

Post a Comment