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.
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
.