Fix NoClassDefFoundError: org/hibernate/cache/CacheProvider

NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider means a Hibernate 3 class (Spring’s orm.hibernate3 factory bean or an old Ehcache provider) runs with Hibernate 4 or newer. Here is the fix for old projects and the Hibernate 7 JCache setup.

NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider means that a class compiled against Hibernate 3 runs with Hibernate 4 or newer, where the CacheProvider interface no longer exists. The interface CacheProvider was the Hibernate 3 plug-in point for a second level cache (a cache shared by all sessions), such as Ehcache 2. Hibernate 4.0 removed it and kept only RegionFactory.

We meet the error after a Hibernate upgrade that leaves a Hibernate 3 piece behind, in most projects either Spring’s orm.hibernate3.LocalSessionFactoryBean or an old hibernate-ehcache 3.x jar. We fix it by replacing the old piece with the one that matches our Hibernate version.

The following example shows the error for a Spring 3.2 app that runs with Hibernate 4.3 on Java 8, and for the same jars with Hibernate 7.4 on Java 25.

java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider;
	at java.lang.Class.getDeclaredFields0(Native Method)
	at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
	at java.lang.Class.getDeclaredFields(Class.java:1916)
	...
Caused by: java.lang.ClassNotFoundException: org.hibernate.cache.CacheProvider
java.lang.NoClassDefFoundError: org/hibernate/cache/CacheProvider
Caused by: java.lang.ClassNotFoundException: org.hibernate.cache.CacheProvider

Notice that Java 8 prints the L…; form, which is the JVM type descriptor of a field type, whereas Java 21 and 25 print the plain class name. Both messages point to the same missing interface. In a Spring application, the frame after getDeclaredFields() is often Spring’s PersistenceAnnotationBeanPostProcessor or AutowiredAnnotationBeanPostProcessor.

Next, we see which old jars still refer to CacheProvider and how to fix a Hibernate 4 or 5 project. After that, we move the cache to Hibernate 7 with JCache and Ehcache 3.

1. Why CacheProvider Cannot Be Found

The JVM throws NoClassDefFoundError when a class was present at compile time but is missing at runtime. The org/hibernate/cache folder of each hibernate-core jar on Maven Central shows when CacheProvider disappeared.

JarCacheProviderRegionFactory
hibernate 3.2.7.gaYesNo
hibernate-core 3.3.2.GAYes, deprecatedYes
hibernate-core 3.6.10.FinalYes, deprecatedYes
hibernate-core 4.0.0.FinalNoYes, in org.hibernate.cache.spi
hibernate-core 4.3.11, 5.6.15, 7.4.11NoYes

A region is a named cache, for example one per cached entity class. The RegionFactory creates the regions, and CacheProvider was its predecessor. Each Hibernate generation plugs Ehcache in differently.

Three columns: Hibernate 3 uses hibernate.cache.provider_class and CacheProvider with EhCacheProvider and Ehcache 2; Hibernate 4 and 5 use region.factory_class and RegionFactory with EhCacheRegionFactory and Ehcache 2; Hibernate 6 and 7 use region.factory_class=jcache and RegionFactory with JCacheRegionFactory and Ehcache 3; a footer lists the versions 3.3, 4.0, 5.2 and 6.0
Only Hibernate 3 has CacheProvider. From 4.0 on, every cache library plugs in through RegionFactory, and since Hibernate 6 Ehcache plugs in only through JCache.

Old jars that refer to the interface can still sit on the classpath. The JVM resolves the missing type lazily, so the error appears when some code first uses the old class.

Two old jars compiled against Hibernate 3, spring-orm with orm.hibernate3.LocalSessionFactoryBean and hibernate-ehcache 3.x with EhCacheProvider, point to CacheProvider, which is missing from hibernate-core 4.0 and newer; the JVM error text on Java 8 and on Java 21 and 25 is shown below
Both old jars point to an interface that newer hibernate-core jars do not contain.

1.1. Spring’s orm.hibernate3 Factory Bean

Up to Spring 4.3, spring-orm had one LocalSessionFactoryBean per Hibernate generation, in the packages orm.hibernate3, orm.hibernate4 and orm.hibernate5. The hibernate3 class declares a field of type CacheProvider, so loading the class works but reading its fields fails. Spring reads the fields of every bean class to find @Autowired and @PersistenceContext, so the context fails at startup.

Class<?> factoryBean = Class.forName("org.springframework.orm.hibernate3.LocalSessionFactoryBean");   // loads
Field[] fields = factoryBean.getDeclaredFields();      // NoClassDefFoundError: org/hibernate/cache/CacheProvider

