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.

<!-- Process cache annotations -->
 
<cache:annotation-driven />

<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)

About these ads

6 thoughts on “5 minutes with – Spring Cache

    • 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, 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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s