I am trying since few days to move my old project based on Springboot 2 / Hibernate 5 / EHCache 2 to the newer Java 17 / Springboot 3 / Hibernate 6 / EHCache 3.
Of course I've read a lot of documentation, tried many configurations and dependencies setup. I also debugged the libraries to figure out what was the reason of my problems.
Before posting the relevant parts of my code, I wish to list the issues I am trying to solve:
I realize it's not easy to answer with so little information at your disposal, but I trust you can tell me if I've made any obvious mistakes in dependency inclusion, application configuration (application.yaml
), or in the code itself.
It follows the relevant code parts.
Thank you in advance!
pom.xml
<properties>
<springboot.version>3.1.2</springboot.version>
<ehcache.version>3.10.8</ehcache.version>
<hibernate.version>6.2.2.Final</hibernate.version> <!-- As for the current version of springboot -->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache.version}</version>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jcache</artifactId>
<version>${hibernate.version}</version>
</dependency>
</dependencies>
application.yaml
spring:
cache:
jcache:
config: file:///app/config/ehcache.xml
jpa:
properties:
hibernate:
cache:
region.factory_class: org.hibernate.cache.jcache.internal.JCacheRegionFactory
use_second_level_cache: true
use_query_cache: true
ehcache.xml
<config
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.10.xsd"
>
<cache-template name="entitiesDefault">
<expiry>
<ttl unit="minutes">1</ttl>
</expiry>
<listeners>
<listener>
<class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>ORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">1000</heap>
</resources>
</cache-template>
<cache-template name="entitiesRelationsDefault">
<expiry>
<ttl unit="minutes">1</ttl>
</expiry>
<listeners>
<listener>
<class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>ORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">1000</heap>
</resources>
</cache-template>
<cache-template name="queriesDefault">
<expiry>
<ttl unit="minutes">1</ttl>
</expiry>
<listeners>
<listener>
<class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>ORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">1000</heap>
</resources>
</cache-template>
<cache
alias="default-update-timestamps-region"
>
<expiry>
<ttl unit="minutes">1</ttl>
</expiry>
<listeners>
<listener>
<class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>ORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">1000</heap>
</resources>
</cache>
<cache
alias="default-query-results-region"
uses-template="queriesDefault"
/>
<cache
alias="DemoEntity"
uses-template="entitiesDefault"
>
<value-type>api.demo.springboot.application.persistence.entities.DemoEntity</value-type>
</cache>
</config>
DemoEntity.java
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.cache.annotation.Cacheable;
import java.io.Serializable;
@Data
@Entity
@Table(name = "DEMO_TABLE")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DemoEntity implements Serializable {
private static final long serialVersionUID = 0L;
@Id
@Column(name = "ID")
private Integer id;
@Column(name = "DESCRIPTION")
private String description;
}
JpaCacheEventListener.java
import lombok.extern.slf4j.Slf4j;
import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class JpaCacheEventListener implements CacheEventListener<Object, Object> {
@Override
public void onEvent(CacheEvent event) {
if (log.isTraceEnabled()) {
log.trace(
"{ type: {}, key: {} }",
event.getType(),
event.getKey()
);
}
}
}
I finally found a solution to all the issues.
I report ONLY the fixes to the posted source code:
application.yaml
spring:
jpa:
properties:
hibernate:
cache:
region.factory_class: org.hibernate.cache.jcache.internal.JCacheRegionFactory
use_second_level_cache: true
use_query_cache: true
javax:
cache:
provider: org.ehcache.jsr107.EhcacheCachingProvider
uri: file:///app/config/ehcache.xml
missing_cache_strategy: fail
ehcache.xml
<!-- Entities (Mandatory: alias must be a FQDN of the entity in order to properly instantiate the cache as configured here!)-->
<cache
alias="it.sisal.betting.api.demo.springboot.application.persistence.entities.DemoEntity"
uses-template="entitiesDefault"
/>
No everything works!!!