CodeDevStack

Calling a @Cacheable method from within the same class is not working

February 02, 2020

I came across this problem when I started working with Spring and it stumped my team for a few hours until we finally figured out what was going on.

We had something like this:

public class someCacheableService {

    @Cacheable("myData")
    public String getString() {
        //some call to a slow service to get string
        myString = someService.getStringFromSlowService();
        return myString;
    }

    public void init(){
        getString();
    }

}

Then we proceeded to call the init() method so as to call getString() and populate the cache.

But when we called the someCacheableService.getString() method from some other class, it was always executed once before Spring’s @Cacheable kicked in and started returning it directly.

This is happening because of how Spring handles proxying to create the caching behavior.

While there a few ways to fix this problem, the easiest solution is to create a method to handle the actual slow service call, and another one that returns the value we need to cache.

public class someCacheableService {

    private String myString;

    @Cacheable("myData")
    public String getString() {
        return myString;
    }

    public void init() {
        //some call to a service to get string
        myString = someService.getStringFromSlowService();
    }

}

By using this method, you need to call init() once to populate the private field and then just call getString() to get the value. The first time it’s called, the method will run and return myString, but all the following calls will trigger Spring’s @Cacheable functionality.

Of course, this is a very specific use case as we are not passing arguments to any of the methods.