0
votes

I would like to cache getText method and update cache on setText. By now cache on getText method works, but I can not update value. Code below is base on tutorial from Hazelcast.

@Service
public class SlowService {

    String text = "Initial value";

    @Cacheable("text")
    public String getText() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return text;
    }

    @CachePut(value = "text", key = "#newText + 1")
    public String setText(String newText) {
        text = newText;
        return text;
    }
}

How to improve code above to make @CachePut annotation work?

EDIT: Tried adding same keys:

@Cacheable(value = "text", key = "#someKey")
    public String getText() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return text;
    }

    @CachePut(key = "#someKey")
    public String setText(String newText) {
        text = newText;
        return text;
    }

But getting:

java.lang.IllegalArgumentException: Null key returned for cache operation (maybe you are using named params on classes without debug info?) Builder[public java.lang.String com.example.demo.SlowService.getText()] caches=[text] | key='#someKey' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

2
Why should it. The keys for the cache differ, so the getText never sees the cached instance. - M. Deinum
Ok, but I followed the tutorial, which I linked. They used key key = "#newText + 1" - Bartek
Tutorial is wrong. You cannot have 2 methods, different chache keys and expect it to work. Another problem with this is that the old values never get cleared (unless there is a timeout on the cache time). - M. Deinum
So, how to achieve update logic with one method? For me it seems that I need two methods, am I wrong? - Bartek
The only thing you need to do is to make sure the cache key is the same for the get and the set method. They currently aren't. - M. Deinum

2 Answers

0
votes

You need to make sure the value that you're caching in the cache is referenced by the same key as in when you are using the cache put.

For example:

Say you're caching text "Hello world" with the key "hw". Your cache would hold a key "hw" with the value "Hello world".

Now say you want to update the value with the "hw" key to some other text. For that, you need to make sure the key you pass in is the same as the one you passed it to cache that instance, which would be "hw" in that case.

That way, the key "hw" would hold an updated value with it.

@Cacheable(value = "text", key = "hw")
public String getText() {
    try {
        TimeUnit.SECONDS.sleep(2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return text;
}

@CachePut(key = "hw")
public String setText(String newText) {
    text = newText;
    return text;
}
0
votes

The problem was with key naming, string name should be enclosed by ', hint. Below working code.

@Service
public class SlowService {

    String text = "Initial value";

    @Cacheable(value = "text", key = "'someKey'")
    public String getText() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return text;
    }

    @CachePut(value = "text", key = "'someKey'")
    public String setText(String newText) {
        text = newText;
        return text;
    }
}