C'est 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 derrière l'exception. Peut-il y avoir plus d'un cacheManager s'exécutant simultanément?
Voici comment j'ai configuré cachManager à l'aide de Sping 3.1.1. Il définit explicitement la portée du cacheManager sur "singleton"
<ehcache:annotation-driven />
<bean
id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
scope="singleton"
/>
Le fichier 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 très sûr que je n'ai affaire qu'à un seul cacheManager dans ma base de code. Quelque chose d'autre est probablement en train d'exécuter la nième instance.
Votre EhCacheManagerFactoryBean peut être un singleton, mais il crée plusieurs CacheManagers et tente de leur donner le même nom. Cela viole Ehcache 2.5 la sémantique .
Les versions d'Ehcache antérieures à la version 2.5 permettaient à tout nombre de CacheManagers du même nom (même ressource de configuration) d'exister dans une machine virtuelle Java.
Ehcache 2.5 et les versions ultérieures ne permettent pas à plusieurs CacheManagers du même nom d’exister dans la même machine virtuelle. Les constructeurs CacheManager () créant des CacheManagers non-Singleton peuvent enfreindre cette règle
Indiquez au bean factory de créer une instance partagée du CacheManager dans la machine virtuelle Java en définissant la propriété shared sur la valeur true.
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:shared="true"/>
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 à l'aide de la configuration Hibernate suivante:
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/>
à la place d'utiliser
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory"/>
Votre problème est l’optimisation du chargement de contexte intégrée au framework de test Spring. Spring (par défaut) ne détruit pas le contexte une fois la classe de test terminée, 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 à l'aide de @DirtiesContext ou, si vous utilisez maven, définir surefire forkMode sur "toujours" et créer un nouveau VM par classe de test.
Vous pouvez également essayer de définir le nom "xxx" sur votre configuration ehcache.xml (sur l'élément ehcache).
Cela a fait l'affaire pour moi, car je pense avoir 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 grande envergure de cela.
Après la mise à niveau vers Hibernate 5, je devais utiliser:
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
au lieu de:
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/>
S'il vous plaît pas le paquet différent.
Pour la postérité: Un meilleur moyen consiste à utiliser la propriété "accept-Exist" de EhCacheManagerFactoryBean .
Dans mon cas, nous avons un gestionnaire de cache personnalisé défini comme bean ..__, ainsi qu'un contexte d'application personnalisé pour que nous n'utilisions pas le coureur Spring Junit ... Par conséquent, le @DirtiesContext ne fonctionne pas.
L'astuce consiste à récupérer l'instance de cache à partir du bean. Sur ce cache, récupérez le cacheManager (l'instance de EHCache). et sur ce cachemanager, appelez la méthode removeCache.
Mettez ceci dans une méthode annotée avec @After et votre cache est supprimé de la VM après chaque test. Comme ça:
@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;
}
Cela m'est arrivé lors du passage à Spring Boot 2.0.2 . Résolu en procédant comme suit:
REMOVE dans application.yml
spring.jpa.properties.hibernate.cache.region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
REMOVE in pom.xml
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
GARDER dans pom.xml seulement
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>
Je l'ai résolu en ajoutant ce qui suit à resources.groovy:
haricots = { ... aclCacheManager (EhCacheManagerFactoryBean) { shared = true } ...}
si vous ne testez que le service métier, et non le cache de second niveau, vous pouvez supprimer la configuration de second niveau de votre fichier de configuration Spring. Votre test sera exécuté avec succès. il y a ma configuration de second 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 le temps d'exécution, 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>
alors j'obtiens la même exception "Un autre CacheManager non nommé existe déjà dans le même ordinateur virtuel"
Pour les futurs lecteurs, la cause de ce problème dans mon cas était que, dans mon fichier pom.xml, j'avais importé la bibliothèque hibernate-ehcache, qui, à mon insu, contenait également déjà la bibliothèque ehcache, puis explicitement importé net.sf.ehache. libray.
Cela semblait fonctionner correctement lorsque je m'exécutais en tant qu'application autonome (un utilitaire de ligne de commande, par exemple), mais cela entraînait l'erreur dans le message d'origine lors de l'exécution sur un serveur Tomcat.
Changer mon fichier pom de:
<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 -->
Correction du problème. Si quelqu'un a la moindre idée de la raison pour laquelle le problème n'apparaît que lorsqu'il est exécuté dans un conteneur Tomcat, cela m'intéressera de savoir.
À partir de Spring Boot 2.1.2 la configuration suivante a permis de résoudre le problème. (Remarque, ce sont des extraits de la configuration globale.)
Dépendances:
<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 config:
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
Configuration 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>
L'application sur laquelle je travaille ralentit considérablement sans cache actif. Donc, pour valider, j'ai simplement exécuté l'application et cliqué sur l'un des points de terminaison intenses en lecture.
Dans glassfish 3.0.1, le problème était lié à l'initialisation de IniShiroFilter à deux reprises, ce qui se produit lorsque des demandes simultanées sont déclenchées juste après le démarrage du serveur. Voici une trace de pile de deux threads différents correspondant à deux requêtes 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)
Un autre fil
[#|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)
L'examen de la trace de pile ApplicationFilterConfig.Java:248 pourrait en être la cause. Sinon, glassfish initialise les filtres dans le mauvais contexte. Pour comparaison, Tomcat initialise les filtres pendant BootStrap.
Cette erreur se produit également avec des fichiers de mappage incorrects. Le message est horrible, ne dit pas la cause.
Régler le EhCacheManagerFactoryBean#shared
sur true
a fonctionné pour moi.
Régler le EhCacheManagerFactoryBean#acceptExisting
sur true
N'A PAS fonctionné pour moi.
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;
}
}
Comme expliqué dans Utilisation d'EhCache au printemps 4 sans XML
Dans mon cas, le problème est le composant-scan et la configuration Java.
root-context.xml
<context:component-scan base-package="org.beansugar">
servlet-context.xml
<context:component-scan base-package="org.beansugar">
spring composant-scan fonctionne deux fois sur les fichiers xml . il génère des beans à l’intérieur de SpringConfig.Java à chaque heure d’exécution . un gestionnaire de cache dupliqué a été créé.
donc, j'ai changé ça comme ci-dessous.
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>
Dans mon cas, la configuration était la suivante:
<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>
Changer de classe de fournisseur EHCache a fait le travail pour moi. J'utilisais la classe de fournisseur de cache en tant que org.hibernate.cache.EhCacheProvider
à la place, j'ai changé cela en: net.sf.ehcache.hibernate.SingletonEhCacheProvider