Spring 3.1.1 MVC @Cacheable not being hit
ehcache, java, spring, spring-mvc
Solution
Even though I had an interface, I had the @Cacheable annotation on the implementation class. Once I moved it to the interface class, it was cached.
Problem
I am writing a webapp, and and trying to cache some pojos that are called from the controller. I wasn't able to get anything working when I tried using org.springframework.cache.annotation.Cacheable, so I switched to com.googlecode.ehcaceh.annotations.Cacheable, and I still can't get it to cache. My code looks like this: ``` @Controller public class Conttroller { @RequestMapping(method = RequestMethod.GET).... public Person getPerson(String id) { LOG.debug("Trying to get resource...); Person person = personService.detect(id); LOG.debug("got person"); ``` and the service looks like: ``` public class PersonService { @Cacheable(cacheName="deviceCache") public Person detect(String id) { LOG.debug("cache missed") ``` My applicationContext looks like ``` <context:component-scan base-package="com.mycompany" /> <ehcache:annotation-driven cache-manager="ehCacheManager" /> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager"> <ref bean="ehCacheManager" /> </property> </bean> <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="/META-INF/ehcache.xml" /> ``` and my ehcache looks like: ``` <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/> <cache name="deviceCache" maxElementsInMemory="100" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU" /> ``` What is interesting is that it caches fine in my unit test... ``` @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath:META-INF/applicationContext-test.xml"}) public class PersonServiceTest { private static final Logger LOG = LoggerFactory.getLogger(PersonServiceTest.class); @Test public void testCache() { LOG.debug("Getting person..."); Device detect = personService.detect("test"); LOG.debug("Getting person again ..."); detect = personService.detect("test"); LOG.debug("Done"); } ``` which produces: ``` 13:45:02.885 [main] DEBUG PersonServiceTest - Getting person... 13:45:02.887 [main] DEBUG c.g.e.a.i.CacheAttributeSourceImpl - Adding CACHE advised method 'detect' with attribute: CacheableAttributeImpl [cacheInstanceResolver=com.googlecode.ehcache.annotations.resolver.SingletonCacheableCacheResolver@5c2bfdff, cacheKeyGenerator=HashCodeCacheKeyGenerator [includeMethod=true, includeParameterTypes=true, useReflection=false, checkforCycles=false], parameterMask=ParameterMask [mask=[]]] 13:45:02.889 [main] DEBUG c.g.e.a.i.EhCacheInterceptor - Generated key '-1043428721379252' for invocation: ReflectiveMethodInvocation: public abstract com.mycompany.Person com.mycompany.PersonServiceImpl.detect(java.lang.String); target is of class [com..mycompany.PersonServiceImpl] 13:45:02.889 [main] DEBUG PersonServiceTest - Missed 13:45:02.927 [main] DEBUG PersonServiceTest - Getting person again ... 13:45:02.927 [main] DEBUG c.g.e.a.i.EhCacheInterceptor - Generated key '-1043428721379252' for invocation: ReflectiveMethodInvocation: 13:45:02.927 [main] DEBUG PersonServiceTest - Done ``` But the output of my war (running through tomcat7/eclipse wtp) is: ``` DEBUG net.sf.ehcache.config.ConfigurationFactory Configuring ehcache from InputStream DEBUG net.sf.ehcache.config.BeanHandler Ignoring ehcache attribute xmlns:xsi DEBUG net.sf.ehcache.config.BeanHandler Ignoring ehcache attribute xsi:noNamespaceSchemaLocation DEBUG net.sf.ehcache.util.PropertyUtil propertiesString is null. DEBUG net.sf.ehcache.config.ConfigurationHelper No CacheManagerEventListenerFactory class specified. Skipping... DEBUG net.sf.ehcache.Cache No BootstrapCacheLoaderFactory class specified. Skipping... DEBUG net.sf.ehcache.Cache CacheWriter factory not configured. Skipping... DEBUG net.sf.ehcache.config.ConfigurationHelper No CacheExceptionHandlerFactory class specified. Skipping... DEBUG net.sf.ehcache.Cache No BootstrapCacheLoaderFactory class specified. Skipping... DEBUG net.sf.ehcache.Cache CacheWriter factory not configured. Skipping... DEBUG net.sf.ehcache.config.ConfigurationHelper No CacheExceptionHandlerFactory class specified. Skipping... DEBUG net.sf.ehcache.store.MemoryStore Initialized net.sf.ehcache.store.NotifyingMemoryStore for deviceCache DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_OFFHEAP_SIZE DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_OFFHEAP_SIZE_BYTES DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_DISK_SIZE DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_DISK_SIZE_BYTES DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: WRITER_QUEUE_LENGTH DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: REMOTE_SIZE DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: OFFHEAP_GET DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: OFFHEAP_PUT DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: OFFHEAP_REMOVE DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: DISK_GET DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: DISK_PUT DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: DISK_REMOVE DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: XA_COMMIT DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: XA_ROLLBACK DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: XA_RECOVERY DEBUG net.sf.ehcache.Cache Initialised cache: deviceCache DEBUG net.sf.ehcache.config.ConfigurationHelper CacheDecoratorFactory not configured. Skipping for 'personCache'. DEBUG net.sf.ehcache.config.ConfigurationHelper CacheDecoratorFactory not configured for defaultCache. Skipping for 'personCache'. DEBUG com.googlecode.ehcache.annotations.impl.CacheAttributeSourceImpl Adding CACHE advised method 'detect' with attribute: CacheableAttributeImpl [cacheInstanceResolver=com.googlecode.ehcache.annotations.resolver.SingletonCacheableCacheResolver@7a1b0c08, cacheKeyGenerator=HashCodeCacheKeyGenerator [includeMethod=true, includeParameterTypes=true, useReflection=false, checkforCycles=false], parameterMask=ParameterMask [mask=[]]] Apr 3, 2013 2:03:12 PM org.springframework.web.context.ContextLoader initWebApplicationContext DEBUG com.mycompany.Controller trying to get resource' DEBUG com.mycompany.PersonServiceImpl Missed DEBUG com.mycompany.Controller got person' DEBUG com.mycompany.Controller trying to get resource' DEBUG com.mycompany.PersonServiceImpl Missed DEBUG com.mycompany.Controller got person' ``` So my question is, why does it work in my unit test, and not webapp? And how would I use the spring annotation instead of the googlecode annotation?