|
Hello!
Similar trouble here: trying to use Ehcache with diskstore (so that cache could survive the application restarts) and due to "hashCodeCalculator.append(System.identityHashCode(method));" it doesn't use previously stored elements. It is not difficult to implement a CacheKeyGenerator similar to the default one, but such a limitation should be clearly stated somewhere (javadoc, user guide, ...) Omar,
Have you made any progress on this? Hello.
I can confirm this. We had the same issue when trying to use Ehcache + spring-modules. The problem, as specified above is with the line "hashCodeCalculator.append(System.identityHashCode(method));" in HashCodeCacheKey class. In a distributed environment, you have to use only the hashcode of the method name, because, obviously, the same instance of the class in different VMs will have different "identityHashCodes". The sollution (work-around) is easy: make another class with exactly the same code in HashCodeCacheKey, just change the line to hashCodeCalculator.append(method.getName().hashCode()) and inject it using spring in <bean id="XXXX" class="org.springmodules.cache.interceptor.proxy.CacheProxyFactoryBean"> <property name="cacheKeyGenerator" ref="myKeyGenenerator" /> .... </bean> Why is linking disabled in this Jira?
This issue partially duplicates http://jira.springframework.org/browse/MOD-478 I'm actually getting the arguments generating different hashes:
for "findTopAristsIntoTuples" generated 185003425 for "d0lby" generated 93889015 for "3month" generated 6452448 resulting cachekey: -1757708674|392138799 for "findTopAristsIntoTuples" generated 185003425 for "d0lby" generated 93889015 for "3month" generated 1704787 resulting cachekey: -1771951954|377895816 I've tried with both generateArgumentHashCode as true and false. 3month is actually a a custom enum, so looking into that now... ah - i see: http://bugs.sun.com/view_bug.do?bug_id=6373406 "A DESCRIPTION OF THE PROBLEM : Some application of Java enums as constants require enum instances to be really constant over different JVM instances. This is currently not the case (as reported in Incident Review ID: 419641). The reason is the call to System.identityHashCode() by java.lang.Enum.hashCode(), whose result is JVM-instance-specific." I've also got to have on because my Groovy beans hash() isn't producing consistent results either :/ I suppose that's because I'm too lazy to implement hashCode for all my models. DEBUG - MyCacheKeyGenerator - for "findAlbums" generated -418364675 DEBUG - MyCacheKeyGenerator - for "The Dream" of type 'com.xx.Artist' generated 6319910 resulting cachekey: 1713976502|-405724855 DEBUG - MyCacheKeyGenerator - for "findAlbums" generated -418364675 DEBUG - MyCacheKeyGenerator - for "The Dream" of type 'com.xx.Artist' generated 6841131 resulting cachekey: 1715018928|-404682413 I'm basically now using: {code} public final Serializable generateKey(MethodInvocation methodInvocation) { HashCodeCalculator hashCodeCalculator = new HashCodeCalculator(); // always use reflection generated hash codes for arguments generateArgumentHashCode = true; Method method = methodInvocation.getMethod(); // see MOD-255 // hashCodeCalculator.append(System.identityHashCode(method)); int methodHash = method.getName().hashCode(); hashCodeCalculator.append(methodHash); if(log.isDebugEnabled()) log.debug("for \"" + method.getName() + "\" generated " + methodHash); 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; // see http://bugs.sun.com/view_bug.do?bug_id=6373406 if (methodArgument instanceof Enum) { hash = methodArgument.toString().hashCode(); if(log.isDebugEnabled()) log.debug("method argument is enum (" + methodArgument.toString() + ") - using toString() hash: " + hash); } else { if (generateArgumentHashCode) { hash = Reflections.reflectionHashCode(methodArgument); } else { hash = Objects.nullSafeHashCode(methodArgument); } } if(log.isDebugEnabled()) log.debug("for \"" + methodArgument + "\" of type '" + methodArgument.getClass().getCanonicalName() + "' generated " + hash); hashCodeCalculator.append(hash); } } long checkSum = hashCodeCalculator.getCheckSum(); int hashCode = hashCodeCalculator.getHashCode(); Serializable cacheKey = new HashCodeCacheKey(checkSum, hashCode); log.debug("resulting cachekey: " + cacheKey); return cacheKey; } {code} |
||||||||||||||||||||||||||||||||||||
'HashCodeCacheKey cannot be used when using distributed caches (eg. Ehcache in distributed mode), because it does not produce equal cache keys for equal MethodInvocation instances. '
What I wanted to say was that HashCodeCacheKeyGenerator generates different HashCodeCacheKeys for MethodInvocations that have equal method
names and equal arguments, but belong to 2 different JVM instances.
hashCodeCalculator.append(System.identityHashCode(method));