5 minutes with – Spring Cache
Many times happens that we read information that we’ve already read just few time ago. These could be database, fileSystem or rss feed independently.
For the very static contexts (as weather forecast services) that changes once a day, calling the resource every time we need to show, it’s a very waste of time for our application.
For solve this problems, the keyword is cache. Now, I show you how implementing ehcache system with spring.
First, the official ehcache web site http://ehcache.org/
In this demo I used a Spring MVC web application and one simple Bean. it has a cached method. In the same Bean I wrote a method to evict the cache.
My libraries
aopalliance-1.0.jar asm-3.0.jar aspectjweaver-1.6.6.jar cglib-2.2.jar commons-logging-1.1.1.jar ehcache-1.6.2.jar jstl-1.2.jar junit-4.8.1.jar lib.txt log4j-1.2.14.jar spring-aop-3.1.0.RELEASE.jar spring-asm-3.1.0.RELEASE.jar spring-beans-3.1.0.RELEASE.jar spring-context-3.1.0.RELEASE.jar spring-core-3.1.0.RELEASE.jar spring-expression-3.1.0.RELEASE.jar spring-test-3.1.0.RELEASE.jar spring-web-3.1.0.RELEASE.jar spring-webmvc-3.1.0.RELEASE.jar standard-1.1.2.jar
In the web.xml is defined the spring servlet definition.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a> xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web=<a href="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd</a> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Spring3MVC</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app> <pre>
The spring-servlet.xml file include the cache manager bean and speaker bean who will be used for calling the cached methods.
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache" /> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml" /> <bean id="Speaker" class="it.sample.springcache.bean.Speaker" />
In ehcache.xml file I configured the speakerCache cache type.
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<defaultCache
maxElementsInMemory="50"
eternal="false"
overflowToDisk="false"
memoryStoreEvictionPolicy="LFU" />
<cache name="persons"
maxElementsInMemory="50"
eternal="false"
overflowToDisk="false"
memoryStoreEvictionPolicy="LFU" />
<cache name="wordCache" eternal="false" maxElementsInMemory="100"
overflowToDisk="false" diskPersistent="false"
timeToIdleSeconds="0" timeToLiveSeconds="60" memoryStoreEvictionPolicy="LRU" />
</ehcache>
All arguments are explained in this link http://ehcache.org/apidocs/net/sf/ehcache/config/CacheConfiguration.html
In few words I configured a cache with max 100 elements in memory and with expiry time of 60 seconds.
Take a look at Speaker class. There are two methods inside: sayWord and clearWord and each of them accept one “word” parameter.
The annotations @Cacheable and @CacheEvict mean “put in cache” and “evict from cache” with the key parameter “word”.
package it.sample.springcache.bean;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
public class Speaker {
@Cacheable(value="wordCache", key="#word")
public String sayWord(String word)
{
return word;
}
@CacheEvict(value="wordCache", key="#word")
public String clearWord(String word)
{
return "Ok";
}
}
The last class is the controller MVC with the annotation for Url /speaker and /speakerclear
package it.sample.springcache.controller;
import it.sample.springcache.bean.Speaker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloWorldController {
@Autowired
Speaker speaker;
@RequestMapping("/speaker")
public ModelAndView speakerWorld(@RequestParam(required=true) String message) {
message = speaker.sayWord(message);
System.out.println(message);
return new ModelAndView("speaker", "message", message);
}
@RequestMapping("/speakerclear")
public ModelAndView speakerWorldClear(@RequestParam(required=true) String message) {
message = speaker.clearWord(message);
System.out.println(message);
return new ModelAndView("speaker", "message", message);
}
}
It’s time to launch Tomcat and browse the url /hello.html?message=hello. If you call again the same url you can check that the method sayWord(“hello”) has been cached. You can call /helloclear.html?message=hello or wait for 60 seconds to evict the value from the cache.
Update
The source code is available at this link SpringCache (Please, substitute the .doc extension with .zip extension)

Hi, how are you able to know that it was being cache? Please send a steps, thank you. This helps me starting with Ehcache.
I’m not sure what you’re asking me about. You can see the method clearWord(“hello”) cached by putting a log message inside a clearWord method. You can see that, the second time you call the method that log message won’t be displayed.
Otherwise, if you’re asking me how check the cache content into your code I’m sorry but I’ve never done that before.
Anyway, you can check it on official web site http://ehcache.org/documentation/code-samples.
I hope to have answered your questions.
Hi, It lok good , Can you please post web.xml content .
I’ve just post it.
Hi, Thanks for posting web.xml. I have done all step, Now when i am start tomcat it showing following exception on tomcat console..May you please identify what may be wrong..
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘cacheManager’ defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Cannot resolve reference to bean ‘ehcache’ while setting bean property ‘cacheManager’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘ehcache’ defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Illegal configuration. No default cache is configured.
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1317)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:872)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:423)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:442)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:458)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:339)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:306)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘ehcache’ defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Illegal configuration. No default cache is configured.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1412)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
… 31 more
Caused by: net.sf.ehcache.CacheException: Illegal configuration. No default cache is configured.
at net.sf.ehcache.config.ConfigurationHelper.createDefaultCache(ConfigurationHelper.java:365)
at net.sf.ehcache.CacheManager.configure(CacheManager.java:321)
at net.sf.ehcache.CacheManager.init(CacheManager.java:237)
at net.sf.ehcache.CacheManager.(CacheManager.java:210)
at org.springframework.cache.ehcache.EhCacheManagerFactoryBean.afterPropertiesSet(EhCacheManagerFactoryBean.java:104)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1409)
… 38 more
May 10, 2013 4:42:06 PM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet /testCache threw load() exception
net.sf.ehcache.CacheException: Illegal configuration. No default cache is configured.
at net.sf.ehcache.config.ConfigurationHelper.createDefaultCache(ConfigurationHelper.java:365)
at net.sf.ehcache.CacheManager.configure(CacheManager.java:321)
at net.sf.ehcache.CacheManager.init(CacheManager.java:237)
at net.sf.ehcache.CacheManager.(CacheManager.java:210)
at org.springframework.cache.ehcache.EhCacheManagerFactoryBean.afterPropertiesSet(EhCacheManagerFactoryBean.java:104)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1409)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1317)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:872)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:423)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:442)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:458)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:339)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:306)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Hi Amit,
I’m very sorry but I’ve mixed two different examples in the article.
It’s been my fault.
Now I’ve just uploaded the complete source code and corrected the article. You can find above in the article.