[Logo] Terracotta Discussion Forums
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
[Expert]
EH-Cache has unpredictable behaviour  XML
Forum Index -> Ehcache
Author Message
ole1999

neo

Joined: 03/14/2012 03:19:18
Messages: 2
Offline

Hi there,

we use annotated ehcache for several methods in a large scale application. We experience mixed-up return values (or so to say wrong return values) if we use the cache annotations for methods which use cache annotations itself.

@com.googlecode.ehcache.annotations.Cacheable(cacheName = "cache")
method A (some parameters) {

// do something really cool
method B(also some parameters);
}

@com.googlecode.ehcache.annotations.Cacheable(cacheName = "cache")
method B (also some parameters) {

// do something really expensive
}


This also occurs if the method B is not using the annotation directly but a internal method in method B does this (and uses the same cache).

This behaviour is very annoying because of the relatively big size of the code base we cannot check all the time if a developer uses the annotation in a call stack once only.

We get no error message or something. But we get mixed results (this type of error is HARD to find). Is there a workaround?

Thanks for any comments on this.
steve

ophanim

Joined: 05/24/2006 14:22:53
Messages: 619
Offline

Hi,
Package up a sample that demonstrates the issue and we'll take a look. I haven't heard anything like this before so I'm curious.


Want to post to this forum? Join the Terracotta Community
ole1999

neo

Joined: 03/14/2012 03:19:18
Messages: 2
Offline

Hi Steve,

good news. We could simplify the problem. It even occurs when we use a single cached function.

@Override
@com.googlecode.ehcache.annotations.Cacheable(cacheName = "cache", keyGenerator = @KeyGenerator (name = "StringCacheKeyGenerator", properties = {
@Property( name="useReflection", value="false" ),
@Property( name="checkforCycles", value="false" ),
@Property( name="includeMethod", value="true" ), @Property( name="includeParameterTypes", value="false" )}))
public String getValue(final String key, final String type,
final Locale locale) {
// some method content
}

This method is called very often and for a wide range of parameters. We encounter a hash code clash for 2 subsequent calls (the method returns the same values when ehache is used):

key: "String 1", type 1
key: "String 2", type 2

By debugging the internal method of EHCache (HashCodeCacheKeyGenerator) we found that hashCode of String 1 differs from HashCode of String 2 by just 31. 31 is the Multiplier which is used for hashCode calculation. So the 2 calls return exactly the same hashCode.

We successfully fixed this behaviour by using StringCacheKeyGenerator as the cacheKeyGenerator-Method.

Could one solve this issue also by using the HashCodeCacheKeyGenerator?

steve

ophanim

Joined: 05/24/2006 14:22:53
Messages: 619
Offline

Thanks, We'll check it out.

Want to post to this forum? Join the Terracotta Community
abroszni

journeyman

Joined: 12/13/2010 17:02:58
Messages: 13
Offline

Hi,
just one precision, HashCodeCacheKeyGenerator is part of ehcache-spring-annotation :
http://code.google.com/p/ehcache-spring-annotations/

which is not developed by Terracotta, so if something is happening there, you should contact them.

However I had a look and I am not certain that the HashCodeCacheKeyGenerator is wrong in your case.
If I understand correctly, you are calling your method:
Code:
 public String getValue(final String key, final String type, final Locale locale) 
 

and you indicate that you used the following parameters:

"String 1", type 1
"String 2", type 2
 


There's one parameter missing here, the Locale, and your second parameter is not a String in your description, but I assume you have tried with
"String 1", "type 1", null
"String 2", "type 2", null

When debugging the HashCodeCacheKeyGenerator method, you found that the hashcode of String "String 1" and "String 2" differs by 31, which makes sense. I don't understand your comment here when you say :

we found that hashCode of String 1 differs from HashCode of String 2 by just 31. 31 is the Multiplier which is used for hashCode calculation. So the 2 calls return exactly the same hashCode.
 

Because "String 1" and "String 2" SHOULD return a different hashcode. The hashcode is used to calculate the key of the Element in the cache.
I hope it is clear that when you enter the parameters with "String 1" and "String 2", your method should return two different results, thus caching two different Elements. (Do not forget that Ehcache is a key-value cache, so caching two different objects means having two keys, one per object).

Be also careful that the HashCodeCacheKeyGenerator is a recursive method, and it calculates the key of the Element by recursing through the parameters you give in the method (and other parameters according to the @Property you set.).
Meaning that "String 1" is not the only parameter used to calculate the hash.

The end of the story is, with the information you've described, I can't see why an issue would be in the HashCodeCacheKeyGenerator.

One last comment, when using a HashCodeCacheKeyGenerator, you can expect to have different parameters giving the same hash, thus the same key.
That's the idea behind the hash function, reducing a set of data to a smaller set, thus having multiple data resulting in one same value. A hash is different from a unique identifier.
The chance is slim as it is a long but it exists.
If you want to avoid it, you should not use the HashCodeCacheKeyGenerator.

If you want to report a bug you could check that there's a real issue by trying a simple Unit test to assess that using different parameters will not fail.
Code:
  @Test
   public void testHashkeyGenerator() {
     HashCodeCacheKeyGenerator generator = new HashCodeCacheKeyGenerator(true, false);
     Long key1 = generator.generateKey(UseYourServiceClassHere.class, "getValue", String.class, "String 1", "type 1", Locale.getDefault());
     Long key2 = generator.generateKey(UseYourServiceClassHere.class, "getValue", String.class, "String 2", "type 2", Locale.getDefault());
     Assert.assertNotEquals(key1, key2);
   }
 

The first parameter is the name of your class using the annotation, the 2nd param is the name of the method onto which you put the @Cacheable annotation, the 3rd param is the class of the Object your method returns, then the following params are the parameters you pass in your method.

If you manage to make this test fail for a couple of sets of parameters, please give the complete sets of parameters you used, as well with the description of your Service class.
And I would advise to post the info in the ehcache-spring-annotations forum
http://groups.google.com/group/ehcache-spring-annotations

but you can also post here, we're glad to help.
Eventually anyway, if there is a bug in the HashCodeCacheKeyGenerator, this has to be fixed by the ehcache-spring-annotations developers.
 
Forum Index -> Ehcache
Go to:   
Powered by JForum 2.1.7 © JForum Team