We saw the same stack trace at the top of the article. The project moved to Hibernate 4 jars but kept the hibernate3 class name in its Spring XML.

1.2. A Hibernate 3 Ehcache Provider

Hibernate 3 projects configured Ehcache with hibernate.cache.provider_class, and the provider class came from hibernate-ehcache 3.x. The class EhCacheProvider implements CacheProvider, so the JVM cannot even load it.

Class<?> provider = Class.forName("org.hibernate.cache.EhCacheProvider");
// NoClassDefFoundError: org/hibernate/cache/CacheProvider
// Caused by: ClassNotFoundException: org.hibernate.cache.CacheProvider

When the old provider name is moved into the newer region.factory_class key, Hibernate 7 stops at startup. Hibernate tries several class loaders and attaches each NoClassDefFoundError as a suppressed exception.

org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.RegionFactory] due to: Unable to resolve name [org.hibernate.cache.EhCacheProvider] as strategy [org.hibernate.cache.spi.RegionFactory]
...
Caused by: java.lang.ClassNotFoundException: Could not load requested class: org.hibernate.cache.EhCacheProvider
	Suppressed: java.lang.NoClassDefFoundError: org/hibernate/cache/CacheProvider
	Caused by: java.lang.ClassNotFoundException: org.hibernate.cache.CacheProvider

2. How to Fix It

There is no jar to add, because Hibernate 4 and later never had CacheProvider. Instead, we remove every Hibernate 3 piece and use the class that matches the hibernate-core version.

Old (Hibernate 3)Hibernate 4.x and 5.xHibernate 6.x and 7.x
hibernate.cache.provider_classhibernate.cache.region.factory_classhibernate.cache.region.factory_class=jcache
org.hibernate.cache.EhCacheProviderorg.hibernate.cache.ehcache.EhCacheRegionFactory (short name ehcache)JCacheRegionFactory (short name jcache)
org.hibernate:hibernate-ehcache:3.xorg.hibernate:hibernate-ehcache, same version as hibernate-coreorg.hibernate.orm:hibernate-jcache plus org.ehcache:ehcache (classifier jakarta)
net.sf.ehcache (Ehcache 2)net.sf.ehcache (Ehcache 2)org.ehcache (Ehcache 3)
Spring orm.hibernate3.LocalSessionFactoryBeanorm.hibernate4 or orm.hibernate5.LocalSessionFactoryBeanorm.hibernate5 (Spring 6) or orm.jpa.hibernate (Spring 7)

2.1. Fixing an Old Hibernate 4 or 5 Project

A legacy app that must stay on Hibernate 4 or 5 needs two changes. First, the Spring factory bean must come from the package that matches Hibernate.

<!-- Before: Hibernate 3 class, fails with Hibernate 4 jars -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<!-- After: Hibernate 4 (use orm.hibernate5 for Hibernate 5) -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

Second, the cache setting moves from the provider to the region factory, and hibernate-ehcache takes the same version as hibernate-core.

# Before (Hibernate 3)
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider

# After (Hibernate 4.x and 5.x, with org.hibernate:hibernate-ehcache)
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

With Hibernate 4.3.11.Final and 5.6.15.Final on Java 8, the second session reads the postal code from the cache (hits=1, one SELECT), and the short name ehcache gives the same result. Keeping only provider_class is not a fix. Hibernate 4.3 then fails with NoCacheRegionFactoryAvailableException, and Hibernate 5.6 with Caching was explicitly requested, but no RegionFactory was defined.

Hibernate 5.6 logs HHH020100: The Ehcache second-level cache provider for Hibernate is deprecated. The hibernate-ehcache module has no final 6.x release, so this setup is a dead end and we should plan the move to JCache.

2.2. Moving to Hibernate 7 With JCache and Ehcache 3

Hibernate 7 reaches Ehcache 3 through JCache (JSR-107), the standard caching API in the javax.cache package. The following example caches a postal code lookup, which a delivery app runs on every checkout although the data changes only a few times a year. A PostalCode has a code (“560001”), a town (“Bengaluru”) and a district (“Bengaluru Urban”). The example runs on Java 25, Hibernate 7.4.11.Final, Ehcache 3.12.0 and an in-memory H2 database. The following dependencies replace hibernate-ehcache.

<dependency>
  <groupId>org.hibernate.orm</groupId>
  <artifactId>hibernate-jcache</artifactId>
  <version>7.4.11.Final</version>
</dependency>
<dependency>
  <groupId>org.ehcache</groupId>
  <artifactId>ehcache</artifactId>
  <version>3.12.0</version>
  <classifier>jakarta</classifier>
  <exclusions>
    <exclusion>
      <groupId>org.glassfish.jaxb</groupId>
      <artifactId>jaxb-runtime</artifactId>
    </exclusion>
  </exclusions>
</dependency>

The settings select the jcache region factory and point Ehcache to its ehcache.xml, which declares one cache per region. We bootstrap with HibernatePersistenceConfiguration.

.property("hibernate.cache.region.factory_class", "jcache")
.property("hibernate.javax.cache.provider", "org.ehcache.jsr107.EhcacheCachingProvider")
.property("hibernate.javax.cache.uri", "ehcache.xml")
.property("hibernate.javax.cache.missing_cache_strategy", "fail")
.property("hibernate.generate_statistics", true)
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PostalCode {

  @Id
  private String code;

  private String town;
  private String district;
}

In Spring Boot 4, the same keys go into application.properties with the spring.jpa.properties. prefix. The statistics prove that the cache works, because the second session finds the postal code in Ehcache and sends no SQL.

Statistics stats = emf.unwrap(SessionFactory.class).getStatistics();
emf.getCache().evictAll();
stats.clear();

emf.runInTransaction(em -> em.find(PostalCode.class, "560001"));
// select pc1_0.code,pc1_0.district,pc1_0.town from PostalCode pc1_0 where pc1_0.code=?
// L2 hits=0, misses=1, puts=1, statements=1

emf.runInTransaction(em -> em.find(PostalCode.class, "560001"));
// no SQL
// L2 hits=1, misses=1, puts=1, statements=1

With Ehcache 3 on Hibernate 6 and 7, every region name needs a cache in ehcache.xml, and each missing piece fails with its own error. Expiry and heap sizing go into the Hibernate Ehcache configuration.

The complete project on GitHub reproduces both errors with the real hibernate-ehcache 3.6.10 and Spring 3.2 jars in test scope, with 11 JUnit tests that check every result (mvn -q test-compile exec:java, mvn test).

3. CacheProvider Error FAQs

3.1. Does Hibernate 7 Still Read hibernate.cache.provider_class?

No. Hibernate 7 ignores the key and logs nothing about it, so even a class that does not exist lets the EntityManagerFactory start normally.

.property("hibernate.cache.use_second_level_cache", true)
.property("hibernate.cache.provider_class", "org.example.NoSuchProvider")   // starts, no error
// region factory: JCacheRegionFactory

The cache still worked, but only because hibernate-jcache was the single region factory on the classpath, and Hibernate picks that one by itself. So we delete the old key, and nobody is misled into thinking it controls the cache.

3.2. Why Does Hibernate 7 Reject EhCacheRegionFactory?

The Hibernate 4 and 5 names belong to the hibernate-ehcache module, which does not exist for Hibernate 6 and 7. Both names fail at startup, whereas jcache starts.

hibernate.cache.region.factory_classRoot cause on Hibernate 7.4
org.hibernate.cache.ehcache.EhCacheRegionFactoryClassNotFoundException: Could not load requested class: org.hibernate.cache.ehcache.EhCacheRegionFactory
ehcacheClassNotFoundException: Could not load requested class: ehcache
jcacheStarts, with hibernate-jcache on the classpath

3.3. How Do I Find the Jar That Still Uses CacheProvider?

The Hibernate 3 to 5 jars use the group id org.hibernate, while Hibernate 6 and 7 use org.hibernate.orm. Filtering the Maven dependency tree on the old group id and on spring-orm lists the suspects.

mvn dependency:tree -Dincludes=org.hibernate,org.springframework:spring-orm
[INFO] com.howtodoinjava:hibernate-cacheprovider-error:jar:1.0.0
[INFO] +- org.hibernate:hibernate-ehcache:jar:3.6.10.Final:test
[INFO] \- org.springframework:spring-orm:jar:3.2.18.RELEASE:test

In the example, both jars are there on purpose. In a real project, any org.hibernate jar next to hibernate-core 6 or 7, or a spring-orm older than the rest of Spring, has to be removed or upgraded.

4. Conclusion

The error NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider comes from a version mix. A Hibernate 3 class runs with Hibernate 4 or newer, where CacheProvider was replaced by RegionFactory. Old projects fix it with the Spring factory bean and the EhCacheRegionFactory that match their Hibernate version. On Hibernate 7, we remove every Hibernate 3 and hibernate-ehcache piece, add hibernate-jcache with Ehcache 3, set region.factory_class to jcache, and check the hit count in the statistics.

5. References

Happy Learning !!

Source Code on Github

Leave a Comment

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.