8

I have the following for the usage of a @Cacheable in spring (3.1):

spring:

<?xml   version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
    xmlns:sec="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 
                            http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
                            http://www.springframework.org/schema/data/mongo
                            http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
                            http://www.springframework.org/schema/cache 
                            http://www.springframework.org/schema/cache/spring-cache.xsd
                            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
                            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache" />
<!-- Ehcache library setup -->
<bean id="ehcache"  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
    p:config-location="classpath:ehcache.xml" />

Maven:

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.5.3</version>
    </dependency>

The to be cached method:

@Cacheable(value="cahceName", key="concat(#param1).concat(‘-’).concat(#param2)")
    public String cachedMethod(String param1,String param2)

Alas, when I debug the code, I see that the cached method gets called more than once even when param1 and param2 are the same (i.e the cahce is not used).

Any ideas?

checklist
  • 12,340
  • 15
  • 58
  • 102
  • note: for the cache to work, you need to call a method that is in an interface. – checklist Aug 13 '12 at 18:52
  • Hi Checklist - Can you please specify which of the two recommendations fixed your issue : key="#param1.concat(‘-’).concat(#param2)" or key="#p0.concat('-').concat(#p1)" ?? or both? – HellishHeat Dec 10 '13 at 12:08

2 Answers2

19

The key does not appear correct -

You may have meant - @Cacheable(value="cacheName", key="#param1.concat(‘-’).concat(#param2)")

Further, if the compilation is done without debug information, the param1, param2 argument names will not be available to expression evaluator. Instead you can refer to them using p0, p1 etc this way:

@Cacheable(value="cahceName", key="#p0.concat('-').concat(#p1)")

Update:

I have a one page test here which demonstrates how this works - https://gist.github.com/3315275

javanna
  • 59,145
  • 14
  • 144
  • 125
Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
  • 1
    can you please elaborate on the debug part? and why is p1 different than paam1 – checklist Aug 09 '12 at 20:17
  • Here is one related question on it - http://stackoverflow.com/questions/11041506/java-compiler-automatically-renaming-parameters-obfuscating – Biju Kunjummen Aug 09 '12 at 20:27
  • I have fixed the key but still it does not work. I even take the key away completely and my method keeps getting called. Is there something else I might be doing wrong? – checklist Aug 10 '12 at 06:33
  • 2
    I have a one page test here - https://gist.github.com/3315275, which demonstrates your scenario, the test works perfectly for me - the method gets called once and then caches. – Biju Kunjummen Aug 10 '12 at 16:11
2

In my case, the problem was caused by using the wrong configuration of the cache provider (Caffeine):

@Bean
public Caffeine<Object, Object> caffeineCacheBuilder() {
    return Caffeine.newBuilder()
        .initialCapacity(100)
        .maximumSize(1000)
        .expireAfterAccess(10, TimeUnit.MINUTES)
        .weakKeys(); // cause problems when concatenated keys used
}

As the docs says, weakKeys() method:

Specifies that each key (not value) stored in the cache should be wrapped in a WeakReference (by default, strong references are used).

Warning: when this method is used, the resulting cache will use identity ({@code ==}) comparison to determine equality of keys. Its {@link Cache#asMap} view will therefore technically violate the {@link Map} specification (in the same way that {@link IdentityHashMap} does).

Leszek Jasek
  • 2,206
  • 1
  • 23
  • 30