I need to have calls to MongoDB cached using spring @Cacheable annotation:
public interface SiteRepository extends PagingAndSortingRepository<Site, String>{
@Cacheable
List<Site> findByStatus(Site.Status status);
}
Unfortunately, annotating any method in the interface with @Cacheable causes the following exception:
Nov 22, 2014 7:11:06 PM org.apache.catalina.core.ApplicationContext
log SEVERE: StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'example': Injection of autowired dependencies
failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: com.example.repositories.mongodb.SiteRepository
com.example.siteRepo; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'siteRepository': Post-processing of
FactoryBean's singleton object failed; nested exception is
org.springframework.aop.framework.AopConfigException: Could not
generate CGLIB subclass of class [class com.sun.proxy.$Proxy92]:
Common causes of this problem include using a final class or a
non-visible class; nested exception is
java.lang.IllegalArgumentException: Cannot subclass final class class
com.sun.proxy.$Proxy92 at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1147)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:633)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
at
org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:602)
at
org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
at
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:521)
at
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:462)
at
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:160) at
org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1189)
at
org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1103)
at
org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1010)
at
org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4935)
at
org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5262)
at
org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5257)
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: Could not
autowire field: com.example.repositories.mongodb.SiteRepository
com.example.siteRepo; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'siteRepository': Post-processing of
FactoryBean's singleton object failed; nested exception is
org.springframework.aop.framework.AopConfigException: Could not
generate CGLIB subclass of class [class com.sun.proxy.$Proxy92]:
Common causes of this problem include using a final class or a
non-visible class; nested exception is
java.lang.IllegalArgumentException: Cannot subclass final class class
com.sun.proxy.$Proxy92 at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
… 27 more Caused by:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'siteRepository': Post-processing of
FactoryBean's singleton object failed; nested exception is
org.springframework.aop.framework.AopConfigException: Could not
generate CGLIB subclass of class [class com.sun.proxy.$Proxy92]:
Common causes of this problem include using a final class or a
non-visible class; nested exception is
java.lang.IllegalArgumentException: Cannot subclass final class class
com.sun.proxy.$Proxy92 at
org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:115)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1465)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:304)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:917)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:860)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:775)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
… 29 more Caused by:
org.springframework.aop.framework.AopConfigException: Could not
generate CGLIB subclass of class [class com.sun.proxy.$Proxy92]:
Common causes of this problem include using a final class or a
non-visible class; nested exception is
java.lang.IllegalArgumentException: Cannot subclass final class class
com.sun.proxy.$Proxy92 at
org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:218)
at
org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
at
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
at
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:409)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1656)
at
org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:112)
… 36 more Caused by: java.lang.IllegalArgumentException: Cannot
subclass final class class com.sun.proxy.$Proxy92 at
org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
at
org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at
org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at
org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at
org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
at
org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:206)
… 43 more
I am looking for a way to cache calls to DB (which are quite expensive). Any idea?
Best Answer
From the Spring documentation on caches:
Probably your cache configuration is colliding with the way that Spring creates implementations of your repository interfaces at runtime.
You could review your caching configuration to make it play nice with spring data (see here for different caching configuration options).
Or, you could do this: