Make everything as simple as possible, but not simpler. -Albert Einstein 

Home Spring Framework Reduce Method calls with Spring 3.1 Cache Abstraction
formats

Reduce Method calls with Spring 3.1 Cache Abstraction

Summary: This article highlights Spring 3.1’s new Cache Abstraction.    In many enterprise applications, there are data access methods that return the same result for the same input parameters.   For these types of use cases, Spring 3.1’s Cache abstraction can reduce method invocations and improve overall application responsiveness.

Prerequisites: If you would like to obtain this article’s complete sample, it may be obtained from our GitHub repository.  All samples are Maven based java projects.

Spring ‘s Cache Abstraction: The Spring Framework provides annotations to enable a developer to transparently apply caching to new and existing applications.  The annotations utilized are @Cacheable and @CacheEvict.

In order to use Spring’s Cache Abstraction, perform the following:

1. Apply the org.springframework.cache.annotation.@Cacheable to a method known to return same object or collection for same method parameters.

2. Apply the org.springframework.cache.annotation.@CacheEvict to a method in order to remove all or some cache entries when invoked.

Let’s Get Started: Listing 1 displays MovieDAOImpl which contain the following methods: getMoviesByGenre(), loadAllMovies()The method getMoviesByGenre() is annotated with @Cacheable(“movies”). This annotation instructs Spring to create a cache (named “movies”) of Movies objects returned by this method.  The first time the method is invoked with a ‘genre’ parameter value,  the method will execute and the collection of Movie objects will be returned .  The  ‘genre’ parameter value and collection of Movie objects will be stored as  key/value pair respectively in the “movies” cache. The next time the getMoviesByGenre() method is called with the “genre” input parameter value, Spring will inspect the “movies” cache and use the “genre” parameter value as key to return the Movie objects.  If found, the Movies will be returned and the method will not be invoked.  The loadAllMovies() is marked with @CacheEvict(value=”movies”,allEntries=true).  This tells Spring to discard the Movie objects from the “movies” cache whenever this method is called.

Listing 1: MovieDAOImpl.java

package techbysample.spring3.sample1.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

import techbysample.spring3.sample1.dao.MovieDAO;
import techbysample.spring3.sample1.model.Movie;

 /**
 *
 * @author TechBySample.com
 *
 */
public class MovieDAOImpl implements MovieDAO {

	private static int invocationCountForGetMoviesByGenre = 0 ;

	@Cacheable("movies")
	public List getMoviesByGenre(String rating) {

		invocationCountForGetMoviesByGenre++;

	    List movies = new ArrayList();

		Movie movie1= new Movie();
		movie1.setTitle("Diehard");
		movie1.setGenre("action");
		movie1.setMovieRating("R");

		Movie movie2= new Movie();
		movie2.setTitle("The Dark Knight");
		movie2.setGenre("action");
		movie2.setMovieRating("PG-13");

		Movie movie3= new Movie();
		movie3.setTitle("Batman Begins");
		movie3.setGenre("action");
		movie3.setMovieRating("PG-13");

		Movie movie4= new Movie();
		movie4.setTitle("The Bourne Identity");
		movie4.setGenre("action");
		movie4.setMovieRating("PG-13");

		Movie movie5= new Movie();
		movie5.setTitle("The Bourne Ultimatum");
		movie5.setGenre("action");
		movie5.setMovieRating("PG-13");

		movies.add(movie1);
		movies.add(movie2);
		movies.add(movie3);
		movies.add(movie4);
		movies.add(movie5);

		System.out.println("Method getMoviesByGenre called " + invocationCountForGetMoviesByGenre + " time(s).") ;

		return movies;
	}

	@CacheEvict(value="movies", allEntries=true)
	public void loadAllMovies() {
		System.out.println("Method loadAllMovies has executed.");
	}

	public int getInvocationCountForGetMoviesByGenre()
	{
		return invocationCountForGetMoviesByGenre;
	}
}

Enable Spring Caching Abstraction: In order to ‘enable’ the cache annotations of @Cacheable and @CacheEvict, the <cache:annotation-driven /> element must be declared in the Spring configuration .xml file.  Listing 2 depicts an example:

Listing 2: MovieDAOTest-simplecache-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/jdbc
            http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/cache
            http://www.springframework.org/schema/cache/spring-cache.xsd">

	<!-- scans the classpath for annotated components (including @Repostory
		and @Service that will be auto-registered as Spring beans -->
	<context:component-scan base-package="techbysample.spring3.sample1" />

	<!-- Process cache annotations -->
	<cache:annotation-driven />

	<!-- generic cache manager configuration-->
	<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<bean
					class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
					p:name="movies" />
			</set>
		</property>

	</bean>

   <bean id="movieDAO" class="techbysample.spring3.sample1.dao.impl.MovieDAOImpl">
   </bean>
</beans>

Spring Cache Storage Implementations: Spring currently provides support for two cache storage providers: ConcurrentHashMap and Ehcache. Our example makes use of the ConcurrentHashMap cache storage provider.

Unit Testing Spring’s Cache Abstraction:  A JUnit test is utilized to demonstrate Spring’s caching behavior.  The  TestMovieDAOSimpleCache testcase  invokes getMoviesByGenre()  50 times with an input parameter of “action”.   Next, the testcase then calls loadAllMovies(), and then calls getMoviesByGenre() 50 additional times using same input parameter, “action”.  With the use of Spring’s caching behavior the getMoviesByGenre() method is actually only executed a total of 2 times!

Change directory to the project’s root folder.

Type:
mvn clean -Dtest=TestMovieDAOSimpleCache test
You should now see results similar to the following:

Resources:
Spring Cache Abstraction

 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
No Comments  comments 

Leave a Reply

Your email address will not be published. Required fields are marked *


*

© Techbysample.com, all rights reserved.