7

I'm trying to configure Spring Boot application with second level cache based on EHCache. I'm getting this exception:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method     failed; nested exception is org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the     hibernate.cache.region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:975)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:752)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at com.yes.wizard.Application.main(Application.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the hibernate.cache.    region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath.
    at org.hibernate.cache.internal.NoCachingRegionFactory.buildEntityRegion(NoCachingRegionFactory.java:83)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:364)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:845)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:338)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
    ... 20 more    

This is my configuration:

Application.class:

@EnableAutoConfiguration
@Configuration
@ComponentScan
@ImportResource(value = "/ws.xml")
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}

CacheConfig.class:

@Configuration
@EnableCaching
public class CachingConfig implements CachingConfigurer {

    @Bean
    @Override
    public CacheManager cacheManager() {
        EhCacheCacheManager cacheManager = new EhCacheCacheManager();
        cacheManager.setCacheManager(ehCacheManagerFactoryBean().getObject());
        return cacheManager;
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        ehCacheManagerFactoryBean.setCacheManagerName("messageCache");
        ehCacheManagerFactoryBean.setShared(true);
        return ehCacheManagerFactoryBean;
    }
}

MyEntity:

@Entity
@XmlRootElement
@Table(name = "my_entity")
@Cacheable(value = true)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class MyEntity { ... }

ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <defaultCache eternal="true" maxElementsInMemory="100" overflowToDisk="false" />
    <cache name="messageCache" maxElementsInMemory="10" eternal="true" overflowToDisk="false" />
</ehcache>

What is causing this?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Tal Etinger
  • 113
  • 1
  • 1
  • 8
  • Spring caching and Hibernate second level caching are different things... – M. Deinum Jan 06 '15 at 15:48
  • EHCache is used as second level cache for hibernate, and in my case I'm using spring data jpa (with hibernate). So where is my confusion? – Tal Etinger Jan 06 '15 at 16:02
  • As stated springs caching abstract and the use of a second level cache for your JPA provider have nothing to do with each other. Basically your setup for Spring Caching doesn't do anything or at least isn't related to the error you have. – M. Deinum Jan 07 '15 at 06:35
  • Here (http://www.ehcache.org/documentation/2.8/integrations/hibernate) you can find some useful details regarding `EhCache` and Hibernate 3.3 / 4.x. It also shows the values for `hibernate.cache.region.factory_class`. – ROMANIA_engineer Dec 06 '15 at 21:36
  • In my case, I forget to create my `application.yml` file into `grails-app/conf/` (Grails 3) – Eduardo Cuomo Jun 26 '17 at 17:01

1 Answers1

19

The key part of the error message is:

Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the hibernate.cache.region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath

You can set the factory_class property in Spring Boot's application.properties file. For example:

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

The class name that you need to use will depend on your EhCache dependency; in this case I used hibernate-ehcache.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • I had the same but an `=` instead of a `:` and this didn't work. Why the different property format? Sorry this is not a question for here but thanks to you I found out what my problem was (and was struck by this question). – HankCa Apr 01 '15 at 02:02
  • 1
    You can use either `=` or `:` to separate keys and values in a properties file – Andy Wilkinson Apr 01 '15 at 06:17
  • Yeah that is what I thought. I tried it again and works. I must have had a funny character from when I copied it before. All's well! – HankCa Apr 01 '15 at 11:26