Google App Engine: Understanding Non-Invasive Caching


In the last post on understanding caching we talked about the general support of GAE for caching and how we could easily incorporate caching in our application. You would also recollect that we talked about the invasive form of caching in which the business layer was aware about the caching framework. In this post let us talk about the non-invasive way to cache. Since caching is one of the cross cutting concerns like security and logging, the non-invasive way to cache is best implemented by aspects.

Since we are using spring in our application, the solution is biased towards that however, you could use the aspectj framework and the concept remains the same.

A quick reference, a JoinPoint is any Method in your app’s code that you wrote whether you were using AOP or not. A Pointcut is telling AOP which Joinpoints you want your advice code to run with/on. An advice is code you want to run when that JoinPoint method is being called, without adding the code directly into your app’s method. An Aspect is the class that holds the advice code.

Normally, we would know the interesting points to apply the advise because there are the entities that we might be requesting again and again or these entities are expensive to create and hence are created and cached.

Let us see what our advise might look like

public class CacheAspect {
	private final static Logger logger = Logger.getLogger(CacheAspect.class);
	public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
		...
		String cacheKey = getCacheKey(pjp.getArgs(), className, methodName);
		Object returnedValue;
		if ((returnedValue = CacheController.get(cacheKey)) == null) {
			logger.info(" CACHE MISS, starting cache process for = " + cacheKey);
			returnedValue = pjp.proceed();
			CacheController.put(cacheKey, returnedValue);
		} else {
			logger.info(" CACHE HIT! for key = " + cacheKey);
		}
		return returnedValue;
	}

As you would notice that this code is an around advice. This aspect is wrapped around a method. The aspect code checks if the value that we are interested in, identified by the key, exists in the cache or not. If not, then get the return value by invoking the method which is being advised.

returnedValue = pjp.proceed();
and put the value in the cache
CacheController.put(cacheKey, returnedValue);

If you would recall, this is very similar to the code that we wrote in the business layer of the last post. The difference here being that this code is non-invasive since it is not present in the business layer but would be applied as an aspect.

Let us look at what a typical method that this would advice would look like

@SuppressWarnings("unchecked")
	public List findAllActive() {
		List<Customer> customers = new ArrayList<Customer>();
		List resultList = getEntityManager().createQuery("SELECT FROM Customer customer WHERE active = true")
				.getResultList();
		customers.addAll(resultList);
		return customers;
	}

Here we are getting a list of active customers and this does not change that frequently.

So how would our aspect work?

Once it is applied on the findAllActive method, it would check whether the list of customers is present in the cache. If yes, then return the value for the cache else, let the call to the datastore proceed and fetch the values from there. Also, set the values to the cache for subsequent requests.

The pointcut definition looks like this


<bean id="cacheAspect" class="com.bookmyhours.audit.CacheAspect">

<aop:config>
		<aop:aspect id="asp2" ref="cacheAspect">
			<aop:around
				pointcut="execution(public * com.bookmyhours.*.dao.*ProjectAssignmentDao.*findAll*(..))"
				method="invoke" />
		aop:aspect>
aop:config>

So we,

  1. Defined the aspect which had the advice.
  2. Next we identified the joinpoint which is nothing but any method in your class and
  3. Next we defined the bean for the aspect and the
  4. Pointcut definition which defines when the aspect should be applied.

The advantage as mentioned earlier is clean code and a non-invasive way to apply caching to your application.

Advertisements

About Vikas Hazrati

Vikas is the Founding Partner @ Knoldus which is a group of software industry veterans who have joined hands to add value to the art of software development. Knoldus does niche Reactive and Big Data product development on Scala, Spark and Functional Java. Knoldus has a strong focus on software craftsmanship which ensures high-quality software development. It partners with the best in the industry like Lightbend (Scala Ecosystem), Databricks (Spark Ecosystem), Confluent (Kafka) and Datastax (Cassandra). To know more, send a mail to hello@knoldus.com or visit www.knoldus.com
This entry was posted in Architecture, Cloud, Java and tagged , , , , . Bookmark the permalink.

One Response to Google App Engine: Understanding Non-Invasive Caching

  1. Pingback: What is the Correct Caching Strategy? « Inphina Thoughts

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s