77 votes

Un autre CacheManager sans nom existe déjà dans la même VM (ehCache 2.5).

Voici ce qui se passe lorsque je lance mes 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 ]

Quelle est la raison de cette exception ? Pourrait-il y avoir plus d'un cacheManager fonctionnant simultanément ?

Voici comment j'ai configuré le cacheManager en utilisant Sping 3.1.1. Il définit explicitement la portée du cacheManager à "singleton".

<ehcache:annotation-driven />

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

Le ehcache.xml ressemble à

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

Enfin ma classe

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

     @Autowired
     private CacheManager ehCacheManager;
      ....
}

Je suis certain de n'avoir affaire qu'à un seul cacheManager dans ma base de code. Quelque chose d'autre est probablement en train d'exécuter la n-ième instance.

4 votes

J'ai vu le même problème avec ehCache 2.5 ou plus. L'utilisation de la version 2.4.7 ne cause pas ce problème, mais il serait bon de savoir comment rendre la version 2.5 compatible avec junit.

1 votes

Merci. Je suis revenu à la version 2.4.7, qui fonctionne bien pour l'instant. Il y a également un article de blog qui traite des solutions de contournement possibles (bien qu'aucune d'entre elles ne semble être très attrayante). norrisshelton.wordpress.com/2012/03/08/

0 votes

La solution de Norris Shelton fonctionne pour moi ( norrisshelton.wordpress.com/2012/03/08/ )

46voto

Emerson Farrugia Points 3085

Votre EhCacheManagerFactoryBean est peut-être un singleton, mais il construit plusieurs CacheManagers et essaie de leur donner le même nom. C'est une violation de Ehcache 2.5 sémantique .

Les versions d'Ehcache antérieures à la version 2.5 permettaient à un nombre quelconque de CacheManagers portant le même nom (même ressource de configuration) d'exister dans une JVM.

Ehcache 2.5 et plus ne permet pas à plusieurs CacheManagers portant le même nom d'exister dans la même JVM. Les constructeurs CacheManager() qui créent des CacheManagers non-Singleton peuvent enfreindre cette règle.

Indiquez au bean d'usine de créer une instance partagée du CacheManager dans la JVM en définissant l'attribut partagé à true.

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

5 votes

Une chose à noter, si Spring utilise l'autoproxie du EhCacheManagerFatoryBean, vous pouvez obtenir l'erreur même si vous définissez p:shared à true. La façon de contourner ce problème est de ne pas utiliser le nom par défaut pour votre fichier, au lieu d'utiliser ehcache.xml renommez le fichier et ajoutez p:config-location à votre déclaration EhCacheManagerFactoryBean avec le nouveau nom de fichier.

1 votes

@TechTrip : J'ai fait exactement ça : J'ai p:config-location="classpath:ehcache-foo.xml" p:shared="true" sur mon EhCacheManagerFactoryBean, et pourtant j'obtiens un conflit parce que deux WARs sur ma JVM utilisent ce même module.

3 votes

Corrigez-moi si je me trompe, mais cela ne signifie-t-il pas qu'un deuxième test réutilisera le cache du premier test avec toutes les données mises en cache encore présentes ? Cela pourrait conduire à un comportement difficile à déboguer parce que le deuxième test ne démarre pas dans un état bien connu. Le résultat du test peut alors dépendre de l'ordre des tests. (Bien sûr, les tests de la boîte noire ne devraient pas dépendre de l'utilisation ou non d'un cache, mais il est parfaitement valide d'avoir des tests de performance qui dépendent de l'état du cache ou peut-être que vous testez votre propre utilitaire de mise en cache qui utilise ehcache sous couvert).

44voto

Felix Reckers Points 252

J'ai eu le même problème avec mes tests d'intégration utilisant JPA (2.0) + Hibernate (3.6.4) + Spring (3.2.4). Le problème a été résolu en utilisant la configuration suivante d'Hibernate :

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

au lieu d'utiliser

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

3 votes

J'ai adapté cette solution pour résoudre mes problèmes de test de Spring Boot : J'ai utilisé org.hibernate.cache.ehcache.EhCacheRegionFactory au lieu de net.sf.ehcache.hibernate.EhCacheRegionFactory pour Hibernate 4 . Avec Spring Boot, vous pouvez définir ceci dans l'application.properties : spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory ou avec un @TestPropertySource si vous voulez limiter la configuration au test.

1 votes

Wow, j'ai sauvé ma journée après la mise à niveau d'Hibernate 4.3.x à 5.2.

23voto

Dejan P Points 251

Votre problème vient de l'optimisation du chargement du contexte intégrée dans le cadre de test de Spring. Spring (par défaut) ne détruit pas le contexte une fois que la classe de test a terminé, dans l'espoir qu'une autre classe de test puisse le réutiliser (au lieu de le créer de toutes pièces).

Vous pouvez remplacer cette valeur par défaut en utilisant @DirtiesContext, ou si vous utilisez maven, vous pouvez définir surefire forkMode sur "always" et créer une nouvelle VM par classe de test.

3 votes

Cela résout proprement le problème pour les environnements de test sans modifier votre configuration d'exécution réelle. Très bien !

2 votes

Forkmode=always est une bonne idée mais est déprécié. voir : maven.apache.org/surefire/maven-surefire-plugin/examples/ TRY forkCount=1 (par défaut), reuseForks=false

12voto

Michael Holst Points 56

Vous pouvez également essayer de définir le nom "xxx" dans votre configuration ehcache.xml (sur l'élément ehcache).

Cela a fonctionné pour moi, car je pense que j'avais une autre configuration de cache cachée dans l'un des modules de mon application.

La solution partagée fonctionne également, mais je ne connais pas les implications de cette solution.

0 votes

Oui ! Cela s'est avéré être la seule solution pour moi. Ajouter l'attribut name à l'élément echache supérieur. Cela ne semble pas être documenté dans l'exemple de fichier ehcache.xml

0 votes

Trop triste que je n'ai lu que la première réponse ici, après cela je retourne dans eclipse lire tout le source init de spring & ehcache pour comprendre que l'attribut name est nécessaire sinon le fichier de configuration est ignoré....

0 votes

Bonne solution, j'ai eu la même exception avec deux tests unitaires dans deux modules différents qui se trouvaient utiliser ehcache, chacun avec leur propre fichier et ceci résout le problème

2voto

roger.li Points 11

Si vous testez seulement votre service d'entreprise, pas le cache de deuxième niveau, vous pouvez supprimer la configuration de deuxième niveau dans votre fichier de configuration de printemps, votre test sera exécuté avec succès. voici ma configuration de deuxième niveau :

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

Si je passe à la configuration complète de la configuration du cache de second niveau, la vraie application web utilise en temps réel, comme ceci :

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

puis j'obtiens la même exception "Un autre CacheManager sans nom existe déjà dans la même VM".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X