Assume you have methods that (almost) always return the same result for the same input arguments. If preparing method result is a heavy operation and/or it consumes time, it is reasonable to cache these results.
Tapestry5: Caching Method Results
One way of building method cache in Tapestry5 is by implementing?MethodAdvice?interface like this:public class CacheMethodResultAdvice implements MethodAdvice {
private static final Logger logger = LoggerFactory.getLogger(CacheMethodResultAdvice.class);
private final Cache cache;
private final Class<?> advisedClass;
private final Object nullObject = new Object();
public CacheMethodResultAdvice(Class<?> advisedClass, Cache cache) {
this.advisedClass = advisedClass;
this.cache = cache;
}
@Override
public void advise(Invocation invocation) {
String invocationSignature = getInvocationSignature(invocation);
String entityCacheKey = String.valueOf(invocationSignature.hashCode());
Object result;
if (cache.containsKey(entityCacheKey))
{
result = cache.get(entityCacheKey);
logger.debug("Using invocation result ({}) from cache '{}'", invocationSignature, result);
invocation.overrideResult(result);
}
else
{
invocation.proceed();
if (!invocation.isFail())
{
result = invocation.getResult();
cache.put(entityCacheKey, result);
}
}
}
private String getInvocationSignature(Invocation invocation) {
StringBuilder builder = new StringBuilder(150);
builder.append(advisedClass.getName());
builder.append('.');
builder.append(invocation.getMethodName());
builder.append('(');
for (int i = 0; i < invocation.getParameterCount(); i++) {
if (i > 0) {
builder.append(',');
}
Class<?> type = invocation.getParameterType(i);
builder.append(type.getName());
builder.append(' ');
Object param = invocation.getParameter(i);
builder.append(param != null ? param : nullObject);
}
builder.append(')');
return builder.toString();
}
}
?Implementation of?getInvocationSignature(...)
?is not ideal, but you may improve it to match your requirements. One issue I see here is building invocation signature for?null
-value parameters in a clustered environment (which is GAE). In this implementation method?nullObject.toString()
?will return something like?java.lang.Object@33aa9b
. And this value will vary in different instances of your application. You may replace?nullObject
?with just?"null"
?string. Just keep in mind that?"null" != null
.