29

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.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user3534483
  • 2,133
  • 5
  • 22
  • 19

5 Answers5

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.

Ruben
  • 3,986
  • 1
  • 21
  • 34
  • 1
    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 explicitely – user3534483 Oct 28 '15 at 08:04
  • 1
    @user3534483 sorry, i was wrong about the default key that Spring uses. I have edited the answer and added the right information. – Ruben Oct 28 '15 at 08:32
  • 1
    "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 downvote – usr-local-ΕΨΗΕΛΩΝ Jul 24 '19 at 10:28
  • @Ruben Why do we need key for no argument method? I can use #1 @Cachable("cache1") method1() #2 @Cachable("cache2") method2() . Is this incorrect way ? – StackOverFlow Jul 03 '20 at 16:20
  • This is a partially correct, and partially incorrect answer. Please see the answer below by Clif. That should be the accepted answer. – Michael Rountree Feb 25 '21 at 15:14
45

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'")
roelofs
  • 2,132
  • 20
  • 25
Cliff
  • 551
  • 4
  • 3
2

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.

Terran
  • 1,091
  • 18
  • 29
  • how to solve this problem on unit testing? https://stackoverflow.com/questions/50519570/spring-boot-2-testing-cacheable-with-mockito-for-method-without-arguments-is – Gowrav Oct 01 '21 at 08:48
  • @Gowrav maybe Mockito is interfering? – Terran Oct 02 '21 at 16:28
  • 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 mockito – Gowrav Oct 04 '21 at 16:42
  • @Gowrav try doReturn(...).when(...). Sometimes reordering this way helps make Mockito behave. – Terran Oct 05 '21 at 09:44
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")
vuhoanghiep1993
  • 715
  • 1
  • 8
  • 15
-1

Add # in the key

@Cacheable(value="usercache", key = "#mykey")
public string sayHello(){
    return "test"
}
slfan
  • 8,950
  • 115
  • 65
  • 78
Giggs
  • 203
  • 1
  • 2
  • 15
  • 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. – Michael Rountree Feb 25 '21 at 15:18