Ehcache automatic key generation and @Cacheable spring annotation
Asked Answered
T

2

12

Does anybody know how the default key generation for Ehcache works? If I have the following method:

@Cacheable(cacheName = CACHE_KEY) // CACHE_KEY is static final field.
public List<DataObject> list(
    int firstRecord, int maxRecords, int pageSize, FilterObject filter) {
    ....
}

where FilterObject is a custom POJO, what should I expect to be the actual cache key?

What I am observing is when using different FilterObject instances and not changing the other arguments of my method call, it always produces the same result - the first call's result is cached and returned.

Probably it is the FilterObject POJO which causes the behaviour - I suppose it is either some serialization, or .toString() issue, because I haven't overridden the relevant methods.

Still I was unable to find exact information on how the cache key for such method is being formed both in Ehcache's website and in the @Cacheable annotation documentation. I'd appreciate any information and recommendations on this topic.

Trevar answered 15/3, 2012 at 11:49 Comment(0)
M
14

This is the default key generator

public class DefaultKeyGenerator implements KeyGenerator {

public static final int NO_PARAM_KEY = 0;
public static final int NULL_PARAM_KEY = 53;

public Object generate(Object target, Method method, Object... params) {
    if (params.length == 1) {
        return (params[0] == null ? NULL_PARAM_KEY : params[0]);
    }
    if (params.length == 0) {
        return NO_PARAM_KEY;
    }
    int hashCode = 17;
    for (Object object : params) {
        hashCode = 31 * hashCode + (object == null ? NULL_PARAM_KEY : object.hashCode());
    }
    return Integer.valueOf(hashCode);
}

}

As you can see, it combines the hash-codes of each method parameter.

Mammy answered 15/3, 2012 at 12:7 Comment(3)
Thanks, this explains the behavior I have observed. Also the code above turns out to be quite self-describing :)Trevar
this seems wrong, why should any method, in any class, all get a key of zero if the method has no parameters? I would assume it would be at least get a unique key, my assumption cost me a bit of time wondering why my new caching wasn't workingGurevich
I believe that some notes regarding the correctness of algorithm should be addedWoehick
H
5

Everything is explained in Spring reference documentation, namely in:

28.3.1.1 Default Key Generation:

[...]

  • If more the one param is given, return a key computed from the hashes of all parameters.

To provide a different default key generator, one needs to implement the org.springframework.cache.KeyGenerator interface. Once configured, the generator will be used for each declaration that doesn not specify its own key generation strategy (see below).

and below:

28.3.1.2 Custom Key Generation Declaration:

[...] the @Cacheable annotation allows the user to specify how the key is generated through its key attribute. The developer can use SpEL to pick the arguments of interest[...]

And an example from the docs:

@Cacheable(value="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

So in your case you should simply implement equals() and hashCode() for FilterObject. Decent IDE can generate them for you.

Heyde answered 15/3, 2012 at 12:6 Comment(2)
Thanks, I haven't looked at spring's documentation for this. Now the odd behavior is explained.Trevar
This explanation corresponds with Spring cache, but the question is about ehcache, with has no key option!Galilean

© 2022 - 2024 — McMap. All rights reserved.