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());
}
}