Spring Ehcache Configuration with @Cacheable Annotation

Written by: Arvind Rai,
Last updated:
August 03, 2018
On this page, we will learn Spring 4 Ehcache configuration example with @Cacheable annotation. Ehcache manages cache to boost performance our Spring application. 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 JavaConfig 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.
Spring 4 Ehcache Configuration Example with @Cacheable Annotation

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/> in XML configuration.
EhCacheManagerFactoryBean: It assigns 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 false.
EhCacheCacheManager: This is a CacheManager backed by an EhCache. We can instantiate it by passing argument of EhCacheManagerFactoryBean.getObject().

Find the JavaConfig.
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;
	}
} 
The equivalent ehcache configuration in Spring xml is given below.
<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

If we annotate our bean 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. When Spring will hit the method for the first time, the result of that method will be cached and for same argument value, Spring will not hit the method next 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 time, if we pass the same argument value, we will get result from cache and 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));
     } 
} 
Find the output.
Output
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 

Download Source Code

Join the Newsletter

(Subscribe to get our latest content directly into your inbox)

WRITTEN BY
ARVIND RAI
ARVIND RAI









©2024 concretepage.com | Privacy Policy | Contact Us