In our project we have two modules: api and api-component, each has a cache.xml file which references another ehcache.xml file, both like this:
cache.xml (in both modules)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache" />
</bean>
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ehcache.xml" />
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true" />
</bean>
<bean class="net.sf.ehcache.management.ManagementService"
init-method="init">
<constructor-arg ref="ehcache" />
<constructor-arg ref="mbeanServer" />
<constructor-arg value="true" />
<constructor-arg value="true" />
<constructor-arg value="true" />
<constructor-arg value="true" />
</bean>
</beans>
ehcache.xml (in both modules)
<ehcache name="ApiCacheManager">
<diskStore path="java.io.tmpdir"/>
<cache name="myCache" -- Different name in each file
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="500"
timeToLiveSeconds="500"
overflowToDisk="false"
statistics="true"
/>
<defaultCache
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
/>
</ehcache>
In an attempt to transform these XML files to Java classes using annotations I came up with these configurations, again in both modules: ApiCacheConfiguration.java and ApiComponentCacheConfiguration.java
import net.sf.ehcache.Cache;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.DiskStoreConfiguration;
import net.sf.ehcache.management.ManagementService;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.interceptor.*;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jmx.support.MBeanServerFactoryBean;
import java.util.Collections;
@Configuration
@EnableCaching
public class ApiCacheConfiguration extends CachingConfigurerSupport {
@Primary
@Bean
public CacheManager cacheManager() {
CompositeCacheManager compositeCacheManager = new CompositeCacheManager();
compositeCacheManager.setCacheManagers(Collections.singleton(ehCacheManager()));
return compositeCacheManager;
}
@Bean
public EhCacheCacheManager ehCacheManager() {
EhCacheCacheManager cacheManager = new EhCacheCacheManager(ehCacheCacheManager());
ManagementService.registerMBeans(
cacheManager.getCacheManager(),
mBeanServer().getObject(),
true,
true,
true,
true);
return cacheManager;
}
@Bean
public MBeanServerFactoryBean mBeanServer() {
MBeanServerFactoryBean mBeanServerFactoryBean = new MBeanServerFactoryBean();
mBeanServerFactoryBean.setLocateExistingServerIfPossible(true);
return mBeanServerFactoryBean;
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver(cacheManager());
}
@Bean
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler();
}
private net.sf.ehcache.CacheManager ehCacheCacheManager() {
net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(ehCacheConfiguration());
cacheManager.setName("ApiCacheManager"); // If name is not set I'm not getting 'InstanceAlreadyExistsException'
cacheManager.addCache(myCache());
return cacheManager;
}
private Cache myCache() {
CacheConfiguration configuration = new CacheConfiguration("myCache", 100) // Different name in each file
.eternal(false)
.timeToIdleSeconds(600)
.timeToLiveSeconds(3600)
.overflowToDisk(false)
.statistics(true);
return new Cache(configuration);
}
private net.sf.ehcache.config.Configuration ehCacheConfiguration() {
DiskStoreConfiguration diskStoreConfiguration = new DiskStoreConfiguration();
diskStoreConfiguration.setPath("java.io.tmpdir");
CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
defaultCacheConfiguration.maxElementsInMemory(1000);
defaultCacheConfiguration.eternal(true);
defaultCacheConfiguration.overflowToDisk(false);
net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration();
configuration.setDefaultCacheConfiguration(defaultCacheConfiguration);
configuration.addDiskStore(diskStoreConfiguration);
return configuration;
}
}
Everything is almost as it's written in the previous ehCache.xml but, I don't know how, multiple beans of ApiCacheManager and ApiComponentCacheManager are being created, throwing these errors:
Caused by: javax.management.InstanceAlreadyExistsException: net.sf.ehcache:type=CacheManager,name=ApiCacheManager
Caused by: javax.management.InstanceAlreadyExistsException: net.sf.ehcache:type=CacheManager,name=ApiComponentCacheManager
This error doesn't appear if the CacheManager names are not set, but multiple beans are registered into JMX:
How do I get only my two CacheManagers into JMX with the names I set? Is there something wrong with the creation of the CacheManager? Maybe is not creating a Singleton?
