Simple Spring Memcached – Spring Caching Abstraction and Memcached

Caching remains the one of the most basic performance enhancing mechanism in any read heavy database application. Spring 3.1 release came up with a cool new feature called Cache Abstraction. Spring Cache Abstraction provides the application developers an easy, transparent and decoupled way to implement any caching solution. Memcached is one of the most popular distributed caching system used across apps. In this post we will focus on how to integrate memcached with a Spring enabled applications. Since Spring directly supports only Ehcache and ConcurrentHashMap so we will fall down to a third party library Simple Spring Memcache to leverage power of spring caching abstraction.
 
 

Getting The Code

Code for this tutorial can be downloaded from following SVN location. https://www.assembla.com/code/weblog4j/subversion/nodes/24/SpringDemos/trunk For the tutorial to work please create the following table in your db. Then modify the datasource in springcache.xml.

CREATE  TABLE IF NOT EXISTS `adconnect`.`books` (
  `book_id` INT NOT NULL AUTO_INCREMENT ,
  `book_name` VARCHAR(500) NULL ,
  `book_author` VARCHAR(500) NULL ,
  `category` VARCHAR(500) NULL ,
  `numpages` INT NULL ,
  `price` FLOAT NULL ,
  PRIMARY KEY (`book_id`) )
ENGINE = InnoDB;

Integration Steps

1. Dependencies - I also assume that you have your hibernate, spring and logs set up. So for downloading SSM dependencies add following to your POM. For full set of dependencies please download the project from SVN url above.

<dependency>
     <groupId>com.google.code.simple-spring-memcached</groupId>
     <artifactId>spring-cache</artifactId>
     <version>3.1.0</version>
</dependency>

<dependency>
     <groupId>com.google.code.simple-spring-memcached</groupId>
     <artifactId>xmemcached-provider</artifactId>
     <version>3.1.0</version>
</dependency>

2. Enable Caching – To enable caching in your spring application add following to your spring context xml.

<cache:annotation-driven/>

3. Configure Spring to enable Memcached based caching  – Add following to your application context xml.

<bean name="cacheManager" class="com.google.code.ssm.spring.SSMCacheManager">
     <property name="caches">
         <set>
             <bean class="com.google.code.ssm.spring.SSMCache">
                 <constructor-arg name="cache" index="0" ref="defaultCache"/>
                 <!-- 5 minutes -->
                 <constructor-arg name="expiration" index="1" value="300"/>
                 <!-- @CacheEvict(..., "allEntries" = true) doesn't work -->
                 <constructor-arg name="allowClear" index="2" value="false"/>
             </bean>
         </set>
     </property>

    </bean>

<bean name="defaultCache" class="com.google.code.ssm.CacheFactory">
     <property name="cacheName" value="defaultCache"/>
     <property name="cacheClientFactory">
        <bean name="cacheClientFactory" class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl"/>
     </property>
     <property name="addressProvider">
         <bean class="com.google.code.ssm.config.DefaultAddressProvider">
            <property name="address" value="127.0.0.1:11211"/>
         </bean>
     </property>
     <property name="configuration">
         <bean class="com.google.code.ssm.providers.CacheConfiguration">
             <property name="consistentHashing" value="true"/>
         </bean>
     </property>

</bean>

SSMCacheManager extends org.springframework.cache.support.AbstractCacheManager – It is an  abstract class and is a manager for underlying Cache.

SSMCache implements org.springframework.cache.Cache – This is actual  wrapper round underlying cache client api.

4. Annotation Driven caching – Spring uses annotation to mark a method that it is to be managed by  cache.  These are the annotations defined by spring caching framework

  1. @Cacheable – This annotation is used to mark a method whose results are to be cached. If a cacheable method is called then spring first looks if result of the method is cached or not. If it present in cache then result is pulled from there else it the method call is made.                                                                                                                         
  2. @CachePut – Methods marked with cacheput annotations are always run and their results are pushed to cache. You should not place both Cacheput and Cacheable annotation on same method as they have different behaviour. Cacheput will result in method getting executed all the time while cacheable results in method getting executed only once.
  3. @CacheEvict – This annotation results in eviction of objects from the cache. This is generally used when the result object is updated hence the old object from cache needs to be purged.
  4. @Caching – This annotation is used if multiple annotations of same type is to be put on a method.

