Guice Caching And Interceptors

14 05 2010

A little while ago I wanted to try out Guice 2′s Interceptors. And amazingly enough, I managed to create an integration towards ehcache in a couple of hours and had fun too.

The result is this

// Calculator.java
package org.slurry.cache4guice;

public interface Calculator {

        public int calculateSomethingWild(Integer number) throws InterruptedException ;

        public int calculateSomethingWild(Integer number,Integer number2) throws InterruptedException ;

}

// CalculatorImpl.java
package org.slurry.cache4guice;

import org.slurry.cache4guice.annotation.Cached;

public class CalculatorImpl implements Calculator {

        @Cached
        public int calculateSomethingWild(Integer number)
                        throws InterruptedException {
                Thread.sleep(2000);

                return number;

        }

        @Cached
        public int calculateSomethingWild(Integer number, Integer number2)
                        throws InterruptedException {
                Thread.sleep(2000);

                return number + number2;
        }

}

And bind it in your module

// GuiceModule.java
package org.slurry.cache4guice;

import com.google.inject.AbstractModule;

public class GuiceModule extends AbstractModule {

        @Override
        protected void configure() {
                bind(Calculator.class).to(CalculatorImpl.class);

        }

}

So what’s backing those annotations in line 19 and 28 of the first source code box, whats doing all the magic?
1. An annotation, dada :)

package org.slurry.cache4guice.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)
public @interface Cached {

}

2. An interceptor, more interesting, look at line 18 the most important thing in the interceptor implementation

package org.slurry.cache4guice.aop;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import com.google.inject.Inject;

public class CacheInterceptor implements MethodInterceptor {

        private CacheManager cacheManager;

        private CacheKeyGenerator cacheKeyGenerator;

        public Object invoke(MethodInvocation invocation) throws Throwable {
                setupCacheIfNecessary(invocation);

                return getResultFromCacheOrMethod(invocation);

        }

...

3. Some Guice setup, in a module look at line 18,19 and 20. And actually line 19 are only needed if you need something injected into your interceptor

package org.slurry.cache4guice.module;

import net.sf.ehcache.CacheManager;

import org.slurry.cache4guice.annotation.Cached;
import org.slurry.cache4guice.aop.CacheInterceptor;
import org.slurry.cache4guice.aop.CacheKeyGenerator;
import org.slurry.cache4guice.cache.StringBasedKeyGenerator;

import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matchers;

public class CacheModule extends AbstractModule {
        protected void configure() {

                bind(CacheManager.class).toInstance(CacheManager.create());
                bind(CacheKeyGenerator.class).to(getCacheKeyGeneratorClass());
                CacheInterceptor cacheInterceptor = new CacheInterceptor();
                requestInjection(cacheInterceptor);
                bindInterceptor(Matchers.any(), Matchers.annotatedWith(Cached.class),
                                cacheInterceptor);
        }

        protected Class getCacheKeyGeneratorClass() {

                return StringBasedKeyGenerator.class;
        }
}

So could it be easier? I mean theres only 3 steps. Now I haven’t shown all the code, only the relevant ones for guice. There’s a little more to it. And I should probably expand the functionality, so there’s a evict from cache annotation, that can evict certain caches. So did you need a cache for guice or did you want to play with interceptors, now you got both :)

All hosted here, with source code and tests,  if you have additions please contribute

http://code.google.com/p/slurry/

About these ads

Actions

Information

4 responses

19 05 2010
James

Interesting, I will pocket this for my next job.

30 12 2010
David Kovacs

Your cache4Guice stuff looks really cool.

I’d love to see more of the source code if possible.

I’m working on a Wicket project where we’ll need Ehcache.

Would love to be able use Wicket + Guice + Ehcache

instead of Wicket + Spring + Ehcache + tons of XML.

Please get back to me if you can. Your solution could be a really elegant option. Thanks.

8 01 2011
ninomartinez

Its open source hostet at Google part of the slurry project

24 12 2012
Ogre

I couldn’t get it working, although my Maven skills are not great. I got:

ArtifactDescriptorException: Failed to read artifact descriptor for org.slurry:cache4guice:jar:1.0.16: UnresolvableModelException: Could not find artifact org.slurry:slurryparent:pom:1.0-SNAPSHOT

Perhaps you can post a brief explanation how to use it on the wiki?

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




Follow

Get every new post delivered to your Inbox.

%d bloggers like this: