1

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 ?

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710

1 Answers1

2

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")
Zavael
  • 2,383
  • 1
  • 32
  • 44
  • But strange that I don't get any exception – gstackoverflow Sep 12 '19 at 12:56
  • maybe it understands the variable, but as stated it is not evaluated after the method call like unless, so it can have some default value (0, null, "") that makes your condition wrongly evaluate to true. Just my assumptions :) definitely it would more helpful with some exception – Zavael Sep 12 '19 at 12:59
  • Condition evaluates before so we don't have any result there but unless evaluates after so we have result there. Is it correct? – gstackoverflow Sep 12 '19 at 13:01
  • we dont have *your* result, but it can be initialized to some default value from the start... I am not sure about that though :( – Zavael Sep 12 '19 at 13:04