Spring 4 Ehcache Configuration Example with @Cacheable Annotation
By Arvind Rai, March 16, 2015
In this page, we will learn Spring 4 Ehcache configuration example with @Cacheable annotation. Ehcache manages cache for boosting performance. Spring provides @Cacheable annotation that uses cache name defined in Ehcache xml file. Spring provides EhCacheManagerFactoryBean and EhCacheCacheManager classes to configure and instantiate Ehcache. The configuration class must be annotated with @EnableCaching annotation which enables annotation driven cache management. Here we will provide a complete example for Spring Ehcache Configuration.
build.gradle
Find the Gradle file to resolve JAR dependency for Spring and Ehcache.build.gradle
apply plugin: 'java' apply plugin: 'eclipse' archivesBaseName = 'concretepage' version = '1' repositories { mavenCentral() } dependencies { compile 'org.springframework.boot:spring-boot-starter:1.2.2.RELEASE' compile 'org.springframework:spring-context-support:4.1.5.RELEASE' compile 'net.sf.ehcache:ehcache-core:2.6.10' }
Project Structure in Eclipse
Find the project structure in eclipse that will help to learn fast.Configuration Class for EhCacheManagerFactoryBean and EhCacheCacheManager
The configuration class will be annotated with @EnableCaching annotation and we need to create bean for EhCacheManagerFactoryBean and EhCacheCacheManager class.@EnableCaching: It enables annotation driven cache management in spring and is same as using <cache:annotation-driven />.
EhCacheManagerFactoryBean: Assign ehcache XML file by calling EhCacheManagerFactoryBean.setConfigLocation(). By passing true to setShared() method, we enable our cache to be shared as singleton at the ClassLoader level. By default it is set to false.
EhCacheCacheManager: This is a CacheManager backed by an EhCache. We can instantiate it by passing argument of EhCacheManagerFactoryBean.getObject().
Find the Configuration file.
AppConfig.java
package com.concretepage; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; @Configurable @EnableCaching public class AppConfig { @Bean public Employee getEmployee(){ return new Employee(); } @Bean public CacheManager getEhCacheManager(){ return new EhCacheCacheManager(getEhCacheFactory().getObject()); } @Bean public EhCacheManagerFactoryBean getEhCacheFactory(){ EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean(); factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); factoryBean.setShared(true); return factoryBean; } }
<cache:annotation-driven /> <bean id="employee" class="com.concretepage.Employee"/> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml" p:shared="true"/>
ehcache.xml
Find the sample ehcache.xml file. We have created a cache with the name empcache that will be used by spring @Cacheable annotation. Here maximum 5000 elements will be cached in memory and after that it will overflow to local disk. Any element will expire if it is idle for more than 200 seconds and alive for more than 500 seconds.ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <cache name="empcache" maxEntriesLocalHeap="5000" maxEntriesLocalDisk="1000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="200" timeToLiveSeconds="500" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> <persistence strategy="localTempSwap"/> </cache> </ehcache>
Using @Cacheable on Bean Method
If we annotate our bean method by Spring @Cacheable annotation, it declares that it will be cached. We need to provide cache name defined in ehcache.xml. In our example we have a cache named as empcache in ehcache.xml and we have provided this name in @Cacheable. Spring will hit the method for the first time. The result of this method will be cached and for same argument value, spring will not hit the method every time. Once the cache is expired, then the spring will hit the method again for the same argument value.Employee.java
package com.concretepage; import org.springframework.cache.annotation.Cacheable; public class Employee { @Cacheable("empcache") public String getEmployee(int empId){ System.out.println("---Inside getEmployee() Method---"); if(empId==1){ return "Shankar"; }else{ return "Vishnu"; } } }
Test Spring Ehcache Application
Now we create a main method to test the application. Here if we call the method passing a value as an argument for the first time, spring will hit the method. And for next hit, if we pass the same argument value, we will get result from cache not by running method.SpringDemo.java
package com.concretepage; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class SpringDemo { public static void main(String... args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.refresh(); Employee employee=(Employee) ctx.getBean(Employee.class); //calling getEmployee method first time. System.out.println("---Fetch Employee with id 1---"); System.out.println("Employee:"+ employee.getEmployee(1)); //calling getEmployee method second time. This time, method will not execute. System.out.println("---Again Fetch Employee with id 1, result will be fetched from cache---"); System.out.println("Employee:"+employee.getEmployee(1)); //calling getEmployee method third time with different value. System.out.println("---Fetch Employee with id 2---"); System.out.println("Employee:"+employee.getEmployee(2)); } }
17:06:49.301 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'getEmployee' ---Fetch Employee with id 1--- ---Inside getEmployee() Method--- 17:06:49.323 [main] DEBUG net.sf.ehcache.store.disk.Segment - put added 0 on heap Employee:Shankar ---Again Fetch Employee with id 1, result will be fetched from cache--- Employee:Shankar ---Fetch Employee with id 2--- ---Inside getEmployee() Method--- 17:06:49.327 [main] DEBUG net.sf.ehcache.store.disk.Segment - put added 0 on heap Employee:Vishnu 17:06:49.332 [empcache.data] DEBUG net.sf.ehcache.store.disk.Segment - fault removed 0 from heap 17:06:49.332 [empcache.data] DEBUG net.sf.ehcache.store.disk.Segment - fault added 0 on disk