Caching in Spring Example + Ehcache + Cacheable + Annotation/JavaConfig

Caching in Spring Example + Ehcache + Cacheable + Annotation/JavaConfig thumbnail
25K
By Dhiraj 25 November, 2016

As we know EhCache is a widely used caching library. Spring provides easy annotation based integration mechanism of ehcache using @Cacheable. Here we will be creating a sample example to integrate Ehcache with spring by using @Cacheable annotation.We will be caching user details and try to fetch the same user detail again and again and compare the time required to fetch it. The spring configuration here in the app will be completely java config.

Environment Setup

1. JDK 8 2. Spring 4 3. Intellij Idea/ eclipse 4. Maven

Project Structure

spring-ehcache-project-structure

Maven Dependencies

Following are the maven dependencies required for spring ehcache implementation.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.developerstack</groupId>
    <artifactId>spring-caching-example</artifactId>
    <version>0.1.0</version>

    <properties>
        <spring.version>4.1.0.RELEASE</spring.version>
    </properties>

    <dependencies>
		<dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
			<version>2.10.0</version>
        </dependency>
		<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
        </dependency>
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
    </dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml$gt
				</configuration>
			</plugin>
		</plugins>
	</build>
	
</project>

Spring Bean Configuration

Now let us configure our beans.

@EnableCaching : Enables Spring's annotation-driven cache management capability. If no config location is specified, a CacheManager will be configured from "ehcache.xml" in the root of the class path (that is, default EhCache initialization - as defined in the EhCache docs - will apply).

CacheManager : Allows for retrieving named Cache regions.

BeanConfig.java
package com.developerstack.config;

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.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableCaching
@ComponentScan(basePackages = "com.developerstack")
public class BeanConfig {

	@Bean
	public CacheManager cacheManager() {
		return new EhCacheCacheManager(ehCacheCacheManager().getObject());
	}

	@Bean
	public EhCacheManagerFactoryBean ehCacheCacheManager() {
		EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
		cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
		cmfb.setShared(true);
		return cmfb;
	}
}
 Other Interesting Posts
Spring 5 Features and Enhancements
Spring Hibernate Integration with complete JavaConfig
Spring MVC Angularjs Integration with complete JavaConfig
Spring Boot Spring MVC Example
Spring Boot Thymeleaf Example
Spring Boot Security Redirect after Login with complete JavaConfig
Spring Security Hibernate Example with complete JavaConfig
Securing REST API with Spring Security Basic Authentication
Spring Security Password Encoding using Bcrypt Encoder
Spring Boot Security Custom Form Login Example
Spring JMS Activemq Integration with Spring Boot
Websocket spring Boot Integration without STOMP with complete JavaConfig
Spring Junit Integration with complete JavaConfig
Spring Ehcache Cacheable Example with complete javaConfig

Following is the model class to hold user details.

UserDetails.java
package com.developerstack.model;

public class UserDetails {
	
	private int id;
	private String firstName;
	private String lastName;
	private String email;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}

}

Let us define our service. Here we are caching the userDetails object. The value user is the same as we defined have defined in our ehcache.xml.

UserServiceImpl.java
package com.developerstack.service.impl;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.developerstack.model.UserDetails;
import com.developerstack.service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService {

	@Cacheable(value="user", key="#id")
	public UserDetails findUser(long id) {
		pause(3000L);
		UserDetails ud1 = new UserDetails();
		ud1.setId(id);
		ud1.setEmail("john@example.com");
		ud1.setFirstName("John");
		ud1.setLastName("Doe");
		return ud1;
	}

	private void pause(long sec) {
		try {
			Thread.sleep(sec);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}

}

Below is the ehcache.xml. This file has the cache configuration.

ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="ehcache.xsd"
	updateCheck="true"
	monitoring="autodetect"
	dynamicConfig="true">

	<diskStore path="java.io.tmpdir" />

	<cache name="user"
		maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000"
		eternal="false"
		diskSpoolBufferSizeMB="20"
		timeToIdleSeconds="300" timeToLiveSeconds="600"
		memoryStoreEvictionPolicy="LFU"
		transactionalMode="off">
		<persistence strategy="localTempSwap" />
	</cache>

</ehcache>

Now let us create Application.java which will execute the service to test whether our caching implementation is working as expected or not. Here we will be calling the same method of the service class with same and different parameters and analyse the time required to execute the methods. based on this we will draw our conclusion on the behaviour of caching.

Application.java
package com.developerstack.config;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.developerstack.service.UserService;

public class Application {

	public static void main(String[] args) {

		ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
		UserService obj = context.getBean("userService", UserService.class);
		
		long initialMillis = System.currentTimeMillis();
		obj.findUser(1L);
		long currentMillis = System.currentTimeMillis();
		System.out.println("Time taken to fetch user for first time " + (currentMillis - initialMillis)/1000 + " sec");
		System.out.println();
		
		System.out.println("*************finding user for second time ****************************");
		initialMillis = System.currentTimeMillis();
		obj.findUser(1L);
		currentMillis = System.currentTimeMillis();
		System.out.println("Time taken to fetch same user again " + (currentMillis - initialMillis)/1000 + " sec");
		System.out.println();
		
		System.out.println("*************finding new user ****************************");
		initialMillis = System.currentTimeMillis();
		obj.findUser(2L);
		currentMillis = System.currentTimeMillis();
		System.out.println("Time taken to fetch another user " + (currentMillis - initialMillis)/1000 + " sec");
		((ConfigurableApplicationContext) context).close();

	}
}

Run Application

1. Run Application.java as a java application. And analyse the console output. For the first time, the method took 3 seconds to find and return the user object. At this point the output is cached with key id. When we again tried to find user with same id, the method did not execute and the user object was returned from cache and hence it took 0 sec to find the user. Next, we again invoked the method with different id, but this time since the user with id 2 is not cached, the mmethod executed and tok 3 seconds to find and return the user object.

spring-ehcache-example

Conclusion

I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

Download the source

Share

If You Appreciate This, You Can Consider:

We are thankful for your never ending support.

About The Author

author-image
A technology savvy professional with an exceptional capacity to analyze, solve problems and multi-task. Technical expertise in highly scalable distributed systems, self-healing systems, and service-oriented architecture. Technical Skills: Java/J2EE, Spring, Hibernate, Reactive Programming, Microservices, Hystrix, Rest APIs, Java 8, Kafka, Kibana, Elasticsearch, etc.

Further Reading on Spring MVC