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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10013288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:02:34  来源:igfitidea点击:

Another unnamed CacheManager already exists in the same VM (ehCache 2.5)

springjunitehcache

提问by simou

This is what happens when I run my junit tests...

这就是我运行 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 ]

What's the reason behind the exception. Could there be more than 1 cacheManager running simultaneously?

异常背后的原因是什么。是否可以同时运行 1 个以上的 cacheManager?

This is how I configured the cachManager using Sping 3.1.1. It sets explicitly the scope of the cacheManager to "singleton"

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

<ehcache:annotation-driven />

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

The ehcache.xml looks like

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>

Finally my class

最后我的课

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

     @Autowired
     private CacheManager ehCacheManager;
      ....
}

I'm very sure that I'm dealing with only one cacheManager in my code base. Something else is probably running the n-th instance.

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

回答by Emerson Farrugia

Your EhCacheManagerFactoryBean may be a singleton, but it's building multiple CacheManagers and trying to give them the same name. That violates Ehcache 2.5 semantics.

您的 EhCacheManagerFactoryBean 可能是一个单例,但它正在构建多个 CacheManager 并尝试为它们提供相同的名称。这违反了 Ehcache 2.5语义

Versions of Ehcache before version 2.5 allowed any number of CacheManagers with the same name (same configuration resource) to exist in a JVM.

Ehcache 2.5 and higher does not allow multiple CacheManagers with the same name to exist in the same JVM. CacheManager() constructors creating non-Singleton CacheManagers can violate this rule

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

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

Tell the factory bean to created a shared instance of the CacheManager in the JVM by setting the sharedproperty to true.

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

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

回答by Felix Reckers

I had the same issue with my integration tests using JPA (2.0) + Hibernate (3.6.4) + Spring (3.2.4). The issue was resolved using following Hibernate configuration:

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

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

instead of using

而不是使用

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

回答by Dejan P

Your problem is the context loading optimization built in the Spring test framework. Spring (per default) does not destroy the context once the test class is done, in hope that another test class might reuse it (instead of creating it from scratch).

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

You can override this default using @DirtiesContext, or if you use maven you can set surefire forkMode to "always" and create a new VM per test class.

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

回答by Michael Holst

You may also try to set name"xxx" on your ehcache.xml configuration (on the ehcache element).

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

That did the trick for me, as I think I had another cache configuration lurking in one of the modules of my app.

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

The shared solution also works, but I don't know the far-ranging implications of that.

共享解决方案也有效,但我不知道它的深远影响。

回答by eyes

After upgrading to Hibernate 5 I had to use:

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

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

instead of:

代替:

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

Please note that the packages differ from each other.

请注意,这些包彼此不同。

回答by Nishith

For posterity: A better way is to use the "accept-existing" property of the EhCacheManagerFactoryBean.

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

回答by roger.li

if you just test your business service,not second level cache,you can remove second level configuration in your spring config file,your test will be run successfully. there is my second level configuration :

如果你只是测试你的业务服务,而不是二级缓存,你可以在你的 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>

if i change to full configuration of second level cache config ,the real webapp use in running time,like this:

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

then i get the same Exception "Another unnamed CacheManager already exists in the same VM"

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

回答by Ronny Shibley

It happened to me when switching to Spring Boot 2.0.2. Resolved it by doing the following:

切换到Spring Boot 2.0.2时发生在我身上。通过执行以下操作解决了它:

REMOVE in application.yml

在 application.yml 中删除

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

REMOVE in pom.xml

在 pom.xml 中删除

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

KEEP in pom.xml only

仅保留在 pom.xml 中

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

回答by Pim Hazebroek

In my case, we have a custom cache manager defined as bean. Also a custom application context so we don't use the spring junit runner... hence the @DirtiesContext doesn't work.

就我而言,我们有一个定义为 bean 的自定义缓存管理器。还有一个自定义应用程序上下文,所以我们不使用 spring junit runner ...因此@DirtiesContext 不起作用。

The trick is to retrieve the cache instance from the bean, on that cache get the cacheManager (the instance from EHCache). and on that cachemanager call the removeCache method.

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

Put this in a method annotated with @After and your cache is removed from the VM after each test. Like this:

把它放在一个用 @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;
}

回答by Dasma

I solved it by adding following to resources.groovy :

我通过在 resources.groovy 中添加以下内容解决了这个问题:

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

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