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

时间:2012-04-04 14:32:23

标签: spring junit ehcache

当我运行junit测试时会发生这种情况......

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.1配置cachManager的方法。它将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>

最后我的班级

@Component
public class BookingCache implements CacheWrapper<String, BookingUIBean> {

     @Autowired
     private CacheManager ehCacheManager;
      ....
}

我非常确定我在代码库中只处理一个cacheManager。其他东西可能正在运行第n个实例。

18 个答案:

答案 0 :(得分:44)

您的EhCacheManagerFactoryBean可能是单例,但它正在构建多个CacheManagers并尝试为它们指定相同的名称。这违反了Ehcache 2.5 semantics

  

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

     

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

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

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

答案 1 :(得分:40)

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

<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"/>

答案 2 :(得分:20)

您的问题是Spring测试框架中构建的上下文加载优化。 Spring(默认情况下)在测试类完成后不会破坏上下文,希望另一个测试类可以重用它(而不是从头开始创建它)。

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

答案 3 :(得分:12)

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

这对我有用,因为我认为我的应用程序的其中一个模块中有另一个缓存配置。

共享解决方案也有效,但我不知道其中涉及的范围很广。

答案 4 :(得分:8)

升级到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"/>

请不要包装。

答案 5 :(得分:6)

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

答案 6 :(得分:2)

在我的例子中,我们有一个定义为bean的自定义缓存管理器。 也是一个自定义应用程序上下文,所以我们不使用spring junit runner ...因此@DirtiesContext不起作用。

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

将此项放入使用@After注释的方法中,并在每次测试后从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;
}

答案 7 :(得分:2)

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

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

答案 8 :(得分:2)

如果您只测试业务服务而不是二级缓存,则可以删除spring配置文件中的二级配置,您的测试将成功运行。有我的第二级配置:

 <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>

如果我更改为二级缓存配置的完整配置,真正的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>

然后我得到相同的异常“另一个未命名的CacheManager已存在于同一个VM”

答案 9 :(得分:2)

切换到 Spring Boot 2.0.2 时发生了这种情况。通过执行以下操作解决了这个问题:

在application.yml中删除

spring.jpa.properties.hibernate.cache.region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory

在pom.xml中删除

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

仅在pom.xml中保留

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
</dependency>

答案 10 :(得分:1)

对于未来的读者,我的案例中出现此问题的原因是在我的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容器中运行时我才有兴趣知道..

答案 11 :(得分:1)

EhCacheManagerFactoryBean#shared设置为true对我有用。

EhCacheManagerFactoryBean#acceptExisting设置为true对我不起作用。

import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
public class EhCacheConfiguration {

    @Bean
    public EhCacheCacheManager ehCacheCacheManager() {

        return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject());
    }


    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {

        EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();

        cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        cacheManagerFactoryBean.setShared(true);

        return cacheManagerFactoryBean;
    }
}

Using EhCache in Spring 4 without XML

中所述

答案 12 :(得分:0)

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

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。 然后创建了重复的缓存管理器。

所以,我改变了如下。

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>

答案 13 :(得分:0)

错误的映射文件也会发生此错误。这个消息太可怕了,不说原因。

答案 14 :(得分:0)

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

[#|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在错误的上下文中初始化过滤器,为了进行比较,Tomcat在BootStrap期间初始化过滤器。

答案 15 :(得分:0)

在我的情况下,配置如下:

<spring.boot.version>1.5.8.RELEASE</spring.boot.version>
<spring.boot.yarn.version>2.4.0.RELEASE</spring.boot.yarn.version>
<spring.version>4.3.7.RELEASE</spring.version>

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>3.5.1-Final</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-ehcache</artifactId>
  <version>3.5.1-Final</version>
</dependency>

更改EHCache提供程序类为我完成了这项工作。我将缓存提供程序类用作org.hibernate.cache.EhCacheProvider,而是将其更改为: net.sf.ehcache.hibernate.SingletonEhCacheProvider

答案 16 :(得分:0)

Spring Boot 2.1.2 开始,以下配置可以解决该问题。 (请注意,这些是整体配置的摘要。)

依赖项:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.2.8.Final</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-ehcache</artifactId>
  <version>5.2.8.Final</version>
</dependency>

application.yml配置:

spring:
  jpa:
    open-in-view: false
    hibernate:
      ddl-auto: none
    show-sql: true
    properties:
      dialect: org.hibernate.dialect.MySQLDialect
      net:
        sf:
          ehcache:
            configurationResourceName: ehcache.xml
      hibernate:
        cache:
          use_second_level_cache: true
          region:
            factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory

ehcache.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
  <!-- Required elements -->
  <diskStore path="java.io.tmpdir"/>
  <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="true"/>

  <!-- Cache settings per class -->
  <cache name="com.mystuff.component.services.example.Book"
    maxElementsInMemory="1000"
    eternal="false"
    timeToIdleSeconds="300"
    timeToLiveSeconds="600"
    overflowToDisk="true"/>
</ehcache>

我正在处理的应用程序在没有可用缓存的情况下急剧降低。因此,要验证,我只运行了应用程序并命中了读取的密集端点之一。

答案 17 :(得分:0)

在我的例子中,Manager 是由这个 bean 创建的(ehCache 2.10):

  <bean id="ehcache"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="shared" value="false"/>
  </bean>

对我有用的唯一解决方案是以这种方式手动销毁它:

@Inject
private EhCacheManagerFactoryBean ehCacheManagerFactoryBean;

然后

ehCacheManagerFactoryBean.destroy();