I have a util module that produces a jar to be used in other applications. I\'d like this module to use caching and would prefer to use Spring\'s annotation-driven
Use this class: http://static.springsource.org/autorepo/docs/spring/3.2.0.M1/api/org/springframework/cache/support/CompositeCacheManager.html like this:
<cache:annotation-driven cache-manager="cacheManager" />
<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<array>
<ref bean="cacheManager1" />
<ref bean="cacheManager2" />
</array>
</property>
<property name="addNoOpCache" value="true" />
</bean>
Spring currently expects the cacheManager to be a Singleton. This is something that the ehcache-spring-annotations project ran into and I've yet to see the request fulfilled. http://code.google.com/p/ehcache-spring-annotations/issues/detail?id=76
As with all things Java and Spring you do have the option to reimplement the class.
http://forums.terracotta.org/forums/posts/list/5618.page#27960 provides a base explanation of what some people have come up with as a workaround and
Is the actual code they came up with. The approach does create a convention to follow but it would be easy enough to reimplement this with your own version if you do not like the actual approach described.
I would consider the following much simpler alternatives:
I did not like the solution of CompositeCacheManager, since its behavior is very dependent on the implementation of underlying caches: it will only work as expected if all underlying cache managers return null on unknown cache name. Some implementations would create them on the fly, resulting in caches with configuration that you did not expect.
In my Project I have been using ABC jar within XYZ war, both implementing ehCache with Spring 3.1,xml-driven configuration(we have ehCache.xml and then spring-context.xml where we are intercepting cache through Spring AOP in both the projects). And we are getting following error:
java.lang.IllegalArgumentException: Cannot find cache named [xxxxxx] for CacheableOperation[] caches=[Cxxxxxxxx] | condition='' | key='#xxxxxxxxxxxxx'
at org.springframework.cache.interceptor.CacheAspectSupport.getCaches(CacheAspectSupport.java:163) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.<init>(CacheAspectSupport.java:443) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.getOperationContext(CacheAspectSupport.java:173) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.createOperationContext(CacheAspectSupport.java:404) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:192) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at com.infy.flypp.dao.ContentDAO$$EnhancerByCGLIB$$9443481.getContentById(<generated>) [cglib-2.2.2.jar:]
Solution:
This is how we solved this issue:
ABCehCache.xml
(from ABC jar) to XYZehCache.xml
(from XYZ war).ABCehCache.xml
(from ABC jar) but all the configuration(like bean instantiation for ehCache.xml
and Spring AOP) inside ABC-spring.xml
will remain same.XYZ-spring.xml
, We imported ABC-spring.xml
and defined composite cache manager.Supported Configuration files:
ABC-spring.xml:
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="CacheManager1" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"></property>
</bean>
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ABCEhcache.xml" />
XYZ-spring.xml:
<import resource="classpath*:ABC-spring.xml" />
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<array>
<ref bean="CacheManager1" />
<ref bean="CacheManager2" />
</array>
</property>
<property name="fallbackToNoOpCache" value="true" />
</bean>
<bean id="CacheManager2" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache" />
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:XYZEhcache.xml" />
this seems to be fixed in 3.2M1, see https://jira.springsource.org/browse/SPR-8696