@Cacheable Demo 

@Cacheable(value = "defaultCache", key = "new Integer(#book_id).toString().concat('.BookVO')")
    public BookVO get(int book_id) throws Exception {
        BookVO bookVO = null;
		try{
			Query query = getSession().createQuery("from BookVO bookVO where bookVO.book_id=:book_id");
			query.setLong("book_id", book_id);
			bookVO =  (BookVO)query.uniqueResult();
		}catch(HibernateException he){
			log.error("Error in finding a bookVO : " + he);
            throw new Exception("Error in finding adPicVO by book_id for book_id : " + bookVO, he);
		}
		return bookVO;
    }

Please note the key attribute of the annotation. This is an example of Spring Expression Language. You can use SePL use to create memcache key according to your requirement. In this example I want a key which should be of form <book_id>.BookVO. 

Another Example – Lets say I want to store a list of bookVO from a given author in that case I can a unique key of form <author_name>.BookVOList so for that I can use following key

@Cacheable(value = "defaultCache", key = "#author.concat('.BookVOList')")
    public List<BookVO> getList(String author) throws Exception {

@CachePut Demo

@CachePut(value = "defaultCache", key = "new Integer(#bookVO.book_id).toString().concat('.BookVO')")
    public BookVO create(BookVO bookVO) throws Exception {
        try{
			getSession().save(bookVO);
			getSession().flush();
		}catch(HibernateException he){
			log.error("Error in inserting bookVO : " + he);
            throw new Exception("Error in inserting bookVO", he);
		}

		return bookVO;
    }

CachePut can be used while inserting data where data inserted can be put in cache after insertion is done

@CacheEvict Demo

@CacheEvict(value = "defaultCache", key = "new Integer(#bookVO.book_id).toString().concat('.BookVO')")
    public BookVO update(BookVO bookVO) throws Exception {
        try{
            Query query = getSession().createQuery("update BookVO bookVO set bookVO.book_name=:book_name, bookVO.book_author=:book_author,bookVO.category=:category,bookVO.numpages=:numpages,bookVO.price=:price " +
                                                   "where bookVO.book_id=:book_id");
            query.setString("book_name", bookVO.getBook_name());
            query.setString("book_author", bookVO.getBook_author());
            query.setString("category", bookVO.getCategory());
            query.setInteger("numpages", bookVO.getNumpages());
            query.setFloat("price", bookVO.getPrice());
			query.setLong("book_id", bookVO.getBook_id());
            query.executeUpdate();
		}catch(HibernateException he){
			log.error("Error in updating bookVO : " + he);
            throw new Exception("Error in updating bookVO", he);
		}

		return bookVO;
    }

Resources

  1. https://code.google.com/p/simple-spring-memcached/
  2. http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/cache.html
  3. http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/expressions.html
  4. http://static.springsource.org/spring/docs/3.1.0.M1/javadoc-api/index.html?org/springframework/cache/CacheManager.html
  5. http://doanduyhai.wordpress.com/2012/07/01/cache-abstraction-in-spring-3/
  6. http://viralpatel.net/blogs/cache-support-spring-3-1-m1/

 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

One Response to "Simple Spring Memcached – Spring Caching Abstraction and Memcached"

  1. Veda says:

    I noticed if there are multiple @Cacheable methods are specified in a class and if they are called from the same class, then only one of the method is cacheable; others are not.

    Work around: Move the ‘Cacheable’ methods to a different class and every other class calls this new ‘Cacheable’ class methods.
    Reason: The proxy class (the default ‘mode’ is ‘proxy’) created by Spring works only for external classes and not a method within the same class!

    Hope this helps others, since it took more than a day to figure out the problem!

Leave a Reply


× three = 3



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close