How to reference method argument in Spring 6.x @CachePut key?

24 views Asked by At

I'm updating an application from Spring 5.x/Boot 2.5 to Spring 6/Boot 3. One controller method uses a @CachePut annotation with a key property referencing a method argument like this:

@CacheEvict(cacheNames = "allNodes", allEntries = true)
@CachePut(cacheNames = "nodes", key = "#node.name")
public Node saveNode(@RequestBody Node node) {
    // ...
}

Node is our own class and it has a name property - it hasn't changed.

This method and the caching has worked well in Spring 5.x, but now with Spring 6.1 the method is producing this exception at runtime:

org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224) ~[spring-expression-6.1.4.jar:6.1.4]
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:111) ~[spring-expression-6.1.4.jar:6.1.4]
    at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorValueRef.getValue(PropertyOrFieldReference.java:416) ~[spring-expression-6.1.4.jar:6.1.4]
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:98) ~[spring-expression-6.1.4.jar:6.1.4]
    at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:114) ~[spring-expression-6.1.4.jar:6.1.4]
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:273) ~[spring-expression-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheOperationExpressionEvaluator.key(CacheOperationExpressionEvaluator.java:106) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:913) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport.generateKey(CacheAspectSupport.java:703) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.performCachePut(CacheAspectSupport.java:1024) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.apply(CacheAspectSupport.java:1016) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:560) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.4.jar:6.1.4]

Did something change in how Spring-Cache resolves method argument names in SpEL key expressions?

Stepping through the classes in the stack trace, CacheEvaluationContext never consults its arguments array when resolving the expression; it only consults variables which doesn't include the arguments.


I discovered that using the key expression like this key = "#result.name" works, but that's only useful by accident here (the method result is the same as its argument). I'd like to understand why #node.name is no longer working.

0

There are 0 answers