@Cacheble annotation on no parameter method
Asked Answered
L

6

30

I want to have @Cacheable annotation on method with no parameter. In that case, I use @Cacheable as follows

@Cacheable(value="usercache", key = "mykey")
public string sayHello(){
    return "test"
}

However, when I call this method, it doesn't get executed and it get exception as below

org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'mykey' cannot be found on object of type 'org.springframework.cache.interceptor.CacheExpressionRootObject' - maybe not public?

Please suggest.

Leotaleotard answered 28/10, 2015 at 5:13 Comment(0)
S
54

It seems that Spring doesn't allow you to provide a static text for the cache key in the SPEL, and it doesn't include as default the name of the method on the key, so, you could be in a situation when two methods using the same cacheName and without a key would potentially cache different results with the same key.

The easiest workaround is to provide the name of the method as the key:

@Cacheable(value="usercache", key = "#root.methodName")
public string sayHello(){
return "test"
}

This would set sayHello as the key.

If you really need a static key, you should define a static variable in the class, and use #root.target:

public static final String MY_KEY = "mykey";

@Cacheable(value="usercache", key = "#root.target.MY_KEY")
public string sayHello(){
return "test"
}

You can find here the list of SPEL expressions that you can use in your key.

Scholl answered 28/10, 2015 at 6:29 Comment(5)
Can you please explain this line - A static key (mykey in your case) would also not make sense, as Spring already binds the Cache to the specific method. so what would be the key that will be stored in cache if i dont mention it explicitelyLeotaleotard
@Leotaleotard sorry, i was wrong about the default key that Spring uses. I have edited the answer and added the right information.Scholl
"It seems that Spring doesn't allow you to provide a static text for the cache key in the SPEL". This is wrong as you can use String literals. E.g. I use in production private static final String CACHE_KEY_ALL = "'##all'"; and works like a charm. Anyway the answer rocks so I will not downvotePetronia
@Scholl Why do we need key for no argument method? I can use #1 @Cachable("cache1") method1() #2 @Cachable("cache2") method2() . Is this incorrect way ?Yuma
This is a partially correct, and partially incorrect answer. Please see the answer below by Clif. That should be the accepted answer.Dulla
G
48

Try adding single quotes around mykey. It's a SPEL expression, and the singles quotes make it a String again.

@Cacheable(value="usercache", key = "'mykey'")
Glendaglenden answered 17/11, 2017 at 0:46 Comment(2)
This should be the correct answer as it is fully correct and directly answers the question.Dulla
This is something usually every java developer misses, i.e. adding single quotes.Stampede
L
3

You can omit the key parameter. Spring will then put the value with key SimpleKey.EMPTY into the cache:

@Cacheable("usercache")

Alternatively (apart from using SPEL outlined in the other solutions) you can always inject the CacheManager and manually handle it.

Leptospirosis answered 31/3, 2021 at 13:8 Comment(4)
how to solve this problem on unit testing? #50520070Cilka
@Cilka maybe Mockito is interfering?Leptospirosis
seems like it, I was unable to get around, if the api has a parameter its working as expected, but without arguments having the same issue, maybe we should log a bug against mockitoCilka
@Cilka try doReturn(...).when(...). Sometimes reordering this way helps make Mockito behave.Leptospirosis
F
0

For me problem is the syntax of key is not right

@Cacheable(value = "name", key = "#object.field1+object.field2")

Right is need # before key items:

@Cacheable(value = "name", key = "#object.field1+#object.field2")
Fomalhaut answered 12/4, 2023 at 8:4 Comment(0)
S
0

I missed to add # before id, like key must be look like, key="#id" not key="id"

@GetMapping("/{id}")
@Cacheable(key = "#id", value = "book")
public Book getBookById(@PathVariable Long id) {
    return bookService.getBookById(id);
}
Signesignet answered 3/2, 2024 at 7:45 Comment(0)
V
-2

Add # in the key

@Cacheable(value="usercache", key = "#mykey")
public string sayHello(){
    return "test"
}
Vickery answered 20/12, 2017 at 7:47 Comment(1)
This is for variable replacement if #mykey is a defined variable somewhere. However, it is not, and therefore, will result in a null key error.Dulla

© 2022 - 2025 — McMap. All rights reserved.