另一个未命名的CacheManager已经存在于同一个VM(ehCache 2.5)

这是当我运行我的junittesting时发生的事情…

Another CacheManager with same name 'cacheManager' already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following: 1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary 2. Shutdown the earlier cacheManager before creating new one with same name. The source of the existing CacheManager is: DefaultConfigurationSource [ ehcache.xml or ehcache-failsafe.xml ] 

这个例外的原因是什么? 可以有多个cacheManager同时运行吗?

这就是我使用Sping 3.1.1configurationcachManager的方法。 它明确地将cacheManager的范围设置为“singleton”

 <ehcache:annotation-driven /> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" scope="singleton" /> 

ehcache.xml看起来像

 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false" maxBytesLocalHeap="100M" name="cacheManager" > .... </ehcache> 

最后是我的class

 @Component public class BookingCache implements CacheWrapper<String, BookingUIBean> { @Autowired private CacheManager ehCacheManager; .... } 

我非常肯定,我只处理我的代码库中的一个cacheManager。 别的东西可能正在运行第n个实例。

你的EhCacheManagerFactoryBean可能是一个singleton,但是它构build了多个CacheManagers并试图给它们命名。 这违反了Ehcache 2.5的语义 。

版本2.5之前的Ehcache允许具有相同名称(相同configuration资源)的任意数量的CacheManagers存在于JVM中。

Ehcache 2.5及更高版本不允许具有相同名称的多个CacheManagers存在于相同的JVM中。 创build非Singleton CacheManagers的CacheManager()构造函数可能违反此规则

通过将共享属性设置为true,告诉工厂bean在JVM中创buildCacheManager的共享实例。

 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true"/> 

我使用JPA(2.0)+ Hibernate(3.6.4)+ Spring(3.2.4)进行集成testing时遇到同样的问题。 使用以下Hibernateconfiguration解决了该问题:

 <property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/> 

而不是使用

 <property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory"/> 

你的问题是在Springtesting框架中构build的上下文加载优化。 一旦testing类完成,Spring(默认)不会破坏上下文,希望另一个testing类可以重用它(而不是从头创build)。

您可以使用@DirtiesContext覆盖此默认值,或者如果您使用maven,则可以将surefire forkMode设置为“always”,并为每个testing类创build一个新的VM。

您也可以尝试在ehcache.xmlconfiguration(在ehcache元素上)上设置名称“xxx”。

这对我来说是诀窍,因为我认为我有另一个cachingconfiguration潜伏在我的应用程序的模块之一。

共同的解决scheme也有效,但我不知道这个问题的深远影响。

后人:更好的方法是使用EhCacheManagerFactoryBean的“accept-existing”属性。

升级到Hibernate 5之后,我不得不使用:

 <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/> 

代替:

 <property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/> 

请不要包装不同。

如果你只是testing你的业务服务,而不是二级caching,你可以在你的springconfiguration文件中删除第二级configuration,你的testing将会成功运行。 有我的第二级configuration:

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceUnitName" value="defaultPU" /> <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" /> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">false</prop> <!-- <prop key="hibernate.hbm2ddl.auto">update</prop> --> <prop key="hibernate.cache.use_second_level_cache">false</prop> <prop key="hibernate.cache.use_query_cache">false</prop> </props> </property> </bean> 

如果我更改为二级cachingconfiguration的完整configuration,真正的webapp在运行时使用,如下所示:

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceUnitName" value="defaultPU" /> <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" /> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">false</prop> <!-- <prop key="hibernate.hbm2ddl.auto">update</prop> --> <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop> <prop key="net.sf.ehcache.configurationResourceName">ehcache/ehcache-hibernate-local.xml</prop> </props> </property> </bean> 

那么我得到相同的exception“另一个未命名的CacheManager已经存在于同一个VM”

在我的情况下,我们有一个定义为bean的自定义cachingpipe理器。 另外一个自定义的应用程序上下文,所以我们不使用春季junit亚军…因此@DirtiesContext不起作用。

