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
Interesting, I will pocket this for my next job.
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.
Its open source hostet at Google part of the slurry project