Search code examples
javaspringcachingehcache

SelfPopulatingCache incumbent cache issue (Spring 4, EhCache 2.10.3)


I have a project setup (the snippets here are from a demo project I have created on GitHub https://github.com/ashishmarwal/self-populating-cache-issue) where a raw eh-cache cache is declared in the ehcache config (ehcache.xml).

<cache name="alphabet-description-cache"
       eternal="false"
       maxElementsInMemory="1000"
       memoryStoreEvictionPolicy="LRU"
       overflowToDisk="false"
       timeToLiveSeconds="300"
       timeToIdleSeconds="300" />

Spring bean descriptor then uses that raw cache to create a decorated (SelfPopulatingCache) using a CacheEntryFactory:

<bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
    <property name="cacheManager" ref="cacheManager"/>
</bean>

<!--Creating a decorated cache instance using the raw cache cinfigured in ehcache.xml -->
<bean id="alphabetDescriptionCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager" ref="cacheManager"/>
    <property name="cacheName" value="alphabet-description-cache"/>
    <property name="cacheEntryFactory" ref="alphabetDescriptionCacheEntryFactory"/>
</bean>

<bean id="alphabetDescriptionCacheEntryFactory" class="com.marwals.ashish.issues.selfpopulatingcache.AlphabetDescriptionCacheEntryFactory" />

We also have a test-context.xml which is used for unit testing and declares a cacheManager as well as the decorated cache (in my perspective I have given different names to these cache managers):

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="cacheManagerName" value="self-populating-cache-issue-demo-test"/>
    <property name="shared" value="true"/>
    <property name="acceptExisting" value="false"/>
    <property name="configLocation" value="classpath:/ehcache.xml"/>
</bean>

<bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
    <property name="cacheManager" ref="cacheManager"/>
</bean>

<bean id="alphabetDescriptionCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager" ref="cacheManager"/>
    <property name="cacheName" value="alphabet-description-cache"/>
    <property name="cacheEntryFactory" ref="alphabetDescriptionCacheEntryFactory"/>
</bean>

<bean id="alphabetDescriptionCacheEntryFactory" class="com.marwals.ashish.issues.selfpopulatingcache.AlphabetDescriptionCacheEntryFactory" />

The problem here is that if I have two different tests each loading either the main or the test-context bean descriptor, I run into an incumbent cache issue:

    Error creating bean with name 'alphabetDescriptionCache' defined in class path resource [test-context.xml]: Invocation of init method failed; 
nested exception is net.sf.ehcache.CacheException: Cannot replace alphabet-description-cache It does not equal the incumbent cache.

Any ideas what could be wrong here? Debugging the code reveals that I have two different cache instance for the same raw cache which is then raised as an error by EhCache's cache manager.

I have created a git repo demonstrating this problem: https://github.com/ashishmarwal/self-populating-cache-issue

Thanks!!!


Solution

  • You explicitly requested a shared cache manager in your Spring configuration

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="cacheManagerName" value="self-populating-cache-issue-demo"/>
        <property name="shared" value="true"/> <!-- here -->
        <property name="acceptExisting" value="false"/>
        <property name="configLocation" value="classpath:/ehcache.xml"/>
    </bean>
    

    This means Ehcache will always return the same CacheManager for a given configuration. In your case (and generally) you don't want that.

    Just setting shared to false solves your problem.