I have following method:
@Cacheable(value = "pow_cache", unless = "#pow==3",condition = "#val<5&&#result<100")
public Double pow(int val, int pow) throws InterruptedException {
System.out.println(String.format("REAL invocation myService.pow(%s, %s)", val, pow));
Thread.sleep(3000);
return Math.pow(val, pow);
}
and following main:
@SpringBootApplication
@EnableCaching
public class Main {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext context = SpringApplication.run(Main.class);
MyService myService = context.getBean(MyService.class);
invokePow(myService, 4, 4);
}
private static void invokePow(MyService myService, int val, int pow) throws InterruptedException {
for (int i = 0; i < 2; i++) {
System.out.println(String.format("invoke myService.pow(%s, %s)", val, pow));
System.out.println(myService.pow(val, pow));
}
}
}
And I see following output:
invoke myService.pow(4, 4)
REAL invocation myService.pow(4, 4)
256.0
invoke myService.pow(4, 4)
256.0
So it means that result was cached but it is unexpected beacause of
condition = "#val<5&&#result<100"
result is 256 and 256<100
is false
What do I wrong ?
There is difference between condition
and unless
. Based on this
public abstract String unless
Spring Expression Language (SpEL) attribute used to veto method caching.
Unlike condition(), this expression is evaluated after the method has been called and can therefore refer to the result. Default is "", meaning that caching is never vetoed.
from spring doc 3.2.x
you can use #result
only in unless
.
You can try
@Cacheable(value = "pow_cache", unless = "#pow==3||#result>100",condition = "#val<5")