诀窍是从bean中检索caching实例,在该caching上获取cacheManager(来自EHCache的实例)。 并在该cachingpipe理器上调用removeCache方法。

把它放在一个用@After注释的方法中,每次testing之后你的caching将从VM中移除。 喜欢这个:

 @After public void destroy() { MyCustomCacheManager customCacheManager = (MyCustomCacheManager) context.getBean("yourCustomCacheManagerBean"); try { net.sf.ehcache.Cache cache = customCacheManager.getCache(); net.sf.ehcache.CacheManager cacheManager = cache.getCacheManager(); cacheManager.removeCache("nameOfYourCache"); } catch (IllegalAccessException e) { e.printStackTrace(); } context.destroy(); context = null; } 

我通过向resources.groovy添加以下内容来解决它:

beans = {… aclCacheManager(EhCacheManagerFactoryBean){shared = true} …}

对于未来的读者来说,在我的情况下这个问题的原因是,在我的pom.xml文件中,我导入了hibernate-ehcache库,其中我也已经包含ehcache库,然后显式导入net.sf.ehache libray。

当我作为一个独立的应用程序(例如一个命令行工具)运行时,这似乎工作正常,但是当它运行在一个tomcat服务器上时,它导致了原始文章中的错误。

改变我的POM文件从:

  <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>5.0.2.Final</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.7.4</version> </dependency> 

至:

  <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>5.0.2.Final</version> </dependency> <!-- ehcache dependency removed --> 

解决了这个问题。 如果有人有任何想法,为什么这个问题只出现在运行在tomcat容器时,我会很有兴趣知道..

在glassfish 3.0.1中,我将问题追溯到IniShiroFilter获得两次初始化,这发生在服务器启动后立即触发并发请求。 以下是来自两个不同线程的对应于两个HTTP请求的堆栈跟踪:

 [#|2012-11-28T08:25:10.630-0800|SEVERE|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=28;_ThreadName=Thread-1;|java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Thread.java:1249) at org.apache.shiro.web.servlet.IniShiroFilter.<init>(IniShiroFilter.java:124) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:303) at com.sun.enterprise.web.WebContainer.createFilterInstance(WebContainer.java:725) at com.sun.enterprise.web.WebModule.createFilterInstance(WebModule.java:1948) at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:248) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) at com.sentilla.filter.DumpFilter.doFilter(DumpFilter.java:152) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:322) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:239) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) at java.lang.Thread.run(Thread.java:662) 

另一个线程

 [#|2012-11-28T08:25:15.299-0800|SEVERE|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=29;_ThreadName=Thread-1;|java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Thread.java:1249) at org.apache.shiro.web.servlet.IniShiroFilter.<init>(IniShiroFilter.java:124) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:303) at com.sun.enterprise.web.WebContainer.createFilterInstance(WebContainer.java:725) at com.sun.enterprise.web.WebModule.createFilterInstance(WebModule.java:1948) at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:248) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) at com.sentilla.filter.DumpFilter.doFilter(DumpFilter.java:152) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:322) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:239) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) at java.lang.Thread.run(Thread.java:662) 

看着堆栈跟踪ApplicationFilterConfig.java:248可能是罪魁祸首。 或者,glassfish在错误的上下文中初始化filter,为了比较,Tomcat在BootStrap期间初始化filter。

在我的情况下,问题是组件扫描和Javaconfiguration。

 root-context.xml <context:component-scan base-package="org.beansugar"> servlet-context.xml <context:component-scan base-package="org.beansugar"> 

spring的组件扫描工作两次在XML文件。 它在每个运行时在SpringConfig.java内部生成bean。 那么创build了重复的cachingpipe理器。

所以,我改变如下。

 root-context.xml <context:component-scan base-package="org.beansugar"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> servlet-context.xml <context:component-scan base-package="org.beansugar" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> 

这个错误也会在错误的映射文件中发生。 信息是可怕的,不说原因。