Tag Archives: ehcache

Spring 4+ with Ehcache 3.x

This post describes an example of using Ehcache with a Spring MVC application deployed on Tomcat (not using Spring boot). It is a legacy app that needs to be upgraded.

The dependencies are:

<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.1</version>
</dependency> 

Application context must be updated in this way:

<!-- ***** CACHE CONFIGURATION v.3 ***** -->
<cache:annotation-driven cache-manager="ehCacheManager" />
<bean id="ehCacheManager" class="org.springframework.cache.jcache.JCacheCacheManager">
  <property name="cacheManager">
    	<bean class="org.springframework.cache.jcache.JCacheManagerFactoryBean" 
        p:cacheManagerUri="classpath:ehcache.xml" />
  </property>
</bean>

The method must be annotated with @Cacheable so that Spring will handle the caching. As a result of this annotation, Spring will create a proxy of the NumberService to intercept calls to the square method and call Ehcache.

This is how to annotate the method (a service or a Dao implementation) providing the cache alias and the key for the cache:

@Cacheable(value = "retrieveUserIdOfMYGroup", key = "#userId")
public ArrayList<Integer> retrieveUserIdOfMYGroup(int userId) {
    [...]
}

Now, ehcache.xml config that is completely different than the previous version of ehcache (this is a simple config):

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.ehcache.org/v3"
    xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
    xsi:schemaLocation="
            http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
            http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
	
	<cache-template name="myDefaults">
	<listeners>
            <listener>
                <class>com.afm.web.configuration.CacheLogger</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
                <events-to-fire-on>EVICTED</events-to-fire-on>
            </listener>
        </listeners>        
	</cache-template>
	
	<!-- @Cacheable(value = "retrieveUserIdOfMYGroup", key = "#userId") -->
	<cache alias="retrieveUserIdOfMYGroup" uses-template="myDefaults">
		<heap unit="entries">200</heap>
	</cache>
            
</config>

Cache listeners allow implementers to register callback methods that will be executed when a cache event occurs and print on the log appender. This is how class CacheLogger is implemented:

public class CacheLogger implements CacheEventListener<Object, Object> {

  protected final Log LOG = LogFactory.getLog(getClass());
	
	@Override
	public void onEvent(CacheEvent<? extends Object, ? extends Object> cacheEvent) {
		LOG.info("Key: " + cacheEvent.getKey()  
      + " | EventType: " + cacheEvent.getType() 
      + " | Old value: " + cacheEvent.getOldValue() 
      + " | New value: " + cacheEvent.getNewValue());		
	}

}
Tagged , ,