Locale aware caching

January 29, 2009 | by Geoff

To help boost the performance of our webapps we like to implement caching. One nice feature of the Spring Framework is its support for AOP features within applications. We utilise this to implement AOP method caching within our Spring enabled web applications. This allows us to write code without needing to worry too much about direct caching as we can easily enable it at the method invocation level with some simple Spring config chicanery.

The SpringModules cache extension provides the legwork for implementing this and Spring AOP the glue. One limitation of this implementation out of the box is that it is not Locale aware. Spring nicely provides a LocaleContextHolder to enable disparate components within the app stack to be locale aware so we needed to leverage this in order to ensure our method caching was able to not only cache method invocations with the same argument signature, but also within the same Locale (not something passed as arguments) .

Below is the meat of our simple solution, a LocaleAwareCacheKeyGenerator:

    public final Serializable generateKey(MethodInvocation methodInvocation) {

        Method method = methodInvocation.getMethod();

        HashCodeCalculator hashCodeCalculator = new HashCodeCalculator();
        hashCodeCalculator.append(method.hashCode());

        // now suck in the locale
        Locale locale = LocaleContextHolder.getLocale();

        // and use the bit we care about for hashcode generation
        if (considerLanguageOnly) {
            hashCodeCalculator.append(locale.getLanguage().hashCode());
        } else {
            hashCodeCalculator.append(locale.hashCode());
        }

        // now try and sort out things for the method args
        Object[] methodArguments = methodInvocation.getArguments();

        if (methodArguments != null) {
            int methodArgumentCount = methodArguments.length;

            for (int i = 0; i < methodArgumentCount; i++) {
                Object methodArgument = methodArguments[i];
                int hash = 0;

                if (generateArgumentHashCode) {
                    hash = Reflections.reflectionHashCode(methodArgument);
                } else {
                    hash = Objects.nullSafeHashCode(methodArgument);
                }

                hashCodeCalculator.append(hash);
            }
        }

        return new HashCodeCacheKey(hashCodeCalculator.getCheckSum(), hashCodeCalculator.getHashCode());
    }

This class simply adds the Locale to the code used in the HashCodeChacheKeyGenerator supplied with Spring. So now we can easily enable locale aware AOP configured method invocation caching transparently to our application code.

Nice!

P.S. An eclipse project with code/test samples is available

Bookmark and Share

Tags: , ,

Leave a Reply