Spring boot with Ehcache 3 and JSR-107

Here we are going to cover how to use Ehcache 3 as a Spring caching  in Spring boot based into JSR-107, before we start we need to just highlight what us JSR-107 :

JSR-107(JCache) Annotations:

In regards to caching, Spring offers support for two sets of annotations that can be used to implement caching. You have the original Spring annotations and the new JSR-107 annotations, for more information you can check :

https://spring.io/blog/2014/04/14/cache-abstraction-jcache-jsr-107-annotations-support

Steps to use EhCache3 with Spring boot :

1- Create a spring boot maven project

2- Add the following maven dependencies in your pom.xml along with spring boot dependencies

<!– ehcache and JSR dependencies–>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache}</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<!– spring boot cache starter–>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

view raw
pom.xml
hosted with ❤ by GitHub

3- Set the spring.cache.jcache.config property to include the classpath and ehcache.xml file, enable the following in application.yml file

Screen Shot 2017-12-22 at 15.55.12.png

4- Enable caching in spring boot main class

@SpringBootApplication
// enable spring boot caching
@EnableCaching
public class AlertManagerApplication {
public static void main(String[] args) {
SpringApplication.run(AlertManagerApplication.class, args);
}
}

view raw
main.java
hosted with ❤ by GitHub

5- Configure your EhCache xml file as the following

<config
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
xmlns='http://www.ehcache.org/v3'>
<service>
<jsr107:defaults enable-management="true" enable-statistics="true"/>
</service>
<!– file persistance enabling–>
<persistence directory="./cache"></persistence>
<!– the 2 caches we will create–>
<cache alias="AlertsConfig" uses-template="config-cache"/>
<cache alias="Alerts" uses-template="alerts-template"/>
<!– the config cache tenplate–>
<cache-template name="config-cache">
<listeners>
<listener>
<!– the the main cache event listener–>
<class>com.demo.alertmanager.services.CacheEventLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>UPDATED</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>EVICTED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap>1</heap>
<offheap unit="MB">1</offheap>
<disk persistent="true" unit="MB">100</disk>
</resources>
</cache-template>
<cache-template name="alerts-template">
<listeners>
<listener>
<class>com.demo.alertmanager.services.CacheEventLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>UPDATED</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>EVICTED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap>1</heap>
<offheap unit="MB">1</offheap>
<disk persistent="true" unit="MB">100</disk>
</resources>
</cache-template>
</config>

view raw
ehcache.xml
hosted with ❤ by GitHub

6- Then you can easily inject the cache manger in your bean class if you do not want to use just simple annotations to enable caching for your operations

@Autowired
private javax.cache.CacheManager cacheManager;
// get access to your cache for further operation
private Cache<String, List<AlertEntry>> getAlertsCache() {
return cacheManager.getCache(CacheNames.Alerts.name());
}
// close the cache manager upon shutting down
@PreDestroy
public void close(){
cacheManager.close();
}

view raw
exmple.java
hosted with ❤ by GitHub

7- Start accessing your caches from cache manager if you want to do direct operation over it like below , please check EhcacheAlertsStore.java in the GitHub project for more information

@Override
// if you want to do atomic update over cache entry
public void updateAlertEntry(String serviceId, String serviceCode, AlertEntry alertEntry) {
//get the JSR cache reference
final Cache<String, List<AlertEntry>> alertsCache = getAlertsCache();
// then invoke atomic update on the cache entry
alertsCache.invoke(serviceId, (mutableEntry, objects) > {
if (mutableEntry.exists() && mutableEntry.getValue() != null) {
logger.debug("updating alert entry into the cache store invoke: {},{}",serviceId,serviceCode);
final List<AlertEntry> alertEntries = mutableEntry.getValue();
// remove only if it has the error code
alertEntries.removeIf(alertEntry1 > alertEntry1.getErrorCode().equals(serviceCode));
alertEntries.add(alertEntry);
mutableEntry.setValue(alertEntries);
}else{
throw new ResourceNotFoundException(String.format("Alert for %s with %s not found", serviceId,serviceCode));
}
// by api design nothing needed here
return null;
});
}

view raw
exmaple2.java
hosted with ❤ by GitHub

8- Complete code sample for testing is on GitHub where you can run it and play with the REST APIs for cache operations via the generated run-time swagger :

https://github.com/Romeh/spring-boot-web-Ehchache-3-Persistance

 

References :

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s